Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

ip-matching

SchoofsKelvin132.9kLGPL-3.0-only2.1.2TypeScript support: included

Utilities for IPv4/IPv6 ranges/subnets/masks parsing/matching, string representations, ...

match, IP, address, IPv4, IPv6, CIDR, notation, range, subnet, subnetwork, net, network, mask

readme

IP-Matching

GitHub package version NPM NPM downloads Codacy Badge

GitHub Sponsors Donate

Standalone module with some handy features regarding IPs:

  • Quick and easy-to-use way to check whether an IP meets a requirement
  • Support for IPv4/IPv6 wildcard addresses, ranges, subnetworks and masks.
  • Supports both parsing and outputting all common IPv6 notations
  • Utility methods, e.g. next/previous IP, range to a list of CIDRs, ...
  • Every release is thoroughly tested and linted before published

Installation

npm install --save ip-matching
# or
yarn add ip-matching

Comes with its own built-in TypeScript declarations with included documentation.

Example

import { getMatch, IPMatch, IPSubnetwork, IPRange, matches } from 'ip-matching';

// matches(ip: string | IP, target: string | IPMatch): boolean;

matches('10.0.0.1', '10.0.0.0/24'); // true
matches('10.0.1.1', '10.0.0.0/24'); // false
matches('abc::def', 'abc:*::def'); // true
matches('abc::def', 'abc:9::def'); // false
matches('0001:2:3:4:5:6:7', '1:2:3:4:5:6:7'); // true

// getMatch returns an instance of
// IPv4, IPv6, IPRange, IPSubnetwork or IPMask, all extending IPMatch
const mySubnet: IPMatch = getMatch('fefe::0001:abcd/112');
mySubnet.type; // 'IPSubnetwork'
mySubnet instanceof IPSubnetwork; // true
mySubnet instanceof IPMatch; // true
mySubnet.toString(); // 'fefe::1:0/112'
mySubnet.matches('FEFE::1:bbbb'); // true
mySubnet.matches('FEFE::2:bbbb'); // false
mySubnet.equals(new IPSubnetwork(new IPv6('fefe::1:abcd'), 112)); // true
mySubnet.getAmount(); // 65536
(mySubnet as IPSubnetwork).getLast().toString(); // 'fefe::1:ffff'

const myIp = new IPv6('a:0:0::B:0:C');
myIp.toString(); // 'a::b:0:c'
myIp.toLongString(); // 'a:0:0:0:0:b:0:c'
myIp.toFullString(); // '000a:0000:0000:0000:0000:000b:0000:000c'
new IPv6('::ffff:a9db:*').toMixedString(); // '::ffff:169.219.*.*'

const myRange = getMatch('10.0.0.0-10.1.2.3') as IPRange;
myRange.convertToMasks().map((mask: IPMask) => mask.convertToSubnet().toString());
// [ '10.0.0.0/16', '10.1.0.0/23', '10.1.2.0/30' ]

const mask1 = getMatch('10.0.1.0/255.0.255.0') as IPMask;
const mask2 = getMatch('10.0.0.0/128.0.0.0') as IPMask;
mask1.isSubsetOf(mask2); // true
mask2.getAmount(); // 2147483648

getMatch('a::abbc:1234/ffff::ff80:000f').toString(); // 'a::ab80:4/ffff::ff80:f'

*Note: The matches function and all constructors error for invalid inputs*

You can take a look at the test code or the TypeScript declarations for all the features.

Allowed patterns

  • IP (IPv4/IPv6)
    • Regular IPv4: 10.0.0.0
    • Wildcard IPv4: 10.0.0.* or even 10.*.0.*
    • Regular IPv6: 2001:0db8:85a3:0000:0000:8a2e:0370:7334
    • Shortened IPv6: 2001:db8:85a3::8a2e:0370:7334 or :: or ::1 or a::
    • Wildcard IPv6: 2001::* or even 2001::*:abc:*
    • Mixed IPv6 (mapped IPv4): ::ffff:127.0.0.1 (no wildcards allowed in IPv4 part)
    • Not allowed: 10.0.1*.0 or 2001::a*c
  • IP Range
    • IPv4: 10.0.0.0-10.1.2.3
    • IPv6: 2001::abc-2001::1:ffff
    • Note: Left side has to be "lower" than the right side
  • IP Subnetwork
    • IPv4: 10.0.0.0/16
    • IPv6: 2001::/123
  • IP Mask
    • IPv4: 10.0.0.0/255.0.64.0
    • IPv6: 2001:abcd::/ffff:ff8::

