A TypeScript/JavaScript library for working with ASN, IPv4, and IPv6 numbers. It provides representations of these internet protocol numbers with the ability to perform various IP related operations like parsing, validating etc. on them

Overview

Coverage Status

ip-num

ip-num is a TypeScript library for working with IPv4, IPv6 and ASN numbers. It provides representations of these internet protocol numbers with the ability to perform various operations like parsing, validating etc. on them.

ip-num can be used with both TypeScript and vanila JavaScript. It also support both usage within a browser environment as well as Node.Js environment.

ip-num makes use of the BigInteger.js library to represents numeric values. This is due to the fact that numeric values when dealing with IP numbers can exceed the value that can safely be represented natively within JavaScript without loosing precisions ie numbers greater than Number.MAX_SAFE_INTEGER

ip-num's source can be found on GitHub

You can have a play at ip-num's API via the Runkit at http://bit.ly/ipnum-repl

Installation

Node.js

If you want to use ip-num from within a Node.js environment, you can install it via npm.

npm install ip-num

check the .travis.yml file for the versions of Node.js ip-num is being built and tested with.

Browser

If you are using a browser, you would have to use a module bundler like browserify, parceljs, webpack etc. to be able to use ip-num as a front-end module.

For quick prototyping, you can download the release from github at https://github.com/ip-num/ip-num/releases

You can then extract the compressed file and include the ip-num.js file located in the dist folder.

Usage

The functionality ip-num exposes can be grouped into 2 broad categories:

  • Modules representing ASN, IPv4, and IPv6 internet protocol numbers
  • Utilities and Validator

How you get access to the above, depends on the module loading mechanism being used. The examples below will show how to access ip-num using ES module mechanism with TypeScript in Node.js, using CommonJs module mechanism with JavaScript in Node.Js, and by including ip-num via a script tag with JavaScript in the browser.

ES module with TypeScript

Import what you need from ip-num and use away

import { Asn } from "ip-num/IPNumber";
import { IPv4 } from "ip-num/IPNumber";
import { IPv6 } from "ip-num/IPNumber";

You can then make use of the imported module in your TypeScript code

let asn = new Asn(65546);
asn.toBinaryString() //10000000000001010

let ipv4 = new IPv4("74.125.43.99");
ipv4.toBinaryString() //01001010011111010010101101100011

