@open-mercato/shared 0.5.1-develop.2657.a01847a9fa → 0.5.1-develop.2663.2c29774b5b

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.
@@ -148,6 +148,8 @@ function ipv4FromHexSegments(high, low) {
148
148
  }
149
149
  export {
150
150
  isBlockedHostname,
151
+ isPrivateIPv4,
152
+ isPrivateIPv6,
151
153
  isPrivateIpAddress,
152
154
  isPrivateUrl
153
155
  };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/lib/network.ts"],
4
- "sourcesContent": ["import { isIP } from 'node:net'\n\nconst BLOCKED_HOSTNAMES = new Set([\n 'localhost',\n 'ip6-localhost',\n 'ip6-loopback',\n 'broadcasthost',\n])\n\nexport function isPrivateIpAddress(address: string): boolean {\n const family = isIP(address)\n if (family === 4) return isPrivateIPv4(address)\n if (family === 6) return isPrivateIPv6(address)\n return false\n}\n\nexport function isBlockedHostname(hostname: string): boolean {\n const normalized = normalizeHostname(hostname)\n if (!normalized) return true\n if (BLOCKED_HOSTNAMES.has(normalized)) return true\n if (normalized.endsWith('.localhost')) return true\n if (normalized.endsWith('.internal')) return true\n if (normalized.endsWith('.local')) return true\n return false\n}\n\nexport function isPrivateUrl(rawUrl: string): boolean {\n const urlToParse = rawUrl.replace(/\\[([0-9a-fA-F:]+)%25[^\\]]*\\]/g, '[$1]')\n let url: URL\n try {\n url = new URL(urlToParse)\n } catch {\n return false\n }\n\n const hostname = normalizeHostname(url.hostname)\n if (isBlockedHostname(hostname)) return true\n return isPrivateIpAddress(hostname)\n}\n\nfunction normalizeHostname(hostname: string): string {\n let normalized = hostname.trim().toLowerCase()\n if (normalized.startsWith('[') && normalized.endsWith(']')) {\n normalized = normalized.slice(1, -1)\n }\n while (normalized.endsWith('.')) {\n normalized = normalized.slice(0, -1)\n }\n return normalized\n}\n\nfunction isPrivateIPv4(address: string): boolean {\n const parts = address.split('.')\n if (parts.length !== 4) return false\n const octets = parts.map((part) => Number(part))\n if (octets.some((o) => !Number.isInteger(o) || o < 0 || o > 255)) return false\n\n const [a, b, c] = octets\n if (a === 0) return true\n if (a === 10) return true\n if (a === 100 && b >= 64 && b <= 127) return true\n if (a === 127) return true\n if (a === 169 && b === 254) return true\n if (a === 172 && b >= 16 && b <= 31) return true\n if (a === 192 && b === 0 && (c === 0 || c === 2)) return true\n if (a === 192 && b === 168) return true\n if (a === 198 && (b === 18 || b === 19)) return true\n if (a === 198 && b === 51 && c === 100) return true\n if (a === 203 && b === 0 && c === 113) return true\n if (a >= 224) return true\n return false\n}\n\nfunction isPrivateIPv6(address: string): boolean {\n const segments = expandIPv6(address)\n if (!segments) return false\n\n if (segments.every((segment) => segment === 0)) return true\n if (segments.slice(0, 7).every((segment) => segment === 0) && segments[7] === 1) return true\n if (isIPv4CompatibleIPv6(segments)) return true\n\n const embedded = embeddedIPv4FromIPv6(segments)\n if (embedded && isPrivateIPv4(embedded)) return true\n\n const [a] = segments\n if ((a & 0xfe00) === 0xfc00) return true\n if ((a & 0xffc0) === 0xfe80) return true\n if ((a & 0xff00) === 0xff00) return true\n return false\n}\n\nfunction expandIPv6(address: string): number[] | null {\n let normalized = address.toLowerCase()\n if (normalized.includes('.')) {\n const lastColon = normalized.lastIndexOf(':')\n if (lastColon === -1) return null\n const ipv4Segments = ipv4ToHexSegments(normalized.slice(lastColon + 1))\n if (!ipv4Segments) return null\n normalized = `${normalized.slice(0, lastColon)}:${ipv4Segments[0].toString(16)}:${ipv4Segments[1].toString(16)}`\n }\n\n const doubleColonParts = normalized.split('::')\n if (doubleColonParts.length > 2) return null\n\n const head = doubleColonParts[0] ? doubleColonParts[0].split(':') : []\n const tail = doubleColonParts[1] ? doubleColonParts[1].split(':') : []\n const headSegments = parseIPv6SegmentList(head)\n const tailSegments = parseIPv6SegmentList(tail)\n if (!headSegments || !tailSegments) return null\n\n if (doubleColonParts.length === 1) {\n return headSegments.length === 8 ? headSegments : null\n }\n\n const missing = 8 - headSegments.length - tailSegments.length\n if (missing < 1) return null\n return [\n ...headSegments,\n ...Array.from({ length: missing }, () => 0),\n ...tailSegments,\n ]\n}\n\nfunction parseIPv6SegmentList(parts: string[]): number[] | null {\n const segments: number[] = []\n for (const part of parts) {\n if (!/^[0-9a-f]{1,4}$/.test(part)) return null\n const value = Number.parseInt(part, 16)\n if (!Number.isInteger(value) || value < 0 || value > 0xffff) return null\n segments.push(value)\n }\n return segments\n}\n\nfunction ipv4ToHexSegments(address: string): [number, number] | null {\n const octets = address.split('.').map((part) => Number(part))\n if (octets.length !== 4) return null\n if (octets.some((octet) => !Number.isInteger(octet) || octet < 0 || octet > 255)) return null\n return [\n (octets[0] << 8) + octets[1],\n (octets[2] << 8) + octets[3],\n ]\n}\n\nfunction embeddedIPv4FromIPv6(segments: number[]): string | null {\n const firstFiveZero = segments.slice(0, 5).every((segment) => segment === 0)\n const isMapped = firstFiveZero && segments[5] === 0xffff\n const isNat64 = segments[0] === 0x0064\n && segments[1] === 0xff9b\n && segments.slice(2, 6).every((segment) => segment === 0)\n const isSixToFour = segments[0] === 0x2002\n\n if (isMapped || isNat64) {\n return ipv4FromHexSegments(segments[6], segments[7])\n }\n if (isSixToFour) {\n return ipv4FromHexSegments(segments[1], segments[2])\n }\n return null\n}\n\nfunction isIPv4CompatibleIPv6(segments: number[]): boolean {\n return segments.slice(0, 6).every((segment) => segment === 0)\n}\n\nfunction ipv4FromHexSegments(high: number, low: number): string {\n return [\n (high >> 8) & 0xff,\n high & 0xff,\n (low >> 8) & 0xff,\n low & 0xff,\n ].join('.')\n}\n"],
5
- "mappings": "AAAA,SAAS,YAAY;AAErB,MAAM,oBAAoB,oBAAI,IAAI;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAEM,SAAS,mBAAmB,SAA0B;AAC3D,QAAM,SAAS,KAAK,OAAO;AAC3B,MAAI,WAAW,EAAG,QAAO,cAAc,OAAO;AAC9C,MAAI,WAAW,EAAG,QAAO,cAAc,OAAO;AAC9C,SAAO;AACT;AAEO,SAAS,kBAAkB,UAA2B;AAC3D,QAAM,aAAa,kBAAkB,QAAQ;AAC7C,MAAI,CAAC,WAAY,QAAO;AACxB,MAAI,kBAAkB,IAAI,UAAU,EAAG,QAAO;AAC9C,MAAI,WAAW,SAAS,YAAY,EAAG,QAAO;AAC9C,MAAI,WAAW,SAAS,WAAW,EAAG,QAAO;AAC7C,MAAI,WAAW,SAAS,QAAQ,EAAG,QAAO;AAC1C,SAAO;AACT;AAEO,SAAS,aAAa,QAAyB;AACpD,QAAM,aAAa,OAAO,QAAQ,iCAAiC,MAAM;AACzE,MAAI;AACJ,MAAI;AACF,UAAM,IAAI,IAAI,UAAU;AAAA,EAC1B,QAAQ;AACN,WAAO;AAAA,EACT;AAEA,QAAM,WAAW,kBAAkB,IAAI,QAAQ;AAC/C,MAAI,kBAAkB,QAAQ,EAAG,QAAO;AACxC,SAAO,mBAAmB,QAAQ;AACpC;AAEA,SAAS,kBAAkB,UAA0B;AACnD,MAAI,aAAa,SAAS,KAAK,EAAE,YAAY;AAC7C,MAAI,WAAW,WAAW,GAAG,KAAK,WAAW,SAAS,GAAG,GAAG;AAC1D,iBAAa,WAAW,MAAM,GAAG,EAAE;AAAA,EACrC;AACA,SAAO,WAAW,SAAS,GAAG,GAAG;AAC/B,iBAAa,WAAW,MAAM,GAAG,EAAE;AAAA,EACrC;AACA,SAAO;AACT;AAEA,SAAS,cAAc,SAA0B;AAC/C,QAAM,QAAQ,QAAQ,MAAM,GAAG;AAC/B,MAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,QAAM,SAAS,MAAM,IAAI,CAAC,SAAS,OAAO,IAAI,CAAC;AAC/C,MAAI,OAAO,KAAK,CAAC,MAAM,CAAC,OAAO,UAAU,CAAC,KAAK,IAAI,KAAK,IAAI,GAAG,EAAG,QAAO;AAEzE,QAAM,CAAC,GAAG,GAAG,CAAC,IAAI;AAClB,MAAI,MAAM,EAAG,QAAO;AACpB,MAAI,MAAM,GAAI,QAAO;AACrB,MAAI,MAAM,OAAO,KAAK,MAAM,KAAK,IAAK,QAAO;AAC7C,MAAI,MAAM,IAAK,QAAO;AACtB,MAAI,MAAM,OAAO,MAAM,IAAK,QAAO;AACnC,MAAI,MAAM,OAAO,KAAK,MAAM,KAAK,GAAI,QAAO;AAC5C,MAAI,MAAM,OAAO,MAAM,MAAM,MAAM,KAAK,MAAM,GAAI,QAAO;AACzD,MAAI,MAAM,OAAO,MAAM,IAAK,QAAO;AACnC,MAAI,MAAM,QAAQ,MAAM,MAAM,MAAM,IAAK,QAAO;AAChD,MAAI,MAAM,OAAO,MAAM,MAAM,MAAM,IAAK,QAAO;AAC/C,MAAI,MAAM,OAAO,MAAM,KAAK,MAAM,IAAK,QAAO;AAC9C,MAAI,KAAK,IAAK,QAAO;AACrB,SAAO;AACT;AAEA,SAAS,cAAc,SAA0B;AAC/C,QAAM,WAAW,WAAW,OAAO;AACnC,MAAI,CAAC,SAAU,QAAO;AAEtB,MAAI,SAAS,MAAM,CAAC,YAAY,YAAY,CAAC,EAAG,QAAO;AACvD,MAAI,SAAS,MAAM,GAAG,CAAC,EAAE,MAAM,CAAC,YAAY,YAAY,CAAC,KAAK,SAAS,CAAC,MAAM,EAAG,QAAO;AACxF,MAAI,qBAAqB,QAAQ,EAAG,QAAO;AAE3C,QAAM,WAAW,qBAAqB,QAAQ;AAC9C,MAAI,YAAY,cAAc,QAAQ,EAAG,QAAO;AAEhD,QAAM,CAAC,CAAC,IAAI;AACZ,OAAK,IAAI,WAAY,MAAQ,QAAO;AACpC,OAAK,IAAI,WAAY,MAAQ,QAAO;AACpC,OAAK,IAAI,WAAY,MAAQ,QAAO;AACpC,SAAO;AACT;AAEA,SAAS,WAAW,SAAkC;AACpD,MAAI,aAAa,QAAQ,YAAY;AACrC,MAAI,WAAW,SAAS,GAAG,GAAG;AAC5B,UAAM,YAAY,WAAW,YAAY,GAAG;AAC5C,QAAI,cAAc,GAAI,QAAO;AAC7B,UAAM,eAAe,kBAAkB,WAAW,MAAM,YAAY,CAAC,CAAC;AACtE,QAAI,CAAC,aAAc,QAAO;AAC1B,iBAAa,GAAG,WAAW,MAAM,GAAG,SAAS,CAAC,IAAI,aAAa,CAAC,EAAE,SAAS,EAAE,CAAC,IAAI,aAAa,CAAC,EAAE,SAAS,EAAE,CAAC;AAAA,EAChH;AAEA,QAAM,mBAAmB,WAAW,MAAM,IAAI;AAC9C,MAAI,iBAAiB,SAAS,EAAG,QAAO;AAExC,QAAM,OAAO,iBAAiB,CAAC,IAAI,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;AACrE,QAAM,OAAO,iBAAiB,CAAC,IAAI,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;AACrE,QAAM,eAAe,qBAAqB,IAAI;AAC9C,QAAM,eAAe,qBAAqB,IAAI;AAC9C,MAAI,CAAC,gBAAgB,CAAC,aAAc,QAAO;AAE3C,MAAI,iBAAiB,WAAW,GAAG;AACjC,WAAO,aAAa,WAAW,IAAI,eAAe;AAAA,EACpD;AAEA,QAAM,UAAU,IAAI,aAAa,SAAS,aAAa;AACvD,MAAI,UAAU,EAAG,QAAO;AACxB,SAAO;AAAA,IACL,GAAG;AAAA,IACH,GAAG,MAAM,KAAK,EAAE,QAAQ,QAAQ,GAAG,MAAM,CAAC;AAAA,IAC1C,GAAG;AAAA,EACL;AACF;AAEA,SAAS,qBAAqB,OAAkC;AAC9D,QAAM,WAAqB,CAAC;AAC5B,aAAW,QAAQ,OAAO;AACxB,QAAI,CAAC,kBAAkB,KAAK,IAAI,EAAG,QAAO;AAC1C,UAAM,QAAQ,OAAO,SAAS,MAAM,EAAE;AACtC,QAAI,CAAC,OAAO,UAAU,KAAK,KAAK,QAAQ,KAAK,QAAQ,MAAQ,QAAO;AACpE,aAAS,KAAK,KAAK;AAAA,EACrB;AACA,SAAO;AACT;AAEA,SAAS,kBAAkB,SAA0C;AACnE,QAAM,SAAS,QAAQ,MAAM,GAAG,EAAE,IAAI,CAAC,SAAS,OAAO,IAAI,CAAC;AAC5D,MAAI,OAAO,WAAW,EAAG,QAAO;AAChC,MAAI,OAAO,KAAK,CAAC,UAAU,CAAC,OAAO,UAAU,KAAK,KAAK,QAAQ,KAAK,QAAQ,GAAG,EAAG,QAAO;AACzF,SAAO;AAAA,KACJ,OAAO,CAAC,KAAK,KAAK,OAAO,CAAC;AAAA,KAC1B,OAAO,CAAC,KAAK,KAAK,OAAO,CAAC;AAAA,EAC7B;AACF;AAEA,SAAS,qBAAqB,UAAmC;AAC/D,QAAM,gBAAgB,SAAS,MAAM,GAAG,CAAC,EAAE,MAAM,CAAC,YAAY,YAAY,CAAC;AAC3E,QAAM,WAAW,iBAAiB,SAAS,CAAC,MAAM;AAClD,QAAM,UAAU,SAAS,CAAC,MAAM,OAC3B,SAAS,CAAC,MAAM,SAChB,SAAS,MAAM,GAAG,CAAC,EAAE,MAAM,CAAC,YAAY,YAAY,CAAC;AAC1D,QAAM,cAAc,SAAS,CAAC,MAAM;AAEpC,MAAI,YAAY,SAAS;AACvB,WAAO,oBAAoB,SAAS,CAAC,GAAG,SAAS,CAAC,CAAC;AAAA,EACrD;AACA,MAAI,aAAa;AACf,WAAO,oBAAoB,SAAS,CAAC,GAAG,SAAS,CAAC,CAAC;AAAA,EACrD;AACA,SAAO;AACT;AAEA,SAAS,qBAAqB,UAA6B;AACzD,SAAO,SAAS,MAAM,GAAG,CAAC,EAAE,MAAM,CAAC,YAAY,YAAY,CAAC;AAC9D;AAEA,SAAS,oBAAoB,MAAc,KAAqB;AAC9D,SAAO;AAAA,IACJ,QAAQ,IAAK;AAAA,IACd,OAAO;AAAA,IACN,OAAO,IAAK;AAAA,IACb,MAAM;AAAA,EACR,EAAE,KAAK,GAAG;AACZ;",
4
+ "sourcesContent": ["import { isIP } from 'node:net'\n\nconst BLOCKED_HOSTNAMES = new Set([\n 'localhost',\n 'ip6-localhost',\n 'ip6-loopback',\n 'broadcasthost',\n])\n\nexport function isPrivateIpAddress(address: string): boolean {\n const family = isIP(address)\n if (family === 4) return isPrivateIPv4(address)\n if (family === 6) return isPrivateIPv6(address)\n return false\n}\n\nexport function isBlockedHostname(hostname: string): boolean {\n const normalized = normalizeHostname(hostname)\n if (!normalized) return true\n if (BLOCKED_HOSTNAMES.has(normalized)) return true\n if (normalized.endsWith('.localhost')) return true\n if (normalized.endsWith('.internal')) return true\n if (normalized.endsWith('.local')) return true\n return false\n}\n\nexport function isPrivateUrl(rawUrl: string): boolean {\n const urlToParse = rawUrl.replace(/\\[([0-9a-fA-F:]+)%25[^\\]]*\\]/g, '[$1]')\n let url: URL\n try {\n url = new URL(urlToParse)\n } catch {\n return false\n }\n\n const hostname = normalizeHostname(url.hostname)\n if (isBlockedHostname(hostname)) return true\n return isPrivateIpAddress(hostname)\n}\n\nfunction normalizeHostname(hostname: string): string {\n let normalized = hostname.trim().toLowerCase()\n if (normalized.startsWith('[') && normalized.endsWith(']')) {\n normalized = normalized.slice(1, -1)\n }\n while (normalized.endsWith('.')) {\n normalized = normalized.slice(0, -1)\n }\n return normalized\n}\n\nexport function isPrivateIPv4(address: string): boolean {\n const parts = address.split('.')\n if (parts.length !== 4) return false\n const octets = parts.map((part) => Number(part))\n if (octets.some((o) => !Number.isInteger(o) || o < 0 || o > 255)) return false\n\n const [a, b, c] = octets\n if (a === 0) return true\n if (a === 10) return true\n if (a === 100 && b >= 64 && b <= 127) return true\n if (a === 127) return true\n if (a === 169 && b === 254) return true\n if (a === 172 && b >= 16 && b <= 31) return true\n if (a === 192 && b === 0 && (c === 0 || c === 2)) return true\n if (a === 192 && b === 168) return true\n if (a === 198 && (b === 18 || b === 19)) return true\n if (a === 198 && b === 51 && c === 100) return true\n if (a === 203 && b === 0 && c === 113) return true\n if (a >= 224) return true\n return false\n}\n\nexport function isPrivateIPv6(address: string): boolean {\n const segments = expandIPv6(address)\n if (!segments) return false\n\n if (segments.every((segment) => segment === 0)) return true\n if (segments.slice(0, 7).every((segment) => segment === 0) && segments[7] === 1) return true\n if (isIPv4CompatibleIPv6(segments)) return true\n\n const embedded = embeddedIPv4FromIPv6(segments)\n if (embedded && isPrivateIPv4(embedded)) return true\n\n const [a] = segments\n if ((a & 0xfe00) === 0xfc00) return true\n if ((a & 0xffc0) === 0xfe80) return true\n if ((a & 0xff00) === 0xff00) return true\n return false\n}\n\nfunction expandIPv6(address: string): number[] | null {\n let normalized = address.toLowerCase()\n if (normalized.includes('.')) {\n const lastColon = normalized.lastIndexOf(':')\n if (lastColon === -1) return null\n const ipv4Segments = ipv4ToHexSegments(normalized.slice(lastColon + 1))\n if (!ipv4Segments) return null\n normalized = `${normalized.slice(0, lastColon)}:${ipv4Segments[0].toString(16)}:${ipv4Segments[1].toString(16)}`\n }\n\n const doubleColonParts = normalized.split('::')\n if (doubleColonParts.length > 2) return null\n\n const head = doubleColonParts[0] ? doubleColonParts[0].split(':') : []\n const tail = doubleColonParts[1] ? doubleColonParts[1].split(':') : []\n const headSegments = parseIPv6SegmentList(head)\n const tailSegments = parseIPv6SegmentList(tail)\n if (!headSegments || !tailSegments) return null\n\n if (doubleColonParts.length === 1) {\n return headSegments.length === 8 ? headSegments : null\n }\n\n const missing = 8 - headSegments.length - tailSegments.length\n if (missing < 1) return null\n return [\n ...headSegments,\n ...Array.from({ length: missing }, () => 0),\n ...tailSegments,\n ]\n}\n\nfunction parseIPv6SegmentList(parts: string[]): number[] | null {\n const segments: number[] = []\n for (const part of parts) {\n if (!/^[0-9a-f]{1,4}$/.test(part)) return null\n const value = Number.parseInt(part, 16)\n if (!Number.isInteger(value) || value < 0 || value > 0xffff) return null\n segments.push(value)\n }\n return segments\n}\n\nfunction ipv4ToHexSegments(address: string): [number, number] | null {\n const octets = address.split('.').map((part) => Number(part))\n if (octets.length !== 4) return null\n if (octets.some((octet) => !Number.isInteger(octet) || octet < 0 || octet > 255)) return null\n return [\n (octets[0] << 8) + octets[1],\n (octets[2] << 8) + octets[3],\n ]\n}\n\nfunction embeddedIPv4FromIPv6(segments: number[]): string | null {\n const firstFiveZero = segments.slice(0, 5).every((segment) => segment === 0)\n const isMapped = firstFiveZero && segments[5] === 0xffff\n const isNat64 = segments[0] === 0x0064\n && segments[1] === 0xff9b\n && segments.slice(2, 6).every((segment) => segment === 0)\n const isSixToFour = segments[0] === 0x2002\n\n if (isMapped || isNat64) {\n return ipv4FromHexSegments(segments[6], segments[7])\n }\n if (isSixToFour) {\n return ipv4FromHexSegments(segments[1], segments[2])\n }\n return null\n}\n\nfunction isIPv4CompatibleIPv6(segments: number[]): boolean {\n return segments.slice(0, 6).every((segment) => segment === 0)\n}\n\nfunction ipv4FromHexSegments(high: number, low: number): string {\n return [\n (high >> 8) & 0xff,\n high & 0xff,\n (low >> 8) & 0xff,\n low & 0xff,\n ].join('.')\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,4 +1,4 @@
1
- const APP_VERSION = "0.5.1-develop.2657.a01847a9fa";
1
+ const APP_VERSION = "0.5.1-develop.2663.2c29774b5b";
2
2
  const appVersion = APP_VERSION;
3
3
  export {
4
4
  APP_VERSION,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/lib/version.ts"],
4
- "sourcesContent": ["// Build-time generated version\nexport const APP_VERSION = '0.5.1-develop.2657.a01847a9fa'\nexport const appVersion = APP_VERSION\n"],
4
+ "sourcesContent": ["// Build-time generated version\nexport const APP_VERSION = '0.5.1-develop.2663.2c29774b5b'\nexport const appVersion = APP_VERSION\n"],
5
5
  "mappings": "AACO,MAAM,cAAc;AACpB,MAAM,aAAa;",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-mercato/shared",
3
- "version": "0.5.1-develop.2657.a01847a9fa",
3
+ "version": "0.5.1-develop.2663.2c29774b5b",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "scripts": {
@@ -49,7 +49,7 @@ function normalizeHostname(hostname: string): string {
49
49
  return normalized
50
50
  }
51
51
 
52
- function isPrivateIPv4(address: string): boolean {
52
+ export function isPrivateIPv4(address: string): boolean {
53
53
  const parts = address.split('.')
54
54
  if (parts.length !== 4) return false
55
55
  const octets = parts.map((part) => Number(part))
@@ -71,7 +71,7 @@ function isPrivateIPv4(address: string): boolean {
71
71
  return false
72
72
  }
73
73
 
74
- function isPrivateIPv6(address: string): boolean {
74
+ export function isPrivateIPv6(address: string): boolean {
75
75
  const segments = expandIPv6(address)
76
76
  if (!segments) return false
77
77