@pactflow/openapi-pact-comparator 2.2.0 → 2.3.0

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
@@ -3912,8 +3912,23 @@ const splitPath = (path) => {
3912
3912
  }
3913
3913
  return path;
3914
3914
  };
3915
- const dereferenceOas = (schema, oas) => (schema.$ref ? get$1(oas, splitPath(schema.$ref)) : schema);
3916
- const dereferenceDoc = (schema, doc) => schema.$ref ? get$1(doc, splitPath(schema.$ref)) : schema;
3915
+ const followRefChain = (schema, doc, seen = new Set()) => {
3916
+ if (!schema.$ref)
3917
+ return { value: schema, ref: undefined };
3918
+ if (seen.has(schema.$ref))
3919
+ return { value: undefined, ref: undefined };
3920
+ const resolved = get$1(doc, splitPath(schema.$ref));
3921
+ if (resolved !== null && typeof resolved === "object" && "$ref" in resolved) {
3922
+ const next = followRefChain(resolved, doc, new Set([...seen, schema.$ref]));
3923
+ return next.value !== undefined
3924
+ ? { value: next.value, ref: next.ref ?? schema.$ref }
3925
+ : next;
3926
+ }
3927
+ return { value: resolved, ref: schema.$ref };
3928
+ };
3929
+ const dereferenceOas = (schema, oas) => (followRefChain(schema, oas).value ?? schema);
3930
+ const dereferenceDoc = (schema, doc) => followRefChain(schema, doc).value;
3931
+ const lastRefInChain = (schema, doc) => followRefChain(schema, doc).ref;
3917
3932
  const traverse = (schema, visitor) => {
3918
3933
  if (typeof schema === "boolean" || schema === undefined) {
3919
3934
  return;
@@ -3997,7 +4012,8 @@ function* iterateMessageList(messages, inlinePathBase, cache, doc) {
3997
4012
  const message = dereferenceDoc(ref, doc);
3998
4013
  if (!message)
3999
4014
  continue;
4000
- const path = "[root]." + ref.$ref.replace(/^#\//, "").replace(/\//g, ".");
4015
+ const finalRef = lastRefInChain(ref, doc) ?? ref.$ref;
4016
+ const path = "[root]." + finalRef.replace(/^#\//, "").replace(/\//g, ".");
4001
4017
  const result = { message, path };
4002
4018
  cache.set(ref.$ref, result);
4003
4019
  yield result;
@@ -4510,12 +4526,13 @@ function checkAsyncapiPreamble(asyncapi, interaction, index, interactionKind) {
4510
4526
  },
4511
4527
  };
4512
4528
  }
4529
+ const interactionKindTitleCase = `${interactionKind.charAt(0).toUpperCase()}${interactionKind.slice(1)}`;
4513
4530
  if (!interaction.asyncapiReferences) {
4514
4531
  return {
4515
4532
  ok: false,
4516
4533
  result: {
4517
4534
  code: "message.references.missing",
4518
- message: `${interactionKind.charAt(0).toUpperCase()}${interactionKind.slice(1)} interaction has no AsyncAPI references in comments.references.AsyncAPI`,
4535
+ message: `${interactionKindTitleCase} interaction has no AsyncAPI references in comments.references.AsyncAPI`,
4519
4536
  mockDetails: {
4520
4537
  ...baseMockDetails(interaction),
4521
4538
  location: `[root].interactions[${index}].comments.references.AsyncAPI`,
@@ -4527,6 +4544,22 @@ function checkAsyncapiPreamble(asyncapi, interaction, index, interactionKind) {
4527
4544
  };
4528
4545
  }
4529
4546
  const { operationId } = interaction.asyncapiReferences;
4547
+ if (!operationId) {
4548
+ return {
4549
+ ok: false,
4550
+ result: {
4551
+ code: "message.references.missing",
4552
+ message: `${interactionKindTitleCase} interaction has a malformed AsyncAPI reference in comments.references.AsyncAPI: expected an "operationId" property`,
4553
+ mockDetails: {
4554
+ ...baseMockDetails(interaction),
4555
+ location: `[root].interactions[${index}].comments.references.AsyncAPI`,
4556
+ value: interaction.asyncapiReferences,
4557
+ },
4558
+ specDetails: { location: "[root]", value: undefined },
4559
+ type: "error",
4560
+ },
4561
+ };
4562
+ }
4530
4563
  if (!asyncapi.operations?.[operationId]) {
4531
4564
  return {
4532
4565
  ok: false,
@@ -6823,7 +6856,10 @@ function requireSideChannel () {
6823
6856
  var channel = {
6824
6857
  assert: function (key) {
6825
6858
  if (!channel.has(key)) {
6826
- throw new $TypeError('Side channel does not contain ' + inspect(key));
6859
+ var keyDesc = key && Object(key) === key
6860
+ ? 'the given object key'
6861
+ : inspect(key);
6862
+ throw new $TypeError('Side channel does not contain ' + keyDesc);
6827
6863
  }
6828
6864
  },
6829
6865
  'delete': function (key) {
@@ -6843,7 +6879,7 @@ function requireSideChannel () {
6843
6879
  $channelData.set(key, value);
6844
6880
  }
6845
6881
  };
6846
- // @ts-expect-error TODO: figure out why this is erroring
6882
+
6847
6883
  return channel;
6848
6884
  };
6849
6885
  return sideChannel;
@@ -6889,6 +6925,7 @@ function requireUtils$1 () {
6889
6925
 
6890
6926
  var formats = /*@__PURE__*/ requireFormats$1();
6891
6927
  var getSideChannel = requireSideChannel();
6928
+ var defineProperty = /*@__PURE__*/ requireEsDefineProperty();
6892
6929
 
6893
6930
  var has = Object.prototype.hasOwnProperty;
6894
6931
  var isArray = Array.isArray;
@@ -6953,6 +6990,19 @@ function requireUtils$1 () {
6953
6990
  return obj;
6954
6991
  };
6955
6992
 
6993
+ var setProperty = function setProperty(obj, key, value) {
6994
+ if (key === '__proto__' && defineProperty) {
6995
+ defineProperty(obj, key, {
6996
+ configurable: true,
6997
+ enumerable: true,
6998
+ value: value,
6999
+ writable: true
7000
+ });
7001
+ } else {
7002
+ obj[key] = value;
7003
+ }
7004
+ };
7005
+
6956
7006
  var merge = function merge(target, source, options) {
6957
7007
  /* eslint no-param-reassign: 0 */
6958
7008
  if (!source) {
@@ -6962,7 +7012,10 @@ function requireUtils$1 () {
6962
7012
  if (typeof source !== 'object' && typeof source !== 'function') {
6963
7013
  if (isArray(target)) {
6964
7014
  var nextIndex = target.length;
6965
- if (options && typeof options.arrayLimit === 'number' && nextIndex > options.arrayLimit) {
7015
+ if (options && typeof options.arrayLimit === 'number' && nextIndex >= options.arrayLimit) {
7016
+ if (options.throwOnLimitExceeded) {
7017
+ throw new RangeError('Array limit exceeded. Only ' + options.arrayLimit + ' element' + (options.arrayLimit === 1 ? '' : 's') + ' allowed in an array.');
7018
+ }
6966
7019
  return markOverflow(arrayToObject(target.concat(source), options), nextIndex);
6967
7020
  }
6968
7021
  target[nextIndex] = source;
@@ -7002,6 +7055,9 @@ function requireUtils$1 () {
7002
7055
  }
7003
7056
  var combined = [target].concat(source);
7004
7057
  if (options && typeof options.arrayLimit === 'number' && combined.length > options.arrayLimit) {
7058
+ if (options.throwOnLimitExceeded) {
7059
+ throw new RangeError('Array limit exceeded. Only ' + options.arrayLimit + ' element' + (options.arrayLimit === 1 ? '' : 's') + ' allowed in an array.');
7060
+ }
7005
7061
  return markOverflow(arrayToObject(combined, options), combined.length - 1);
7006
7062
  }
7007
7063
  return combined;
@@ -7025,6 +7081,12 @@ function requireUtils$1 () {
7025
7081
  target[i] = item;
7026
7082
  }
7027
7083
  });
7084
+ if (options && typeof options.arrayLimit === 'number' && target.length > options.arrayLimit) {
7085
+ if (options.throwOnLimitExceeded) {
7086
+ throw new RangeError('Array limit exceeded. Only ' + options.arrayLimit + ' element' + (options.arrayLimit === 1 ? '' : 's') + ' allowed in an array.');
7087
+ }
7088
+ return markOverflow(arrayToObject(target, options), target.length - 1);
7089
+ }
7028
7090
  return target;
7029
7091
  }
7030
7092
 
@@ -7032,9 +7094,9 @@ function requireUtils$1 () {
7032
7094
  var value = source[key];
7033
7095
 
7034
7096
  if (has.call(acc, key)) {
7035
- acc[key] = merge(acc[key], value, options);
7097
+ setProperty(acc, key, merge(acc[key], value, options));
7036
7098
  } else {
7037
- acc[key] = value;
7099
+ setProperty(acc, key, value);
7038
7100
  }
7039
7101
 
7040
7102
  if (isOverflow(source) && !isOverflow(acc)) {
@@ -7053,7 +7115,7 @@ function requireUtils$1 () {
7053
7115
 
7054
7116
  var assign = function assignSingleSource(target, source) {
7055
7117
  return Object.keys(source).reduce(function (acc, key) {
7056
- acc[key] = source[key];
7118
+ setProperty(acc, key, source[key]);
7057
7119
  return acc;
7058
7120
  }, target);
7059
7121
  };
@@ -7099,6 +7161,13 @@ function requireUtils$1 () {
7099
7161
  var out = '';
7100
7162
  for (var j = 0; j < string.length; j += limit) {
7101
7163
  var segment = string.length >= limit ? string.slice(j, j + limit) : string;
7164
+ if (j + limit < string.length) {
7165
+ var last = segment.charCodeAt(segment.length - 1);
7166
+ if (last >= 0xD800 && last <= 0xDBFF) {
7167
+ segment = segment.slice(0, -1);
7168
+ j -= 1;
7169
+ }
7170
+ }
7102
7171
  var arr = [];
7103
7172
 
7104
7173
  for (var i = 0; i < segment.length; ++i) {
@@ -7152,7 +7221,7 @@ function requireUtils$1 () {
7152
7221
 
7153
7222
  var compact = function compact(value) {
7154
7223
  var queue = [{ obj: { o: value }, prop: 'o' }];
7155
- var refs = [];
7224
+ var refs = getSideChannel();
7156
7225
 
7157
7226
  for (var i = 0; i < queue.length; ++i) {
7158
7227
  var item = queue[i];
@@ -7162,9 +7231,9 @@ function requireUtils$1 () {
7162
7231
  for (var j = 0; j < keys.length; ++j) {
7163
7232
  var key = keys[j];
7164
7233
  var val = obj[key];
7165
- if (typeof val === 'object' && val !== null && refs.indexOf(val) === -1) {
7234
+ if (typeof val === 'object' && val !== null && !refs.has(val)) {
7166
7235
  queue[queue.length] = { obj: obj, prop: key };
7167
- refs[refs.length] = val;
7236
+ refs.set(val, true);
7168
7237
  }
7169
7238
  }
7170
7239
  }
@@ -7186,9 +7255,12 @@ function requireUtils$1 () {
7186
7255
  return !!(obj.constructor && obj.constructor.isBuffer && obj.constructor.isBuffer(obj));
7187
7256
  };
7188
7257
 
7189
- var combine = function combine(a, b, arrayLimit, plainObjects) {
7258
+ var combine = function combine(a, b, arrayLimit, plainObjects, throwOnLimitExceeded) {
7190
7259
  // If 'a' is already an overflow object, add to it
7191
7260
  if (isOverflow(a)) {
7261
+ if (throwOnLimitExceeded) {
7262
+ throw new RangeError('Array limit exceeded. Only ' + arrayLimit + ' element' + (arrayLimit === 1 ? '' : 's') + ' allowed in an array.');
7263
+ }
7192
7264
  var newIndex = getMaxIndex(a) + 1;
7193
7265
  a[newIndex] = b;
7194
7266
  setMaxIndex(a, newIndex);
@@ -7197,6 +7269,9 @@ function requireUtils$1 () {
7197
7269
 
7198
7270
  var result = [].concat(a, b);
7199
7271
  if (result.length > arrayLimit) {
7272
+ if (throwOnLimitExceeded) {
7273
+ throw new RangeError('Array limit exceeded. Only ' + arrayLimit + ' element' + (arrayLimit === 1 ? '' : 's') + ' allowed in an array.');
7274
+ }
7200
7275
  return markOverflow(arrayToObject(result, { plainObjects: plainObjects }), result.length - 1);
7201
7276
  }
7202
7277
  return result;
@@ -7644,8 +7719,19 @@ function requireParse$1 () {
7644
7719
  });
7645
7720
  };
7646
7721
 
7647
- var parseArrayValue = function (val, options, currentArrayLength) {
7722
+ var parseArrayValue = function (val, options, currentArrayLength, isFlatArrayValue) {
7648
7723
  if (val && typeof val === 'string' && options.comma && val.indexOf(',') > -1) {
7724
+ if (isFlatArrayValue && options.throwOnLimitExceeded) {
7725
+ var commaCount = 0;
7726
+ var commaIndex = val.indexOf(',');
7727
+ while (commaIndex > -1) {
7728
+ commaCount += 1;
7729
+ if (commaCount >= options.arrayLimit) {
7730
+ throw new RangeError('Array limit exceeded. Only ' + options.arrayLimit + ' element' + (options.arrayLimit === 1 ? '' : 's') + ' allowed in an array.');
7731
+ }
7732
+ commaIndex = val.indexOf(',', commaIndex + 1);
7733
+ }
7734
+ }
7649
7735
  return val.split(',');
7650
7736
  }
7651
7737
 
@@ -7722,7 +7808,8 @@ function requireParse$1 () {
7722
7808
  parseArrayValue(
7723
7809
  part.slice(pos + 1),
7724
7810
  options,
7725
- isArray(obj[key]) ? obj[key].length : 0
7811
+ isArray(obj[key]) ? obj[key].length : 0,
7812
+ part.indexOf('[]=') === -1
7726
7813
  ),
7727
7814
  function (encodedVal) {
7728
7815
  return options.decoder(encodedVal, defaults.decoder, charset, 'value');
@@ -7740,10 +7827,7 @@ function requireParse$1 () {
7740
7827
  }
7741
7828
 
7742
7829
  if (options.comma && isArray(val) && val.length > options.arrayLimit) {
7743
- if (options.throwOnLimitExceeded) {
7744
- throw new RangeError('Array limit exceeded. Only ' + options.arrayLimit + ' element' + (options.arrayLimit === 1 ? '' : 's') + ' allowed in an array.');
7745
- }
7746
- val = utils.combine([], val, options.arrayLimit, options.plainObjects);
7830
+ val = utils.combine([], val, options.arrayLimit, options.plainObjects, options.throwOnLimitExceeded);
7747
7831
  }
7748
7832
 
7749
7833
  if (key !== null) {
@@ -7753,7 +7837,8 @@ function requireParse$1 () {
7753
7837
  obj[key],
7754
7838
  val,
7755
7839
  options.arrayLimit,
7756
- options.plainObjects
7840
+ options.plainObjects,
7841
+ options.throwOnLimitExceeded
7757
7842
  );
7758
7843
  } else if (!existing || options.duplicates === 'last') {
7759
7844
  obj[key] = val;
@@ -7788,7 +7873,8 @@ function requireParse$1 () {
7788
7873
  [],
7789
7874
  leaf,
7790
7875
  options.arrayLimit,
7791
- options.plainObjects
7876
+ options.plainObjects,
7877
+ options.throwOnLimitExceeded
7792
7878
  );
7793
7879
  }
7794
7880
  } else {
@@ -8193,7 +8279,8 @@ function* compareReqHeader(ajv, route, interaction, index, config) {
8193
8279
  Object.entries(operation.responses).reduce((acc, [_status, response]) => {
8194
8280
  return [
8195
8281
  ...acc,
8196
- ...Object.keys(dereferenceOas(response || {}, oas)?.content || {}),
8282
+ ...Object.keys(dereferenceOas(response || {}, oas)
8283
+ ?.content || {}),
8197
8284
  ];
8198
8285
  }, []);
8199
8286
  const availableResponseContentType = operation.produces ||
@@ -17252,7 +17339,7 @@ function requireFastUri () {
17252
17339
  if (parsed.host && (options.domainHost || (schemeHandler && schemeHandler.domainHost)) && isIP === false && nonSimpleDomain(parsed.host)) {
17253
17340
  // convert Unicode IDN -> ASCII IDN
17254
17341
  try {
17255
- parsed.host = URL.domainToASCII(parsed.host.toLowerCase());
17342
+ parsed.host = new URL('http://' + parsed.host).hostname;
17256
17343
  } catch (e) {
17257
17344
  parsed.error = parsed.error || "Host's domain name can not be converted to ASCII: " + e;
17258
17345
  }
@@ -20412,9 +20499,7 @@ const AsyncMessage = Type.Object({
20412
20499
  metadata: Type.Optional(Type.Record(Type.String(), Type.String())),
20413
20500
  comments: Type.Optional(Type.Object({
20414
20501
  references: Type.Optional(Type.Object({
20415
- AsyncAPI: Type.Optional(Type.Object({
20416
- operationId: Type.String(),
20417
- })),
20502
+ AsyncAPI: Type.Optional(Type.Unknown()),
20418
20503
  })),
20419
20504
  })),
20420
20505
  });
@@ -20434,9 +20519,7 @@ const SyncMessage = Type.Object({
20434
20519
  response: Type.Array(SyncMessageSide),
20435
20520
  comments: Type.Optional(Type.Object({
20436
20521
  references: Type.Optional(Type.Object({
20437
- AsyncAPI: Type.Optional(Type.Object({
20438
- operationId: Type.String(),
20439
- })),
20522
+ AsyncAPI: Type.Optional(Type.Unknown()),
20440
20523
  })),
20441
20524
  })),
20442
20525
  });
@@ -20526,29 +20609,32 @@ const interactionV4 = (i) => ({
20526
20609
  headers: flattenValues(i.response?.headers),
20527
20610
  },
20528
20611
  });
20612
+ const asAsyncapiReferences = (asyncapiRef) => {
20613
+ if (!asyncapiRef)
20614
+ return undefined;
20615
+ if (typeof asyncapiRef !== "object")
20616
+ return {};
20617
+ return { ...asyncapiRef };
20618
+ };
20529
20619
  const parseAsyncInteraction = (i) => {
20530
- const asyncapiRef = i.comments?.references?.AsyncAPI;
20620
+ const asyncapiRef = asAsyncapiReferences(i.comments?.references?.AsyncAPI);
20531
20621
  return {
20532
20622
  _kind: "async",
20533
20623
  description: i.description,
20534
20624
  providerState: i.providerState,
20535
- asyncapiReferences: asyncapiRef
20536
- ? { operationId: asyncapiRef.operationId }
20537
- : undefined,
20625
+ asyncapiReferences: asyncapiRef,
20538
20626
  payload: parseAsPactV4Body(i.contents),
20539
20627
  contentType: i.contents?.contentType,
20540
20628
  metadata: i.metadata,
20541
20629
  };
20542
20630
  };
20543
20631
  const parseSyncInteraction = (i) => {
20544
- const asyncapiRef = i.comments?.references?.AsyncAPI;
20632
+ const asyncapiRef = asAsyncapiReferences(i.comments?.references?.AsyncAPI);
20545
20633
  return {
20546
20634
  _kind: "sync",
20547
20635
  description: i.description,
20548
20636
  providerState: i.providerState,
20549
- asyncapiReferences: asyncapiRef
20550
- ? { operationId: asyncapiRef.operationId }
20551
- : undefined,
20637
+ asyncapiReferences: asyncapiRef,
20552
20638
  request: {
20553
20639
  payload: parseAsPactV4Body(i.request.contents),
20554
20640
  contentType: i.request.contents?.contentType,