node-ip-ts 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,435 @@
1
+ <div align="center">
2
+
3
+ ### A modern, type-safe IP address utility library for Node.js
4
+
5
+ **node-ip-ts** is a full TypeScript rewrite of the popular [`ip`](https://www.npmjs.com/package/ip) package —
6
+ rebuilt from the ground up with strict types, ES Modules, and zero external dependencies.
7
+
8
+ [Installation](#installation) · [Quick Start](#quick-start) · [API Reference](#api-reference) · [Contributing](#contributing)
9
+
10
+ </div>
11
+
12
+ ---
13
+
14
+ ## Why node-ip-ts?
15
+
16
+ The original `ip` package has millions of weekly downloads but ships no TypeScript types and only supports CommonJS. **node-ip-ts** solves that:
17
+
18
+ | | `ip` | `node-ip-ts` |
19
+ | --------------------- | :--: | :----------: |
20
+ | TypeScript support | ❌ | ✅ |
21
+ | ES Module support | ❌ | ✅ |
22
+ | CommonJS support | ✅ | ✅ |
23
+ | Type declarations | ❌ | ✅ |
24
+ | Strict null checks | ❌ | ✅ |
25
+ | External dependencies | 0 | 0 |
26
+ | API compatibility | — | ✅ drop-in |
27
+
28
+ ---
29
+
30
+ ## Installation
31
+
32
+ ```bash
33
+ # npm
34
+ npm install node-node-ip-ts
35
+
36
+ # pnpm
37
+ pnpm add node-node-ip-ts
38
+
39
+ # yarn
40
+ yarn add node-node-ip-ts
41
+ ```
42
+
43
+ > **Requirements:** Node.js ≥ 16
44
+
45
+ ---
46
+
47
+ ## Quick Start
48
+
49
+ ### ESM / TypeScript
50
+
51
+ ```ts
52
+ import * as ip from "node-node-ip-ts";
53
+
54
+ // Address classification
55
+ ip.address(); // first private IPv4 address, e.g. '192.168.1.42'
56
+ ip.address("public"); // first public IPv4 address
57
+ ip.address("private"); // first private IPv4 address
58
+ ip.address("eth0"); // first IPv4 address on eth0
59
+ ip.address("eth0", 6); // first IPv6 address on eth0
60
+
61
+ // Address classification
62
+ ip.isPrivate("192.168.1.1"); // true
63
+ ip.isPublic("8.8.8.8"); // true
64
+ ip.isLoopback("127.0.0.1"); // true
65
+
66
+ // Subnet operations
67
+ ip.cidr("192.168.1.134/26"); // '192.168.1.128'
68
+ const subnet = ip.cidrSubnet("192.168.1.134/26");
69
+ subnet.contains("192.168.1.180"); // true
70
+
71
+ // Conversion
72
+ ip.toLong("255.255.255.255"); // 4294967295
73
+ ip.fromLong(4294967295); // '255.255.255.255'
74
+ ```
75
+
76
+ ### Named imports (tree-shakeable)
77
+
78
+ ```ts
79
+ import { isPrivate, cidrSubnet, toLong } from "node-ip-ts";
80
+ ```
81
+
82
+ ### CommonJS
83
+
84
+ ```js
85
+ const ip = require("node-ip-ts");
86
+ ip.isPrivate("10.0.0.1"); // true
87
+ ```
88
+
89
+ ---
90
+
91
+ ## API Reference
92
+
93
+ ### Address Classification
94
+
95
+ #### `isPrivate(addr: string): boolean`
96
+
97
+ Returns `true` if the address falls within any private/reserved range:
98
+
99
+ - `10.0.0.0/8` — RFC 1918
100
+ - `172.16.0.0/12` — RFC 1918
101
+ - `192.168.0.0/16` — RFC 1918
102
+ - `169.254.0.0/16` — link-local
103
+ - `fc00::/7` — IPv6 ULA
104
+ - `fe80::/10` — IPv6 link-local
105
+ - `::1`, `::` — loopback
106
+
107
+ ```ts
108
+ ip.isPrivate("192.168.0.1"); // true
109
+ ip.isPrivate("10.0.0.1"); // true
110
+ ip.isPrivate("fd12:3456:789a:1::1"); // true (IPv6 ULA)
111
+ ip.isPrivate("::ffff:192.168.0.1"); // true (IPv4-mapped IPv6)
112
+ ip.isPrivate("8.8.8.8"); // false
113
+ ```
114
+
115
+ #### `isPublic(addr: string): boolean`
116
+
117
+ Inverse of `isPrivate`. Returns `true` for publicly routable addresses.
118
+
119
+ ```ts
120
+ ip.isPublic("1.1.1.1"); // true
121
+ ip.isPublic("10.0.0.1"); // false
122
+ ```
123
+
124
+ #### `isLoopback(addr: string): boolean`
125
+
126
+ Returns `true` for loopback addresses. Supports dotted-decimal, octal, hexadecimal, and long-integer notation.
127
+
128
+ ```ts
129
+ ip.isLoopback("127.0.0.1"); // true
130
+ ip.isLoopback("::1"); // true
131
+ ip.isLoopback("0x7f.0.0.1"); // true (hex notation)
132
+ ip.isLoopback("0177.0.0.1"); // true (octal notation)
133
+ ip.isLoopback("2130706433"); // true (integer notation)
134
+ ip.isLoopback("8.8.8.8"); // false
135
+ ```
136
+
137
+ #### `isV4Format(ip: string): boolean`
138
+
139
+ ```ts
140
+ ip.isV4Format("192.168.0.1"); // true
141
+ ip.isV4Format("::1"); // false
142
+ ```
143
+
144
+ #### `isV6Format(ip: string): boolean`
145
+
146
+ ```ts
147
+ ip.isV6Format("::1"); // true
148
+ ip.isV6Format("::ffff:192.168.0.1"); // true
149
+ ip.isV6Format("192.168.0.1"); // false
150
+ ```
151
+
152
+ ---
153
+
154
+ ### Subnet & CIDR
155
+
156
+ #### `cidr(cidrString: string): string`
157
+
158
+ Returns the network address for a given CIDR string.
159
+
160
+ ```ts
161
+ ip.cidr("192.168.1.134/26"); // '192.168.1.128'
162
+ ip.cidr("2607:f0d0:1002:51::4/56"); // '2607:f0d0:1002::'
163
+ ```
164
+
165
+ #### `cidrSubnet(cidrString: string): SubnetInfo`
166
+
167
+ Returns a full `SubnetInfo` object for a given CIDR string.
168
+
169
+ ```ts
170
+ const s = ip.cidrSubnet("192.168.1.134/26");
171
+
172
+ s.networkAddress; // '192.168.1.128'
173
+ s.firstAddress; // '192.168.1.129'
174
+ s.lastAddress; // '192.168.1.190'
175
+ s.broadcastAddress; // '192.168.1.191'
176
+ s.subnetMask; // '255.255.255.192'
177
+ s.subnetMaskLength; // 26
178
+ s.numHosts; // 62
179
+ s.length; // 64
180
+ s.contains("192.168.1.150"); // true
181
+ s.contains("192.168.1.200"); // false
182
+ ```
183
+
184
+ #### `subnet(addr: string, mask: string): SubnetInfo`
185
+
186
+ Same as `cidrSubnet` but takes address and mask separately.
187
+
188
+ ```ts
189
+ const s = ip.subnet("192.168.1.134", "255.255.255.192");
190
+ ```
191
+
192
+ #### `mask(addr: string, mask: string): string`
193
+
194
+ Applies a subnet mask to an address via bitwise AND.
195
+
196
+ ```ts
197
+ ip.mask("192.168.1.134", "255.255.255.0"); // '192.168.1.0'
198
+ ip.mask("192.168.1.134", "::ffff:ff00"); // '::ffff:c0a8:100'
199
+ ```
200
+
201
+ #### `fromPrefixLen(prefixlen: number, family?: string | number): string`
202
+
203
+ Converts a prefix length to a subnet mask string.
204
+
205
+ ```ts
206
+ ip.fromPrefixLen(24); // '255.255.255.0'
207
+ ip.fromPrefixLen(64); // 'ffff:ffff:ffff:ffff::' (auto-detects IPv6)
208
+ ip.fromPrefixLen(24, "ipv6"); // 'ffff:ff00::'
209
+ ```
210
+
211
+ ---
212
+
213
+ ### Bitwise Operations
214
+
215
+ #### `not(addr: string): string`
216
+
217
+ Bitwise NOT — useful for computing wildcard masks.
218
+
219
+ ```ts
220
+ ip.not("255.255.255.0"); // '0.0.0.255'
221
+ ```
222
+
223
+ #### `or(a: string, b: string): string`
224
+
225
+ Bitwise OR. Supports same-protocol and mixed IPv4/IPv6 inputs.
226
+
227
+ ```ts
228
+ ip.or("0.0.0.255", "192.168.1.10"); // '192.168.1.255'
229
+ ip.or("::ff", "::abcd:dcba:abcd:dcba"); // '::abcd:dcba:abcd:dcff'
230
+ ip.or("0.0.0.255", "::abcd:dcba:abcd:dcba"); // '::abcd:dcba:abcd:dcff'
231
+ ```
232
+
233
+ #### `isEqual(a: string, b: string): boolean`
234
+
235
+ Deep equality check, IPv4/IPv6 aware (e.g. `127.0.0.1` equals `::ffff:7f00:1`).
236
+
237
+ ```ts
238
+ ip.isEqual("127.0.0.1", "::ffff:127.0.0.1"); // true
239
+ ip.isEqual("127.0.0.1", "::7f00:1"); // true
240
+ ip.isEqual("127.0.0.1", "::7f00:2"); // false
241
+ ```
242
+
243
+ ---
244
+
245
+ ### Buffer Conversion
246
+
247
+ #### `toBuffer(ip: string, buff?: Buffer, offset?: number): Buffer`
248
+
249
+ Converts an IP string to a raw `Buffer` (4 bytes for IPv4, 16 for IPv6). Optionally writes into an existing buffer at a given offset.
250
+
251
+ ```ts
252
+ ip.toBuffer("127.0.0.1");
253
+ // <Buffer 7f 00 00 01>
254
+
255
+ const buf = Buffer.alloc(128);
256
+ ip.toBuffer("127.0.0.1", buf, 64);
257
+ // writes 4 bytes into buf at offset 64
258
+ ```
259
+
260
+ #### `toString(buff: Buffer, offset?: number, length?: number): string`
261
+
262
+ Converts a `Buffer` back to an IP address string.
263
+
264
+ ```ts
265
+ ip.toString(Buffer.from("7f000001", "hex")); // '127.0.0.1'
266
+ ip.toString(buf, 64, 4); // '127.0.0.1'
267
+ ```
268
+
269
+ ---
270
+
271
+ ### Long Integer Conversion
272
+
273
+ #### `toLong(ip: string): number`
274
+
275
+ Converts a dotted-decimal IPv4 address to an unsigned 32-bit integer.
276
+
277
+ ```ts
278
+ ip.toLong("127.0.0.1"); // 2130706433
279
+ ip.toLong("255.255.255.255"); // 4294967295
280
+ ```
281
+
282
+ #### `fromLong(ipl: number): string`
283
+
284
+ Converts an unsigned 32-bit integer back to dotted-decimal.
285
+
286
+ ```ts
287
+ ip.fromLong(2130706433); // '127.0.0.1'
288
+ ip.fromLong(4294967295); // '255.255.255.255'
289
+ ```
290
+
291
+ #### `normalizeToLong(addr: string): number`
292
+
293
+ Normalizes an IPv4 address in any notation (decimal, octal, hex, compact) to an unsigned long. Returns `-1` on invalid input.
294
+
295
+ ```ts
296
+ ip.normalizeToLong("127.0.0.1"); // 2130706433 (standard)
297
+ ip.normalizeToLong("0x7f.0x0.0x0.1"); // 2130706433 (hex)
298
+ ip.normalizeToLong("0177.0.0.01"); // 2130706433 (octal)
299
+ ip.normalizeToLong("0x7f000001"); // 2130706433 (single hex)
300
+ ip.normalizeToLong("127.1"); // 2130706433 (compact)
301
+ ip.normalizeToLong("256.0.0.1"); // -1 (invalid)
302
+ ```
303
+
304
+ ---
305
+
306
+ ### Network Interface
307
+
308
+ #### `address(name?: string, family?: string | number): string`
309
+
310
+ Returns an IP address from the current machine's network interfaces.
311
+
312
+ ```ts
313
+ ip.address(); // first private IPv4 address, e.g. '192.168.1.42'
314
+ ip.address("public"); // first public IPv4 address
315
+ ip.address("private"); // first private IPv4 address
316
+ ip.address("eth0"); // first IPv4 address on eth0
317
+ ip.address("eth0", 6); // first IPv6 address on eth0
318
+ ```
319
+
320
+ Falls back to `loopback()` if no matching interface is found.
321
+
322
+ #### `loopback(family?: string | number): string`
323
+
324
+ Returns the loopback address for the given IP family.
325
+
326
+ ```ts
327
+ ip.loopback(); // '127.0.0.1'
328
+ ip.loopback("ipv4"); // '127.0.0.1'
329
+ ip.loopback("ipv6"); // 'fe80::1'
330
+ ```
331
+
332
+ ---
333
+
334
+ ### Types
335
+
336
+ ```ts
337
+ import type { IPFamily, SubnetInfo } from "node-ip-ts";
338
+
339
+ type IPFamily = "ipv4" | "ipv6";
340
+
341
+ interface SubnetInfo {
342
+ networkAddress: string;
343
+ firstAddress: string;
344
+ lastAddress: string;
345
+ broadcastAddress: string;
346
+ subnetMask: string;
347
+ subnetMaskLength: number;
348
+ numHosts: number;
349
+ length: number;
350
+ contains(other: string): boolean;
351
+ }
352
+ ```
353
+
354
+ ---
355
+
356
+ ## Project Structure
357
+
358
+ ```
359
+ node-ip-ts/
360
+ ├── src/
361
+ │ └── index.ts # Single source file — all named exports
362
+ ├── dist/
363
+ │ ├── esm/ # ES Module build (.js + .js.map)
364
+ │ ├── cjs/ # CommonJS build (.js + .js.map)
365
+ │ └── types/ # Type declarations (.d.ts + .d.ts.map)
366
+ ├── __tests__/
367
+ │ └── ip.test.ts # Jest test suite
368
+ ├── tsconfig.esm.json
369
+ ├── tsconfig.cjs.json
370
+ ├── tsconfig.types.json
371
+ └── package.json
372
+ ```
373
+
374
+ ---
375
+
376
+ ## Contributing
377
+
378
+ Contributions are welcome! Here's how to get started:
379
+
380
+ ```bash
381
+ # Clone the repo
382
+ git clone https://github.com/your-org/node-ip-ts.git
383
+ cd node-ip-ts
384
+
385
+ # Install dependencies
386
+ npm install
387
+
388
+ # Run tests
389
+ npm test
390
+
391
+ # Build
392
+ npm run build
393
+ ```
394
+
395
+ ### Guidelines
396
+
397
+ - All changes must pass the existing test suite (`npm test`)
398
+ - New features must include corresponding tests
399
+ - Code must pass TypeScript strict mode
400
+ - Keep zero external runtime dependencies
401
+
402
+ ### Reporting Issues
403
+
404
+ Please [open an issue](https://github.com/your-org/node-ip-ts/issues/new) with a minimal reproduction case.
405
+
406
+ ---
407
+
408
+ ## Migration from `ip`
409
+
410
+ **node-ip-ts** is designed to be a drop-in replacement. Simply swap your import:
411
+
412
+ ```diff
413
+ - const ip = require('ip');
414
+ + const ip = require('node-ip-ts');
415
+ ```
416
+
417
+ Or for TypeScript / ESM:
418
+
419
+ ```ts
420
+ import * as ip from "node-ip-ts";
421
+ ```
422
+
423
+ All function names and behaviours are identical to the original library.
424
+
425
+ ---
426
+
427
+ ## License
428
+
429
+ MIT © Deni Irawan Nugraha
430
+
431
+ ---
432
+
433
+ <div align="center">
434
+ <sub>If this library saved you time, consider giving it a ⭐ on GitHub.</sub>
435
+ </div>
package/jest.config.js ADDED
@@ -0,0 +1,22 @@
1
+ /** @type {import('jest').Config} */
2
+ export default {
3
+ preset: 'ts-jest/presets/default-esm',
4
+ extensionsToTreatAsEsm: ['.ts'],
5
+ testEnvironment: 'node',
6
+ moduleNameMapper: {
7
+ '^(\\.{1,2}/.*)\\.js$': '$1',
8
+ },
9
+ transform: {
10
+ '^.+\\.tsx?$': [
11
+ 'ts-jest',
12
+ {
13
+ useESM: true,
14
+ tsconfig: {
15
+ module: 'ES2020',
16
+ moduleResolution: 'bundler',
17
+ },
18
+ },
19
+ ],
20
+ },
21
+ testMatch: ['**/*.test.ts'],
22
+ };
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "node-ip-ts",
3
+ "version": "1.0.0",
4
+ "author": "Deni Irawan Nugraha <deni.irawan40563@gmail.com>",
5
+ "license": "MIT",
6
+ "homepage": "https://github.com/denycode-dev/node-ip-ts",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/denycode-dev/node-ip-ts.git",
10
+ "directory": "packages/node-ip-ts"
11
+ },
12
+ "keywords": [
13
+ "ip",
14
+ "ip address",
15
+ "ip address library",
16
+ "ip address parser",
17
+ "ip address validator",
18
+ "ip address converter",
19
+ "ip address to buffer",
20
+ "buffer to ip address"
21
+ ],
22
+ "description": "Modern TypeScript IP address library",
23
+ "type": "module",
24
+ "main": "./dist/cjs/index.js",
25
+ "module": "./dist/esm/index.js",
26
+ "types": "./dist/types/index.d.ts",
27
+ "exports": {
28
+ ".": {
29
+ "import": "./dist/esm/index.js",
30
+ "require": "./dist/cjs/index.js",
31
+ "types": "./dist/types/index.d.ts"
32
+ }
33
+ },
34
+ "scripts": {
35
+ "build": "tsc -p tsconfig.esm.json && tsc -p tsconfig.cjs.json && tsc -p tsconfig.types.json",
36
+ "test": "node --experimental-vm-modules node_modules/jest/bin/jest.js",
37
+ "test:watch": "node --experimental-vm-modules node_modules/jest/bin/jest.js --watch"
38
+ },
39
+ "devDependencies": {
40
+ "@types/jest": "^29.5.12",
41
+ "@types/node": "^20.12.7",
42
+ "jest": "^29.7.0",
43
+ "ts-jest": "^29.1.2",
44
+ "typescript": "^5.4.5"
45
+ }
46
+ }