@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.cjs CHANGED
@@ -3914,8 +3914,23 @@ const splitPath = (path) => {
3914
3914
  }
3915
3915
  return path;
3916
3916
  };
3917
- const dereferenceOas = (schema, oas) => (schema.$ref ? get$1(oas, splitPath(schema.$ref)) : schema);
3918
- const dereferenceDoc = (schema, doc) => schema.$ref ? get$1(doc, splitPath(schema.$ref)) : schema;
3917
+ const followRefChain = (schema, doc, seen = new Set()) => {
3918
+ if (!schema.$ref)
3919
+ return { value: schema, ref: undefined };
3920
+ if (seen.has(schema.$ref))
3921
+ return { value: undefined, ref: undefined };
3922
+ const resolved = get$1(doc, splitPath(schema.$ref));
3923
+ if (resolved !== null && typeof resolved === "object" && "$ref" in resolved) {
3924
+ const next = followRefChain(resolved, doc, new Set([...seen, schema.$ref]));
3925
+ return next.value !== undefined
3926
+ ? { value: next.value, ref: next.ref ?? schema.$ref }
3927
+ : next;
3928
+ }
3929
+ return { value: resolved, ref: schema.$ref };
3930
+ };
3931
+ const dereferenceOas = (schema, oas) => (followRefChain(schema, oas).value ?? schema);
3932
+ const dereferenceDoc = (schema, doc) => followRefChain(schema, doc).value;
3933
+ const lastRefInChain = (schema, doc) => followRefChain(schema, doc).ref;
3919
3934
  const traverse = (schema, visitor) => {
3920
3935
  if (typeof schema === "boolean" || schema === undefined) {
3921
3936
  return;
@@ -3999,7 +4014,8 @@ function* iterateMessageList(messages, inlinePathBase, cache, doc) {
3999
4014
  const message = dereferenceDoc(ref, doc);
4000
4015
  if (!message)
4001
4016
  continue;
4002
- const path = "[root]." + ref.$ref.replace(/^#\//, "").replace(/\//g, ".");
4017
+ const finalRef = lastRefInChain(ref, doc) ?? ref.$ref;
4018
+ const path = "[root]." + finalRef.replace(/^#\//, "").replace(/\//g, ".");
4003
4019
  const result = { message, path };
4004
4020
  cache.set(ref.$ref, result);
4005
4021
  yield result;
@@ -4512,12 +4528,13 @@ function checkAsyncapiPreamble(asyncapi, interaction, index, interactionKind) {
4512
4528
  },
4513
4529
  };
4514
4530
  }
4531
+ const interactionKindTitleCase = `${interactionKind.charAt(0).toUpperCase()}${interactionKind.slice(1)}`;
4515
4532
  if (!interaction.asyncapiReferences) {
4516
4533
  return {
4517
4534
  ok: false,
4518
4535
  result: {
4519
4536
  code: "message.references.missing",
4520
- message: `${interactionKind.charAt(0).toUpperCase()}${interactionKind.slice(1)} interaction has no AsyncAPI references in comments.references.AsyncAPI`,
4537
+ message: `${interactionKindTitleCase} interaction has no AsyncAPI references in comments.references.AsyncAPI`,
4521
4538
  mockDetails: {
4522
4539
  ...baseMockDetails(interaction),
4523
4540
  location: `[root].interactions[${index}].comments.references.AsyncAPI`,
@@ -4529,6 +4546,22 @@ function checkAsyncapiPreamble(asyncapi, interaction, index, interactionKind) {
4529
4546
  };
4530
4547
  }
4531
4548
  const { operationId } = interaction.asyncapiReferences;
4549
+ if (!operationId) {
4550
+ return {
4551
+ ok: false,
4552
+ result: {
4553
+ code: "message.references.missing",
4554
+ message: `${interactionKindTitleCase} interaction has a malformed AsyncAPI reference in comments.references.AsyncAPI: expected an "operationId" property`,
4555
+ mockDetails: {
4556
+ ...baseMockDetails(interaction),
4557
+ location: `[root].interactions[${index}].comments.references.AsyncAPI`,
4558
+ value: interaction.asyncapiReferences,
4559
+ },
4560
+ specDetails: { location: "[root]", value: undefined },
4561
+ type: "error",
4562
+ },
4563
+ };
4564
+ }
4532
4565
  if (!asyncapi.operations?.[operationId]) {
4533
4566
  return {
4534
4567
  ok: false,
@@ -6825,7 +6858,10 @@ function requireSideChannel () {
6825
6858
  var channel = {
6826
6859
  assert: function (key) {
6827
6860
  if (!channel.has(key)) {
6828
- throw new $TypeError('Side channel does not contain ' + inspect(key));
6861
+ var keyDesc = key && Object(key) === key
6862
+ ? 'the given object key'
6863
+ : inspect(key);
6864
+ throw new $TypeError('Side channel does not contain ' + keyDesc);
6829
6865
  }
6830
6866
  },
6831
6867
  'delete': function (key) {
@@ -6845,7 +6881,7 @@ function requireSideChannel () {
6845
6881
  $channelData.set(key, value);
6846
6882
  }
6847
6883
  };
6848
- // @ts-expect-error TODO: figure out why this is erroring
6884
+
6849
6885
  return channel;
6850
6886
  };
6851
6887
  return sideChannel;
@@ -6891,6 +6927,7 @@ function requireUtils$1 () {
6891
6927
 
6892
6928
  var formats = /*@__PURE__*/ requireFormats$1();
6893
6929
  var getSideChannel = requireSideChannel();
6930
+ var defineProperty = /*@__PURE__*/ requireEsDefineProperty();
6894
6931
 
6895
6932
  var has = Object.prototype.hasOwnProperty;
6896
6933
  var isArray = Array.isArray;
@@ -6955,6 +6992,19 @@ function requireUtils$1 () {
6955
6992
  return obj;
6956
6993
  };
6957
6994
 
6995
+ var setProperty = function setProperty(obj, key, value) {
6996
+ if (key === '__proto__' && defineProperty) {
6997
+ defineProperty(obj, key, {
6998
+ configurable: true,
6999
+ enumerable: true,
7000
+ value: value,
7001
+ writable: true
7002
+ });
7003
+ } else {
7004
+ obj[key] = value;
7005
+ }
7006
+ };
7007
+
6958
7008
  var merge = function merge(target, source, options) {
6959
7009
  /* eslint no-param-reassign: 0 */
6960
7010
  if (!source) {
@@ -6964,7 +7014,10 @@ function requireUtils$1 () {
6964
7014
  if (typeof source !== 'object' && typeof source !== 'function') {
6965
7015
  if (isArray(target)) {
6966
7016
  var nextIndex = target.length;
6967
- if (options && typeof options.arrayLimit === 'number' && nextIndex > options.arrayLimit) {
7017
+ if (options && typeof options.arrayLimit === 'number' && nextIndex >= options.arrayLimit) {
7018
+ if (options.throwOnLimitExceeded) {
7019
+ throw new RangeError('Array limit exceeded. Only ' + options.arrayLimit + ' element' + (options.arrayLimit === 1 ? '' : 's') + ' allowed in an array.');
7020
+ }
6968
7021
  return markOverflow(arrayToObject(target.concat(source), options), nextIndex);
6969
7022
  }
6970
7023
  target[nextIndex] = source;
@@ -7004,6 +7057,9 @@ function requireUtils$1 () {
7004
7057
  }
7005
7058
  var combined = [target].concat(source);
7006
7059
  if (options && typeof options.arrayLimit === 'number' && combined.length > options.arrayLimit) {
7060
+ if (options.throwOnLimitExceeded) {
7061
+ throw new RangeError('Array limit exceeded. Only ' + options.arrayLimit + ' element' + (options.arrayLimit === 1 ? '' : 's') + ' allowed in an array.');
7062
+ }
7007
7063
  return markOverflow(arrayToObject(combined, options), combined.length - 1);
7008
7064
  }
7009
7065
  return combined;
@@ -7027,6 +7083,12 @@ function requireUtils$1 () {
7027
7083
  target[i] = item;
7028
7084
  }
7029
7085
  });
7086
+ if (options && typeof options.arrayLimit === 'number' && target.length > options.arrayLimit) {
7087
+ if (options.throwOnLimitExceeded) {
7088
+ throw new RangeError('Array limit exceeded. Only ' + options.arrayLimit + ' element' + (options.arrayLimit === 1 ? '' : 's') + ' allowed in an array.');
7089
+ }
7090
+ return markOverflow(arrayToObject(target, options), target.length - 1);
7091
+ }
7030
7092
  return target;
7031
7093
  }
7032
7094
 
@@ -7034,9 +7096,9 @@ function requireUtils$1 () {
7034
7096
  var value = source[key];
7035
7097
 
7036
7098
  if (has.call(acc, key)) {
7037
- acc[key] = merge(acc[key], value, options);
7099
+ setProperty(acc, key, merge(acc[key], value, options));
7038
7100
  } else {
7039
- acc[key] = value;
7101
+ setProperty(acc, key, value);
7040
7102
  }
7041
7103
 
7042
7104
  if (isOverflow(source) && !isOverflow(acc)) {
@@ -7055,7 +7117,7 @@ function requireUtils$1 () {
7055
7117
 
7056
7118
  var assign = function assignSingleSource(target, source) {
7057
7119
  return Object.keys(source).reduce(function (acc, key) {
7058
- acc[key] = source[key];
7120
+ setProperty(acc, key, source[key]);
7059
7121
  return acc;
7060
7122
  }, target);
7061
7123
  };
@@ -7101,6 +7163,13 @@ function requireUtils$1 () {
7101
7163
  var out = '';
7102
7164
  for (var j = 0; j < string.length; j += limit) {
7103
7165
  var segment = string.length >= limit ? string.slice(j, j + limit) : string;
7166
+ if (j + limit < string.length) {
7167
+ var last = segment.charCodeAt(segment.length - 1);
7168
+ if (last >= 0xD800 && last <= 0xDBFF) {
7169
+ segment = segment.slice(0, -1);
7170
+ j -= 1;
7171
+ }
7172
+ }
7104
7173
  var arr = [];
7105
7174
 
7106
7175
  for (var i = 0; i < segment.length; ++i) {
@@ -7154,7 +7223,7 @@ function requireUtils$1 () {
7154
7223
 
7155
7224
  var compact = function compact(value) {
7156
7225
  var queue = [{ obj: { o: value }, prop: 'o' }];
7157
- var refs = [];
7226
+ var refs = getSideChannel();
7158
7227
 
7159
7228
  for (var i = 0; i < queue.length; ++i) {
7160
7229
  var item = queue[i];
@@ -7164,9 +7233,9 @@ function requireUtils$1 () {
7164
7233
  for (var j = 0; j < keys.length; ++j) {
7165
7234
  var key = keys[j];
7166
7235
  var val = obj[key];
7167
- if (typeof val === 'object' && val !== null && refs.indexOf(val) === -1) {
7236
+ if (typeof val === 'object' && val !== null && !refs.has(val)) {
7168
7237
  queue[queue.length] = { obj: obj, prop: key };
7169
- refs[refs.length] = val;
7238
+ refs.set(val, true);
7170
7239
  }
7171
7240
  }
7172
7241
  }
@@ -7188,9 +7257,12 @@ function requireUtils$1 () {
7188
7257
  return !!(obj.constructor && obj.constructor.isBuffer && obj.constructor.isBuffer(obj));
7189
7258
  };
7190
7259
 
7191
- var combine = function combine(a, b, arrayLimit, plainObjects) {
7260
+ var combine = function combine(a, b, arrayLimit, plainObjects, throwOnLimitExceeded) {
7192
7261
  // If 'a' is already an overflow object, add to it
7193
7262
  if (isOverflow(a)) {
7263
+ if (throwOnLimitExceeded) {
7264
+ throw new RangeError('Array limit exceeded. Only ' + arrayLimit + ' element' + (arrayLimit === 1 ? '' : 's') + ' allowed in an array.');
7265
+ }
7194
7266
  var newIndex = getMaxIndex(a) + 1;
7195
7267
  a[newIndex] = b;
7196
7268
  setMaxIndex(a, newIndex);
@@ -7199,6 +7271,9 @@ function requireUtils$1 () {
7199
7271
 
7200
7272
  var result = [].concat(a, b);
7201
7273
  if (result.length > arrayLimit) {
7274
+ if (throwOnLimitExceeded) {
7275
+ throw new RangeError('Array limit exceeded. Only ' + arrayLimit + ' element' + (arrayLimit === 1 ? '' : 's') + ' allowed in an array.');
7276
+ }
7202
7277
  return markOverflow(arrayToObject(result, { plainObjects: plainObjects }), result.length - 1);
7203
7278
  }
7204
7279
  return result;
@@ -7646,8 +7721,19 @@ function requireParse$1 () {
7646
7721
  });
7647
7722
  };
7648
7723
 
7649
- var parseArrayValue = function (val, options, currentArrayLength) {
7724
+ var parseArrayValue = function (val, options, currentArrayLength, isFlatArrayValue) {
7650
7725
  if (val && typeof val === 'string' && options.comma && val.indexOf(',') > -1) {
7726
+ if (isFlatArrayValue && options.throwOnLimitExceeded) {
7727
+ var commaCount = 0;
7728
+ var commaIndex = val.indexOf(',');
7729
+ while (commaIndex > -1) {
7730
+ commaCount += 1;
7731
+ if (commaCount >= options.arrayLimit) {
7732
+ throw new RangeError('Array limit exceeded. Only ' + options.arrayLimit + ' element' + (options.arrayLimit === 1 ? '' : 's') + ' allowed in an array.');
7733
+ }
7734
+ commaIndex = val.indexOf(',', commaIndex + 1);
7735
+ }
7736
+ }
7651
7737
  return val.split(',');
7652
7738
  }
7653
7739
 
@@ -7724,7 +7810,8 @@ function requireParse$1 () {
7724
7810
  parseArrayValue(
7725
7811
  part.slice(pos + 1),
7726
7812
  options,
7727
- isArray(obj[key]) ? obj[key].length : 0
7813
+ isArray(obj[key]) ? obj[key].length : 0,
7814
+ part.indexOf('[]=') === -1
7728
7815
  ),
7729
7816
  function (encodedVal) {
7730
7817
  return options.decoder(encodedVal, defaults.decoder, charset, 'value');
@@ -7742,10 +7829,7 @@ function requireParse$1 () {
7742
7829
  }
7743
7830
 
7744
7831
  if (options.comma && isArray(val) && val.length > options.arrayLimit) {
7745
- if (options.throwOnLimitExceeded) {
7746
- throw new RangeError('Array limit exceeded. Only ' + options.arrayLimit + ' element' + (options.arrayLimit === 1 ? '' : 's') + ' allowed in an array.');
7747
- }
7748
- val = utils.combine([], val, options.arrayLimit, options.plainObjects);
7832
+ val = utils.combine([], val, options.arrayLimit, options.plainObjects, options.throwOnLimitExceeded);
7749
7833
  }
7750
7834
 
7751
7835
  if (key !== null) {
@@ -7755,7 +7839,8 @@ function requireParse$1 () {
7755
7839
  obj[key],
7756
7840
  val,
7757
7841
  options.arrayLimit,
7758
- options.plainObjects
7842
+ options.plainObjects,
7843
+ options.throwOnLimitExceeded
7759
7844
  );
7760
7845
  } else if (!existing || options.duplicates === 'last') {
7761
7846
  obj[key] = val;
@@ -7790,7 +7875,8 @@ function requireParse$1 () {
7790
7875
  [],
7791
7876
  leaf,
7792
7877
  options.arrayLimit,
7793
- options.plainObjects
7878
+ options.plainObjects,
7879
+ options.throwOnLimitExceeded
7794
7880
  );
7795
7881
  }
7796
7882
  } else {
@@ -8195,7 +8281,8 @@ function* compareReqHeader(ajv, route, interaction, index, config) {
8195
8281
  Object.entries(operation.responses).reduce((acc, [_status, response]) => {
8196
8282
  return [
8197
8283
  ...acc,
8198
- ...Object.keys(dereferenceOas(response || {}, oas)?.content || {}),
8284
+ ...Object.keys(dereferenceOas(response || {}, oas)
8285
+ ?.content || {}),
8199
8286
  ];
8200
8287
  }, []);
8201
8288
  const availableResponseContentType = operation.produces ||
@@ -17254,7 +17341,7 @@ function requireFastUri () {
17254
17341
  if (parsed.host && (options.domainHost || (schemeHandler && schemeHandler.domainHost)) && isIP === false && nonSimpleDomain(parsed.host)) {
17255
17342
  // convert Unicode IDN -> ASCII IDN
17256
17343
  try {
17257
- parsed.host = URL.domainToASCII(parsed.host.toLowerCase());
17344
+ parsed.host = new URL('http://' + parsed.host).hostname;
17258
17345
  } catch (e) {
17259
17346
  parsed.error = parsed.error || "Host's domain name can not be converted to ASCII: " + e;
17260
17347
  }
@@ -20414,9 +20501,7 @@ const AsyncMessage = Type.Object({
20414
20501
  metadata: Type.Optional(Type.Record(Type.String(), Type.String())),
20415
20502
  comments: Type.Optional(Type.Object({
20416
20503
  references: Type.Optional(Type.Object({
20417
- AsyncAPI: Type.Optional(Type.Object({
20418
- operationId: Type.String(),
20419
- })),
20504
+ AsyncAPI: Type.Optional(Type.Unknown()),
20420
20505
  })),
20421
20506
  })),
20422
20507
  });
@@ -20436,9 +20521,7 @@ const SyncMessage = Type.Object({
20436
20521
  response: Type.Array(SyncMessageSide),
20437
20522
  comments: Type.Optional(Type.Object({
20438
20523
  references: Type.Optional(Type.Object({
20439
- AsyncAPI: Type.Optional(Type.Object({
20440
- operationId: Type.String(),
20441
- })),
20524
+ AsyncAPI: Type.Optional(Type.Unknown()),
20442
20525
  })),
20443
20526
  })),
20444
20527
  });
@@ -20528,29 +20611,32 @@ const interactionV4 = (i) => ({
20528
20611
  headers: flattenValues(i.response?.headers),
20529
20612
  },
20530
20613
  });
20614
+ const asAsyncapiReferences = (asyncapiRef) => {
20615
+ if (!asyncapiRef)
20616
+ return undefined;
20617
+ if (typeof asyncapiRef !== "object")
20618
+ return {};
20619
+ return { ...asyncapiRef };
20620
+ };
20531
20621
  const parseAsyncInteraction = (i) => {
20532
- const asyncapiRef = i.comments?.references?.AsyncAPI;
20622
+ const asyncapiRef = asAsyncapiReferences(i.comments?.references?.AsyncAPI);
20533
20623
  return {
20534
20624
  _kind: "async",
20535
20625
  description: i.description,
20536
20626
  providerState: i.providerState,
20537
- asyncapiReferences: asyncapiRef
20538
- ? { operationId: asyncapiRef.operationId }
20539
- : undefined,
20627
+ asyncapiReferences: asyncapiRef,
20540
20628
  payload: parseAsPactV4Body(i.contents),
20541
20629
  contentType: i.contents?.contentType,
20542
20630
  metadata: i.metadata,
20543
20631
  };
20544
20632
  };
20545
20633
  const parseSyncInteraction = (i) => {
20546
- const asyncapiRef = i.comments?.references?.AsyncAPI;
20634
+ const asyncapiRef = asAsyncapiReferences(i.comments?.references?.AsyncAPI);
20547
20635
  return {
20548
20636
  _kind: "sync",
20549
20637
  description: i.description,
20550
20638
  providerState: i.providerState,
20551
- asyncapiReferences: asyncapiRef
20552
- ? { operationId: asyncapiRef.operationId }
20553
- : undefined,
20639
+ asyncapiReferences: asyncapiRef,
20554
20640
  request: {
20555
20641
  payload: parseAsPactV4Body(i.request.contents),
20556
20642
  contentType: i.request.contents?.contentType,