A Modern, Immutable, and Zero-Dependency Library for IP Addresses in JavaScript

The IP Address Library You’ve Been Waiting For

Ever found yourself wrestling with IP addresses in a Node.js application? Maybe you’re validating user input, checking if an IP belongs to a certain subnet, or just trying to convert between different formats. While there are libraries out there, many feel a bit dated or come with a baggage of dependencies.

What if there was a modern, clean, and powerful way to handle this?

Meet @se-oss/ip-address! It’s a brand-new, zero-dependency library designed from the ground up for modern JavaScript and TypeScript development. It provides an immutable, intuitive API for both IPv4 and IPv6 addresses and CIDR ranges.

Why Another IP Library?

That’s a fair question. Here’s what makes @se-oss/ip-address different:

  • Immutable API: Create an IP object once, and it can’t be changed. Operations like next() or previous() return a new instance, preventing bugs from accidental modifications.
  • Zero Dependencies: It’s lightweight and secure. No need to worry about a bloated node_modules folder or transitive dependency vulnerabilities.
  • TypeScript First: Written entirely in TypeScript, offering excellent autocompletion and type safety out of the box.
  • Comprehensive: Handles IPv4, IPv6, and CIDR notation with a consistent, easy-to-use API.

Getting Started

Installation is as simple as you’d expect.

pnpm install @se-oss/ip-address

Or if you prefer npm or yarn:

# npm
npm install @se-oss/ip-address

# yarn
yarn add @se-oss/ip-address

The Fun Part: Code Examples

Let’s dive into what you can do with it.

Parsing and Validation

The library makes it trivial to parse and validate any IP address. The parseIP factory automatically detects the IP version.

import { IPv4, IPv6, parseIP } from '@se-oss/ip-address';

// Let the factory do the work
const ip = parseIP('192.168.1.1'); // Returns an IPv4 instance
const ip6 = parseIP('2001:db8::1'); // Returns an IPv6 instance

console.log(ip.version); // 4
console.log(ip6.version); // 6

// Or validate without creating an instance
if (IPv4.isValid('10.0.0.1')) {
  console.log('Yep, a valid IPv4 address.');
}

// It throws a specific error for invalid addresses
try {
  parseIP('not.an.ip');
} catch (error) {
  console.error(error.message); // "Invalid IP address: not.an.ip"
}

Working with IPv4 Addresses

Once you have an IPv4 instance, you can perform all sorts of checks and conversions.

import { IPv4 } from '@se-oss/ip-address';

const ip = new IPv4('192.168.1.1');

// Check its type
console.log(ip.isPrivate()); // true
console.log(ip.isLoopback()); // false

// Convert it to other formats
console.log(ip.toBigInt()); // 3232235777n
console.log(ip.toBytes()); // [192, 168, 1, 1]
console.log(ip.toArpa()); // "1.1.168.192.in-addr.arpa"

// Get the next IP (returns a new instance!)
const nextIp = ip.next();
console.log(nextIp.address); // "192.168.1.2"

IPv6 is a First-Class Citizen

IPv6 is just as easy, with full support for its unique features, like handling IPv4-mapped addresses.

import { IPv6 } from '@se-oss/ip-address';

const ip6 = new IPv6('2001:db8::8a2e:370:7334');

// Get compressed vs. expanded address
console.log(ip6.address); // "2001:db8::8a2e:370:7334"
console.log(ip6.expandedAddress); // "2001:0db8:0000:0000:0000:8a2e:0370:7334"

// Check its type
console.log(ip6.isGlobalUnicast()); // true

// Handle IPv4-mapped addresses seamlessly
const mappedIp = new IPv6('::ffff:192.168.1.1');
console.log(mappedIp.isIPv4Mapped()); // true

const ipv4 = mappedIp.toIPv4();
console.log(ipv4.address); // "192.168.1.1"

Mastering Subnets with CIDR

Need to work with subnets? The CIDR class has you covered. This is incredibly useful for network calculations.

import { CIDR } from '@se-oss/ip-address';

const cidr = new CIDR('10.0.0.0/24');

// Get network details
console.log(cidr.network.address); // "10.0.0.0"
console.log(cidr.broadcast.address); // "10.0.0.255"
console.log(cidr.first.address); // "10.0.0.1" (First usable IP)
console.log(cidr.last.address); // "10.0.0.254" (Last usable IP)

// Check if an IP falls within the range
console.log(cidr.contains('10.0.0.123')); // true
console.log(cidr.contains('10.0.1.1')); // false

Under the Hood

One of the reasons this library is so precise is its use of native BigInt. This allows for accurate calculations on large 128-bit IPv6 addresses without running into floating-point limitations that can plague number-based approaches.

Final Thoughts

Whether you’re building a security tool, a network scanner, or just need to handle IP data reliably in your web application, @se-oss/ip-address offers a clean, modern, and safe API to get the job done. It’s lightweight, has no dependencies, and its immutable design can help you write more predictable code.

Give it a try! Check out the GitHub repository to see the source, and don’t forget to leave a star if you find it useful. We welcome contributions and feedback!

Similar Posts