The IPMask's toString() method does not automatically simplify e.g. /255.0.0.0 to /8, even though those are equivalent. Since 2.0.0, IPMask comes with a method convertToSubnet() which returns an equivalent IPSubnetwork if possible, otherwise undefined.

changelog

Changelog

Keep track of all changes between versions. Should basically match the release descriptions on GitHub.

2.1.2

Project changes

  • Updated description (in package.json)
    • This module is more like 50% matching and 50% IP-related utilities
  • Updated README
    • Added badges for GitHub/NPM and Codacy grade
    • Reworded certain parts and improved formatting
    • Improved the example, showcasing more functionality
  • Added CHANGELOG

Development changes

  • Renamed script names to be more logical/consistent
  • Add Codacy for static analysis of source code

2.1.1

Development changes

  • Added ESLint
    • Setup for TypeScript code base (including tests)
    • Includes VS Code build task in watch mode with problem matcher
    • Included in the prepack script, thus running in CI for every release and pushed commit
  • Typescript updated to ^4.3.5
  • @microsoft/api-extractor updated to ^7.18.1
  • Small refactor of unreleased code

2.1.0

New features

  • Added toBits() to IPv4/IPv6, producing e.g. [1, 1, 0, 0, 0, 0, ...] for 192.0.0.0 (length 32 and 128 for IPv4 and IPv6 respectively)
  • Added IPv4.fromBits(bits) and IPv6.fromBits(bits), accepting the "bit arrays" produced from toBits()
    • Accepts arrays (with length 32 for IPv4 and length 128 for IPv6) filled with 0's and 1's
  • Added IPv4.bits = 32 and IPv6.bits = 128, both on the class and class objects (e.g. new IPv4('0.0.0.0').bits)
  • Added getAmount() to IPMatch, allowing you see how many IP addresses a match (e.g. a range/subnet) matches
  • Added isSubsetOf(mask) to IPMask, allowing to check whether one mask is a subset of another mask
    • Mask A is a subset of mask B if every IP address that is matched by A is also matched by B

Changes

  • Caching added to convertToMasks()/convertToSubnets(), making repeated calls a lot cheaper
  • matches(ip) in IPRange no longer errors for passing an IPv4 to an IPv6 range and vice-versa, instead returning false now
    • This is line with matches() in general, where it only errors if the input is neither an IP nor a string that can be converted to one

2.0.0

Lots of changes since the previous v1.2.1 version.

New features

  • Added getNext() and getPrevious() to IPv4 and IPv4
  • Added getFirst() and getLast() to IPRange and IPSubnetwork
  • Added IPMask subclass, supporting any mask (e.g. 255.0.128.0)
  • Added convertToSubnets() to IPRange (optimized CIDR array)
  • Added convertToSubnet() to IPMask (only supports traditional subnet masks)
  • Added convertToMasks() to IPMatch

Improved documentation

  • Improved JSDoc comments in the source code
  • API Extractor generating an index.d.ts for package.json "typings"
  • Added workflow file (GitHub Actions)
    • Tries to compile the code
    • Runs API Extractor (in validation mode)
    • Runs all the tests
    • Packages an NPM-ready tarball (uploaded as artifact)
    • Prepares a release draft for tags starting with v

Bug fixes

  • Improved IPSubnetwork parsing (supports /0 now)

Development changes

  • Added API Extractor support
  • Switched to Jest for testing
  • Removed unused files (e.g. ESLint)
  • Updated .gitignore, .vscode tasks/settings, ...
  • License change to LGPL-3.0-only