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