@pactflow/openapi-pact-comparator 1.6.1 → 1.7.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
@@ -881,6 +881,18 @@ function overRest(func, start, transform) {
881
881
  };
882
882
  }
883
883
 
884
+ /**
885
+ * The base implementation of `_.rest` which doesn't validate or coerce arguments.
886
+ *
887
+ * @private
888
+ * @param {Function} func The function to apply a rest parameter to.
889
+ * @param {number} [start=func.length-1] The start position of the rest parameter.
890
+ * @returns {Function} Returns the new function.
891
+ */
892
+ function baseRest(func, start) {
893
+ return setToString(overRest(func, start, identity), func + '');
894
+ }
895
+
884
896
  /** Used as references for various `Number` constants. */
885
897
  var MAX_SAFE_INTEGER = 9007199254740991;
886
898
 
@@ -944,6 +956,63 @@ function isArrayLike(value) {
944
956
  return value != null && isLength(value.length) && !isFunction(value);
945
957
  }
946
958
 
959
+ /**
960
+ * Checks if the given arguments are from an iteratee call.
961
+ *
962
+ * @private
963
+ * @param {*} value The potential iteratee value argument.
964
+ * @param {*} index The potential iteratee index or key argument.
965
+ * @param {*} object The potential iteratee object argument.
966
+ * @returns {boolean} Returns `true` if the arguments are from an iteratee call,
967
+ * else `false`.
968
+ */
969
+ function isIterateeCall(value, index, object) {
970
+ if (!isObject(object)) {
971
+ return false;
972
+ }
973
+ var type = typeof index;
974
+ if (type == 'number'
975
+ ? (isArrayLike(object) && isIndex(index, object.length))
976
+ : (type == 'string' && index in object)
977
+ ) {
978
+ return eq(object[index], value);
979
+ }
980
+ return false;
981
+ }
982
+
983
+ /**
984
+ * Creates a function like `_.assign`.
985
+ *
986
+ * @private
987
+ * @param {Function} assigner The function to assign values.
988
+ * @returns {Function} Returns the new assigner function.
989
+ */
990
+ function createAssigner(assigner) {
991
+ return baseRest(function(object, sources) {
992
+ var index = -1,
993
+ length = sources.length,
994
+ customizer = length > 1 ? sources[length - 1] : undefined,
995
+ guard = length > 2 ? sources[2] : undefined;
996
+
997
+ customizer = (assigner.length > 3 && typeof customizer == 'function')
998
+ ? (length--, customizer)
999
+ : undefined;
1000
+
1001
+ if (guard && isIterateeCall(sources[0], sources[1], guard)) {
1002
+ customizer = length < 3 ? undefined : customizer;
1003
+ length = 1;
1004
+ }
1005
+ object = Object(object);
1006
+ while (++index < length) {
1007
+ var source = sources[index];
1008
+ if (source) {
1009
+ assigner(object, source, index, customizer);
1010
+ }
1011
+ }
1012
+ return object;
1013
+ });
1014
+ }
1015
+
947
1016
  /** Used for built-in method references. */
948
1017
  var objectProto$9 = Object.prototype;
949
1018
 
