pnpm 10.33.2 → 10.33.3

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.
Files changed (31) hide show
  1. package/dist/node_modules/.modules.yaml +66 -66
  2. package/dist/node_modules/.pnpm/lock.yaml +8 -8
  3. package/dist/node_modules/.pnpm-workspace-state-v1.json +1 -1
  4. package/dist/node_modules/ip-address/dist/address-error.js.map +1 -1
  5. package/dist/node_modules/ip-address/dist/common.js +21 -0
  6. package/dist/node_modules/ip-address/dist/common.js.map +1 -1
  7. package/dist/node_modules/ip-address/dist/ip-address.js.map +1 -1
  8. package/dist/node_modules/ip-address/dist/ipv4.js +193 -68
  9. package/dist/node_modules/ip-address/dist/ipv4.js.map +1 -1
  10. package/dist/node_modules/ip-address/dist/ipv6.js +345 -131
  11. package/dist/node_modules/ip-address/dist/ipv6.js.map +1 -1
  12. package/dist/node_modules/ip-address/dist/v4/constants.js.map +1 -1
  13. package/dist/node_modules/ip-address/dist/v6/constants.js +5 -0
  14. package/dist/node_modules/ip-address/dist/v6/constants.js.map +1 -1
  15. package/dist/node_modules/ip-address/dist/v6/helpers.js +12 -3
  16. package/dist/node_modules/ip-address/dist/v6/helpers.js.map +1 -1
  17. package/dist/node_modules/ip-address/dist/v6/regular-expressions.js.map +1 -1
  18. package/dist/node_modules/ip-address/package.json +45 -35
  19. package/dist/node_modules/socks/.claude/settings.local.json +26 -0
  20. package/dist/node_modules/socks/package.json +2 -2
  21. package/dist/pnpm.cjs +38 -4
  22. package/package.json +1 -1
  23. package/dist/node_modules/ip-address/dist/address-error.d.ts.map +0 -1
  24. package/dist/node_modules/ip-address/dist/common.d.ts.map +0 -1
  25. package/dist/node_modules/ip-address/dist/ip-address.d.ts.map +0 -1
  26. package/dist/node_modules/ip-address/dist/ipv4.d.ts.map +0 -1
  27. package/dist/node_modules/ip-address/dist/ipv6.d.ts.map +0 -1
  28. package/dist/node_modules/ip-address/dist/v4/constants.d.ts.map +0 -1
  29. package/dist/node_modules/ip-address/dist/v6/constants.d.ts.map +0 -1
  30. package/dist/node_modules/ip-address/dist/v6/helpers.d.ts.map +0 -1
  31. package/dist/node_modules/ip-address/dist/v6/regular-expressions.d.ts.map +0 -1
@@ -34,6 +34,7 @@ const ipv4_1 = require("./ipv4");
34
34
  const regular_expressions_1 = require("./v6/regular-expressions");
35
35
  const address_error_1 = require("./address-error");
36
36
  const common_1 = require("./common");