let ipv6 = new IPv6("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
ipv6.toBinaryString() //11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111

CommonJs with JavaScript

All external modules in ip-num are exported and made available via the global ip-num module. So you can require ('ip-num') and then access the module you want to use in your application, or access the module in one go, while requiring; as shown below:

const Asn = require("ip-num").Asn;
const IPv4 = require("ip-num").IPv4;
const IPv6 = require("ip-num").IPv6;

The imported module can then be used:

let asn = new Asn(65546);
asn.toBinaryString() //10000000000001010

let ipv4 = new IPv4("74.125.43.99");
ipv4.toBinaryString() //01001010011111010010101101100011

let ipv6 = new IPv6("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
ipv6.toBinaryString() //11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111

Via Script tag with JavaScript

Including the ip-num library via the script tag in the browser exposes ipnum variable from which you can access the modules exposes by the library.

<script src="https://ip-num.github.io/ip-num/ip-num.js"></script>
........
let asn = new ipnum.Asn(65546);
console.log(asn.toBinaryString()); //10000000000001010

let ipv4 = new ipnum.IPv4("74.125.43.99")
console.log(ipv4.toBinaryString()); //01001010011111010010101101100011

let ipv6 = new ipnum.IPv6("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
console.log(ipv6.toBinaryString()); //11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111

Documentation

Documentation can be found at https://ip-num.github.io/ip-num/

Examples

Find below, some example of the usage of ip-num. For a more comprehensive overview of the API, please refer to the documentation.

ip-num makes use of the BigInteger.js library to represents numeric values. This is due to the fact that numeric values that needs to be worked with when dealing with IP numbers can exceed the numeric value that can be safely represented natively within JavaScript without loosing precisions ie numbers greater than Number.MAX_SAFE_INTEGER

Overview

An overview covering some part of the module structure of ip-num is represented below:

IPNumber/ -- module that contains IP numbers implementations
├── AbstractIPNum -- contains common implementation to ASN, IPv4 and IPv6 
│   ├── Asn
│   ├── IPv4
|     ├── IPv4Mask
│   ├── IPv6
|     ├── IPv6Mask

IPRange/ -- module that contains IP ranges implementations
├── AbstractIPRange -- contains common implementation for IPv4 and IPv6 CIDR ranges 
│   ├── IPv4CidrRange
│   ├── IPv6CidrRange
├── RangedSet -- Represents a continuous segment of either IPv4 or IPv6 numbers without adhering to classless inter-domain routing scheme

IPPool/
├── Pool -- Represents a collection of IP numbers as single or set

ASN

import { Asn } from "ip-num/IPNumber";
..........
// creating
let asA = Asn.fromNumber(1234) // using the fromNumber factory method to create an instance from number
let asB = Asn.fromString("AS1234") // using the fromString factory method to create an instance from string
let asC = Asn.fromString("1234") // string without the "AS" prefix is also supported
let asD = Asn.fromString("1.10") // string in asdot+ format is also supported
let asE = Asn.fromBinaryString('1111') // using the fromBinaryString to create an instance from binary string

// converting between different ASN string representations
Asn.fromNumber(65526).toASDotPlus() // will give "0.65526"
Asn.fromNumber(65546).toASDot() // will give "1.10"
Asn.fromNumber(2).toBinaryString() // will give 10

// check if previous and next values exist, getting previous and next values
Asn.fromNumber(Math.pow(2, 32) - 1).hasNext() // false
Asn.fromNumber(2).hasNext() // true
Asn.fromNumber(0).hasPrevious() // false
Asn.fromNumber(2).hasPrevious() // true

See the ASN documentation for more information

IPv4

import { IPv4 } from "ip-num/IPNumber";

// creating
let firstIPv4 = new IPv4("74.125.43.99") // Creating an instance using the constructor
let secondIPv4 = IPv4.fromBigInteger(bigInt("1876843053")) // Using the fromBigInteger convenience method
let thirdIPv4 = IPv4.fromDecimalDottedString("111.222.90.45") // Using the fromDecimalDottedString convenience method
let fourthIPv4 = IPv4.fromBinaryString("01001010011111010010101101100011") // using the fromBinaryString convenience method

// converting an IPv4 instance to binary string representation
firstIPv4.toBinaryString() // will be 01001010011111010010101101100011

// comparing IPV4
firstIPv4.isEquals(thirdIPv4) // false
firstIPv4.isLessThan(thirdIPv4) // true
firstIPv4.isGreaterThan(thirdIPv4) // false

See the IPv4 documentation for more information

IPv6

import { IPv6 } from "ip-num/IPNumber";

// creating
let firstIPv6 = new IPv6("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff") // Creating an instance using the constructor
let secondIPv6 = IPv6.fromBigInteger(bigInt("100")) // Using the fromBigInteger convenience method
let thirdIPv6 = IPv6.fromHexadecimalString("::") // Using the fromDecimalDottedString convenience method. Not abbreviated representation of IPv6 string is supported
let fourthIPv6 = IPv6.fromBinaryString("01001010011111010010101101100011") // using the fromBinaryString convenience method
   
// converting an IPv6 instance to binary string representation
firstIPv6.toBinaryString() // will be 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
   
// comparing IPV6
firstIPv6.isEquals(thirdIPv6) // false
firstIPv6.isLessThan(thirdIPv6) // false
firstIPv6.isGreaterThan(thirdIPv6) // true

See the IPv6 documentation for more information

IPv4 Ranges

import {IPv4CidrRange} from "ip-num/IPRange";

// creating an IPv4 range from CIDR notation
let ipv4Range = IPv4CidrRange.fromCidr("192.198.0.0/24");

// get first and last IPv4 number in the range
ipv4Range.getFirst().toString() // gives 192.198.0.0
ipv4Range.getLast().toString() // gives 192.198.0.255

// getting number of IPv4 numbers in the range
ipv4Range.getSize() // Returns 256

// splitting ranges
ipv4Range.split()[0].toCidrString() // returns 192.198.0.0/25
ipv4Range.split()[1].toCidrString() // returns 192.198.0.128/25

Performing set like operations with IP Ranges:

import {IPv4CidrRange} from "ip-num/IPRange";

let containerRange = IPv4CidrRange.fromCidr("192.168.0.0/24");
let firstRange = IPv4CidrRange.fromCidr("192.168.0.0/25");
let secondRange = IPv4CidrRange.fromCidr("192.168.0.128/25");

console.log(containerRange.inside(firstRange)) // false

console.log(containerRange.inside(secondRange)) // false;

console.log(firstRange.inside(containerRange)); // true;
console.log(secondRange.inside(containerRange)); // true;

See the IPv4CidrRange documentation for more information

IPv6 Ranges

import {IPv6CidrRange} from "ip-num/IPRange";

// creating an IPv6 range from CIDR notation
let ipv6Range = IPv6CidrRange.fromCidr("2001:db8::/33");

// get first and last IPv6 number in the range
ipv6Range.getFirst().toString() // gives 2001:db8:0:0:0:0:0:0
ipv6Range.getLast().toString() // gives 2001:db8:7fff:ffff:ffff:ffff:ffff:ffff

// getting number of IPv6 numbers in the range
ipv6Range.getSize() // Returns 39614081257132168796771975168

// splitting ranges
ipv6Range.split()[0].toCidrString() // returns 2001:db8:0:0:0:0:0:0/34
ipv6Range.split()[1].toCidrString() // returns 2001:db8:4000:0:0:0:0:0/34

Performing set like operations with IP Ranges:

import {IPv6CidrRange} from "ip-num/IPRange";
let containerRange = new IPv6CidrRange(new IPv6("2001:db8::"), new IPv6Prefix(47));
let firstRange = new IPv6CidrRange(new IPv6("2001:db8::"), new IPv6Prefix(48));
let secondRange = new IPv6CidrRange(new IPv6("2001:db8:1::"), new IPv6Prefix(48));

console.log(containerRange.inside(firstRange)); // false
console.log(containerRange.inside(secondRange)); // false;

console.log(firstRange.inside(containerRange)) // true;
console.log(secondRange.inside(containerRange)) // true;

See the IPv6CidrRange documentation for more information

AbstractIPNum and AbstractIPRange

When working in TypeScript, you have the ability to abstract ASN, IPv4 and IPv6 as an AbstractIPNum, and IPv4CidrRange and IPv6CidrRange as AbstractIPRange

import {AbstractIPNum} from "ip-num/IPNumber";
import {AbstractIPRange} from "ip-num/IPRange";
import {Asn} from "ip-num/IPNumber";
import {IPv4} from "ip-num/IPNumber";
import {IPv6} from "ip-num/IPNumber";
import {IPv4CidrRange} from "ip-num/IPRange";
import {IPv6CidrRange} from "ip-num/IPRange";
import {IPv4Prefix} from "ip-num/Prefix";
import {IPv6Prefix} from "ip-num/Prefix";


// representing ASN, IPv4 and IPv6 as a AbstractIPNum
let ipNumbers: AbstractIPNum[] = [];
ipNumbers.push(new Asn("200"));
ipNumbers.push(new IPv4("133.245.233.255"));
ipNumbers.push(new IPv6("2001:800:0:0:0:0:0:2002"))

// console logs AS200
//              133.245.233.255
//              2001:800:0:0:0:0:0:2002
ipNumbers.forEach(ip => {
   console.log(ip.toString());
});


// representing IPv4CidrRange and IPv6CidrRange as AbstractIPRange

let ipRanges: AbstractIPRange<IPv4 | IPv6, IPv4Prefix | IPv6Prefix>[] = [];
ipRanges.push(IPv4CidrRange.fromCidr("192.198.0.0/24"));
ipRanges.push(IPv6CidrRange.fromCidr("2001:db8::/33"));

// console logs 192.198.0.0/24
//               2001:db8:0:0:0:0:0:0/33
ipRanges.forEach(iprange => {
   console.log(iprange.toCidrString());
});

See the IPNumber documentation for more information See the IPRange documentation for more information

IPv4Mask and IPv6Mask

IPv4Mask and IPv6Mask are used to represent subnet masks in IPv4 and IPv6 respectively.

Subnet masks are in all respects IP numbers with the only restriction that they must contain contiguous on bits (1's) followed by contiguous off bits (0's). This means IPv4Mask and IPv6Mask can perform all the operations available on IPv4 and IPv6. The only difference is that the invariant required for a subnet is enforced in the constructor of IPv4Mask and IPv6Mask. For example:

The following code will throw an exception:

import {IPv4Mask} from 'ip-num/IPNumber'
import {IPv6Mask} from 'ip-num/IPNumber'

let ipv4Mask = new IPv4Mask("10.255.10.3");
let ipv6Mask = new IPv6Mask("3ffe:1900:4545:0003:0200:f8ff:fe21:67cf");

While the following code works fine:

import {IPv4Mask} from 'ip-num/IPNumber'
import {IPv6Mask} from 'ip-num/IPNumber'

let iPv4Mask = new IPv4Mask("255.0.0.0");
let iPv6Mask = new IPv6Mask("ffff:ffff:ffff:ffff:ffff:ffff:0:0");

See the IPv4Mask documentation for more information See the IPv6Mask documentation for more information

IPv4-Mapped IPv6 Address Support

IPv4-Mapped IPv6 Address IPv6 allows embedding an IPv4 address within an IPv6 address. See IPv6 Addresses with Embedded IPv4 Addresses

ip-num offers various ways to create an IPv4-Mapped IPv6 Address:

Converting from an existing IPv4
import { IPv4 } from "ip-num/IPNumber";

let ipv4 = new IPv4("74.125.43.99")
ipv4.toIPv4MappedIPv6().toString() // produces ::ffff:4a7d:2b63
From an existing IPv4 using convenience method on IPv6
import { IPv6 } from "ip-num/IPNumber";
import { IPv4 } from "ip-num/IPNumber";

let ipv6 = IPv6.fromIPv4(new IPv4("74.125.43.99"))
ipv6.toString() // produces ::ffff:4a7d:2b63
From dot-decimal notation using convenience method on IPv6
import { IPv6 } from "ip-num/IPNumber";

let ipv6 = IPv6.fromIPv4DotDecimalString("74.125.43.99")
ipv6.toString() // produces ::ffff:4a7d:2b63

IP Pool

Pool allows for working with collections of IP numbers and ranges.

Creating Pools from list of IP numbers and converting to IP ranges

import {IPv4} from "ip-num/IPNumber";
import {Pool} from "ip-num/IPPool";

let pool = Pool.fromIPNumbers([
IPv4.fromDecimalDottedString("10.0.0.1"), 
IPv4.fromDecimalDottedString("10.0.0.2")
]);

let ranges = pool.getRanges();
console.log(ranges[0].toCidrRange().toCidrString()); // prints "10.0.0.1/32"
console.log(ranges[1].toCidrRange().toCidrString()); // prints "10.0.0.2/32"

Aggregating IP ranges

import {IPv4} from "ip-num/IPNumber";
import {Pool} from "ip-num/IPPool";
import {RangedSet} from "ip-num/IPRange";
import {IPv4CidrRange} from "ip-num/IPRange";

let arrays: RangedSet<IPv4>[] = new Array<RangedSet<IPv4>>();

arrays.push(RangedSet.fromCidrRange(IPv4CidrRange.fromCidr("192.168.0.0/26")));
arrays.push(RangedSet.fromCidrRange(IPv4CidrRange.fromCidr("192.168.0.64/26")));
arrays.push(RangedSet.fromCidrRange(IPv4CidrRange.fromCidr("192.168.0.128/27")));
arrays.push(RangedSet.fromCidrRange(IPv4CidrRange.fromCidr("192.168.0.160/27")));
arrays.push(RangedSet.fromCidrRange(IPv4CidrRange.fromCidr("192.168.0.192/26")));

let pool = Pool.fromRangeSet(arrays);
let aggregatedPool = pool.aggregate();

console.log(aggregatedPool.getRanges()[0].toRangeString()) // prints("192.168.0.0-192.168.0.255");
console.log(aggregatedPool.getRanges().length) // prints 1;

Validation and Utilities

Various validation are exposed via the Validator module. ip-num also provide various utility operations. These utility operations can be found in BinaryUtils, IPv6Utils, and HexadecimalUtils.

For example to expand and collapse IPv6 numbers:

import * as IPv6Utils from 'ip-num/IPv6Utils'

// expanding
IPv6Utils.expandIPv6Number("::") // Expands to 0000:0000:0000:0000:0000:0000:0000:0000
IPv6Utils.expandIPv6Number("FF01::101")// Expands to FF01:0000:0000:0000:0000:0000:0000:0101
// collapsing
IPv6Utils.collapseIPv6Number("0000:0000:0000:0000:0000:0000:0000:0000") // Collapses to :: 
IPv6Utils.collapseIPv6Number("FF01:0:0:0:0:0:0:101") // Collapses to FF01::101

To check if a given string is valid cidr notation:

import {Validator} from 'ip-num/Validator'

let result = Validator.isValidIPv4CidrNotation("123.234.334.23")
// result => [false, ["Cidr notation should be in the form [ip number]/[range]"]]
let result = Validator.isValidIPv4CidrNotation("10.0.0.0/8")
// result => [true, []]

See the Validator documentation for more information See the BinaryUtils documentation for more information See the IPv6Utils documentation for more information See the HexadecimalUtils documentation for more information

License

The ip-num library is released under the MIT license

Contributing

To discuss a new feature or ask a question, open an issue. Find the issue tracker here

Found a bug and you want to provide a fix for it? Then feel free to submit a pull request. It will be appreciated if the changes made are backed with tests.

Change log

View latest releases here

v1.2.1
v1.2.0
  • Introduced AbstractIpRange to abstract over the IPRange (ie: IPv4Range and IPv6Range). Issue #15
  • Extend the IPRange interface. Issue #20
  • Add method to IPRange to return the adjacent ranges. Issue #19
  • Add ability to validate if a CIDR notation represents a valid range. Issue #21
  • Changed target to es5 so as to support Internet Explorer 11. Issue #22
v1.1.1
  • Fixed isValidIPv4String() incorrectly returns true for some invalid addresses. Issue #9
  • Improved Validator.isValidIPv6String and added test coverage. Issue #10
  • Added convenient methods for creating IPv4 (IPv4.fromBinaryString) and IPv6 (IPv6.fromBinaryString) from binary string Issue #11
  • Added convenient methods for creating ASN (ASN.fromBinaryString) Issue #13
  • Prepend with "::" if toString value for IPv6 has leading zeros. Issue #12
  • Implemented support for IPv4-Mapped IPv6 Address. Issue #3
v1.1.0

Version 1.1.0 was Unpublished.

v1.0.1
  • Renamed Subnet to SubnetMask Issue #1
  • Fixed the throwing of invalid integer: NaN when invalid IPv4 and IPv6 strings are passed to Validator .isValidIPv4String and Validator.isValidIPv6String validators. Fixed by saiyeek Issue #5
  • Fixed Validator.isValidIPv4CidrNotation improper validation of IPv4 CIDR Issue #6

Acknowledgement

Special thanks to JetBrains for supporting the development of ip-num with a free IDE licence.

You can find more information about JetBrains support for open source projects here

Comments
  • Possible bug in Pool.aggregate()

    Possible bug in Pool.aggregate()

    import { IPv6Prefix, IPv6CidrRange, Pool } from 'ip-num';
    
    const pool = Pool.fromRangeSet([
        IPv6CidrRange.fromCidr('2aaa:2aaa:1::/48').toRangeSet(),
        IPv6CidrRange.fromCidr('2aaa:2aaa:2::/48').toRangeSet(),
    ]);
    
    const to48 = pool
        .aggregate()
        .getRanges()
        .flatMap(entry => {
            return (entry.toCidrRange() as IPv6CidrRange).splitInto(new IPv6Prefix(48)).map(entry => {
                return entry.toCidrString();
            });
        });
    
    const direct = pool
        .aggregate()
        .getRanges()
        .map(entry => {
            return entry.toCidrRange().toCidrString();
        });
    
    console.dir('to48 = ');
    console.dir(to48);
    console.dir('direct = ');
    console.dir(direct);
    

    logs the following:

    'to48 = '
    [ '2aaa:2aaa:0:0:0:0:0:0/48', '2aaa:2aaa:1:0:0:0:0:0/48' ]
    'direct = '
    [ '2aaa:2aaa:0:0:0:0:0:0/47' ]
    
    opened by lenovouser 9
  • IP ranges do not round trip correctly as strings

    IP ranges do not round trip correctly as strings

    We are seeing this:

    const cidr = "1.2.3.4/5";
    IPv4CidrRange.fromCidr(cidr).toCidrString();
    
    // -> 0.0.0.0/5
    

    The CIDR we put in ("1.2.3.4/5") is not the CIDR we get out ("0.0.0.0/5")

    I can see roughly why this is happening, as /5 is a very big range.

    The problem for us is that 1.2.3.4/5 is used as an internal placeholder in CDK: https://github.com/aws/aws-cdk/blob/cea1039e3664fdfa89c6f00cdaeb1a0185a12678/packages/%40aws-cdk/aws-ec2/lib/vpc.ts#L2198

    We are seeing tests break when we render our templates and try and round trip things.

    What would "you expect to happen" if you put string into a CIDR, then call toCidrString on it? I would say it should be the same, but I am sure there are some optimisations going on internally that are causing this.

    opened by hlascelles 5
  • Bug: Some type definitions still has dependency on big-integer lib in 1.4.0 and 1.4.0-1

    Bug: Some type definitions still has dependency on big-integer lib in 1.4.0 and 1.4.0-1

    Hi, There seems to be some lingering dependencies for big-integer library in type definitions. Have tried to re-install all node modules, have also checked that I have the latest release 1.4.0 and 1.4.0-1. Errors only goes away when installing big-integer lib manually.

    `Error: node_modules/ip-num/AbstractIPNum.d.ts:1:25 - error TS2307: Cannot find module 'big-integer' or its corresponding type declarations. 1 import * as bigInt from "big-integer"; ~~~~~~~~~~~~~ Error: node_modules/ip-num/AbstractIpRange.d.ts:1:25 - error TS2307: Cannot find module 'big-integer' or its corresponding type declarations. 1 import * as bigInt from "big-integer"; ~~~~~~~~~~~~~

    Error: node_modules/ip-num/IPv4.d.ts:3:25 - error TS2307: Cannot find module 'big-integer' or its corresponding type declarations. 3 import * as bigInt from "big-integer"; ~~~~~~~~~~~~~

    Error: node_modules/ip-num/IPv4CidrRange.d.ts:3:25 - error TS2307: Cannot find module 'big-integer' or its corresponding type declarations. 3 import * as bigInt from "big-integer"; ~~~~~~~~~~~~~

    Error: node_modules/ip-num/IPv6.d.ts:3:25 - error TS2307: Cannot find module 'big-integer/BigInteger' or its corresponding type declarations. 3 import * as bigInt from "big-integer/BigInteger"; ~~~~~~~~~~~~~~~~~~~~~~~~

    Error: node_modules/ip-num/IPv6CidrRange.d.ts:3:25 - error TS2307: Cannot find module 'big-integer' or its corresponding type declarations. 3 import * as bigInt from "big-integer"; ~~~~~~~~~~~~~

    Error: node_modules/ip-num/SubnetMask.d.ts:2:25 - error[90m TS2307: Cannot find module 'big-integer' or its corresponding type declarations. 2 import * as bigInt from "big-integer"; ~~~~~~~~~~~~~

    Error: node_modules/ip-num/interface/IPNumber.d.ts:1:28 - error TS2307: Cannot find module 'big-integer' or its corresponding type declarations.

    1 import { BigInteger } from "big-integer"; ~~~~~~~~~~~~~

    Error: node_modules/ip-num/interface/IPRange.d.ts:2:25 - error TS2307: Cannot find module 'big-integer' or its corresponding type declarations. 2 import bigInt = require("big-integer"); ~~~~~~~~~~~~~ `

    Cheers, Kevin

    opened by kevinava 3
  • IPv4CidrRange equality check very slow

    IPv4CidrRange equality check very slow

    After adding an IPv4CidrRange as a property of an object, my jest-based unit tests started taking incredibly long to run. It turns out a lot of time was spent parsing BigInts. The frequency of stacks containing expect's jasmineUtils's equality check suggests that comparing the equality of objects containing IPv4CidrRange is very expensive. I also noticed that in your own unit tests, you always convert to a string before checking equality. That's a sufficient workaround if you want to compare two CIDRs, but won't work if you want to compare two structures containing CIDRs as properties.

    The root cause appears to be that IPv4CidrRange is iterable, so expect's iterableEquality is iterating over every IPv4 in the range and checking equality for each. My tests were working with /18 networks and were taking a half-minute each. A simple demo comparing two identical /8s took well over an hour before I gave up and cancelled it.

    // test/demo.test.ts
    import { IPv4CidrRange } from "ip-num";
    
    for (let i = 32; i >= 16; i--) {
      test(`demo/${i}`, () => {
        let actual = IPv4CidrRange.fromCidr(`10.0.0.0/${i}`)
        let expected = IPv4CidrRange.fromCidr(`10.0.0.0/${i}`)
        expect(actual).toEqual(expected)
      })
    }
    
    $ time npm run test -t demo
    
    > [email protected] test /home/demo
    > jest "demo"
    
    
     PASS  test/demo.test.ts (39.255 s)
      ✓ demo/32 (7 ms)
      ✓ demo/31 (3 ms)
      ✓ demo/30 (5 ms)
      ✓ demo/29 (6 ms)
      ✓ demo/28 (8 ms)
      ✓ demo/27 (18 ms)
      ✓ demo/26 (26 ms)
      ✓ demo/25 (42 ms)
      ✓ demo/24 (71 ms)
      ✓ demo/23 (128 ms)
      ✓ demo/22 (249 ms)
      ✓ demo/21 (473 ms)
      ✓ demo/20 (939 ms)
      ✓ demo/19 (1882 ms)
      ✓ demo/18 (3802 ms)
      ✓ demo/17 (7632 ms)
      ✓ demo/16 (15394 ms)
    
    Test Suites: 1 passed, 1 total
    Tests:       17 passed, 17 total
    Snapshots:   0 total
    Time:        39.317 s
    Ran all test suites matching /demo/i.
    npm run test -t 'demo'  46.22s user 0.79s system 116% cpu 40.451 total
    
    opened by AWS-MattB 3
  • Quick check for whether string is an IP, IPv4 or IPv6

    Quick check for whether string is an IP, IPv4 or IPv6

    I know that the net node module can do this, but since this is the grand ip library for JavaScript, then perhaps these utility functions can be put here to avoid relying on Node functionality.

    opened by CMCDragonkai 3
  • IPv6 Collapse and Expand sometimes not working with CIDRs.

    IPv6 Collapse and Expand sometimes not working with CIDRs.

    It appears that in some cases when collapsing or expanding and IPv6 address with a CIDR that the collapse or expand is not completed as expected, and expand also can get an error, where the same IPv6 address without a CIDR works fine.

    // Errors or collapse not complete
    console.log(ipNum.collapseIPv6Number("2001:0555:0001:0800::/128"));
    //"2001:555:1:800:0:/128"
    console.log(ipNum.collapseIPv6Number("2001:0555:0001:0800::/50"));
    //"2001:555:1:800:0:/50"
    
    // works ok without cidrs
    console.log(ipNum.collapseIPv6Number("2001:0555:0001:0800::"));
    //"2001:0555:0001:0800:0000:0000:0000:0000"
    
    // Errors or expansion not complete
    console.log(ipNum.expandIPv6Number("2001:0470:0001:0800:0:0:0:0/128"));
    //Error: Given string is already longer than given final length after padding: 4
    console.log(ipNum.expandIPv6Number("2001:0555:0001:0800:0:0:0:0/50"));
    //"2001:0555:0001:0800:0000:0000:0000:0/50"
    console.log(ipNum.expandIPv6Number("2001:0555:0001:0800:0000:0000:0000:0000/50"));
    //Error: Given string is already longer than given final length after padding: 4
    console.log(ipNum.expandIPv6Number("2001:0555:0001:0800::/128"));
    //"2001:0555:0001:0800:0000:0000:0000:/128"
    console.log(ipNum.expandIPv6Number("2001:0555:0001:0800::/50"));
    //"2001:0555:0001:0800:0000:0000:0000:0/50"
    
    // works ok without cidrs
    console.log(ipNum.expandIPv6Number("2001:0555:0001:0800::"));
    //"2001:0555:0001:0800:0000:0000:0000:0000"
    console.log(ipNum.expandIPv6Number("2001:0555:0001:0800:0000:0000:0000:0000"));
    //"2001:0555:0001:0800:0000:0000:0000:0000"
    
    opened by ahayden-lg 3
  • Multiple

    Multiple "::" not considered invalid

    I noticed that invalid IPv6 values with 2 sets of "::" are not marked as in valid and are converted. But per the IPv6 specs only one "::" is allowed, because you can't tell how many 0s "::" should be expanded to if there are 2 "::"s. For example, I would have expected each of the following to not be considered valid:

    console.log(ipNum.expandIPv6Number("::123::"));
    console.log(ipNum.collapseIPv6Number("12::123::"));
    console.log(ipNum.Validator.isValidIPv6String("::123::234")[0]);
    
    "0000:0000:0000:0000:0000:0000:0000:0123"
    "12:0:123::"
    true
    

    Hopefully this is helpful.

    opened by ahayden-lg 3
  • Collapsing already collapsed IPv6 returns invalid IPv6 addr

    Collapsing already collapsed IPv6 returns invalid IPv6 addr

    Collapsing an already collapsed IPv6 address returns an invalid IPv6 address. This is important to collapse an IPv6 address, when it is not known if the address is already collapsed.

    Example (v. 1.3.2):

    var ipNum = require("ip-num")
    ipNum.collapseIPv6Number("2123:470:1:b95::7316");
    --> "2123:470:1:b95:0:7316"
    
    opened by ahayden-lg 3
  • Fix `.aggregate()`

    Fix `.aggregate()`

    Closes https://github.com/ip-num/ip-num/issues/82

    I am not a 100% sure whether my fix is actually correct, so please check the actual logic of it. All the previous tests that were made for this module continue to work though.

    opened by lenovouser 2
  • Bump y18n from 3.2.1 to 3.2.2

    Bump y18n from 3.2.1 to 3.2.2

    Bumps y18n from 3.2.1 to 3.2.2.

    Commits
    Maintainer changes

    This version was pushed to npm by oss-bot, a new releaser for y18n since your current version.


    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 2
  • Bump elliptic from 6.5.3 to 6.5.4

    Bump elliptic from 6.5.3 to 6.5.4

    Bumps elliptic from 6.5.3 to 6.5.4.

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 2
  • Validator throwing errors instead of return them

    Validator throwing errors instead of return them

    Validator.isValidIPv6Mask throws error if we pass invalid IPv6 string to it.

    For example: ` import {Validator} from "ip-num"

    console.log(Validator.isValidIPv6Mask("")); // throws "Given IPv6 is not confirm to a valid IPv6 address" `

    opened by nneekkiitt 0
  • Ipv6 from mapped ipv4.

    Ipv6 from mapped ipv4.

    I think Ipv6 from mapped ipv4 will be good feature.

    // It works.
    new IPv6('::ffff:4a7d:2b63');
    
    // But, it doesn't work.
    new IPv6('::ffff:74.125.43.99');
    
    opened by dbwodlf3 1
  • Some IPv6 addresses cause parsing errors

    Some IPv6 addresses cause parsing errors

    When using

    new IPv6("::ffff:172.20.0.6");
    

    I get an error:

    Error: Given string is already longer than given final length after padding: 4 leftPadWithZeroBit BinaryUtils.js:68 paddedArray IPv6Utils.js:16 expandWithZero IPv6Utils.js:15 expandIPv6Number IPv6Utils.js:40 IPv6 IPNumber.js:537

    With some research I found that the standard (not sure if there is a standard?) notation for this would be 0:0:0:0:0:ffff:ac14:6. Would it be possible for the IPv6 method to handle this case if its just a different notation?

    opened by tobias47n9e 2
  • Revisit the content of the release artifacts

    Revisit the content of the release artifacts

    Right now .ts file are included in the release. Ideally the release should just contain .js and .d.ts file. Revisit this setup and make necessary changes

    opened by dadepo 0
Releases(v1.5.0)
ESDoc - Good Documentation for JavaScript

ESDoc ESDoc is a documentation generator for JavaScript. Please try it out! Features Generates good documentation. Measures documentation coverage. In

ESDoc 2.7k Dec 29, 2022
Simple JavaScript Duckumentation generator.

Warning: JSDuck is no more maintained! If you're looking to adopt a documentation tool, try something else. If you're using JSDuck, consider moving ov

Sencha Labs 1.5k Nov 28, 2022
:book: documentation for modern JavaScript

The documentation system for modern JavaScript ?? Current maintenance status Supports modern JavaScript: ES5, ES2017, JSX, Vue and Flow type annotatio

null 5.6k Jan 4, 2023
YUI Javascript Documentation Tool

YUIDoc YUI's JavaScript Documentation engine. Overview YUIDoc is a Node.js application used at build time to generate API documentation for JavaScript

YUI Library 889 Dec 25, 2022
Learn, design or document codebase by putting breadcrumbs in source code. Live updates, multi-language support and more.

What · Demo · Get started · Features · Case studies · Support What Have you ever got lost in a big or unknown codebase? This tool will help you to sol

Bohdan Liashenko 2.6k Jan 3, 2023
Pointers to useful, well-written, and otherwise beautiful documentation.

DO YOU WANT TO BUILD AND WRITE GLORIOUS TECHNICAL DOCUMENTATION FULL TIME? EMAIL [email protected]. WE NEED YOU. Beautiful Docs I love documentation. If

Mark Phillips 7.9k Jan 4, 2023
Literate Programming can be Quick and Dirty.

____ /\ _`\ \ \ \/\ \ ___ ___ ___ ___ \ \ \ \ \ / __`\ /'___\ /'___\ / __`\ \ \ \_\ \ /\ \ \

Jeremy Ashkenas 3.5k Dec 31, 2022
Tsailun - open source online document and collaboration

Open source selfhosted web-based wiki/doc/knowledge management and collaboration

null 125 Dec 30, 2022
iSphinx 2 Jun 24, 2022
Convert arrays to bitmask representations to quickly operate with them through bitwise operations. (uses JSBI)

Bitmask Set (JSBI) Convert arrays to bitmask representations to quickly operate with them through bitwise operations. In general, this approach can be

codescrum 4 Sep 7, 2022
⚡️The Fullstack React Framework — built on Next.js

The Fullstack React Framework "Zero-API" Data Layer — Built on Next.js — Inspired by Ruby on Rails Read the Documentation “Zero-API” data layer lets y

⚡️Blitz 12.5k Jan 4, 2023
Nodeparse - A lightweight, vanilla replacement for Express framework when parsing the HTTP body's data or parsing the URL parameters and queries with NodeJS.

nodeparse A lightweight, vanilla replacement for Express framework when parsing the HTTP body's data or parsing the URL parameters and queries with No

Trần Quang Kha 1 Jan 8, 2022
A jQuery-free general purpose library for building credit card forms, validating inputs and formatting numbers.

A jQuery-free general purpose library for building credit card forms, validating inputs and formatting numbers.

Jesse Pollak 528 Dec 30, 2022
Only 90's kids remember... well not really, but these beloved effects that would follow your mouse around will always be classic reminders of the old, beloved internet.

90's Cursor Effects "Knowing the codes" used to be all the rage, I want to bring a few back. A repo of the old effects that inspired creativity and th

Tim Holman 2.6k Jan 9, 2023
A JavaScript plugin for entering and validating international telephone numbers

International Telephone Input A JavaScript plugin for entering and validating international telephone numbers. It adds a flag dropdown to any input, d

Jack O'Connor 6.6k Dec 30, 2022
Little Javascript / Typescript library for validating format of string like email, url, password...

String-Validators Little Javascript / Typescript library for validating format of string like email, url, password... Signaler un Bug · Proposer une F

J.Delauney 3 Oct 14, 2022
A javascript based module to access and perform operations on Linode object storage via code.

Linode Object Storage JS Module A javascript based module to access and perform operations on Linode object storage via code. Code Guardian Installing

Core.ai 3 Jan 11, 2022
A work-in-progress HTML sanitizer that strives for: performance like window.Sanitizer, readiness like DOMPurify, and ability to run in a WebWorker like neither of those.

Amuchina A work-in-progress HTML sanitizer that strives for: performance like window.Sanitizer, readiness like DOMPurify, and ability to run in a WebW

Fabio Spampinato 9 Sep 17, 2022
🌐 Text Input Component for validating and formatting international phone numbers.

React Native Intl Phone Field Try the Expo Snack ?? ??️ Demo It's a javascript-only (no native code) component that can run in iOS, Android, Expo & Re

Ivanka Todorova 24 Jul 8, 2022
A simple to do list webpage where you can log the daily tasks you have to do, mark them as checked, modify them, reorder them and remove them. Made using HTML, CSS and JavaScript.

To-Do-List This Webpage is for an app called To-Do-List which helps you add, remove or check tasks you have to do. It is a simple web page which conta

Zeeshan Haider 9 Mar 12, 2022