@@ -3175,6 +3244,209 @@ function createBaseEach(eachFunc, fromRight) {
3175
3244
  */
3176
3245
  var baseEach = createBaseEach(baseForOwn);
3177
3246
 
3247
+ /**
3248
+ * This function is like `assignValue` except that it doesn't assign
3249
+ * `undefined` values.
3250
+ *
3251
+ * @private
3252
+ * @param {Object} object The object to modify.
3253
+ * @param {string} key The key of the property to assign.
3254
+ * @param {*} value The value to assign.
3255
+ */
3256
+ function assignMergeValue(object, key, value) {
3257
+ if ((value !== undefined && !eq(object[key], value)) ||
3258
+ (value === undefined && !(key in object))) {
3259
+ baseAssignValue(object, key, value);
3260
+ }
3261
+ }
3262
+
3263
+ /**
3264
+ * This method is like `_.isArrayLike` except that it also checks if `value`
3265
+ * is an object.
3266
+ *
3267
+ * @static
3268
+ * @memberOf _
3269
+ * @since 4.0.0
3270
+ * @category Lang
3271
+ * @param {*} value The value to check.
3272
+ * @returns {boolean} Returns `true` if `value` is an array-like object,
3273
+ * else `false`.
3274
+ * @example
3275
+ *
3276
+ * _.isArrayLikeObject([1, 2, 3]);
3277
+ * // => true
3278
+ *
3279
+ * _.isArrayLikeObject(document.body.children);
3280
+ * // => true
3281
+ *
3282
+ * _.isArrayLikeObject('abc');
3283
+ * // => false
3284
+ *
3285
+ * _.isArrayLikeObject(_.noop);
3286
+ * // => false
3287
+ */
3288
+ function isArrayLikeObject(value) {
3289
+ return isObjectLike(value) && isArrayLike(value);
3290
+ }
3291
+
3292
+ /**
3293
+ * Gets the value at `key`, unless `key` is "__proto__" or "constructor".
3294
+ *
3295
+ * @private
3296
+ * @param {Object} object The object to query.
3297
+ * @param {string} key The key of the property to get.
3298
+ * @returns {*} Returns the property value.
3299
+ */
3300
+ function safeGet(object, key) {
3301
+ if (key === 'constructor' && typeof object[key] === 'function') {
3302
+ return;
3303
+ }
3304
+
3305
+ if (key == '__proto__') {
3306
+ return;
3307
+ }
3308
+
3309
+ return object[key];
3310
+ }
3311
+
3312
+ /**
3313
+ * Converts `value` to a plain object flattening inherited enumerable string
3314
+ * keyed properties of `value` to own properties of the plain object.
3315
+ *
3316
+ * @static
3317
+ * @memberOf _
3318
+ * @since 3.0.0
3319
+ * @category Lang
3320
+ * @param {*} value The value to convert.
3321
+ * @returns {Object} Returns the converted plain object.
3322
+ * @example
3323
+ *
3324
+ * function Foo() {
3325
+ * this.b = 2;
3326
+ * }
3327
+ *
3328
+ * Foo.prototype.c = 3;
3329
+ *
3330
+ * _.assign({ 'a': 1 }, new Foo);
3331
+ * // => { 'a': 1, 'b': 2 }
3332
+ *
3333
+ * _.assign({ 'a': 1 }, _.toPlainObject(new Foo));
3334
+ * // => { 'a': 1, 'b': 2, 'c': 3 }
3335
+ */
3336
+ function toPlainObject(value) {
3337
+ return copyObject(value, keysIn(value));
3338
+ }
3339
+
3340
+ /**
3341
+ * A specialized version of `baseMerge` for arrays and objects which performs
3342
+ * deep merges and tracks traversed objects enabling objects with circular
3343
+ * references to be merged.
3344
+ *
3345
+ * @private
3346
+ * @param {Object} object The destination object.
3347
+ * @param {Object} source The source object.
3348
+ * @param {string} key The key of the value to merge.
3349
+ * @param {number} srcIndex The index of `source`.
3350
+ * @param {Function} mergeFunc The function to merge values.
3351
+ * @param {Function} [customizer] The function to customize assigned values.
3352
+ * @param {Object} [stack] Tracks traversed source values and their merged
3353
+ * counterparts.
3354
+ */
3355
+ function baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) {
3356
+ var objValue = safeGet(object, key),
3357
+ srcValue = safeGet(source, key),
3358
+ stacked = stack.get(srcValue);
3359
+
3360
+ if (stacked) {
3361
+ assignMergeValue(object, key, stacked);
3362
+ return;
3363
+ }
3364
+ var newValue = customizer
3365
+ ? customizer(objValue, srcValue, (key + ''), object, source, stack)
3366
+ : undefined;
3367
+
3368
+ var isCommon = newValue === undefined;
3369
+
3370
+ if (isCommon) {
3371
+ var isArr = isArray(srcValue),
3372
+ isBuff = !isArr && isBuffer(srcValue),
3373
+ isTyped = !isArr && !isBuff && isTypedArray(srcValue);
3374
+
3375
+ newValue = srcValue;
3376
+ if (isArr || isBuff || isTyped) {
3377
+ if (isArray(objValue)) {
3378
+ newValue = objValue;
3379
+ }
3380
+ else if (isArrayLikeObject(objValue)) {
3381
+ newValue = copyArray(objValue);
3382
+ }
3383
+ else if (isBuff) {
3384
+ isCommon = false;
3385
+ newValue = cloneBuffer(srcValue, true);
3386
+ }
3387
+ else if (isTyped) {
3388
+ isCommon = false;
3389
+ newValue = cloneTypedArray(srcValue, true);
3390
+ }
3391
+ else {
3392
+ newValue = [];
3393
+ }
3394
+ }
3395
+ else if (isPlainObject(srcValue) || isArguments(srcValue)) {
3396
+ newValue = objValue;
3397
+ if (isArguments(objValue)) {
3398
+ newValue = toPlainObject(objValue);
3399
+ }
3400
+ else if (!isObject(objValue) || isFunction(objValue)) {
3401
+ newValue = initCloneObject(srcValue);
3402
+ }
3403
+ }
3404
+ else {
3405
+ isCommon = false;
3406
+ }
3407
+ }
3408
+ if (isCommon) {
3409
+ // Recursively merge objects and arrays (susceptible to call stack limits).
3410
+ stack.set(srcValue, newValue);
3411
+ mergeFunc(newValue, srcValue, srcIndex, customizer, stack);
3412
+ stack['delete'](srcValue);
3413
+ }
3414
+ assignMergeValue(object, key, newValue);
3415
+ }
3416
+
3417
+ /**
3418
+ * The base implementation of `_.merge` without support for multiple sources.
3419
+ *
3420
+ * @private
3421
+ * @param {Object} object The destination object.
3422
+ * @param {Object} source The source object.
3423
+ * @param {number} srcIndex The index of `source`.
3424
+ * @param {Function} [customizer] The function to customize merged values.
3425
+ * @param {Object} [stack] Tracks traversed source values and their merged
3426
+ * counterparts.
3427
+ */
3428
+ function baseMerge(object, source, srcIndex, customizer, stack) {
3429
+ if (object === source) {
3430
+ return;
3431
+ }
3432
+ baseFor(source, function(srcValue, key) {
3433
+ stack || (stack = new Stack);
3434
+ if (isObject(srcValue)) {
3435
+ baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack);
3436
+ }
3437
+ else {
3438
+ var newValue = customizer
3439
+ ? customizer(safeGet(object, key), srcValue, (key + ''), object, source, stack)
3440
+ : undefined;
3441
+
3442
+ if (newValue === undefined) {
3443
+ newValue = srcValue;
3444
+ }
3445
+ assignMergeValue(object, key, newValue);
3446
+ }
3447
+ }, keysIn);
3448
+ }
3449
+
3178
3450
  /**
3179
3451
  * This function is like `arrayIncludes` except that it accepts a comparator.
3180
3452
  *
@@ -3273,6 +3545,41 @@ function parent(object, path) {
3273
3545
  return path.length < 2 ? object : baseGet(object, baseSlice(path, 0, -1));
3274
3546
  }
3275
3547
 
3548
+ /**
3549
+ * This method is like `_.assign` except that it recursively merges own and
3550
+ * inherited enumerable string keyed properties of source objects into the
3551
+ * destination object. Source properties that resolve to `undefined` are
3552
+ * skipped if a destination value exists. Array and plain object properties
3553
+ * are merged recursively. Other objects and value types are overridden by
3554
+ * assignment. Source objects are applied from left to right. Subsequent
3555
+ * sources overwrite property assignments of previous sources.
3556
+ *
3557
+ * **Note:** This method mutates `object`.
3558
+ *
3559
+ * @static
3560
+ * @memberOf _
3561
+ * @since 0.5.0
3562
+ * @category Object
3563
+ * @param {Object} object The destination object.
3564
+ * @param {...Object} [sources] The source objects.
3565
+ * @returns {Object} Returns `object`.
3566
+ * @example
3567
+ *
3568
+ * var object = {
3569
+ * 'a': [{ 'b': 2 }, { 'd': 4 }]
3570
+ * };
3571
+ *
3572
+ * var other = {
3573
+ * 'a': [{ 'c': 3 }, { 'e': 5 }]
3574
+ * };
3575
+ *
3576
+ * _.merge(object, other);
3577
+ * // => { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] }
3578
+ */
3579
+ var merge = createAssigner(function(object, source, srcIndex) {
3580
+ baseMerge(object, source, srcIndex);
3581
+ });
3582
+
3276
3583
  /**
3277
3584
  * The base implementation of `_.unset`.
3278
3585
  *
@@ -3589,22 +3896,6 @@ const traverseWithDereferencing = (schema, visitor) => {
3589
3896
  _traverseWithDereferencing(schema, schema, [], visitor);
3590
3897
  };
3591
3898
 
3592
- const transformRequestSchema = (schema) => {
3593
- // OpenAPI defines allOf to mean the union of all sub-schemas. JSON-Schema
3594
- // defines allOf to mean that *every* sub-schema needs to be satisfied. In
3595
- // draft 2019-09, JSON-Schema added "unevaluatedProperties" to support this
3596
- // behaviour
3597
- traverseWithDereferencing(schema, (s) => {
3598
- if (s.allOf) {
3599
- forEach(s.allOf, (ss) => {
3600
- delete ss.additionalProperties;
3601
- });
3602
- s.unevaluatedProperties = false;
3603
- }
3604
- });
3605
- return schema;
3606
- };
3607
-
3608
3899
  const transformResponseSchema = (schema, noTransformNonNullableResponseSchema) => {
3609
3900
  // a provider must provide a superset of what the consumer asks for
3610
3901
  // additionalProperties expected in pact response are disallowed
@@ -3628,30 +3919,62 @@ const transformResponseSchema = (schema, noTransformNonNullableResponseSchema) =
3628
3919
  }
3629
3920
  delete s.required;
3630
3921
  });
3631
- // OpenAPI defines allOf to mean the union of all sub-schemas. JSON-Schema
3632
- // defines allOf to mean that *every* sub-schema needs to be satisfied. In
3633
- // draft 2019-09, JSON-Schema added "unevaluatedProperties" to support this
3634
- // behaviour
3635
- traverseWithDereferencing(schema, (s) => {
3636
- if (s.allOf) {
3637
- forEach(s.allOf, (ss) => {
3638
- let subschema = ss;
3639
- if (subschema.$ref) {
3640
- subschema = get$1(schema, splitPath(subschema.$ref));
3641
- }
3642
- delete subschema.additionalProperties;
3643
- if (subschema.allOf) {
3644
- // traversal is depth-first; if nested allOf, remove
3645
- // unevaluatedProperties from previously set deeper schema
3646
- delete subschema.unevaluatedProperties;
3647
- }
3648
- });
3649
- s.unevaluatedProperties = false;
3650
- }
3651
- });
3652
3922
  return schema;
3653
3923
  };
3654
3924
 
3925
+ function _flat(s, root) {
3926
+ if (s.allOf) {
3927
+ const { allOf, ...others } = s;
3928
+ return merge(others, ...allOf.map((ss) => {
3929
+ let dereferenced;
3930
+ if (ss.$ref) {
3931
+ const { $ref, ...others } = ss;
3932
+ dereferenced = {
3933
+ ...others,
3934
+ ...get$1(root, splitPath($ref)),
3935
+ };
3936
+ }
3937
+ return _flat(dereferenced || ss, root);
3938
+ }));
3939
+ }
3940
+ if (s.properties) {
3941
+ for (const ss in s.properties) {
3942
+ s.properties[ss] = _flat(s.properties[ss], root);
3943
+ }
3944
+ return s;
3945
+ }
3946
+ for (const key of [
3947
+ "oneOf",
3948
+ "anyOf",
3949
+ "not",
3950
+ "items",
3951
+ "additionalProperties",
3952
+ ]) {
3953
+ if (s[key]) {
3954
+ return {
3955
+ ...s,
3956
+ [key]: Array.isArray(s[key])
3957
+ ? s[key].map((ss) => _flat(ss, root))
3958
+ : _flat(s[key], root),
3959
+ };
3960
+ }
3961
+ }
3962
+ return s;
3963
+ }
3964
+ // OpenAPI defines allOf to mean the union of all sub-schemas. JSON-Schema
3965
+ // defines allOf to mean that *every* sub-schema needs to be satisfied.
3966
+ // To handle the difference, we flatten 'allOf'
3967
+ function flattenAllOf(s, refs) {
3968
+ // main schema
3969
+ const flattened = _flat(s, s);
3970
+ // any other references
3971
+ for (const ref of refs) {
3972
+ const path = splitPath(ref);
3973
+ set(flattened, path, _flat(get$1(s, path), s));
3974
+ }
3975
+ return flattened;
3976
+ }
3977
+
3655
3978
  // draft-06 onwards converts exclusiveMinimum and exclusiveMaximum to numbers
3656
3979
  const convertExclusiveMinMax = (s) => {
3657
3980
  if (s.exclusiveMaximum === true) {
@@ -3714,13 +4037,13 @@ const minimumSchema = (originalSchema, oas) => {
3714
4037
  const subschema = cloneDeep(get$1(oas, path, {}));
3715
4038
  delete subschema.description;
3716
4039
  delete subschema.example;
3717
- traverse(schema, cleanupDiscriminators);
4040
+ traverse(subschema, cleanupDiscriminators);
3718
4041
  traverse(subschema, collectReferences);
3719
4042
  traverse(subschema, handleNullableSchema);
3720
4043
  traverse(subschema, convertExclusiveMinMax);
3721
4044
  set(schema, path, subschema);
3722
4045
  }
3723
- return schema;
4046
+ return flattenAllOf(schema, refAdded);
3724
4047
  };
3725
4048
 
3726
4049
  const isSimpleSchema = (s, oas) => {
@@ -7334,7 +7657,7 @@ function* compareReqBody(ajv, route, interaction, index, config) {
7334
7657
  : true)) {
7335
7658
  const value = parseBody(body, requestContentType, config.get("legacy-parser"));
7336
7659
  const schemaId = `[root].paths.${path}.${method}.requestBody.content.${contentType}`;
7337
- const validate = getValidateFunction(ajv, schemaId, () => transformRequestSchema(minimumSchema(schema, oas)));
7660
+ const validate = getValidateFunction(ajv, schemaId, () => minimumSchema(schema, oas));
7338
7661
  if (!validate(value)) {
7339
7662
  for (const error of validate.errors) {
7340
7663
  yield {
@@ -19108,6 +19431,7 @@ var Ajv$1 = /*@__PURE__*/getDefaultExportFromCjs(ajvExports);
19108
19431
  // a full schema can be found at https://github.com/pactflow/pact-schemas