37
+ const isCorrect6 = common.isCorrect(constants6.BITS);
37
38
  function assert(condition) {
38
39
  if (!condition) {
39
40
  throw new Error('Assertion failed.');
@@ -77,7 +78,6 @@ function unsignByte(b) {
77
78
  }
78
79
  /**
79
80
  * Represents an IPv6 address
80
- * @class Address6
81
81
  * @param {string} address - An IPv6 address string
82
82
  * @param {number} [groups=8] - How many octets to parse
83
83
  * @example
@@ -94,18 +94,14 @@ class Address6 {
94
94
  // #region Attributes
95
95
  /**
96
96
  * Returns true if the given address is in the subnet of the current address
97
- * @memberof Address6
98
- * @instance
99
97
  * @returns {boolean}
100
98
  */
101
99
  this.isInSubnet = common.isInSubnet;
102
100
  /**
103
101
  * Returns true if the address is correct, false otherwise
104
- * @memberof Address6
105
- * @instance
106
102
  * @returns {boolean}
107
103
  */
108
- this.isCorrect = common.isCorrect(constants6.BITS);
104
+ this.isCorrect = isCorrect6;
109
105
  if (optionalGroups === undefined) {
110
106
  this.groups = constants6.GROUPS;
111
107
  }
@@ -136,6 +132,13 @@ class Address6 {
136
132
  this.addressMinusSuffix = address;
137
133
  this.parsedAddress = this.parse(this.addressMinusSuffix);
138
134
  }
135
+ /**
136
+ * Returns true if the given string is a valid IPv6 address (with optional
137
+ * CIDR subnet and zone identifier), false otherwise. Host bits in the
138
+ * subnet portion are allowed (e.g. `2001:db8::1/32` is valid); for strict
139
+ * network-address validation compare `correctForm()` to
140
+ * `startAddress().correctForm()`, or use `networkForm()`.
141
+ */
139
142
  static isValid(address) {
140
143
  try {
141
144
  // eslint-disable-next-line no-new
@@ -147,9 +150,8 @@ class Address6 {
147
150
  }
148
151
  }
149
152
  /**
150
- * Convert a BigInt to a v6 address object
151
- * @memberof Address6
152
- * @static
153
+ * Convert a BigInt to a v6 address object. The value must be in the
154
+ * range `[0, 2**128 - 1]`; otherwise `AddressError` is thrown.
153
155
  * @param {bigint} bigInt - a BigInt to convert
154
156
  * @returns {Address6}
155
157
  * @example
@@ -158,19 +160,21 @@ class Address6 {
158
160
  * address.correctForm(); // '::e8:d4a5:1000'
159
161
  */
160
162
  static fromBigInt(bigInt) {
163
+ if (bigInt < 0n || bigInt > (1n << BigInt(constants6.BITS)) - 1n) {
164
+ throw new address_error_1.AddressError('IPv6 BigInt must be in the range 0 to 2**128 - 1');
165
+ }
161
166
  const hex = bigInt.toString(16).padStart(32, '0');
162
167
  const groups = [];
163
- let i;
164
- for (i = 0; i < constants6.GROUPS; i++) {
168
+ for (let i = 0; i < constants6.GROUPS; i++) {
165
169
  groups.push(hex.slice(i * 4, (i + 1) * 4));
166
170
  }
167
171
  return new Address6(groups.join(':'));
168
172
  }
169
173
  /**
170
- * Convert a URL (with optional port number) to an address object
171
- * @memberof Address6
172
- * @static
173
- * @param {string} url - a URL with optional port number
174
+ * Parse a URL (with optional bracketed host and port) into an address and
175
+ * port. Returns either `{ address, port }` on success or
176
+ * `{ error, address: null, port: null }` if the URL could not be parsed.
177
+ * Ports are returned as numbers (or `null` if absent or out of range).
174
178
  * @example
175
179
  * var addressAndPort = Address6.fromURL('http://[ffff::]:8080/foo/');
176
180
  * addressAndPort.address.correctForm(); // 'ffff::'
@@ -229,10 +233,92 @@ class Address6 {
229
233
  port,
230
234
  };
231
235
  }
236
+ /**
237
+ * Construct an `Address6` from an address and a hex subnet mask given as
238
+ * separate strings (e.g. as returned by Node's `os.networkInterfaces()`).
239
+ * Throws `AddressError` if the mask is non-contiguous (e.g.
240
+ * `ffff::ffff`).
241
+ * @example
242
+ * var address = Address6.fromAddressAndMask('fe80::1', 'ffff:ffff:ffff:ffff::');
243
+ * address.subnetMask; // 64
244
+ */
245
+ static fromAddressAndMask(address, mask) {
246
+ const bits = common.prefixLengthFromMask(new Address6(mask).bigInt(), constants6.BITS);
247
+ return new Address6(`${address}/${bits}`);
248
+ }
249
+ /**
250
+ * Construct an `Address6` from an address and a Cisco-style wildcard mask
251
+ * given as separate strings (e.g. `::ffff:ffff:ffff:ffff` for a `/64`).
252
+ * The wildcard mask is the bitwise inverse of the subnet mask. Throws
253
+ * `AddressError` if the mask is non-contiguous.
254
+ * @example
255
+ * var address = Address6.fromAddressAndWildcardMask('fe80::1', '::ffff:ffff:ffff:ffff');
256
+ * address.subnetMask; // 64
257
+ */
258
+ static fromAddressAndWildcardMask(address, wildcardMask) {
259
+ const wildcard = new Address6(wildcardMask).bigInt();
260
+ const allOnes = (BigInt(1) << BigInt(constants6.BITS)) - BigInt(1);
261
+ // eslint-disable-next-line no-bitwise
262
+ const mask = wildcard ^ allOnes;
263
+ const bits = common.prefixLengthFromMask(mask, constants6.BITS);
264
+ return new Address6(`${address}/${bits}`);
265
+ }
266
+ /**
267
+ * Construct an `Address6` from a wildcard pattern with trailing `*`
268
+ * groups. The number of trailing wildcards determines the prefix
269
+ * length: each `*` represents 16 bits. `::` is expanded to zero groups
270
+ * (not wildcards) before evaluating trailing wildcards.
271
+ *
272
+ * Only trailing whole-group wildcards are supported. Partial-group
273
+ * wildcards (e.g. `2001:db8::0*`) and interior wildcards (e.g.
274
+ * `*::1`) throw `AddressError`.
275
+ * @example
276
+ * Address6.fromWildcard('2001:db8:*:*:*:*:*:*').subnet; // '/32'
277
+ * Address6.fromWildcard('2001:db8::*').subnet; // '/112'
278
+ * Address6.fromWildcard('*:*:*:*:*:*:*:*').subnet; // '/0'
279
+ */
280
+ static fromWildcard(input) {
281
+ if (input.includes('%') || input.includes('/')) {
282
+ throw new address_error_1.AddressError('Wildcard pattern must not include a zone or CIDR suffix');
283
+ }
284
+ const halves = input.split('::');
285
+ if (halves.length > 2) {
286
+ throw new address_error_1.AddressError("Wildcard pattern cannot contain more than one '::'");
287
+ }
288
+ let groups;
289
+ if (halves.length === 2) {
290
+ const left = halves[0] === '' ? [] : halves[0].split(':');
291
+ const right = halves[1] === '' ? [] : halves[1].split(':');
292
+ const remaining = constants6.GROUPS - left.length - right.length;
293
+ if (remaining < 1) {
294
+ throw new address_error_1.AddressError("Wildcard pattern with '::' has too many groups");
295
+ }
296
+ groups = [...left, ...new Array(remaining).fill('0'), ...right];
297
+ }
298
+ else {
299
+ groups = input.split(':');
300
+ }
301
+ if (groups.length !== constants6.GROUPS) {
302
+ throw new address_error_1.AddressError('Wildcard pattern must have 8 groups');
303
+ }
304
+ let firstWildcard = -1;
305
+ for (let i = 0; i < groups.length; i++) {
306
+ if (groups[i] === '*') {
307
+ if (firstWildcard === -1) {
308
+ firstWildcard = i;
309
+ }
310
+ }
311
+ else if (firstWildcard !== -1) {
312
+ throw new address_error_1.AddressError('Wildcard `*` must only appear in trailing groups (e.g. `2001:db8:*:*:*:*:*:*`)');
313
+ }
314
+ }
315
+ const trailing = firstWildcard === -1 ? 0 : groups.length - firstWildcard;
316
+ const replaced = groups.map((g) => (g === '*' ? '0' : g));
317
+ const subnetBits = constants6.BITS - trailing * 16;
318
+ return new Address6(`${replaced.join(':')}/${subnetBits}`);
319
+ }
232
320
  /**
233
321
  * Create an IPv6-mapped address given an IPv4 address
234
- * @memberof Address6
235
- * @static
236
322
  * @param {string} address - An IPv4 address string
237
323
  * @returns {Address6}
238
324
  * @example
@@ -247,8 +333,6 @@ class Address6 {
247
333
  }
248
334
  /**
249
335
  * Return an address from ip6.arpa form
250
- * @memberof Address6
251
- * @static
252
336
  * @param {string} arpaFormAddress - an 'ip6.arpa' form address
253
337
  * @returns {Adress6}
254
338
  * @example
@@ -273,8 +357,6 @@ class Address6 {
273
357
  }
274
358
  /**
275
359
  * Return the Microsoft UNC transcription of the address
276
- * @memberof Address6
277
- * @instance
278
360
  * @returns {String} the Microsoft UNC transcription of the address
279
361
  */
280
362
  microsoftTranscription() {
@@ -282,8 +364,6 @@ class Address6 {
282
364
  }
283
365
  /**
284
366
  * Return the first n bits of the address, defaulting to the subnet mask
285
- * @memberof Address6
286
- * @instance
287
367
  * @param {number} [mask=subnet] - the number of bits to mask
288
368
  * @returns {String} the first n bits of the address as a string
289
369
  */
@@ -292,8 +372,6 @@ class Address6 {
292
372
  }
293
373
  /**
294
374
  * Return the number of possible subnets of a given size in the address
295
- * @memberof Address6
296
- * @instance
297
375
  * @param {number} [subnetSize=128] - the subnet size
298
376
  * @returns {String}
299
377
  */
@@ -309,8 +387,6 @@ class Address6 {
309
387
  }
310
388
  /**
311
389
  * Helper function getting start address.
312
- * @memberof Address6
313
- * @instance
314
390
  * @returns {bigint}
315
391
  */
316
392
  _startAddress() {
@@ -319,8 +395,6 @@ class Address6 {
319
395
  /**
320
396
  * The first address in the range given by this address' subnet
321
397
  * Often referred to as the Network Address.
322
- * @memberof Address6
323
- * @instance
324
398
  * @returns {Address6}
325
399
  */
326
400
  startAddress() {
@@ -329,8 +403,6 @@ class Address6 {
329
403
  /**
330
404
  * The first host address in the range given by this address's subnet ie
331
405
  * the first address after the Network Address
332
- * @memberof Address6
333
- * @instance
334
406
  * @returns {Address6}
335
407
  */
336
408
  startAddressExclusive() {
@@ -339,8 +411,6 @@ class Address6 {
339
411
  }
340
412
  /**
341
413
  * Helper function getting end address.
342
- * @memberof Address6
343
- * @instance
344
414
  * @returns {bigint}
345
415
  */
346
416
  _endAddress() {
@@ -349,8 +419,6 @@ class Address6 {
349
419
  /**
350
420
  * The last address in the range given by this address' subnet
351
421
  * Often referred to as the Broadcast
352
- * @memberof Address6
353
- * @instance
354
422
  * @returns {Address6}
355
423
  */
356
424
  endAddress() {
@@ -359,8 +427,6 @@ class Address6 {
359
427
  /**
360
428
  * The last host address in the range given by this address's subnet ie
361
429
  * the last address prior to the Broadcast Address
362
- * @memberof Address6
363
- * @instance
364
430
  * @returns {Address6}
365
431
  */
366
432
  endAddressExclusive() {
@@ -368,36 +434,73 @@ class Address6 {
368
434
  return Address6.fromBigInt(this._endAddress() - adjust);
369
435
  }
370
436
  /**
371
- * Return the scope of the address
372
- * @memberof Address6
373
- * @instance
437
+ * The hex form of the subnet mask, e.g. `ffff:ffff:ffff:ffff::` for a
438
+ * `/64`. Returns an `Address6`; call `.correctForm()` for the string.
439
+ * @returns {Address6}
440
+ */
441
+ subnetMaskAddress() {
442
+ return Address6.fromBigInt(BigInt(`0b${'1'.repeat(this.subnetMask)}${'0'.repeat(constants6.BITS - this.subnetMask)}`));
443
+ }
444
+ /**
445
+ * The Cisco-style wildcard mask, e.g. `::ffff:ffff:ffff:ffff` for a
446
+ * `/64`. This is the bitwise inverse of `subnetMaskAddress()`. Returns
447
+ * an `Address6`; call `.correctForm()` for the string.
448
+ * @returns {Address6}
449
+ */
450
+ wildcardMask() {
451
+ return Address6.fromBigInt(BigInt(`0b${'0'.repeat(this.subnetMask)}${'1'.repeat(constants6.BITS - this.subnetMask)}`));
452
+ }
453
+ /**
454
+ * The network address in CIDR string form, e.g. `2001:db8::/32` for
455
+ * `2001:db8::1/32`. For an address with no explicit subnet the prefix
456
+ * is `/128`, e.g. `networkForm()` on `2001:db8::1` returns
457
+ * `2001:db8::1/128`.
458
+ * @returns {string}
459
+ */
460
+ networkForm() {
461
+ return `${this.startAddress().correctForm()}/${this.subnetMask}`;
462
+ }
463
+ /**
464
+ * Return the scope of the address. The 4-bit scope field
465
+ * ([RFC 4291 §2.7](https://datatracker.ietf.org/doc/html/rfc4291#section-2.7))
466
+ * is only defined for multicast addresses; for unicast addresses the scope
467
+ * is derived from the address type per
468
+ * [RFC 4007 §6](https://datatracker.ietf.org/doc/html/rfc4007#section-6).
374
469
  * @returns {String}
375
470
  */
376
471
  getScope() {
377
- let scope = constants6.SCOPES[parseInt(this.getBits(12, 16).toString(10), 10)];
378
- if (this.getType() === 'Global unicast' && scope !== 'Link local') {
379
- scope = 'Global';
472
+ const type = this.getType();
473
+ if (type === 'Multicast' || type.startsWith('Multicast ')) {
474
+ const scope = constants6.SCOPES[parseInt(this.getBits(12, 16).toString(10), 10)];
475
+ return scope || 'Unknown';
476
+ }
477
+ // RFC 4291 §2.5.3: the loopback address is treated as having Link-Local
478
+ // scope. (Multicast scope 1, "Interface-Local", is a different concept
479
+ // used only for loopback transmission of multicast.)
480
+ if (type === 'Link-local unicast' || type === 'Loopback') {
481
+ return 'Link local';
482
+ }
483
+ // RFC 4007 §6: the unspecified address has no scope.
484
+ if (type === 'Unspecified') {
485
+ return 'Unknown';
380
486
  }
381
- return scope || 'Unknown';
487
+ return 'Global';
382
488
  }
383
489
  /**
384
490
  * Return the type of the address
385
- * @memberof Address6
386
- * @instance
387
491
  * @returns {String}
388
492
  */
389
493
  getType() {
390
- for (const subnet of Object.keys(constants6.TYPES)) {
391
- if (this.isInSubnet(new Address6(subnet))) {
392
- return constants6.TYPES[subnet];
494
+ for (let i = 0; i < TYPE_SUBNETS.length; i++) {
495
+ const entry = TYPE_SUBNETS[i];
496
+ if (this.isInSubnet(entry[0])) {
497
+ return entry[1];
393
498
  }
394
499
  }
395
500
  return 'Global unicast';
396
501
  }
397
502
  /**
398
503
  * Return the bits in the given range as a BigInt
399
- * @memberof Address6
400
- * @instance
401
504
  * @returns {bigint}
402
505
  */
403
506
  getBits(start, end) {
@@ -405,8 +508,6 @@ class Address6 {
405
508
  }
406
509
  /**
407
510
  * Return the bits in the given range as a base-2 string
408
- * @memberof Address6
409
- * @instance
410
511
  * @returns {String}
411
512
  */
412
513
  getBitsBase2(start, end) {
@@ -414,8 +515,6 @@ class Address6 {
414
515
  }
415
516
  /**
416
517
  * Return the bits in the given range as a base-16 string
417
- * @memberof Address6
418
- * @instance
419
518
  * @returns {String}
420
519
  */
421
520
  getBitsBase16(start, end) {
@@ -429,8 +528,6 @@ class Address6 {
429
528
  }
430
529
  /**
431
530
  * Return the bits that are set past the subnet mask length
432
- * @memberof Address6
433
- * @instance
434
531
  * @returns {String}
435
532
  */
436
533
  getBitsPastSubnet() {
@@ -438,10 +535,8 @@ class Address6 {
438
535
  }
439
536
  /**
440
537
  * Return the reversed ip6.arpa form of the address
441
- * @memberof Address6
442
538
  * @param {Object} options
443
539
  * @param {boolean} options.omitSuffix - omit the "ip6.arpa" suffix
444
- * @instance
445
540
  * @returns {String}
446
541
  */
447
542
  reverseForm(options) {
@@ -467,10 +562,10 @@ class Address6 {
467
562
  return 'ip6.arpa.';
468
563
  }
469
564
  /**
470
- * Return the correct form of the address
471
- * @memberof Address6
472
- * @instance
473
- * @returns {String}
565
+ * Returns the address in correct form, per
566
+ * [RFC 5952](https://datatracker.ietf.org/doc/html/rfc5952): leading zeros
567
+ * stripped, the longest run of zero groups collapsed to `::`, and hex digits
568
+ * lowercased (e.g. `2001:db8::1`). This is the recommended form for display.
474
569
  */
475
570
  correctForm() {
476
571
  let i;
@@ -514,8 +609,6 @@ class Address6 {
514
609
  }
515
610
  /**
516
611
  * Return a zero-padded base-2 string representation of the address
517
- * @memberof Address6
518
- * @instance
519
612
  * @returns {String}
520
613
  * @example
521
614
  * var address = new Address6('2001:4860:4001:803::1011');
@@ -524,10 +617,22 @@ class Address6 {
524
617
  * // 0000000000000000000000000000000000000000000000000001000000010001'
525
618
  */
526
619
  binaryZeroPad() {
527
- return this.bigInt().toString(2).padStart(constants6.BITS, '0');
620
+ if (this._binaryZeroPad === undefined) {
621
+ this._binaryZeroPad = this.bigInt().toString(2).padStart(constants6.BITS, '0');
622
+ }
623
+ return this._binaryZeroPad;
528
624
  }
625
+ /**
626
+ * Parses a v4-in-v6 string (e.g. `::ffff:192.168.0.1`) by extracting the
627
+ * trailing IPv4 address into `this.address4` / `this.parsedAddress4` and
628
+ * returning the address with the v4 portion converted to two v6 groups.
629
+ * Used internally by `parse()`.
630
+ */
529
631
  // TODO: Improve the semantics of this helper function
530
632
  parse4in6(address) {
633
+ if (address.indexOf('.') === -1) {
634
+ return address;
635
+ }
531
636
  const groups = address.split(':');
532
637
  const lastGroup = groups.slice(-1)[0];
533
638
  const address4 = lastGroup.match(constants4.RE_ADDRESS);
@@ -536,7 +641,12 @@ class Address6 {
536
641
  this.address4 = new ipv4_1.Address4(this.parsedAddress4);
537
642
  for (let i = 0; i < this.address4.groups; i++) {
538
643
  if (/^0[0-9]+/.test(this.address4.parsedAddress[i])) {
539
- throw new address_error_1.AddressError("IPv4 addresses can't have leading zeroes.", address.replace(constants4.RE_ADDRESS, this.address4.parsedAddress.map(spanLeadingZeroes4).join('.')));
644
+ // The prefix groups haven't been through the bad-character check
645
+ // yet, so escape them before including in the error HTML.
646
+ const highlighted = this.address4.parsedAddress.map(spanLeadingZeroes4).join('.');
647
+ const prefix = groups.slice(0, -1).map(helpers.escapeHtml).join(':');
648
+ const separator = groups.length > 1 ? ':' : '';
649
+ throw new address_error_1.AddressError("IPv4 addresses can't have leading zeroes.", `${prefix}${separator}${highlighted}`);
540
650
  }
541
651
  }
542
652
  this.v4 = true;
@@ -545,6 +655,13 @@ class Address6 {
545
655
  }
546
656
  return address;
547
657
  }
658
+ /**
659
+ * Parses an IPv6 address string into its 8 hexadecimal groups (expanding
660
+ * any `::` elision and any trailing v4-in-v6 portion) and stores the result
661
+ * on `this.parsedAddress`. Called automatically by the constructor; you
662
+ * typically don't need to call it directly. Throws `AddressError` if the
663
+ * input is malformed.
664
+ */
548
665
  // TODO: Make private?
549
666
  parse(address) {
550
667
  address = this.parse4in6(address);
@@ -594,18 +711,16 @@ class Address6 {
594
711
  return groups;
595
712
  }
596
713
  /**
597
- * Return the canonical form of the address
598
- * @memberof Address6
599
- * @instance
600
- * @returns {String}
714
+ * Returns the canonical (fully expanded) form of the address: all 8 groups,
715
+ * each padded to 4 hex digits, with no `::` collapsing
716
+ * (e.g. `2001:0db8:0000:0000:0000:0000:0000:0001`). Useful for sorting and
717
+ * byte-exact comparison.
601
718
  */
602
719
  canonicalForm() {
603
720
  return this.parsedAddress.map(paddedHex).join(':');
604
721
  }
605
722
  /**
606
723
  * Return the decimal form of the address
607
- * @memberof Address6
608
- * @instance
609
724
  * @returns {String}
610
725
  */
611
726
  decimal() {
@@ -613,8 +728,6 @@ class Address6 {
613
728
  }
614
729
  /**
615
730
  * Return the address as a BigInt
616
- * @memberof Address6
617
- * @instance
618
731
  * @returns {bigint}
619
732
  */
620
733
  bigInt() {
@@ -622,8 +735,6 @@ class Address6 {
622
735
  }
623
736
  /**
624
737
  * Return the last two groups of this address as an IPv4 address string
625
- * @memberof Address6
626
- * @instance
627
738
  * @returns {Address4}
628
739
  * @example
629
740
  * var address = new Address6('2001:4860:4001::1825:bf11');
@@ -631,12 +742,10 @@ class Address6 {
631
742
  */
632
743
  to4() {
633
744
  const binary = this.binaryZeroPad().split('');
634
- return ipv4_1.Address4.fromHex(BigInt(`0b${binary.slice(96, 128).join('')}`).toString(16));
745
+ return ipv4_1.Address4.fromHex(BigInt(`0b${binary.slice(96, 128).join('')}`).toString(16).padStart(8, '0'));
635
746
  }
636
747
  /**
637
748
  * Return the v4-in-v6 form of the address
638
- * @memberof Address6
639
- * @instance
640
749
  * @returns {String}
641
750
  */
642
751
  to4in6() {
@@ -650,10 +759,10 @@ class Address6 {
650
759
  return correct + infix + address4.address;
651
760
  }
652
761
  /**
653
- * Return an object containing the Teredo properties of the address
654
- * @memberof Address6
655
- * @instance
656
- * @returns {Object}
762
+ * Decodes the Teredo tunneling fields embedded in this address. Returns the
763
+ * Teredo prefix, server IPv4, client IPv4, raw flag bits, cone-NAT flag,
764
+ * UDP port, and Microsoft-format flag breakdown (reserved, universal/local,
765
+ * group/individual, nonce). Only meaningful for addresses in `2001::/32`.
657
766
  */
658
767
  inspectTeredo() {
659
768
  /*
@@ -684,7 +793,7 @@ class Address6 {
684
793
  const server4 = ipv4_1.Address4.fromHex(this.getBitsBase16(32, 64));
685
794
  const bitsForClient4 = this.getBits(96, 128);
686
795
  // eslint-disable-next-line no-bitwise
687
- const client4 = ipv4_1.Address4.fromHex((bitsForClient4 ^ BigInt('0xffffffff')).toString(16));
796
+ const client4 = ipv4_1.Address4.fromHex((bitsForClient4 ^ BigInt('0xffffffff')).toString(16).padStart(8, '0'));
688
797
  const flagsBase2 = this.getBitsBase2(64, 80);
689
798
  const coneNat = (0, common_1.testBit)(flagsBase2, 15);
690
799
  const reserved = (0, common_1.testBit)(flagsBase2, 14);
@@ -707,10 +816,9 @@ class Address6 {
707
816
  };
708
817
  }
709
818
  /**
710
- * Return an object containing the 6to4 properties of the address
711
- * @memberof Address6
712
- * @instance
713
- * @returns {Object}
819
+ * Decodes the 6to4 tunneling fields embedded in this address. Returns the
820
+ * 6to4 prefix and the embedded IPv4 gateway address. Only meaningful for
821
+ * addresses in `2002::/16`.
714
822
  */
715
823
  inspect6to4() {
716
824
  /*
@@ -726,8 +834,6 @@ class Address6 {
726
834
  }
727
835
  /**
728
836
  * Return a v6 6to4 address from a v6 v4inv6 address
729
- * @memberof Address6
730
- * @instance
731
837
  * @returns {Address6}
732
838
  */
733
839
  to6to4() {
@@ -744,9 +850,80 @@ class Address6 {
744
850
  return new Address6(addr6to4);
745
851
  }
746
852
  /**
747
- * Return a byte array
748
- * @memberof Address6
749
- * @instance
853
+ * Embed an IPv4 address into a NAT64 IPv6 address using the encoding
854
+ * defined by [RFC 6052](https://datatracker.ietf.org/doc/html/rfc6052).
855
+ * The default prefix is the well-known prefix `64:ff9b::/96`. The prefix
856
+ * length must be one of 32, 40, 48, 56, 64, or 96; for prefixes shorter
857
+ * than /64 the IPv4 octets are split around the reserved bits 64–71.
858
+ * @example
859
+ * Address6.fromAddress4Nat64('192.0.2.33').correctForm(); // '64:ff9b::c000:221'
860
+ * Address6.fromAddress4Nat64('192.0.2.33', '2001:db8::/32').correctForm(); // '2001:db8:c000:221::'
861
+ */
862
+ static fromAddress4Nat64(address, prefix = '64:ff9b::/96') {
863
+ const v4 = new ipv4_1.Address4(address);
864
+ const prefix6 = new Address6(prefix);
865
+ const pl = prefix6.subnetMask;
866
+ if (pl !== 32 && pl !== 40 && pl !== 48 && pl !== 56 && pl !== 64 && pl !== 96) {
867
+ throw new address_error_1.AddressError('NAT64 prefix length must be 32, 40, 48, 56, 64, or 96');
868
+ }
869
+ const prefixBits = prefix6.binaryZeroPad();
870
+ const v4Bits = v4.binaryZeroPad();
871
+ let bits;
872
+ if (pl === 96) {
873
+ bits = prefixBits.slice(0, 96) + v4Bits;
874
+ }
875
+ else {
876
+ const beforeU = 64 - pl;
877
+ bits =
878
+ prefixBits.slice(0, pl) +
879
+ v4Bits.slice(0, beforeU) +
880
+ '00000000' +
881
+ v4Bits.slice(beforeU) +
882
+ '0'.repeat(128 - 72 - (32 - beforeU));
883
+ }
884
+ const hex = BigInt(`0b${bits}`).toString(16).padStart(32, '0');
885
+ const groups = [];
886
+ for (let i = 0; i < 8; i++) {
887
+ groups.push(hex.slice(i * 4, (i + 1) * 4));
888
+ }
889
+ return new Address6(groups.join(':'));
890
+ }
891
+ /**
892
+ * Extract the embedded IPv4 address from a NAT64 IPv6 address using the
893
+ * encoding defined by [RFC 6052](https://datatracker.ietf.org/doc/html/rfc6052).
894
+ * The default prefix is the well-known prefix `64:ff9b::/96`. Returns
895
+ * `null` if this address is not contained within the given prefix.
896
+ * @example
897
+ * new Address6('64:ff9b::c000:221').toAddress4Nat64()!.correctForm(); // '192.0.2.33'
898
+ */
899
+ toAddress4Nat64(prefix = '64:ff9b::/96') {
900
+ const prefix6 = new Address6(prefix);
901
+ const pl = prefix6.subnetMask;
902
+ if (pl !== 32 && pl !== 40 && pl !== 48 && pl !== 56 && pl !== 64 && pl !== 96) {
903
+ throw new address_error_1.AddressError('NAT64 prefix length must be 32, 40, 48, 56, 64, or 96');
904
+ }
905
+ if (!this.isInSubnet(prefix6)) {
906
+ return null;
907
+ }
908
+ const bits = this.binaryZeroPad();
909
+ let v4Bits;
910
+ if (pl === 96) {
911
+ v4Bits = bits.slice(96, 128);
912
+ }
913
+ else {
914
+ const beforeU = 64 - pl;
915
+ v4Bits = bits.slice(pl, pl + beforeU) + bits.slice(72, 72 + (32 - beforeU));
916
+ }
917
+ const octets = [];
918
+ for (let i = 0; i < 4; i++) {
919
+ octets.push(parseInt(v4Bits.slice(i * 8, (i + 1) * 8), 2).toString());
920
+ }
921
+ return new ipv4_1.Address4(octets.join('.'));
922
+ }
923
+ /**
924
+ * Return a byte array.
925
+ *
926
+ * To get a Node.js `Buffer`, wrap the result: `Buffer.from(address.toByteArray())`.
750
927
  * @returns {Array}
751
928
  */
752
929
  toByteArray() {
@@ -760,27 +937,27 @@ class Address6 {
760
937
  return bytes;
761
938
  }
762
939
  /**
763
- * Return an unsigned byte array
764
- * @memberof Address6
765
- * @instance
940
+ * Return an unsigned byte array.
941
+ *
942
+ * To get a Node.js `Buffer`, wrap the result: `Buffer.from(address.toUnsignedByteArray())`.
766
943
  * @returns {Array}
767
944
  */
768
945
  toUnsignedByteArray() {
769
946
  return this.toByteArray().map(unsignByte);
770
947
  }
771
948
  /**
772
- * Convert a byte array to an Address6 object
773
- * @memberof Address6
774
- * @static
949
+ * Convert a byte array to an Address6 object.
950
+ *
951
+ * To convert from a Node.js `Buffer`, spread it: `Address6.fromByteArray([...buf])`.
775
952
  * @returns {Address6}
776
953
  */
777
954
  static fromByteArray(bytes) {
778
955
  return this.fromUnsignedByteArray(bytes.map(unsignByte));
779
956
  }
780
957
  /**
781
- * Convert an unsigned byte array to an Address6 object
782
- * @memberof Address6
783
- * @static
958
+ * Convert an unsigned byte array to an Address6 object.
959
+ *
960
+ * To convert from a Node.js `Buffer`, spread it: `Address6.fromUnsignedByteArray([...buf])`.
784
961
  * @returns {Address6}
785
962
  */
786
963
  static fromUnsignedByteArray(bytes) {
@@ -795,8 +972,6 @@ class Address6 {
795
972
  }
796
973
  /**
797
974
  * Returns true if the address is in the canonical form, false otherwise
798
- * @memberof Address6
799
- * @instance
800
975
  * @returns {boolean}
801
976
  */
802
977
  isCanonical() {
@@ -804,8 +979,6 @@ class Address6 {
804
979
  }
805
980
  /**
806
981
  * Returns true if the address is a link local address, false otherwise
807
- * @memberof Address6
808
- * @instance
809
982
  * @returns {boolean}
810
983
  */
811
984
  isLinkLocal() {
@@ -818,53 +991,81 @@ class Address6 {
818
991
  }
819
992
  /**
820
993
  * Returns true if the address is a multicast address, false otherwise
821
- * @memberof Address6
822
- * @instance
823
994
  * @returns {boolean}
824
995
  */
825
996
  isMulticast() {
826
- return this.getType() === 'Multicast';
997
+ const type = this.getType();
998
+ return type === 'Multicast' || type.startsWith('Multicast ');
827
999
  }
828
1000
  /**
829
- * Returns true if the address is a v4-in-v6 address, false otherwise
830
- * @memberof Address6
831
- * @instance
1001
+ * Returns true if the address was written in v4-in-v6 dotted-quad notation
1002
+ * (e.g. `::ffff:127.0.0.1`), false otherwise. This is a notation-level flag
1003
+ * and does not reflect whether the address bits lie in the IPv4-mapped
1004
+ * (`::ffff:0:0/96`) subnet — for that, see {@link isMapped4}.
832
1005
  * @returns {boolean}
833
1006
  */
834
1007
  is4() {
835
1008
  return this.v4;
836
1009
  }
1010
+ /**
1011
+ * Returns true if the address is an IPv4-mapped IPv6 address in
1012
+ * `::ffff:0:0/96` ([RFC 4291 §2.5.5.2](https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.5.2)),
1013
+ * false otherwise. Unlike {@link is4}, this checks the underlying address
1014
+ * bits rather than the textual notation, so `::ffff:127.0.0.1` and
1015
+ * `::ffff:7f00:1` both return true.
1016
+ * @returns {boolean}
1017
+ */
1018
+ isMapped4() {
1019
+ return this.isInSubnet(IPV4_MAPPED_SUBNET);
1020
+ }
837
1021
  /**
838
1022
  * Returns true if the address is a Teredo address, false otherwise
839
- * @memberof Address6
840
- * @instance
841
1023
  * @returns {boolean}
842
1024
  */
843
1025
  isTeredo() {
844
- return this.isInSubnet(new Address6('2001::/32'));
1026
+ return this.isInSubnet(TEREDO_SUBNET);
845
1027
  }
846
1028
  /**
847
1029
  * Returns true if the address is a 6to4 address, false otherwise
848
- * @memberof Address6
849
- * @instance
850
1030
  * @returns {boolean}
851
1031
  */
852
1032
  is6to4() {
853
- return this.isInSubnet(new Address6('2002::/16'));
1033
+ return this.isInSubnet(SIX_TO_FOUR_SUBNET);
854
1034
  }
855
1035
  /**
856
1036
  * Returns true if the address is a loopback address, false otherwise
857
- * @memberof Address6
858
- * @instance
859
1037
  * @returns {boolean}
860
1038
  */
861
1039
  isLoopback() {
862
1040
  return this.getType() === 'Loopback';
863
1041
  }
1042
+ /**
1043
+ * Returns true if the address is a Unique Local Address in `fc00::/7` ([RFC 4193](https://datatracker.ietf.org/doc/html/rfc4193)). ULAs are the IPv6 equivalent of IPv4 [RFC 1918](https://datatracker.ietf.org/doc/html/rfc1918) private addresses.
1044
+ * @returns {boolean}
1045
+ */
1046
+ isULA() {
1047
+ return this.isInSubnet(ULA_SUBNET);
1048
+ }
1049
+ /**
1050
+ * Returns true if the address is the unspecified address `::`.
1051
+ * @returns {boolean}
1052
+ */
1053
+ isUnspecified() {
1054
+ return this.getType() === 'Unspecified';
1055
+ }
1056
+ /**
1057
+ * Returns true if the address is in the documentation prefix `2001:db8::/32` ([RFC 3849](https://datatracker.ietf.org/doc/html/rfc3849)).
1058
+ * @returns {boolean}
1059
+ */
1060
+ isDocumentation() {
1061
+ return this.isInSubnet(DOCUMENTATION_SUBNET);
1062
+ }
864
1063
  // #endregion
865
1064
  // #region HTML
866
1065
  /**
867
- * @returns {String} the address in link form with a default port of 80
1066
+ * Returns the address as an HTTP URL with the host bracketed, e.g.
1067
+ * `http://[2001:db8::1]/`. If `optionalPort` is provided it is appended,
1068
+ * e.g. `http://[2001:db8::1]:8080/`.
868
1069
  */
869
1070
  href(optionalPort) {
870
1071
  if (optionalPort === undefined) {
@@ -876,7 +1077,12 @@ class Address6 {
876
1077
  return `http://[${this.correctForm()}]${optionalPort}/`;
877
1078
  }
878
1079
  /**
879
- * @returns {String} a link suitable for conveying the address via a URL hash
1080
+ * Returns an HTML `<a>` element whose `href` encodes the address in a URL
1081
+ * hash fragment (default prefix `/#address=`). Useful for linking between
1082
+ * pages of an address-inspector UI.
1083
+ * @param options.className - CSS class for the rendered `<a>` element
1084
+ * @param options.prefix - hash prefix prepended to the address (default `/#address=`)
1085
+ * @param options.v4 - when true, render the address in v4-in-v6 form
880
1086
  */
881
1087
  link(options) {
882
1088
  if (!options) {
@@ -896,10 +1102,13 @@ class Address6 {
896
1102
  formFunction = this.to4in6;
897
1103
  }
898
1104
  const form = formFunction.call(this);
1105
+ const safeHref = helpers.escapeHtml(`${options.prefix}${form}`);
1106
+ const safeForm = helpers.escapeHtml(form);
899
1107
  if (options.className) {
900
- return `<a href="${options.prefix}${form}" class="${options.className}">${form}</a>`;
1108
+ const safeClass = helpers.escapeHtml(options.className);
1109
+ return `<a href="${safeHref}" class="${safeClass}">${safeForm}</a>`;
901
1110
  }
902
- return `<a href="${options.prefix}${form}">${form}</a>`;
1111
+ return `<a href="${safeHref}">${safeForm}</a>`;
903
1112
  }
904
1113
  /**
905
1114
  * Groups an address
@@ -908,13 +1117,13 @@ class Address6 {
908
1117
  group() {
909
1118
  if (this.elidedGroups === 0) {
910
1119
  // The simple case
911
- return helpers.simpleGroup(this.address).join(':');
1120
+ return helpers.simpleGroup(this.addressMinusSuffix).join(':');
912
1121
  }
913
1122
  assert(typeof this.elidedGroups === 'number');
914
1123
  assert(typeof this.elisionBegin === 'number');
915
1124
  // The elided case
916
1125
  const output = [];
917
- const [left, right] = this.address.split('::');
1126
+ const [left, right] = this.addressMinusSuffix.split('::');
918
1127
  if (left.length) {
919
1128
  output.push(...helpers.simpleGroup(left));
920
1129
  }
@@ -944,8 +1153,6 @@ class Address6 {
944
1153
  /**
945
1154
  * Generate a regular expression string that can be used to find or validate
946
1155
  * all variations of this address
947
- * @memberof Address6
948
- * @instance
949
1156
  * @param {boolean} substringSearch
950
1157
  * @returns {string}
951
1158
  */
@@ -990,8 +1197,6 @@ class Address6 {
990
1197
  /**
991
1198
  * Generate a regular expression that can be used to find or validate all
992
1199
  * variations of this address.
993
- * @memberof Address6
994
- * @instance
995
1200
  * @param {boolean} substringSearch
996
1201
  * @returns {RegExp}
997
1202
  */
@@ -1000,4 +1205,13 @@ class Address6 {
1000
1205
  }
1001
1206
  }
1002
1207
  exports.Address6 = Address6;
1208
+ const TYPE_SUBNETS = Object.keys(constants6.TYPES).map((subnet) => [
1209
+ new Address6(subnet),
1210
+ constants6.TYPES[subnet],
1211
+ ]);
1212
+ const TEREDO_SUBNET = new Address6('2001::/32');
1213
+ const SIX_TO_FOUR_SUBNET = new Address6('2002::/16');
1214
+ const ULA_SUBNET = new Address6('fc00::/7');
1215
+ const DOCUMENTATION_SUBNET = new Address6('2001:db8::/32');
1216
+ const IPV4_MAPPED_SUBNET = new Address6('::ffff:0:0/96');
1003
1217
  //# sourceMappingURL=ipv6.js.map