Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ buildstamp.json
package-main.json

# Temp
tmp
temp
test-results

Expand Down
4 changes: 2 additions & 2 deletions .size-limit.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"LICENSE",
"package-main.json"
],
"limit": "60.31 kB",
"limit": "60.40 kB",
"brotli": false,
"gzip": false
},
Expand All @@ -32,7 +32,7 @@
"LICENSE",
"package-main.json"
],
"limit": "18.30 kB",
"limit": "18.32 kB",
"gzip": true
},
{
Expand Down
58 changes: 29 additions & 29 deletions COHERENCE.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
# Coherence across libraries
> Autogenerated by `src/scripts/build-coherence-md.ts`
> Autogenerated by [`src/scripts/build-coherence-md.ts`](./src/scripts/build-coherence-md.ts)
## IPv4
Address | node:net | [`ip`](https://github.com/indutny/node-ip) | [`@webpod/ip`](https://github.com/webpod/ip) | [`@webpod/ip/core`](https://github.com/webpod/ip) | [`is-ip`](https://github.com/sindresorhus/is-ip) | [`ipaddr.js`](https://github.com/whitequark/ipaddr.js/) | [`ip-address`](https://github.com/beaugunderson/ip-address) | [`ip2buf`](https://github.com/reklatsmasters/ip2buf) | [`neoip`](https://github.com/Zaptic/neoip) | Comment
Address | node:net | [`@webpod/ip`](https://github.com/webpod/ip) | [`@webpod/ip/core`](https://github.com/webpod/ip) | [`ip`](https://github.com/indutny/node-ip) | [`is-ip`](https://github.com/sindresorhus/is-ip) | [`ipaddr.js`](https://github.com/whitequark/ipaddr.js/) | [`ip-address`](https://github.com/beaugunderson/ip-address) | [`ip2buf`](https://github.com/reklatsmasters/ip2buf) | [`neoip`](https://github.com/Zaptic/neoip) | Comment
--- | --- | --- | --- | --- | --- | --- | --- | --- | --- | ---
`127.0.0.1` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | localhost
`192.168.1.1` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | private LAN
`255.255.255.255` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | broadcast
`0.0.0.0` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | unspecified
`8.8.8.8` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | Google DNS
`256.1.1.1` | ✓ | | ✓ | | ✓ | ✓ | ✓ | ✓ | ✓ | octet out of range
`256.1.1.1` | ✓ | | ✓ | | ✓ | ✓ | ✓ | ✓ | ✓ | octet out of range
`192.168.1` | ✓ | ✓ | ✓ | ✓ | ✓ | ❌ | ✓ | ✓ | ✓ | not enough octets
`192.168.1.1.1` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | too many octets
`192.168.01.1` | ✓ | | ✓ | | ✓ | ❌ | ❌ | ❌ | ✓ | leading octet zero
`192.168.01.1` | ✓ | | ✓ | | ✓ | ❌ | ❌ | ❌ | ✓ | leading octet zero
`abc.def.gha.bcd` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | non-numeric
`...` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | empty octets
`1..2.3` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | empty middle octet
`` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | empty string
## IPv6
Address | node:net | [`ip`](https://github.com/indutny/node-ip) | [`@webpod/ip`](https://github.com/webpod/ip) | [`@webpod/ip/core`](https://github.com/webpod/ip) | [`is-ip`](https://github.com/sindresorhus/is-ip) | [`ipaddr.js`](https://github.com/whitequark/ipaddr.js/) | [`ip-address`](https://github.com/beaugunderson/ip-address) | [`ip2buf`](https://github.com/reklatsmasters/ip2buf) | [`neoip`](https://github.com/Zaptic/neoip) | Comment
Address | node:net | [`@webpod/ip`](https://github.com/webpod/ip) | [`@webpod/ip/core`](https://github.com/webpod/ip) | [`ip`](https://github.com/indutny/node-ip) | [`is-ip`](https://github.com/sindresorhus/is-ip) | [`ipaddr.js`](https://github.com/whitequark/ipaddr.js/) | [`ip-address`](https://github.com/beaugunderson/ip-address) | [`ip2buf`](https://github.com/reklatsmasters/ip2buf) | [`neoip`](https://github.com/Zaptic/neoip) | Comment
--- | --- | --- | --- | --- | --- | --- | --- | --- | --- | ---
`::1` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | loopback
`::` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | unspecified
Expand All @@ -26,26 +26,26 @@ Address | node:net | [`ip`](https://github.com/indutny/node-ip) | [`@webpod/ip`]
`::ffff:192.0.2.128` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | IPv4-mapped IPv6
`2001:0db8:85a3:0000:0000:8a2e:0370:7334` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | full form
`0:0:0:0:0:0:0:1` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | expanded loopback
`2001::85a3::7334` | ✓ | | ✓ | | ✓ | ✓ | ✓ | ✓ | ✓ | multiple ::
`12345::` | ✓ | | ✓ | | ✓ | ✓ | ✓ | ✓ | ✓ | hextet too long
`2001::85a3::7334` | ✓ | | ✓ | | ✓ | ✓ | ✓ | ✓ | ✓ | multiple ::
`12345::` | ✓ | | ✓ | | ✓ | ✓ | ✓ | ✓ | ✓ | hextet too long
`abcd:efgh::1` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | non-hex character
`1:2:3:4:5:6:7` | ✓ | | ✓ | | ✓ | ✓ | ✓ | ❌ | ✓ | too few hextets
`1:2:3:4:5:6:7` | ✓ | | ✓ | | ✓ | ✓ | ✓ | ❌ | ✓ | too few hextets
`1:2:3:4:5:6:7:8:9` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | too many hextets
`:1:2:3:4:5:6:7` | ✓ | | ✓ | | ✓ | ✓ | ✓ | ✓ | ✓ | leading colon without ::
`1:2:3:4:5:6:7:` | ✓ | | ✓ | | ✓ | ✓ | ✓ | ✓ | ✓ | trailing colon without ::
`1:2:3::4:5:6:7:8` | ✓ | | ✓ | | ✓ | ❌ | ✓ | ✓ | ✓ | too many hextets with ::
`1:2::4:5::8` | ✓ | | ✓ | | ✓ | ✓ | ✓ | ✓ | ✓ | multiple compressors ::
`:::` | ✓ | | ✓ | | ✓ | ✓ | ✓ | ✓ | ✓ | triple colon not allowed
`:1:2:3:4:5:6:7` | ✓ | | ✓ | | ✓ | ✓ | ✓ | ✓ | ✓ | leading colon without ::
`1:2:3:4:5:6:7:` | ✓ | | ✓ | | ✓ | ✓ | ✓ | ✓ | ✓ | trailing colon without ::
`1:2:3::4:5:6:7:8` | ✓ | | ✓ | | ✓ | ❌ | ✓ | ✓ | ✓ | too many hextets with ::
`1:2::4:5::8` | ✓ | | ✓ | | ✓ | ✓ | ✓ | ✓ | ✓ | multiple compressors ::
`:::` | ✓ | | ✓ | | ✓ | ✓ | ✓ | ✓ | ✓ | triple colon not allowed
`::g` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | invalid hex digit after compression
`2001:db8:85a3:0:0:8a2e:37023:7334` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | hextet exceeds 16 bits
`::ffff:999.0.2.128` | ✓ | | ✓ | | ✓ | ✓ | ✓ | ✓ | ✓ | invalid embedded IPv4
`::ffff:999.0.2.128` | ✓ | | ✓ | | ✓ | ✓ | ✓ | ✓ | ✓ | invalid embedded IPv4
`::ffff:192.0.2` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | truncated IPv4 in mapped address
`2001:db8:::` | ✓ | | ✓ | | ✓ | ✓ | ✓ | ✓ | ✓ | extra colon at end
`` | ✓ | | ✓ | | ✓ | ✓ | ✓ | ✓ | ✓ | empty string
`2001:db8:::` | ✓ | | ✓ | | ✓ | ✓ | ✓ | ✓ | ✓ | extra colon at end
`` | ✓ | | ✓ | | ✓ | ✓ | ✓ | ✓ | ✓ | empty string
## Private IP
Address | [`ip`](https://github.com/indutny/node-ip) | [`@webpod/ip`](https://github.com/webpod/ip) | [`@webpod/ip/core`](https://github.com/webpod/ip) | [`ipaddr.js`](https://github.com/whitequark/ipaddr.js/) | [`neoip`](https://github.com/Zaptic/neoip) | Comment
Address | [`@webpod/ip`](https://github.com/webpod/ip) | [`@webpod/ip/core`](https://github.com/webpod/ip) | [`ip`](https://github.com/indutny/node-ip) | [`ipaddr.js`](https://github.com/whitequark/ipaddr.js/) | [`neoip`](https://github.com/Zaptic/neoip) | Comment
--- | --- | --- | --- | --- | --- | ---
`0.0.0.0` | | ✓ | | ✓ | ✓ | unspecified
`0.0.0.0` | | ✓ | | ✓ | ✓ | unspecified
`127.0.0.1` | ✓ | ✓ | ✓ | ✓ | ✓ | loopback
`127.0.0.2` | ✓ | ✓ | ✓ | ✓ | ✓ | loopback range
`127.1.1.1` | ✓ | ✓ | ✓ | ✓ | ✓ | loopback shorthand
Expand All @@ -64,7 +64,7 @@ Address | [`ip`](https://github.com/indutny/node-ip) | [`@webpod/ip`](https://gi
`10.0.2.3` | ✓ | ✓ | ✓ | ✓ | ✓ | private 10/8
`10.1.23.45` | ✓ | ✓ | ✓ | ✓ | ✓ | private 10/8
`12.1.2.3` | ✓ | ✓ | ✓ | ✓ | ✓ | public, outside 10/8
`198.18.0.0` | | ✓ | | ❌ | ✓ | benchmark range
`198.18.0.0` | | ✓ | | ❌ | ✓ | benchmark range
`fd12:3456:789a:1::1` | ✓ | ✓ | ✓ | ✓ | ✓ | ULA fc00::/7
`fe80::f2de:f1ff:fe3f:307e` | ✓ | ✓ | ✓ | ✓ | ✓ | link-local fe80::/10
`::ffff:10.100.1.42` | ✓ | ✓ | ✓ | ❌ | ✓ | IPv4-mapped private
Expand All @@ -75,14 +75,14 @@ Address | [`ip`](https://github.com/indutny/node-ip) | [`@webpod/ip`](https://gi
`::1` | ✓ | ✓ | ✓ | ✓ | ✓ | loopback
`fe80::1` | ✓ | ✓ | ✓ | ✓ | ✓ | link-local
`0x7f.1` | ✓ | ✓ | ✓ | ✓ | ✓ | CVE-2023-42282: hex loopback
`127.1` | | ✓ | | ✓ | ✓ | CVE-2024-29415: short loopback
`127.1` | | ✓ | | ✓ | ✓ | CVE-2024-29415: short loopback
`2130706433` | ✓ | ✓ | ✓ | ✓ | ✓ | CVE-2024-29415: integer loopback
`::fFFf:127.0.0.1` | | ✓ | | ❌ | ✓ | CVE-2024-29415: IPv6-mapped loopback
`::0:ffff:127.0.0.1` | | ✓ | | ❌ | ✓ | ↑
`0::0:ffff:127.0.0.1` | | ✓ | | ❌ | ✓ | ↑
`0:0:0:0:0:ffff:127.0.0.1` | | ✓ | | ❌ | ✓ | ↑
`017700000001` | ✓ | n/a | n/a | ❌ | ❌ | octal 127.0.0.1
`01200034567` | ✓ | n/a | n/a | ❌ | ❌ | invalid: octal-style
`012.1.2.3` | ✓ | n/a | n/a | ❌ | ❌ | invalid: octal-style IPv4
`000:0:0000::01` | | ✓ | | ✓ | ✓ | valid: zero-compression
`::fFFf:127.255.255.256` | ✓ | n/a | n/a | n/a | ✓ | invalid: IPv4 overflow
`::fFFf:127.0.0.1` | | ✓ | | ❌ | ✓ | CVE-2024-29415: IPv6-mapped loopback
`::0:ffff:127.0.0.1` | | ✓ | | ❌ | ✓ | ↑
`0::0:ffff:127.0.0.1` | | ✓ | | ❌ | ✓ | ↑
`0:0:0:0:0:ffff:127.0.0.1` | | ✓ | | ❌ | ✓ | ↑
`017700000001` | n/a | n/a | ✓ | ❌ | ❌ | octal 127.0.0.1
`01200034567` | n/a | n/a | ✓ | ❌ | ❌ | invalid: octal-style
`012.1.2.3` | n/a | n/a | ✓ | ❌ | ❌ | invalid: octal-style IPv4
`000:0:0000::01` | | ✓ | | ✓ | ✓ | valid: zero-compression
`::fFFf:127.255.255.256` | n/a | n/a | ✓ | n/a | ✓ | invalid: IPv4 overflow
12 changes: 12 additions & 0 deletions META.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Package meta across libraries
> Autogenerated by [`src/scripts/build-meta-md.ts`](./src/scripts/build-meta-md.ts)

| Package | Publish size | Install size | Node.js | Modules | Types |
| --- | ---: | ---: | ---: | ---: | ---: |
| [`@webpod/ip`](https://github.com/webpod/ip) | 59.1 kB | 56.1 kB | \>= 10 | ESM, CJS | ✓ |
| [`ip`](https://github.com/indutny/node-ip) | 15.1 kB | 15.1 kB | n/a | CJS | ❌ |
| [`is-ip`](https://github.com/sindresorhus/is-ip) | 4.9 kB | 42.7 kB | \>=14.16 | ESM | ✓ |
| [`ipaddr.js`](https://github.com/whitequark/ipaddr.js/) | 60.8 kB | 60.8 kB | \>= 10 | CJS | ✓ |
| [`ip-address`](https://github.com/beaugunderson/ip-address) | 172.4 kB | 172.4 kB | \>= 12 | CJS | ✓ |
| [`ip2buf`](https://github.com/reklatsmasters/ip2buf) | n/a | n/a | \>=6 | CJS | ❌ |
| [`neoip`](https://github.com/Zaptic/neoip) | 40.3 kB | 40.3 kB | n/a | ESM, CJS | ✓ |
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ Address.isSpecial('1.2.3.4') // false
```

## Alternatives
Follow [coherence.md](./COHERENCE.md) and [benchmark.md](./BENCHMARK.md) to explore suitable options.
Follow [coherence.md](./COHERENCE.md), [benchmark.md](./BENCHMARK.md) and [meta.md](./META.md) to explore suitable options.

## License
MIT
3 changes: 3 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 7 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
"description": "Lite IP tools",
"type": "module",
"main": "target/cjs/index.cjs",
"module": "target/esm/index.mjs",
"types": "target/dts/index.d.ts",
"browser": "target/esm/core.mjs",
"exports": {
".": {
"types": "./target/dts/index.d.ts",
Expand All @@ -23,14 +26,15 @@
"require": "./target/cjs/index.cjs"
}
},
"module": "target/esm/index.mjs",
"types": "target/dts/index.d.ts",
"files": [
"target/cjs",
"target/esm",
"target/dts",
"lib"
],
"engines": {
"node": ">=10"
},
"scripts": {
"build": "concurrently 'npm:build:*'",
"build:js": "node ./src/scripts/build.mjs --entry='src/main/ts/core.ts:src/main/ts/index.ts'",
Expand All @@ -42,6 +46,7 @@
"build:pkgjson": "node ./src/scripts/build-pkgjson.ts",
"_build:bench": "node ./src/scripts/build-bench-md.ts",
"_build:coh": "node ./src/scripts/build-coherence-md.ts",
"_build:meta": "node ./src/scripts/build-meta-md.ts",
"test": "concurrently 'npm:test:*'",
"test:target": "git diff --exit-code --quiet || (echo 'Uncommitted changes' && exit 1)",
"test:size": "size-limit",
Expand Down
2 changes: 1 addition & 1 deletion src/scripts/build-bench-md.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ function toMarkdown(results: NamedResult[]): string {


let output = `# Performance across libraries
> Autogenerated by \`src/scripts/build-bench-md.ts\`
> Autogenerated by [\`src/scripts/build-bench-md.ts\`](./src/scripts/build-bench-md.ts)

${systemNote()}
`
Expand Down
2 changes: 1 addition & 1 deletion src/scripts/build-coherence-md.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ export const suites: {title: string, method: string, cases: [string, boolean, st
]

let output = `# Coherence across libraries
> Autogenerated by \`src/scripts/build-coherence-md.ts\`
> Autogenerated by [\`src/scripts/build-coherence-md.ts\`](./src/scripts/build-coherence-md.ts)
`

for (const {title, method, cases} of suites) {
Expand Down
123 changes: 123 additions & 0 deletions src/scripts/build-meta-md.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import path from 'node:path'
import fs from 'node:fs'
import cp from 'node:child_process'
import { tools } from '../test/bench/stand/index.ts'

const __dirname = path.dirname(new URL(import.meta.url).pathname)
const outfile = path.resolve(__dirname, '../../META.md')
const tmpbase = path.resolve(__dirname, '../../tmp')

interface PackageInfo {
name: string
size: string // unpacked size of package
installSize: string // unpacked size + deps
node: string
browser: boolean
moduleTypes: string[]
types: boolean
}

function formatSize(bytes: number): string {
if (!bytes) return 'n/a'
if (bytes > 1024 * 1024) return (bytes / 1024 / 1024).toFixed(1) + ' MB'
return (bytes / 1024).toFixed(1) + ' kB'
}

async function getNpmMetadata(pkg: string) {
const res = await fetch(`https://registry.npmjs.org/${pkg}`)
if (!res.ok) throw new Error(`Failed to fetch ${pkg}`)
return res.json()
}

async function getPackageInfo(pkg: string, repo: string): Promise<PackageInfo> {
console.log(`fetching ${pkg} meta...`)

const tmp = path.join(tmpbase, pkg.replace('/', '-'))
await fs.promises.mkdir(tmp, { recursive: true })
await fs.promises.writeFile(path.join(tmp, 'package.json'), JSON.stringify({dependencies: { [pkg]: 'latest' }}))

const {promise, resolve, reject} = Promise.withResolvers()
cp.exec('npm install --prefer-offline --no-audit --no-fund --ignore-scripts --package-lock-only', { cwd: tmp }, (err) => err ? reject(err) : resolve(true))
await promise

const pkgLock = JSON.parse(await fs.promises.readFile(path.join(tmp, 'package-lock.json'), 'utf-8'))

const meta = await getNpmMetadata(pkg)
const latest = meta['dist-tags'].latest
const pkgInfo = meta.versions[latest]
const unpackedSize = pkgInfo.dist?.unpackedSize ?? 0

let installSize = 0
for (const [location, {version}] of Object.entries(pkgLock.packages as Record<string, {version?: string}> ?? {})) {
try {
if (!version) continue
const name = location === '' ? pkg : location.replace('node_modules/', '')
const depMeta = await getNpmMetadata(name)
installSize += depMeta.versions[version]?.dist?.unpackedSize ?? 0
} catch {
/* ignore missing dep sizes */
}
}

const engines = pkgInfo.engines?.node ?? 'n/a'
const browser = !!pkgInfo.browser
const hasTypes =
!!pkgInfo.types ||
!!pkgInfo.typings ||
(pkgInfo.devDependencies && Object.keys(pkgInfo.devDependencies).some(d => d.startsWith('@types/')))

const moduleTypes: string[] = []
if (pkgInfo.type === 'module' || pkgInfo.module || pkgInfo.exports?.['.']?.import) {
moduleTypes.push('ESM')
}
if (pkgInfo.main || pkgInfo.exports?.['.']?.require) {
moduleTypes.push('CJS')
}

return {
name: `[\`${pkg}\`](${repo})`,
size: formatSize(unpackedSize),
installSize: formatSize(installSize),
node: engines.replace('>', '\\>').replace('<', '\\<'),
browser,
moduleTypes,
types: hasTypes,
}
}

function toMarkdown(pkgs: PackageInfo[]): string {
const headers = [
'Package',
'Publish size',
'Install size',
'Node.js',
'Modules',
'Types',
]
const table = [
`| ${headers.join(' | ')} |`,
`| ${headers.map((_, i) => '---' + (i > 0 ? ':' : '')).join(' | ')} |`,
...pkgs.map(p =>
`| ${p.name} | ${p.size} | ${p.installSize} | ${p.node} | ${p.moduleTypes.join(', ')} | ${p.types ? '✓' : '❌'} |`
),
]
return table.join('\n')
}

let output = `# Package meta across libraries
> Autogenerated by [\`src/scripts/build-meta-md.ts\`](./src/scripts/build-meta-md.ts)

`

const packages = Object.keys(tools).filter((k) => k !== 'node:net' && k !== '@webpod/ip/core')
const results: PackageInfo[] = []
for (const pkg of packages) {
try {
results.push(await getPackageInfo(pkg, tools[pkg]?.ref as string || `https://www.npmjs.com/package/${pkg}`))
} catch (err) {
console.error(`Failed to fetch ${pkg}:`, err)
}
}
output += toMarkdown(results)

fs.writeFileSync(outfile, output)
13 changes: 6 additions & 7 deletions src/test/bench/stand/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,6 @@ export const tools: Record<string, Record<string, Checker | string>> = {
isIPv4: (addr) => net.isIPv4(addr),
isIPv6: (addr) => net.isIPv6(addr),
},
ip: {
ref: 'https://github.com/indutny/node-ip',
isIPv4: (addr) => ip.isV4Format(addr),
isIPv6: (addr) => ip.isV6Format(addr),
isPrivate: (addr) => ip.isPrivate(addr),
},
'@webpod/ip': {
ref: 'https://github.com/webpod/ip',
isIPv4: (addr) => wpip.isV4Format(addr),
Expand All @@ -39,7 +33,12 @@ export const tools: Record<string, Record<string, Checker | string>> = {
} catch { return null }
},
},

ip: {
ref: 'https://github.com/indutny/node-ip',
isIPv4: (addr) => ip.isV4Format(addr),
isIPv6: (addr) => ip.isV6Format(addr),
isPrivate: (addr) => ip.isPrivate(addr),
},
'is-ip': {
ref: 'https://github.com/sindresorhus/is-ip',
isIPv4: (addr) => isip.isIPv4(addr),
Expand Down
Loading