19109
19432
  // but we don't use that here, because we try to be permissive with input
19110
19433
  const Interaction = Type.Object({
19434
+ _skip: Type.Optional(Type.Boolean()),
19111
19435
  type: Type.Optional(Type.String()),
19112
19436
  description: Type.Optional(Type.String()),
19113
19437
  providerState: Type.Optional(Type.String()),
@@ -19236,9 +19560,9 @@ const parse = (pact) => {
19236
19560
  const interactionParser = version >= 4 ? interactionV4 : version >= 3 ? interactionV3 : interactionV1;
19237
19561
  return {
19238
19562
  metadata,
19239
- interactions: interactions
19240
- .filter(supportedInteractions)
19241
- .map(interactionParser),
19563
+ interactions: interactions.map((i) => supportedInteractions(i)
19564
+ ? interactionParser(i)
19565
+ : { _skip: true }),
19242
19566
  };
19243
19567
  };
19244
19568
  class ParserError extends Error {
@@ -24020,6 +24344,10 @@ class Comparator {
24020
24344
  }
24021
24345
  const parsedPact = parse(pact);
24022
24346
  for (const [index, interaction] of parsedPact.interactions.entries()) {
24347
+ if (interaction._skip) {
24348
+ // non http/synchronous have been zero-ed out
24349
+ continue;
24350
+ }
24023
24351
  const { method, path, query } = interaction.request;
24024
24352
  let pathWithLeadingSlash = path.startsWith("/") ? path : `/${path}`;
24025
24353
  if (this.#config.get("no-percent-encoding")) {