@pactflow/openapi-pact-comparator 1.6.0 → 1.6.1

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/dist/index.cjs CHANGED
@@ -3716,6 +3716,7 @@ const minimumSchema = (originalSchema, oas) => {
3716
3716
  const subschema = cloneDeep(get$1(oas, path, {}));
3717
3717
  delete subschema.description;
3718
3718
  delete subschema.example;
3719
+ traverse(schema, cleanupDiscriminators);
3719
3720
  traverse(subschema, collectReferences);
3720
3721
  traverse(subschema, handleNullableSchema);
3721
3722
  traverse(subschema, convertExclusiveMinMax);
@@ -15168,44 +15169,6 @@ var uri = {};
15168
15169
 
15169
15170
  var fastUri = {exports: {}};
15170
15171
 
15171
- var scopedChars;
15172
- var hasRequiredScopedChars;
15173
-
15174
- function requireScopedChars () {
15175
- if (hasRequiredScopedChars) return scopedChars;
15176
- hasRequiredScopedChars = 1;
15177
-
15178
- const HEX = {
15179
- 0: 0,
15180
- 1: 1,
15181
- 2: 2,
15182
- 3: 3,
15183
- 4: 4,
15184
- 5: 5,
15185
- 6: 6,
15186
- 7: 7,
15187
- 8: 8,
15188
- 9: 9,
15189
- a: 10,
15190
- A: 10,
15191
- b: 11,
15192
- B: 11,
15193
- c: 12,
15194
- C: 12,
15195
- d: 13,
15196
- D: 13,
15197
- e: 14,
15198
- E: 14,
15199
- f: 15,
15200
- F: 15
15201
- };
15202
-
15203
- scopedChars = {
15204
- HEX
15205
- };
15206
- return scopedChars;
15207
- }
15208
-
15209
15172
  var utils;
15210
15173
  var hasRequiredUtils;
15211
15174
 
@@ -15213,62 +15176,100 @@ function requireUtils () {
15213
15176
  if (hasRequiredUtils) return utils;
15214
15177
  hasRequiredUtils = 1;
15215
15178
 
15216
- const { HEX } = requireScopedChars();
15179
+ /** @type {(value: string) => boolean} */
15180
+ const isUUID = RegExp.prototype.test.bind(/^[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}$/iu);
15217
15181
 
15218
- const IPV4_REG = /^(?:(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)$/u;
15182
+ /** @type {(value: string) => boolean} */
15183
+ const isIPv4 = RegExp.prototype.test.bind(/^(?:(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)$/u);
15219
15184
 
15220
- function normalizeIPv4 (host) {
15221
- if (findToken(host, '.') < 3) { return { host, isIPV4: false } }
15222
- const matches = host.match(IPV4_REG) || [];
15223
- const [address] = matches;
15224
- if (address) {
15225
- return { host: stripLeadingZeros(address, '.'), isIPV4: true }
15226
- } else {
15227
- return { host, isIPV4: false }
15185
+ /**
15186
+ * @param {Array<string>} input
15187
+ * @returns {string}
15188
+ */
15189
+ function stringArrayToHexStripped (input) {
15190
+ let acc = '';
15191
+ let code = 0;
15192
+ let i = 0;
15193
+
15194
+ for (i = 0; i < input.length; i++) {
15195
+ code = input[i].charCodeAt(0);
15196
+ if (code === 48) {
15197
+ continue
15198
+ }
15199
+ if (!((code >= 48 && code <= 57) || (code >= 65 && code <= 70) || (code >= 97 && code <= 102))) {
15200
+ return ''
15201
+ }
15202
+ acc += input[i];
15203
+ break
15228
15204
  }
15205
+
15206
+ for (i += 1; i < input.length; i++) {
15207
+ code = input[i].charCodeAt(0);
15208
+ if (!((code >= 48 && code <= 57) || (code >= 65 && code <= 70) || (code >= 97 && code <= 102))) {
15209
+ return ''
15210
+ }
15211
+ acc += input[i];
15212
+ }
15213
+ return acc
15229
15214
  }
15230
15215
 
15231
15216
  /**
15232
- * @param {string[]} input
15233
- * @param {boolean} [keepZero=false]
15234
- * @returns {string|undefined}
15217
+ * @typedef {Object} GetIPV6Result
15218
+ * @property {boolean} error - Indicates if there was an error parsing the IPv6 address.
15219
+ * @property {string} address - The parsed IPv6 address.
15220
+ * @property {string} [zone] - The zone identifier, if present.
15235
15221
  */
15236
- function stringArrayToHexStripped (input, keepZero = false) {
15237
- let acc = '';
15238
- let strip = true;
15239
- for (const c of input) {
15240
- if (HEX[c] === undefined) return undefined
15241
- if (c !== '0' && strip === true) strip = false;
15242
- if (!strip) acc += c;
15222
+
15223
+ /**
15224
+ * @param {string} value
15225
+ * @returns {boolean}
15226
+ */
15227
+ const nonSimpleDomain = RegExp.prototype.test.bind(/[^!"$&'()*+,\-.;=_`a-z{}~]/u);
15228
+
15229
+ /**
15230
+ * @param {Array<string>} buffer
15231
+ * @returns {boolean}
15232
+ */
15233
+ function consumeIsZone (buffer) {
15234
+ buffer.length = 0;
15235
+ return true
15236
+ }
15237
+
15238
+ /**
15239
+ * @param {Array<string>} buffer
15240
+ * @param {Array<string>} address
15241
+ * @param {GetIPV6Result} output
15242
+ * @returns {boolean}
15243
+ */
15244
+ function consumeHextets (buffer, address, output) {
15245
+ if (buffer.length) {
15246
+ const hex = stringArrayToHexStripped(buffer);
15247
+ if (hex !== '') {
15248
+ address.push(hex);
15249
+ } else {
15250
+ output.error = true;
15251
+ return false
15252
+ }
15253
+ buffer.length = 0;
15243
15254
  }
15244
- if (keepZero && acc.length === 0) acc = '0';
15245
- return acc
15255
+ return true
15246
15256
  }
15247
15257
 
15258
+ /**
15259
+ * @param {string} input
15260
+ * @returns {GetIPV6Result}
15261
+ */
15248
15262
  function getIPV6 (input) {
15249
15263
  let tokenCount = 0;
15250
15264
  const output = { error: false, address: '', zone: '' };
15265
+ /** @type {Array<string>} */
15251
15266
  const address = [];
15267
+ /** @type {Array<string>} */
15252
15268
  const buffer = [];
15253
- let isZone = false;
15254
15269
  let endipv6Encountered = false;
15255
15270
  let endIpv6 = false;
15256
15271
 
15257
- function consume () {
15258
- if (buffer.length) {
15259
- if (isZone === false) {
15260
- const hex = stringArrayToHexStripped(buffer);
15261
- if (hex !== undefined) {
15262
- address.push(hex);
15263
- } else {
15264
- output.error = true;
15265
- return false
15266
- }
15267
- }
15268
- buffer.length = 0;
15269
- }
15270
- return true
15271
- }
15272
+ let consume = consumeHextets;
15272
15273
 
15273
15274
  for (let i = 0; i < input.length; i++) {
15274
15275
  const cursor = input[i];
@@ -15277,29 +15278,28 @@ function requireUtils () {
15277
15278
  if (endipv6Encountered === true) {
15278
15279
  endIpv6 = true;
15279
15280
  }
15280
- if (!consume()) { break }
15281
- tokenCount++;
15282
- address.push(':');
15283
- if (tokenCount > 7) {
15281
+ if (!consume(buffer, address, output)) { break }
15282
+ if (++tokenCount > 7) {
15284
15283
  // not valid
15285
15284
  output.error = true;
15286
15285
  break
15287
15286
  }
15288
- if (i - 1 >= 0 && input[i - 1] === ':') {
15287
+ if (i > 0 && input[i - 1] === ':') {
15289
15288
  endipv6Encountered = true;
15290
15289
  }
15290
+ address.push(':');
15291
15291
  continue
15292
15292
  } else if (cursor === '%') {
15293
- if (!consume()) { break }
15293
+ if (!consume(buffer, address, output)) { break }
15294
15294
  // switch to zone detection
15295
- isZone = true;
15295
+ consume = consumeIsZone;
15296
15296
  } else {
15297
15297
  buffer.push(cursor);
15298
15298
  continue
15299
15299
  }
15300
15300
  }
15301
15301
  if (buffer.length) {
15302
- if (isZone) {
15302
+ if (consume === consumeIsZone) {
15303
15303
  output.zone = buffer.join('');
15304
15304
  } else if (endIpv6) {
15305
15305
  address.push(buffer.join(''));
@@ -15311,6 +15311,17 @@ function requireUtils () {
15311
15311
  return output
15312
15312
  }
15313
15313
 
15314
+ /**
15315
+ * @typedef {Object} NormalizeIPv6Result
15316
+ * @property {string} host - The normalized host.
15317
+ * @property {string} [escapedHost] - The escaped host.
15318
+ * @property {boolean} isIPV6 - Indicates if the host is an IPv6 address.
15319
+ */
15320
+
15321
+ /**
15322
+ * @param {string} host
15323
+ * @returns {NormalizeIPv6Result}
15324
+ */
15314
15325
  function normalizeIPv6 (host) {
15315
15326
  if (findToken(host, ':') < 2) { return { host, isIPV6: false } }
15316
15327
  const ipv6 = getIPV6(host);
@@ -15322,35 +15333,17 @@ function requireUtils () {
15322
15333
  newHost += '%' + ipv6.zone;
15323
15334
  escapedHost += '%25' + ipv6.zone;
15324
15335
  }
15325
- return { host: newHost, escapedHost, isIPV6: true }
15336
+ return { host: newHost, isIPV6: true, escapedHost }
15326
15337
  } else {
15327
15338
  return { host, isIPV6: false }
15328
15339
  }
15329
15340
  }
15330
15341
 
15331
- function stripLeadingZeros (str, token) {
15332
- let out = '';
15333
- let skip = true;
15334
- const l = str.length;
15335
- for (let i = 0; i < l; i++) {
15336
- const c = str[i];
15337
- if (c === '0' && skip) {
15338
- if ((i + 1 <= l && str[i + 1] === token) || i + 1 === l) {
15339
- out += c;
15340
- skip = false;
15341
- }
15342
- } else {
15343
- if (c === token) {
15344
- skip = true;
15345
- } else {
15346
- skip = false;
15347
- }
15348
- out += c;
15349
- }
15350
- }
15351
- return out
15352
- }
15353
-
15342
+ /**
15343
+ * @param {string} str
15344
+ * @param {string} token
15345
+ * @returns {number}
15346
+ */
15354
15347
  function findToken (str, token) {
15355
15348
  let ind = 0;
15356
15349
  for (let i = 0; i < str.length; i++) {
@@ -15359,98 +15352,160 @@ function requireUtils () {
15359
15352
  return ind
15360
15353
  }
15361
15354
 
15362
- const RDS1 = /^\.\.?\//u;
15363
- const RDS2 = /^\/\.(?:\/|$)/u;
15364
- const RDS3 = /^\/\.\.(?:\/|$)/u;
15365
- const RDS5 = /^\/?(?:.|\n)*?(?=\/|$)/u;
15366
-
15367
- function removeDotSegments (input) {
15355
+ /**
15356
+ * @param {string} path
15357
+ * @returns {string}
15358
+ *
15359
+ * @see https://datatracker.ietf.org/doc/html/rfc3986#section-5.2.4
15360
+ */
15361
+ function removeDotSegments (path) {
15362
+ let input = path;
15368
15363
  const output = [];
15364
+ let nextSlash = -1;
15365
+ let len = 0;
15369
15366
 
15370
- while (input.length) {
15371
- if (input.match(RDS1)) {
15372
- input = input.replace(RDS1, '');
15373
- } else if (input.match(RDS2)) {
15374
- input = input.replace(RDS2, '/');
15375
- } else if (input.match(RDS3)) {
15376
- input = input.replace(RDS3, '/');
15377
- output.pop();
15378
- } else if (input === '.' || input === '..') {
15379
- input = '';
15380
- } else {
15381
- const im = input.match(RDS5);
15382
- if (im) {
15383
- const s = im[0];
15384
- input = input.slice(s.length);
15385
- output.push(s);
15367
+ // eslint-disable-next-line no-cond-assign
15368
+ while (len = input.length) {
15369
+ if (len === 1) {
15370
+ if (input === '.') {
15371
+ break
15372
+ } else if (input === '/') {
15373
+ output.push('/');
15374
+ break
15386
15375
  } else {
15387
- throw new Error('Unexpected dot segment condition')
15376
+ output.push(input);
15377
+ break
15378
+ }
15379
+ } else if (len === 2) {
15380
+ if (input[0] === '.') {
15381
+ if (input[1] === '.') {
15382
+ break
15383
+ } else if (input[1] === '/') {
15384
+ input = input.slice(2);
15385
+ continue
15386
+ }
15387
+ } else if (input[0] === '/') {
15388
+ if (input[1] === '.' || input[1] === '/') {
15389
+ output.push('/');
15390
+ break
15391
+ }
15392
+ }
15393
+ } else if (len === 3) {
15394
+ if (input === '/..') {
15395
+ if (output.length !== 0) {
15396
+ output.pop();
15397
+ }
15398
+ output.push('/');
15399
+ break
15388
15400
  }
15389
15401
  }
15402
+ if (input[0] === '.') {
15403
+ if (input[1] === '.') {
15404
+ if (input[2] === '/') {
15405
+ input = input.slice(3);
15406
+ continue
15407
+ }
15408
+ } else if (input[1] === '/') {
15409
+ input = input.slice(2);
15410
+ continue
15411
+ }
15412
+ } else if (input[0] === '/') {
15413
+ if (input[1] === '.') {
15414
+ if (input[2] === '/') {
15415
+ input = input.slice(2);
15416
+ continue
15417
+ } else if (input[2] === '.') {
15418
+ if (input[3] === '/') {
15419
+ input = input.slice(3);
15420
+ if (output.length !== 0) {
15421
+ output.pop();
15422
+ }
15423
+ continue
15424
+ }
15425
+ }
15426
+ }
15427
+ }
15428
+
15429
+ // Rule 2E: Move normal path segment to output
15430
+ if ((nextSlash = input.indexOf('/', 1)) === -1) {
15431
+ output.push(input);
15432
+ break
15433
+ } else {
15434
+ output.push(input.slice(0, nextSlash));
15435
+ input = input.slice(nextSlash);
15436
+ }
15390
15437
  }
15438
+
15391
15439
  return output.join('')
15392
15440
  }
15393
15441
 
15394
- function normalizeComponentEncoding (components, esc) {
15442
+ /**
15443
+ * @param {import('../types/index').URIComponent} component
15444
+ * @param {boolean} esc
15445
+ * @returns {import('../types/index').URIComponent}
15446
+ */
15447
+ function normalizeComponentEncoding (component, esc) {
15395
15448
  const func = esc !== true ? escape : unescape;
15396
- if (components.scheme !== undefined) {
15397
- components.scheme = func(components.scheme);
15449
+ if (component.scheme !== undefined) {
15450
+ component.scheme = func(component.scheme);
15398
15451
  }
15399
- if (components.userinfo !== undefined) {
15400
- components.userinfo = func(components.userinfo);
15452
+ if (component.userinfo !== undefined) {
15453
+ component.userinfo = func(component.userinfo);
15401
15454
  }
15402
- if (components.host !== undefined) {
15403
- components.host = func(components.host);
15455
+ if (component.host !== undefined) {
15456
+ component.host = func(component.host);
15404
15457
  }
15405
- if (components.path !== undefined) {
15406
- components.path = func(components.path);
15458
+ if (component.path !== undefined) {
15459
+ component.path = func(component.path);
15407
15460
  }
15408
- if (components.query !== undefined) {
15409
- components.query = func(components.query);
15461
+ if (component.query !== undefined) {
15462
+ component.query = func(component.query);
15410
15463
  }
15411
- if (components.fragment !== undefined) {
15412
- components.fragment = func(components.fragment);
15464
+ if (component.fragment !== undefined) {
15465
+ component.fragment = func(component.fragment);
15413
15466
  }
15414
- return components
15467
+ return component
15415
15468
  }
15416
15469
 
15417
- function recomposeAuthority (components) {
15470
+ /**
15471
+ * @param {import('../types/index').URIComponent} component
15472
+ * @returns {string|undefined}
15473
+ */
15474
+ function recomposeAuthority (component) {
15418
15475
  const uriTokens = [];
15419
15476
 
15420
- if (components.userinfo !== undefined) {
15421
- uriTokens.push(components.userinfo);
15477
+ if (component.userinfo !== undefined) {
15478
+ uriTokens.push(component.userinfo);
15422
15479
  uriTokens.push('@');
15423
15480
  }
15424
15481
 
15425
- if (components.host !== undefined) {
15426
- let host = unescape(components.host);
15427
- const ipV4res = normalizeIPv4(host);
15428
-
15429
- if (ipV4res.isIPV4) {
15430
- host = ipV4res.host;
15431
- } else {
15432
- const ipV6res = normalizeIPv6(ipV4res.host);
15482
+ if (component.host !== undefined) {
15483
+ let host = unescape(component.host);
15484
+ if (!isIPv4(host)) {
15485
+ const ipV6res = normalizeIPv6(host);
15433
15486
  if (ipV6res.isIPV6 === true) {
15434
15487
  host = `[${ipV6res.escapedHost}]`;
15435
15488
  } else {
15436
- host = components.host;
15489
+ host = component.host;
15437
15490
  }
15438
15491
  }
15439
15492
  uriTokens.push(host);
15440
15493
  }
15441
15494
 
15442
- if (typeof components.port === 'number' || typeof components.port === 'string') {
15495
+ if (typeof component.port === 'number' || typeof component.port === 'string') {
15443
15496
  uriTokens.push(':');
15444
- uriTokens.push(String(components.port));
15497
+ uriTokens.push(String(component.port));
15445
15498
  }
15446
15499
 
15447
15500
  return uriTokens.length ? uriTokens.join('') : undefined
15448
15501
  }
15449
15502
  utils = {
15503
+ nonSimpleDomain,
15450
15504
  recomposeAuthority,
15451
15505
  normalizeComponentEncoding,
15452
15506
  removeDotSegments,
15453
- normalizeIPv4,
15507
+ isIPv4,
15508
+ isUUID,
15454
15509
  normalizeIPv6,
15455
15510
  stringArrayToHexStripped
15456
15511
  };
@@ -15464,192 +15519,271 @@ function requireSchemes () {
15464
15519
  if (hasRequiredSchemes) return schemes;
15465
15520
  hasRequiredSchemes = 1;
15466
15521
 
15467
- const UUID_REG = /^[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}$/iu;
15522
+ const { isUUID } = requireUtils();
15468
15523
  const URN_REG = /([\da-z][\d\-a-z]{0,31}):((?:[\w!$'()*+,\-.:;=@]|%[\da-f]{2})+)/iu;
15469
15524
 
15470
- function isSecure (wsComponents) {
15471
- return typeof wsComponents.secure === 'boolean' ? wsComponents.secure : String(wsComponents.scheme).toLowerCase() === 'wss'
15525
+ const supportedSchemeNames = /** @type {const} */ (['http', 'https', 'ws',
15526
+ 'wss', 'urn', 'urn:uuid']);
15527
+
15528
+ /** @typedef {supportedSchemeNames[number]} SchemeName */
15529
+
15530
+ /**
15531
+ * @param {string} name
15532
+ * @returns {name is SchemeName}
15533
+ */
15534
+ function isValidSchemeName (name) {
15535
+ return supportedSchemeNames.indexOf(/** @type {*} */ (name)) !== -1
15536
+ }
15537
+
15538
+ /**
15539
+ * @callback SchemeFn
15540
+ * @param {import('../types/index').URIComponent} component
15541
+ * @param {import('../types/index').Options} options
15542
+ * @returns {import('../types/index').URIComponent}
15543
+ */
15544
+
15545
+ /**
15546
+ * @typedef {Object} SchemeHandler
15547
+ * @property {SchemeName} scheme - The scheme name.
15548
+ * @property {boolean} [domainHost] - Indicates if the scheme supports domain hosts.
15549
+ * @property {SchemeFn} parse - Function to parse the URI component for this scheme.
15550
+ * @property {SchemeFn} serialize - Function to serialize the URI component for this scheme.
15551
+ * @property {boolean} [skipNormalize] - Indicates if normalization should be skipped for this scheme.
15552
+ * @property {boolean} [absolutePath] - Indicates if the scheme uses absolute paths.
15553
+ * @property {boolean} [unicodeSupport] - Indicates if the scheme supports Unicode.
15554
+ */
15555
+
15556
+ /**
15557
+ * @param {import('../types/index').URIComponent} wsComponent
15558
+ * @returns {boolean}
15559
+ */
15560
+ function wsIsSecure (wsComponent) {
15561
+ if (wsComponent.secure === true) {
15562
+ return true
15563
+ } else if (wsComponent.secure === false) {
15564
+ return false
15565
+ } else if (wsComponent.scheme) {
15566
+ return (
15567
+ wsComponent.scheme.length === 3 &&
15568
+ (wsComponent.scheme[0] === 'w' || wsComponent.scheme[0] === 'W') &&
15569
+ (wsComponent.scheme[1] === 's' || wsComponent.scheme[1] === 'S') &&
15570
+ (wsComponent.scheme[2] === 's' || wsComponent.scheme[2] === 'S')
15571
+ )
15572
+ } else {
15573
+ return false
15574
+ }
15472
15575
  }
15473
15576
 
15474
- function httpParse (components) {
15475
- if (!components.host) {
15476
- components.error = components.error || 'HTTP URIs must have a host.';
15577
+ /** @type {SchemeFn} */
15578
+ function httpParse (component) {
15579
+ if (!component.host) {
15580
+ component.error = component.error || 'HTTP URIs must have a host.';
15477
15581
  }
15478
15582
 
15479
- return components
15583
+ return component
15480
15584
  }
15481
15585
 
15482
- function httpSerialize (components) {
15483
- const secure = String(components.scheme).toLowerCase() === 'https';
15586
+ /** @type {SchemeFn} */
15587
+ function httpSerialize (component) {
15588
+ const secure = String(component.scheme).toLowerCase() === 'https';
15484
15589
 
15485
15590
  // normalize the default port
15486
- if (components.port === (secure ? 443 : 80) || components.port === '') {
15487
- components.port = undefined;
15591
+ if (component.port === (secure ? 443 : 80) || component.port === '') {
15592
+ component.port = undefined;
15488
15593
  }
15489
15594
 
15490
15595
  // normalize the empty path
15491
- if (!components.path) {
15492
- components.path = '/';
15596
+ if (!component.path) {
15597
+ component.path = '/';
15493
15598
  }
15494
15599
 
15495
15600
  // NOTE: We do not parse query strings for HTTP URIs
15496
15601
  // as WWW Form Url Encoded query strings are part of the HTML4+ spec,
15497
15602
  // and not the HTTP spec.
15498
15603
 
15499
- return components
15604
+ return component
15500
15605
  }
15501
15606
 
15502
- function wsParse (wsComponents) {
15607
+ /** @type {SchemeFn} */
15608
+ function wsParse (wsComponent) {
15503
15609
  // indicate if the secure flag is set
15504
- wsComponents.secure = isSecure(wsComponents);
15610
+ wsComponent.secure = wsIsSecure(wsComponent);
15505
15611
 
15506
15612
  // construct resouce name
15507
- wsComponents.resourceName = (wsComponents.path || '/') + (wsComponents.query ? '?' + wsComponents.query : '');
15508
- wsComponents.path = undefined;
15509
- wsComponents.query = undefined;
15613
+ wsComponent.resourceName = (wsComponent.path || '/') + (wsComponent.query ? '?' + wsComponent.query : '');
15614
+ wsComponent.path = undefined;
15615
+ wsComponent.query = undefined;
15510
15616
 
15511
- return wsComponents
15617
+ return wsComponent
15512
15618
  }
15513
15619
 
15514
- function wsSerialize (wsComponents) {
15620
+ /** @type {SchemeFn} */
15621
+ function wsSerialize (wsComponent) {
15515
15622
  // normalize the default port
15516
- if (wsComponents.port === (isSecure(wsComponents) ? 443 : 80) || wsComponents.port === '') {
15517
- wsComponents.port = undefined;
15623
+ if (wsComponent.port === (wsIsSecure(wsComponent) ? 443 : 80) || wsComponent.port === '') {
15624
+ wsComponent.port = undefined;
15518
15625
  }
15519
15626
 
15520
15627
  // ensure scheme matches secure flag
15521
- if (typeof wsComponents.secure === 'boolean') {
15522
- wsComponents.scheme = (wsComponents.secure ? 'wss' : 'ws');
15523
- wsComponents.secure = undefined;
15628
+ if (typeof wsComponent.secure === 'boolean') {
15629
+ wsComponent.scheme = (wsComponent.secure ? 'wss' : 'ws');
15630
+ wsComponent.secure = undefined;
15524
15631
  }
15525
15632
 
15526
15633
  // reconstruct path from resource name
15527
- if (wsComponents.resourceName) {
15528
- const [path, query] = wsComponents.resourceName.split('?');
15529
- wsComponents.path = (path && path !== '/' ? path : undefined);
15530
- wsComponents.query = query;
15531
- wsComponents.resourceName = undefined;
15634
+ if (wsComponent.resourceName) {
15635
+ const [path, query] = wsComponent.resourceName.split('?');
15636
+ wsComponent.path = (path && path !== '/' ? path : undefined);
15637
+ wsComponent.query = query;
15638
+ wsComponent.resourceName = undefined;
15532
15639
  }
15533
15640
 
15534
15641
  // forbid fragment component
15535
- wsComponents.fragment = undefined;
15642
+ wsComponent.fragment = undefined;
15536
15643
 
15537
- return wsComponents
15644
+ return wsComponent
15538
15645
  }
15539
15646
 
15540
- function urnParse (urnComponents, options) {
15541
- if (!urnComponents.path) {
15542
- urnComponents.error = 'URN can not be parsed';
15543
- return urnComponents
15647
+ /** @type {SchemeFn} */
15648
+ function urnParse (urnComponent, options) {
15649
+ if (!urnComponent.path) {
15650
+ urnComponent.error = 'URN can not be parsed';
15651
+ return urnComponent
15544
15652
  }
15545
- const matches = urnComponents.path.match(URN_REG);
15653
+ const matches = urnComponent.path.match(URN_REG);
15546
15654
  if (matches) {
15547
- const scheme = options.scheme || urnComponents.scheme || 'urn';
15548
- urnComponents.nid = matches[1].toLowerCase();
15549
- urnComponents.nss = matches[2];
15550
- const urnScheme = `${scheme}:${options.nid || urnComponents.nid}`;
15551
- const schemeHandler = SCHEMES[urnScheme];
15552
- urnComponents.path = undefined;
15655
+ const scheme = options.scheme || urnComponent.scheme || 'urn';
15656
+ urnComponent.nid = matches[1].toLowerCase();
15657
+ urnComponent.nss = matches[2];
15658
+ const urnScheme = `${scheme}:${options.nid || urnComponent.nid}`;
15659
+ const schemeHandler = getSchemeHandler(urnScheme);
15660
+ urnComponent.path = undefined;
15553
15661
 
15554
15662
  if (schemeHandler) {
15555
- urnComponents = schemeHandler.parse(urnComponents, options);
15663
+ urnComponent = schemeHandler.parse(urnComponent, options);
15556
15664
  }
15557
15665
  } else {
15558
- urnComponents.error = urnComponents.error || 'URN can not be parsed.';
15666
+ urnComponent.error = urnComponent.error || 'URN can not be parsed.';
15559
15667
  }
15560
15668
 
15561
- return urnComponents
15669
+ return urnComponent
15562
15670
  }
15563
15671
 
15564
- function urnSerialize (urnComponents, options) {
15565
- const scheme = options.scheme || urnComponents.scheme || 'urn';
15566
- const nid = urnComponents.nid.toLowerCase();
15672
+ /** @type {SchemeFn} */
15673
+ function urnSerialize (urnComponent, options) {
15674
+ if (urnComponent.nid === undefined) {
15675
+ throw new Error('URN without nid cannot be serialized')
15676
+ }
15677
+ const scheme = options.scheme || urnComponent.scheme || 'urn';
15678
+ const nid = urnComponent.nid.toLowerCase();
15567
15679
  const urnScheme = `${scheme}:${options.nid || nid}`;
15568
- const schemeHandler = SCHEMES[urnScheme];
15680
+ const schemeHandler = getSchemeHandler(urnScheme);
15569
15681
 
15570
15682
  if (schemeHandler) {
15571
- urnComponents = schemeHandler.serialize(urnComponents, options);
15683
+ urnComponent = schemeHandler.serialize(urnComponent, options);
15572
15684
  }
15573
15685
 
15574
- const uriComponents = urnComponents;
15575
- const nss = urnComponents.nss;
15576
- uriComponents.path = `${nid || options.nid}:${nss}`;
15686
+ const uriComponent = urnComponent;
15687
+ const nss = urnComponent.nss;
15688
+ uriComponent.path = `${nid || options.nid}:${nss}`;
15577
15689
 
15578
15690
  options.skipEscape = true;
15579
- return uriComponents
15691
+ return uriComponent
15580
15692
  }
15581
15693
 
15582
- function urnuuidParse (urnComponents, options) {
15583
- const uuidComponents = urnComponents;
15584
- uuidComponents.uuid = uuidComponents.nss;
15585
- uuidComponents.nss = undefined;
15694
+ /** @type {SchemeFn} */
15695
+ function urnuuidParse (urnComponent, options) {
15696
+ const uuidComponent = urnComponent;
15697
+ uuidComponent.uuid = uuidComponent.nss;
15698
+ uuidComponent.nss = undefined;
15586
15699
 
15587
- if (!options.tolerant && (!uuidComponents.uuid || !UUID_REG.test(uuidComponents.uuid))) {
15588
- uuidComponents.error = uuidComponents.error || 'UUID is not valid.';
15700
+ if (!options.tolerant && (!uuidComponent.uuid || !isUUID(uuidComponent.uuid))) {
15701
+ uuidComponent.error = uuidComponent.error || 'UUID is not valid.';
15589
15702
  }
15590
15703
 
15591
- return uuidComponents
15704
+ return uuidComponent
15592
15705
  }
15593
15706
 
15594
- function urnuuidSerialize (uuidComponents) {
15595
- const urnComponents = uuidComponents;
15707
+ /** @type {SchemeFn} */
15708
+ function urnuuidSerialize (uuidComponent) {
15709
+ const urnComponent = uuidComponent;
15596
15710
  // normalize UUID
15597
- urnComponents.nss = (uuidComponents.uuid || '').toLowerCase();
15598
- return urnComponents
15711
+ urnComponent.nss = (uuidComponent.uuid || '').toLowerCase();
15712
+ return urnComponent
15599
15713
  }
15600
15714
 
15601
- const http = {
15715
+ const http = /** @type {SchemeHandler} */ ({
15602
15716
  scheme: 'http',
15603
15717
  domainHost: true,
15604
15718
  parse: httpParse,
15605
15719
  serialize: httpSerialize
15606
- };
15720
+ });
15607
15721
 
15608
- const https = {
15722
+ const https = /** @type {SchemeHandler} */ ({
15609
15723
  scheme: 'https',
15610
15724
  domainHost: http.domainHost,
15611
15725
  parse: httpParse,
15612
15726
  serialize: httpSerialize
15613
- };
15727
+ });
15614
15728
 
15615
- const ws = {
15729
+ const ws = /** @type {SchemeHandler} */ ({
15616
15730
  scheme: 'ws',
15617
15731
  domainHost: true,
15618
15732
  parse: wsParse,
15619
15733
  serialize: wsSerialize
15620
- };
15734
+ });
15621
15735
 
15622
- const wss = {
15736
+ const wss = /** @type {SchemeHandler} */ ({
15623
15737
  scheme: 'wss',
15624
15738
  domainHost: ws.domainHost,
15625
15739
  parse: ws.parse,
15626
15740
  serialize: ws.serialize
15627
- };
15741
+ });
15628
15742
 
15629
- const urn = {
15743
+ const urn = /** @type {SchemeHandler} */ ({
15630
15744
  scheme: 'urn',
15631
15745
  parse: urnParse,
15632
15746
  serialize: urnSerialize,
15633
15747
  skipNormalize: true
15634
- };
15748
+ });
15635
15749
 
15636
- const urnuuid = {
15750
+ const urnuuid = /** @type {SchemeHandler} */ ({
15637
15751
  scheme: 'urn:uuid',
15638
15752
  parse: urnuuidParse,
15639
15753
  serialize: urnuuidSerialize,
15640
15754
  skipNormalize: true
15641
- };
15755
+ });
15642
15756
 
15643
- const SCHEMES = {
15757
+ const SCHEMES = /** @type {Record<SchemeName, SchemeHandler>} */ ({
15644
15758
  http,
15645
15759
  https,
15646
15760
  ws,
15647
15761
  wss,
15648
15762
  urn,
15649
15763
  'urn:uuid': urnuuid
15650
- };
15764
+ });
15765
+
15766
+ Object.setPrototypeOf(SCHEMES, null);
15767
+
15768
+ /**
15769
+ * @param {string|undefined} scheme
15770
+ * @returns {SchemeHandler|undefined}
15771
+ */
15772
+ function getSchemeHandler (scheme) {
15773
+ return (
15774
+ scheme && (
15775
+ SCHEMES[/** @type {SchemeName} */ (scheme)] ||
15776
+ SCHEMES[/** @type {SchemeName} */(scheme.toLowerCase())])
15777
+ ) ||
15778
+ undefined
15779
+ }
15651
15780
 
15652
- schemes = SCHEMES;
15781
+ schemes = {
15782
+ wsIsSecure,
15783
+ SCHEMES,
15784
+ isValidSchemeName,
15785
+ getSchemeHandler,
15786
+ };
15653
15787
  return schemes;
15654
15788
  }
15655
15789
 
@@ -15659,29 +15793,50 @@ function requireFastUri () {
15659
15793
  if (hasRequiredFastUri) return fastUri.exports;
15660
15794
  hasRequiredFastUri = 1;
15661
15795
 
15662
- const { normalizeIPv6, normalizeIPv4, removeDotSegments, recomposeAuthority, normalizeComponentEncoding } = requireUtils();
15663
- const SCHEMES = requireSchemes();
15796
+ const { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizeComponentEncoding, isIPv4, nonSimpleDomain } = requireUtils();
15797
+ const { SCHEMES, getSchemeHandler } = requireSchemes();
15664
15798
 
15799
+ /**
15800
+ * @template {import('./types/index').URIComponent|string} T
15801
+ * @param {T} uri
15802
+ * @param {import('./types/index').Options} [options]
15803
+ * @returns {T}
15804
+ */
15665
15805
  function normalize (uri, options) {
15666
15806
  if (typeof uri === 'string') {
15667
- uri = serialize(parse(uri, options), options);
15807
+ uri = /** @type {T} */ (serialize(parse(uri, options), options));
15668
15808
  } else if (typeof uri === 'object') {
15669
- uri = parse(serialize(uri, options), options);
15809
+ uri = /** @type {T} */ (parse(serialize(uri, options), options));
15670
15810
  }
15671
15811
  return uri
15672
15812
  }
15673
15813
 
15814
+ /**
15815
+ * @param {string} baseURI
15816
+ * @param {string} relativeURI
15817
+ * @param {import('./types/index').Options} [options]
15818
+ * @returns {string}
15819
+ */
15674
15820
  function resolve (baseURI, relativeURI, options) {
15675
- const schemelessOptions = Object.assign({ scheme: 'null' }, options);
15676
- const resolved = resolveComponents(parse(baseURI, schemelessOptions), parse(relativeURI, schemelessOptions), schemelessOptions, true);
15677
- return serialize(resolved, { ...schemelessOptions, skipEscape: true })
15821
+ const schemelessOptions = options ? Object.assign({ scheme: 'null' }, options) : { scheme: 'null' };
15822
+ const resolved = resolveComponent(parse(baseURI, schemelessOptions), parse(relativeURI, schemelessOptions), schemelessOptions, true);
15823
+ schemelessOptions.skipEscape = true;
15824
+ return serialize(resolved, schemelessOptions)
15678
15825
  }
15679
15826
 
15680
- function resolveComponents (base, relative, options, skipNormalization) {
15827
+ /**
15828
+ * @param {import ('./types/index').URIComponent} base
15829
+ * @param {import ('./types/index').URIComponent} relative
15830
+ * @param {import('./types/index').Options} [options]
15831
+ * @param {boolean} [skipNormalization=false]
15832
+ * @returns {import ('./types/index').URIComponent}
15833
+ */
15834
+ function resolveComponent (base, relative, options, skipNormalization) {
15835
+ /** @type {import('./types/index').URIComponent} */
15681
15836
  const target = {};
15682
15837
  if (!skipNormalization) {
15683
- base = parse(serialize(base, options), options); // normalize base components
15684
- relative = parse(serialize(relative, options), options); // normalize relative components
15838
+ base = parse(serialize(base, options), options); // normalize base component
15839
+ relative = parse(serialize(relative, options), options); // normalize relative component
15685
15840
  }
15686
15841
  options = options || {};
15687
15842
 
@@ -15710,7 +15865,7 @@ function requireFastUri () {
15710
15865
  target.query = base.query;
15711
15866
  }
15712
15867
  } else {
15713
- if (relative.path.charAt(0) === '/') {
15868
+ if (relative.path[0] === '/') {
15714
15869
  target.path = removeDotSegments(relative.path);
15715
15870
  } else {
15716
15871
  if ((base.userinfo !== undefined || base.host !== undefined || base.port !== undefined) && !base.path) {
@@ -15737,6 +15892,12 @@ function requireFastUri () {
15737
15892
  return target
15738
15893
  }
15739
15894
 
15895
+ /**
15896
+ * @param {import ('./types/index').URIComponent|string} uriA
15897
+ * @param {import ('./types/index').URIComponent|string} uriB
15898
+ * @param {import ('./types/index').Options} options
15899
+ * @returns {boolean}
15900
+ */
15740
15901
  function equal (uriA, uriB, options) {
15741
15902
  if (typeof uriA === 'string') {
15742
15903
  uriA = unescape(uriA);
@@ -15755,8 +15916,13 @@ function requireFastUri () {
15755
15916
  return uriA.toLowerCase() === uriB.toLowerCase()
15756
15917
  }
15757
15918
 
15919
+ /**
15920
+ * @param {Readonly<import('./types/index').URIComponent>} cmpts
15921
+ * @param {import('./types/index').Options} [opts]
15922
+ * @returns {string}
15923
+ */
15758
15924
  function serialize (cmpts, opts) {
15759
- const components = {
15925
+ const component = {
15760
15926
  host: cmpts.host,
15761
15927
  scheme: cmpts.scheme,
15762
15928
  userinfo: cmpts.userinfo,
@@ -15776,28 +15942,28 @@ function requireFastUri () {
15776
15942
  const uriTokens = [];
15777
15943
 
15778
15944
  // find scheme handler
15779
- const schemeHandler = SCHEMES[(options.scheme || components.scheme || '').toLowerCase()];
15945
+ const schemeHandler = getSchemeHandler(options.scheme || component.scheme);
15780
15946
 
15781
15947
  // perform scheme specific serialization
15782
- if (schemeHandler && schemeHandler.serialize) schemeHandler.serialize(components, options);
15948
+ if (schemeHandler && schemeHandler.serialize) schemeHandler.serialize(component, options);
15783
15949
 
15784
- if (components.path !== undefined) {
15950
+ if (component.path !== undefined) {
15785
15951
  if (!options.skipEscape) {
15786
- components.path = escape(components.path);
15952
+ component.path = escape(component.path);
15787
15953
 
15788
- if (components.scheme !== undefined) {
15789
- components.path = components.path.split('%3A').join(':');
15954
+ if (component.scheme !== undefined) {
15955
+ component.path = component.path.split('%3A').join(':');
15790
15956
  }
15791
15957
  } else {
15792
- components.path = unescape(components.path);
15958
+ component.path = unescape(component.path);
15793
15959
  }
15794
15960
  }
15795
15961
 
15796
- if (options.reference !== 'suffix' && components.scheme) {
15797
- uriTokens.push(components.scheme, ':');
15962
+ if (options.reference !== 'suffix' && component.scheme) {
15963
+ uriTokens.push(component.scheme, ':');
15798
15964
  }
15799
15965
 
15800
- const authority = recomposeAuthority(components);
15966
+ const authority = recomposeAuthority(component);
15801
15967
  if (authority !== undefined) {
15802
15968
  if (options.reference !== 'suffix') {
15803
15969
  uriTokens.push('//');
@@ -15805,51 +15971,49 @@ function requireFastUri () {
15805
15971
 
15806
15972
  uriTokens.push(authority);
15807
15973
 
15808
- if (components.path && components.path.charAt(0) !== '/') {
15974
+ if (component.path && component.path[0] !== '/') {
15809
15975
  uriTokens.push('/');
15810
15976
  }
15811
15977
  }
15812
- if (components.path !== undefined) {
15813
- let s = components.path;
15978
+ if (component.path !== undefined) {
15979
+ let s = component.path;
15814
15980
 
15815
15981
  if (!options.absolutePath && (!schemeHandler || !schemeHandler.absolutePath)) {
15816
15982
  s = removeDotSegments(s);
15817
15983
  }
15818
15984
 
15819
- if (authority === undefined) {
15820
- s = s.replace(/^\/\//u, '/%2F'); // don't allow the path to start with "//"
15985
+ if (
15986
+ authority === undefined &&
15987
+ s[0] === '/' &&
15988
+ s[1] === '/'
15989
+ ) {
15990
+ // don't allow the path to start with "//"
15991
+ s = '/%2F' + s.slice(2);
15821
15992
  }
15822
15993
 
15823
15994
  uriTokens.push(s);
15824
15995
  }
15825
15996
 
15826
- if (components.query !== undefined) {
15827
- uriTokens.push('?', components.query);
15997
+ if (component.query !== undefined) {
15998
+ uriTokens.push('?', component.query);
15828
15999
  }
15829
16000
 
15830
- if (components.fragment !== undefined) {
15831
- uriTokens.push('#', components.fragment);
16001
+ if (component.fragment !== undefined) {
16002
+ uriTokens.push('#', component.fragment);
15832
16003
  }
15833
16004
  return uriTokens.join('')
15834
16005
  }
15835
16006
 
15836
- const hexLookUp = Array.from({ length: 127 }, (_v, k) => /[^!"$&'()*+,\-.;=_`a-z{}~]/u.test(String.fromCharCode(k)));
15837
-
15838
- function nonSimpleDomain (value) {
15839
- let code = 0;
15840
- for (let i = 0, len = value.length; i < len; ++i) {
15841
- code = value.charCodeAt(i);
15842
- if (code > 126 || hexLookUp[code]) {
15843
- return true
15844
- }
15845
- }
15846
- return false
15847
- }
15848
-
15849
16007
  const URI_PARSE = /^(?:([^#/:?]+):)?(?:\/\/((?:([^#/?@]*)@)?(\[[^#/?\]]+\]|[^#/:?]*)(?::(\d*))?))?([^#?]*)(?:\?([^#]*))?(?:#((?:.|[\n\r])*))?/u;
15850
16008
 
16009
+ /**
16010
+ * @param {string} uri
16011
+ * @param {import('./types/index').Options} [opts]
16012
+ * @returns
16013
+ */
15851
16014
  function parse (uri, opts) {
15852
16015
  const options = Object.assign({}, opts);
16016
+ /** @type {import('./types/index').URIComponent} */
15853
16017
  const parsed = {
15854
16018
  scheme: undefined,
15855
16019
  userinfo: undefined,
@@ -15859,9 +16023,15 @@ function requireFastUri () {
15859
16023
  query: undefined,
15860
16024
  fragment: undefined
15861
16025
  };
15862
- const gotEncoding = uri.indexOf('%') !== -1;
16026
+
15863
16027
  let isIP = false;
15864
- if (options.reference === 'suffix') uri = (options.scheme ? options.scheme + ':' : '') + '//' + uri;
16028
+ if (options.reference === 'suffix') {
16029
+ if (options.scheme) {
16030
+ uri = options.scheme + ':' + uri;
16031
+ } else {
16032
+ uri = '//' + uri;
16033
+ }
16034
+ }
15865
16035
 
15866
16036
  const matches = uri.match(URI_PARSE);
15867
16037
 
@@ -15880,13 +16050,12 @@ function requireFastUri () {
15880
16050
  parsed.port = matches[5];
15881
16051
  }
15882
16052
  if (parsed.host) {
15883
- const ipv4result = normalizeIPv4(parsed.host);
15884
- if (ipv4result.isIPV4 === false) {
15885
- const ipv6result = normalizeIPv6(ipv4result.host);
16053
+ const ipv4result = isIPv4(parsed.host);
16054
+ if (ipv4result === false) {
16055
+ const ipv6result = normalizeIPv6(parsed.host);
15886
16056
  parsed.host = ipv6result.host.toLowerCase();
15887
16057
  isIP = ipv6result.isIPV6;
15888
16058
  } else {
15889
- parsed.host = ipv4result.host;
15890
16059
  isIP = true;
15891
16060
  }
15892
16061
  }
@@ -15906,7 +16075,7 @@ function requireFastUri () {
15906
16075
  }
15907
16076
 
15908
16077
  // find scheme handler
15909
- const schemeHandler = SCHEMES[(options.scheme || parsed.scheme || '').toLowerCase()];
16078
+ const schemeHandler = getSchemeHandler(options.scheme || parsed.scheme);
15910
16079
 
15911
16080
  // check if scheme can't handle IRIs
15912
16081
  if (!options.unicodeSupport && (!schemeHandler || !schemeHandler.unicodeSupport)) {
@@ -15923,11 +16092,13 @@ function requireFastUri () {
15923
16092
  }
15924
16093
 
15925
16094
  if (!schemeHandler || (schemeHandler && !schemeHandler.skipNormalize)) {
15926
- if (gotEncoding && parsed.scheme !== undefined) {
15927
- parsed.scheme = unescape(parsed.scheme);
15928
- }
15929
- if (gotEncoding && parsed.host !== undefined) {
15930
- parsed.host = unescape(parsed.host);
16095
+ if (uri.indexOf('%') !== -1) {
16096
+ if (parsed.scheme !== undefined) {
16097
+ parsed.scheme = unescape(parsed.scheme);
16098
+ }
16099
+ if (parsed.host !== undefined) {
16100
+ parsed.host = unescape(parsed.host);
16101
+ }
15931
16102
  }
15932
16103
  if (parsed.path) {
15933
16104
  parsed.path = escape(unescape(parsed.path));
@@ -15951,7 +16122,7 @@ function requireFastUri () {
15951
16122
  SCHEMES,
15952
16123
  normalize,
15953
16124
  resolve,
15954
- resolveComponents,
16125
+ resolveComponent,
15955
16126
  equal,
15956
16127
  serialize,
15957
16128
  parse