@squiz/dx-json-schema-lib 1.87.0 → 1.88.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.
Files changed (66) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/lib/formatted-text/v1/resolveFormattedTextNodes.d.ts +5 -2
  3. package/lib/formatted-text/v1/resolveFormattedTextNodes.js +9 -3
  4. package/lib/formatted-text/v1/resolveFormattedTextNodes.js.map +1 -1
  5. package/lib/formatted-text/v1/resolveFormattedTextNodes.spec.js +58 -0
  6. package/lib/formatted-text/v1/resolveFormattedTextNodes.spec.js.map +1 -1
  7. package/lib/index.d.ts +1 -0
  8. package/lib/index.js +1 -0
  9. package/lib/index.js.map +1 -1
  10. package/lib/utils/jsonBreakDetector/checks/findArrayConstraintNarrowing.d.ts +6 -0
  11. package/lib/utils/jsonBreakDetector/checks/findArrayConstraintNarrowing.js +93 -0
  12. package/lib/utils/jsonBreakDetector/checks/findArrayConstraintNarrowing.js.map +1 -0
  13. package/lib/utils/jsonBreakDetector/checks/findConstChanges.d.ts +6 -0
  14. package/lib/utils/jsonBreakDetector/checks/findConstChanges.js +75 -0
  15. package/lib/utils/jsonBreakDetector/checks/findConstChanges.js.map +1 -0
  16. package/lib/utils/jsonBreakDetector/checks/findEnumNarrowing.d.ts +6 -0
  17. package/lib/utils/jsonBreakDetector/checks/findEnumNarrowing.js +90 -0
  18. package/lib/utils/jsonBreakDetector/checks/findEnumNarrowing.js.map +1 -0
  19. package/lib/utils/jsonBreakDetector/checks/findFieldTypeChanges.d.ts +8 -0
  20. package/lib/utils/jsonBreakDetector/checks/findFieldTypeChanges.js +86 -0
  21. package/lib/utils/jsonBreakDetector/checks/findFieldTypeChanges.js.map +1 -0
  22. package/lib/utils/jsonBreakDetector/checks/findNewRequiredFields.d.ts +6 -0
  23. package/lib/utils/jsonBreakDetector/checks/findNewRequiredFields.js +68 -0
  24. package/lib/utils/jsonBreakDetector/checks/findNewRequiredFields.js.map +1 -0
  25. package/lib/utils/jsonBreakDetector/checks/findNumericConstraintNarrowing.d.ts +6 -0
  26. package/lib/utils/jsonBreakDetector/checks/findNumericConstraintNarrowing.js +179 -0
  27. package/lib/utils/jsonBreakDetector/checks/findNumericConstraintNarrowing.js.map +1 -0
  28. package/lib/utils/jsonBreakDetector/checks/findStringConstraintNarrowing.d.ts +6 -0
  29. package/lib/utils/jsonBreakDetector/checks/findStringConstraintNarrowing.js +106 -0
  30. package/lib/utils/jsonBreakDetector/checks/findStringConstraintNarrowing.js.map +1 -0
  31. package/lib/utils/jsonBreakDetector/compareSubschemas.d.ts +9 -0
  32. package/lib/utils/jsonBreakDetector/compareSubschemas.js +49 -0
  33. package/lib/utils/jsonBreakDetector/compareSubschemas.js.map +1 -0
  34. package/lib/utils/jsonBreakDetector/dereference/dereference.d.ts +6 -0
  35. package/lib/utils/jsonBreakDetector/dereference/dereference.js +52 -0
  36. package/lib/utils/jsonBreakDetector/dereference/dereference.js.map +1 -0
  37. package/lib/utils/jsonBreakDetector/dereference/dereference.spec.d.ts +1 -0
  38. package/lib/utils/jsonBreakDetector/dereference/dereference.spec.js +225 -0
  39. package/lib/utils/jsonBreakDetector/dereference/dereference.spec.js.map +1 -0
  40. package/lib/utils/jsonBreakDetector/jsonBreakDetector.d.ts +8 -0
  41. package/lib/utils/jsonBreakDetector/jsonBreakDetector.js +35 -0
  42. package/lib/utils/jsonBreakDetector/jsonBreakDetector.js.map +1 -0
  43. package/lib/utils/jsonBreakDetector/jsonBreakDetector.spec.d.ts +1 -0
  44. package/lib/utils/jsonBreakDetector/jsonBreakDetector.spec.js +2761 -0
  45. package/lib/utils/jsonBreakDetector/jsonBreakDetector.spec.js.map +1 -0
  46. package/lib/utils/jsonBreakDetector/types.d.ts +25 -0
  47. package/lib/utils/jsonBreakDetector/types.js +28 -0
  48. package/lib/utils/jsonBreakDetector/types.js.map +1 -0
  49. package/package.json +1 -1
  50. package/src/formatted-text/v1/resolveFormattedTextNodes.spec.ts +70 -0
  51. package/src/formatted-text/v1/resolveFormattedTextNodes.ts +18 -3
  52. package/src/index.ts +2 -0
  53. package/src/utils/jsonBreakDetector/checks/findArrayConstraintNarrowing.ts +121 -0
  54. package/src/utils/jsonBreakDetector/checks/findConstChanges.ts +97 -0
  55. package/src/utils/jsonBreakDetector/checks/findEnumNarrowing.ts +124 -0
  56. package/src/utils/jsonBreakDetector/checks/findFieldTypeChanges.ts +105 -0
  57. package/src/utils/jsonBreakDetector/checks/findNewRequiredFields.ts +97 -0
  58. package/src/utils/jsonBreakDetector/checks/findNumericConstraintNarrowing.ts +243 -0
  59. package/src/utils/jsonBreakDetector/checks/findStringConstraintNarrowing.ts +139 -0
  60. package/src/utils/jsonBreakDetector/compareSubschemas.ts +67 -0
  61. package/src/utils/jsonBreakDetector/dereference/dereference.spec.ts +245 -0
  62. package/src/utils/jsonBreakDetector/dereference/dereference.ts +65 -0
  63. package/src/utils/jsonBreakDetector/jsonBreakDetector.spec.ts +3041 -0
  64. package/src/utils/jsonBreakDetector/jsonBreakDetector.ts +36 -0
  65. package/src/utils/jsonBreakDetector/types.ts +29 -0
  66. package/tsconfig.tsbuildinfo +1 -1
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.findFieldTypeChanges = findFieldTypeChanges;
4
+ exports.hasTypeChange = hasTypeChange;
5
+ const types_1 = require("../types");
6
+ /**
7
+ * Recursively function to compare field type values at each schema level, accumulating dotted paths.
8
+ * */
9
+ function findFieldTypeChanges(beforeSchema, afterSchema, path, typeChanges) {
10
+ var _a, _b;
11
+ // Get the current schema level child properties
12
+ const beforeProperties = (_a = beforeSchema.properties) !== null && _a !== void 0 ? _a : {};
13
+ const afterProperties = (_b = afterSchema.properties) !== null && _b !== void 0 ? _b : {};
14
+ // Recurse into latest nested object properties.
15
+ for (const [key, afterPropertySchema] of Object.entries(afterProperties)) {
16
+ // Only objects have types
17
+ if (!afterPropertySchema || typeof afterPropertySchema !== 'object') {
18
+ continue;
19
+ }
20
+ const beforePropertySchema = beforeProperties[key];
21
+ const childPath = path ? `${path}.${key}` : key;
22
+ // Only compare type on fields that existed in the before schema. New fields are skipped.
23
+ if (beforePropertySchema && typeof beforePropertySchema === 'object') {
24
+ // Only compare type on fields that existed in the before schema.
25
+ if (hasTypeChange(beforePropertySchema, afterPropertySchema)) {
26
+ (0, types_1.pushBreak)(typeChanges, childPath, types_1.BREAK_MESSAGES.type);
27
+ }
28
+ // Compare `type` on this property, then recurse into its nested schema so child fields are checked too.
29
+ findFieldTypeChanges(beforePropertySchema, afterPropertySchema, childPath, typeChanges);
30
+ }
31
+ }
32
+ // If instead the current schema level is an array, get the items schema
33
+ const beforeItems = beforeSchema.items;
34
+ const afterItems = afterSchema.items;
35
+ // Recurse into latest array item schemas.
36
+ if (afterItems && typeof afterItems === 'object' && !Array.isArray(afterItems)) {
37
+ const itemsPath = path ? `${path}[]` : '[]';
38
+ const beforeItemSchema = beforeItems && typeof beforeItems === 'object' && !Array.isArray(beforeItems) ? beforeItems : undefined;
39
+ // Compare the `items` schema `type` for array fields, e.g. `tags[]` when
40
+ // `items: { type: 'string' }` becomes `items: { type: 'number' }`.
41
+ if (beforeItemSchema) {
42
+ if (hasTypeChange(beforeItemSchema, afterItems)) {
43
+ (0, types_1.pushBreak)(typeChanges, itemsPath, types_1.BREAK_MESSAGES.type);
44
+ }
45
+ findFieldTypeChanges(beforeItemSchema, afterItems, itemsPath, typeChanges);
46
+ }
47
+ }
48
+ }
49
+ function toTypeArray(type) {
50
+ return Array.isArray(type) ? type : [type];
51
+ }
52
+ /**
53
+ * Returns true when every type allowed by `beforeType` is still allowed by `afterType`.
54
+ * In JSON Schema, integer is a subset of number, so relaxing integer to number is not breaking.
55
+ */
56
+ function isBeforeTypeCoveredByAfterType(beforeType, afterType) {
57
+ const afterTypes = new Set(toTypeArray(afterType));
58
+ for (const type of toTypeArray(beforeType)) {
59
+ // Integer is a subset of number, so relaxing integer to number is not breaking.
60
+ if (type === 'integer') {
61
+ if (afterTypes.has('integer') || afterTypes.has('number')) {
62
+ continue;
63
+ }
64
+ return false;
65
+ }
66
+ if (!afterTypes.has(type)) {
67
+ return false;
68
+ }
69
+ }
70
+ return true;
71
+ }
72
+ /** Returns true when the JSON Schema `type` keyword narrows between two schemas. */
73
+ function hasTypeChange(beforeSchema, afterSchema) {
74
+ const beforeType = beforeSchema.type;
75
+ const afterType = afterSchema.type;
76
+ // If both types are undefined, there is no change.
77
+ if (beforeType === undefined && afterType === undefined) {
78
+ return false;
79
+ }
80
+ // If one type is undefined, there is a change.
81
+ if (beforeType === undefined || afterType === undefined) {
82
+ return true;
83
+ }
84
+ return !isBeforeTypeCoveredByAfterType(beforeType, afterType);
85
+ }
86
+ //# sourceMappingURL=findFieldTypeChanges.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"findFieldTypeChanges.js","sourceRoot":"","sources":["../../../../src/utils/jsonBreakDetector/checks/findFieldTypeChanges.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import { JSONSchema } from '@squiz/json-schema-library';
2
+ import { JsonBreak } from '../types';
3
+ /**
4
+ * Recursively compares required and dependentRequired fields at each schema level, accumulating dotted paths.
5
+ */
6
+ export declare function findNewRequiredFields(beforeSchema: JSONSchema, afterSchema: JSONSchema, path: string, newRequiredFields: JsonBreak[]): void;
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.findNewRequiredFields = findNewRequiredFields;
4
+ const types_1 = require("../types");
5
+ function getDependentRequired(schema) {
6
+ const dependentRequired = schema.dependentRequired;
7
+ return dependentRequired !== null && dependentRequired !== void 0 ? dependentRequired : {};
8
+ }
9
+ function findNewDependentRequiredFields(beforeSchema, afterSchema, path, newRequiredFields) {
10
+ var _a, _b;
11
+ const beforeDependentRequired = getDependentRequired(beforeSchema);
12
+ const afterDependentRequired = getDependentRequired(afterSchema);
13
+ const beforeProperties = (_a = beforeSchema.properties) !== null && _a !== void 0 ? _a : {};
14
+ for (const [triggerField, afterDependentFields] of Object.entries(afterDependentRequired)) {
15
+ if (!Array.isArray(afterDependentFields)) {
16
+ continue;
17
+ }
18
+ // Adding dependentRequired for a newly added trigger field is not a breaking change.
19
+ if (!(triggerField in beforeProperties)) {
20
+ continue;
21
+ }
22
+ const beforeDependentFields = (_b = beforeDependentRequired[triggerField]) !== null && _b !== void 0 ? _b : [];
23
+ for (const field of afterDependentFields) {
24
+ if (!beforeDependentFields.includes(field)) {
25
+ (0, types_1.pushBreak)(newRequiredFields, path ? `${path}.${field}` : field, types_1.BREAK_MESSAGES.dependentRequired);
26
+ }
27
+ }
28
+ }
29
+ }
30
+ /**
31
+ * Recursively compares required and dependentRequired fields at each schema level, accumulating dotted paths.
32
+ */
33
+ function findNewRequiredFields(beforeSchema, afterSchema, path, newRequiredFields) {
34
+ var _a, _b, _c, _d;
35
+ // Get whats required at the current schema level
36
+ const beforeRequired = (_a = beforeSchema.required) !== null && _a !== void 0 ? _a : [];
37
+ const afterRequired = (_b = afterSchema.required) !== null && _b !== void 0 ? _b : [];
38
+ // Collect fields present in afterSchema.required but not in beforeSchema.required.
39
+ for (const field of afterRequired) {
40
+ if (!beforeRequired.includes(field)) {
41
+ (0, types_1.pushBreak)(newRequiredFields, path ? `${path}.${field}` : field, types_1.BREAK_MESSAGES.required);
42
+ }
43
+ }
44
+ findNewDependentRequiredFields(beforeSchema, afterSchema, path, newRequiredFields);
45
+ // Get the current schema level child properties
46
+ const beforeProperties = (_c = beforeSchema.properties) !== null && _c !== void 0 ? _c : {};
47
+ const afterProperties = (_d = afterSchema.properties) !== null && _d !== void 0 ? _d : {};
48
+ // Recurse into latest nested object properties.
49
+ for (const [key, afterPropertySchema] of Object.entries(afterProperties)) {
50
+ // Skip if the property is not an object.
51
+ if (!afterPropertySchema || typeof afterPropertySchema !== 'object') {
52
+ continue;
53
+ }
54
+ const beforePropertySchema = beforeProperties[key];
55
+ const childPath = path ? `${path}.${key}` : key;
56
+ // Missing before property is treated as an empty schema with no required fields.
57
+ findNewRequiredFields(beforePropertySchema && typeof beforePropertySchema === 'object' ? beforePropertySchema : {}, afterPropertySchema, childPath, newRequiredFields);
58
+ }
59
+ // If instead the current schema level is an array, get the items schema
60
+ const beforeItems = beforeSchema.items;
61
+ const afterItems = afterSchema.items;
62
+ // Recurse into array item schemas (tuple items are not supported).
63
+ if (afterItems && typeof afterItems === 'object' && !Array.isArray(afterItems)) {
64
+ const itemsPath = path ? `${path}[]` : '[]';
65
+ findNewRequiredFields(beforeItems && typeof beforeItems === 'object' && !Array.isArray(beforeItems) ? beforeItems : {}, afterItems, itemsPath, newRequiredFields);
66
+ }
67
+ }
68
+ //# sourceMappingURL=findNewRequiredFields.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"findNewRequiredFields.js","sourceRoot":"","sources":["../../../../src/utils/jsonBreakDetector/checks/findNewRequiredFields.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import { JsonBreak } from '../types';
2
+ import { JSONSchema } from '@squiz/json-schema-library';
3
+ /** Recursively detects narrowed numeric constraints at each schema level, accumulating dotted paths. */
4
+ export declare function findNumericConstraintNarrowing(beforeSchema: JSONSchema, afterSchema: JSONSchema, path: string, breaks: JsonBreak[]): void;
5
+ /** Checks numeric constraint keywords on a single schema for narrowing changes. */
6
+ export declare function checkNumericConstraintNarrowing(beforeSchema: JSONSchema, afterSchema: JSONSchema, path: string, breaks: JsonBreak[]): void;
@@ -0,0 +1,179 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.findNumericConstraintNarrowing = findNumericConstraintNarrowing;
4
+ exports.checkNumericConstraintNarrowing = checkNumericConstraintNarrowing;
5
+ const types_1 = require("../types");
6
+ /** Recursively detects narrowed numeric constraints at each schema level, accumulating dotted paths. */
7
+ function findNumericConstraintNarrowing(beforeSchema, afterSchema, path, breaks) {
8
+ var _a, _b;
9
+ const beforeProperties = (_a = beforeSchema.properties) !== null && _a !== void 0 ? _a : {};
10
+ const afterProperties = (_b = afterSchema.properties) !== null && _b !== void 0 ? _b : {};
11
+ // Recurse into latest nested object properties.
12
+ for (const [key, afterPropertySchema] of Object.entries(afterProperties)) {
13
+ if (!afterPropertySchema || typeof afterPropertySchema !== 'object') {
14
+ continue;
15
+ }
16
+ const beforePropertySchema = beforeProperties[key];
17
+ const childPath = path ? `${path}.${key}` : key;
18
+ // Only compare numeric constraints on fields that existed in the before schema. New fields are skipped.
19
+ if (beforePropertySchema && typeof beforePropertySchema === 'object') {
20
+ checkNumericConstraintNarrowing(beforePropertySchema, afterPropertySchema, childPath, breaks);
21
+ findNumericConstraintNarrowing(beforePropertySchema, afterPropertySchema, childPath, breaks);
22
+ }
23
+ }
24
+ const beforeItems = beforeSchema.items;
25
+ const afterItems = afterSchema.items;
26
+ // Recurse into latest nested array items.
27
+ if (afterItems && typeof afterItems === 'object' && !Array.isArray(afterItems)) {
28
+ const itemsPath = path ? `${path}[]` : '[]';
29
+ const beforeItemSchema = beforeItems && typeof beforeItems === 'object' && !Array.isArray(beforeItems) ? beforeItems : undefined;
30
+ // Only compare numeric constraints on items that existed in the before schema. New items are skipped.
31
+ if (beforeItemSchema) {
32
+ checkNumericConstraintNarrowing(beforeItemSchema, afterItems, itemsPath, breaks);
33
+ findNumericConstraintNarrowing(beforeItemSchema, afterItems, itemsPath, breaks);
34
+ }
35
+ }
36
+ }
37
+ /** Returns true when a schema represents a numeric field. */
38
+ function isNumericFieldSchema(schema) {
39
+ const type = schema.type;
40
+ if (type === 'number' || type === 'integer') {
41
+ return true;
42
+ }
43
+ // Type can be defined as a union of strings e.g. ['number', 'integer'], so check if 'number' or 'integer' is included.
44
+ if (Array.isArray(type) && (type.includes('number') || type.includes('integer'))) {
45
+ return true;
46
+ }
47
+ return (schema.minimum !== undefined ||
48
+ schema.exclusiveMinimum !== undefined ||
49
+ schema.maximum !== undefined ||
50
+ schema.exclusiveMaximum !== undefined ||
51
+ schema.multipleOf !== undefined);
52
+ }
53
+ /** Returns the strictest lower bound from `minimum` and `exclusiveMinimum`, which may both be set. */
54
+ function getEffectiveLowerBound(schema) {
55
+ const minimum = schema.minimum;
56
+ const exclusiveMinimum = schema.exclusiveMinimum;
57
+ // Both are defined, need to figure out which is lower
58
+ if (minimum !== undefined && exclusiveMinimum !== undefined) {
59
+ // min 5 is same as exclusiveMinimum 6 (x >= minimum and x > exclusiveMinimum)
60
+ // so if they are the same exclusiveMinimum is the effective lower bound
61
+ if (minimum > exclusiveMinimum) {
62
+ return { value: minimum, keyword: 'minimum' };
63
+ }
64
+ return { value: exclusiveMinimum, keyword: 'exclusiveMinimum' };
65
+ }
66
+ if (minimum !== undefined) {
67
+ return { value: minimum, keyword: 'minimum' };
68
+ }
69
+ if (exclusiveMinimum !== undefined) {
70
+ return { value: exclusiveMinimum, keyword: 'exclusiveMinimum' };
71
+ }
72
+ return undefined;
73
+ }
74
+ /** Returns the strictest upper bound from `maximum` and `exclusiveMaximum`, which may both be set. */
75
+ function getEffectiveUpperBound(schema) {
76
+ const maximum = schema.maximum;
77
+ const exclusiveMaximum = schema.exclusiveMaximum;
78
+ if (maximum !== undefined && exclusiveMaximum !== undefined) {
79
+ // max 4 is same as exclusiveMaximum 5 (x <= maximum and x < exclusiveMaximum)
80
+ // so if they are the same exclusiveMaximum is the effective upper bound
81
+ if (maximum < exclusiveMaximum) {
82
+ return { value: maximum, keyword: 'maximum' };
83
+ }
84
+ return { value: exclusiveMaximum, keyword: 'exclusiveMaximum' };
85
+ }
86
+ if (maximum !== undefined) {
87
+ return { value: maximum, keyword: 'maximum' };
88
+ }
89
+ if (exclusiveMaximum !== undefined) {
90
+ return { value: exclusiveMaximum, keyword: 'exclusiveMaximum' };
91
+ }
92
+ return undefined;
93
+ }
94
+ /** Returns true when afterSchema requires a stricter lower bound than beforeSchema. */
95
+ function hasLowerBoundIncreased(beforeSchema, afterSchema) {
96
+ const beforeBound = getEffectiveLowerBound(beforeSchema);
97
+ const afterBound = getEffectiveLowerBound(afterSchema);
98
+ if (afterBound === undefined) {
99
+ return false;
100
+ }
101
+ if (beforeBound === undefined) {
102
+ return true;
103
+ }
104
+ if (afterBound.value > beforeBound.value) {
105
+ return true;
106
+ }
107
+ if (afterBound.value < beforeBound.value) {
108
+ return false;
109
+ }
110
+ // Same effective value, but inclusive vs exclusive still differs (e.g. minimum: 5 allows 5, exclusiveMinimum: 5 does not).
111
+ return afterBound.keyword === 'exclusiveMinimum' && beforeBound.keyword === 'minimum';
112
+ }
113
+ /** Returns true when afterSchema allows a stricter upper bound than beforeSchema. */
114
+ function hasUpperBoundLowered(beforeSchema, afterSchema) {
115
+ const beforeBound = getEffectiveUpperBound(beforeSchema);
116
+ const afterBound = getEffectiveUpperBound(afterSchema);
117
+ if (afterBound === undefined) {
118
+ return false;
119
+ }
120
+ if (beforeBound === undefined) {
121
+ return true;
122
+ }
123
+ if (afterBound.value < beforeBound.value) {
124
+ return true;
125
+ }
126
+ if (afterBound.value > beforeBound.value) {
127
+ return false;
128
+ }
129
+ // Same effective value, but inclusive vs exclusive still differs (e.g. maximum: 10 allows 10, exclusiveMaximum: 10 does not).
130
+ return afterBound.keyword === 'exclusiveMaximum' && beforeBound.keyword === 'maximum';
131
+ }
132
+ /** Picks the break message for the keyword that supplies the effective lower bound in the after schema. */
133
+ function getLowerBoundBreakMessage(_beforeSchema, afterSchema) {
134
+ const afterBound = getEffectiveLowerBound(afterSchema);
135
+ return (afterBound === null || afterBound === void 0 ? void 0 : afterBound.keyword) === 'exclusiveMinimum' ? types_1.BREAK_MESSAGES.exclusiveMinimum : types_1.BREAK_MESSAGES.minimum;
136
+ }
137
+ /** Picks the break message for the keyword that supplies the effective upper bound in the after schema. */
138
+ function getUpperBoundBreakMessage(_beforeSchema, afterSchema) {
139
+ const afterBound = getEffectiveUpperBound(afterSchema);
140
+ return (afterBound === null || afterBound === void 0 ? void 0 : afterBound.keyword) === 'exclusiveMaximum' ? types_1.BREAK_MESSAGES.exclusiveMaximum : types_1.BREAK_MESSAGES.maximum;
141
+ }
142
+ /**
143
+ * Returns true when afterSchema narrows the set of allowed multiples.
144
+ * A value valid under the before `multipleOf` may be invalid under the after `multipleOf`
145
+ * unless the before factor is itself a multiple of the after factor.
146
+ */
147
+ function hasMultipleOfNarrowed(beforeSchema, afterSchema) {
148
+ const afterMultipleOf = afterSchema.multipleOf;
149
+ const beforeMultipleOf = beforeSchema.multipleOf;
150
+ if (afterMultipleOf === undefined) {
151
+ return false;
152
+ }
153
+ if (beforeMultipleOf === undefined) {
154
+ return true;
155
+ }
156
+ if (beforeMultipleOf === afterMultipleOf) {
157
+ return false;
158
+ }
159
+ // Check if the constraint is strictly narrowed
160
+ // e.g. from 4 to 2 is ok as previous valid entries will still be valid
161
+ // but from 4 to 3 is not
162
+ return beforeMultipleOf % afterMultipleOf !== 0;
163
+ }
164
+ /** Checks numeric constraint keywords on a single schema for narrowing changes. */
165
+ function checkNumericConstraintNarrowing(beforeSchema, afterSchema, path, breaks) {
166
+ if (!isNumericFieldSchema(beforeSchema) && !isNumericFieldSchema(afterSchema)) {
167
+ return;
168
+ }
169
+ if (hasLowerBoundIncreased(beforeSchema, afterSchema)) {
170
+ (0, types_1.pushBreak)(breaks, path, getLowerBoundBreakMessage(beforeSchema, afterSchema));
171
+ }
172
+ if (hasUpperBoundLowered(beforeSchema, afterSchema)) {
173
+ (0, types_1.pushBreak)(breaks, path, getUpperBoundBreakMessage(beforeSchema, afterSchema));
174
+ }
175
+ if (hasMultipleOfNarrowed(beforeSchema, afterSchema)) {
176
+ (0, types_1.pushBreak)(breaks, path, types_1.BREAK_MESSAGES.multipleOf);
177
+ }
178
+ }
179
+ //# sourceMappingURL=findNumericConstraintNarrowing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"findNumericConstraintNarrowing.js","sourceRoot":"","sources":["../../../../src/utils/jsonBreakDetector/checks/findNumericConstraintNarrowing.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import { JsonBreak } from '../types';
2
+ import { JSONSchema } from '@squiz/json-schema-library';
3
+ /** Recursively detects narrowed string constraints at each schema level, accumulating dotted paths. */
4
+ export declare function findStringConstraintNarrowing(beforeSchema: JSONSchema, afterSchema: JSONSchema, path: string, breaks: JsonBreak[]): void;
5
+ /** Checks string constraint keywords on a single schema for narrowing changes. */
6
+ export declare function checkStringConstraintNarrowing(beforeSchema: JSONSchema, afterSchema: JSONSchema, path: string, breaks: JsonBreak[]): void;
@@ -0,0 +1,106 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.findStringConstraintNarrowing = findStringConstraintNarrowing;
4
+ exports.checkStringConstraintNarrowing = checkStringConstraintNarrowing;
5
+ const types_1 = require("../types");
6
+ /** Recursively detects narrowed string constraints at each schema level, accumulating dotted paths. */
7
+ function findStringConstraintNarrowing(beforeSchema, afterSchema, path, breaks) {
8
+ var _a, _b;
9
+ const beforeProperties = (_a = beforeSchema.properties) !== null && _a !== void 0 ? _a : {};
10
+ const afterProperties = (_b = afterSchema.properties) !== null && _b !== void 0 ? _b : {};
11
+ // Recurse into latest nested object properties.
12
+ for (const [key, afterPropertySchema] of Object.entries(afterProperties)) {
13
+ // Skip if the property is not an object.
14
+ if (!afterPropertySchema || typeof afterPropertySchema !== 'object') {
15
+ continue;
16
+ }
17
+ const beforePropertySchema = beforeProperties[key];
18
+ const childPath = path ? `${path}.${key}` : key;
19
+ // Only compare string constraints on fields that existed in the before schema. New fields are skipped.
20
+ if (beforePropertySchema && typeof beforePropertySchema === 'object') {
21
+ checkStringConstraintNarrowing(beforePropertySchema, afterPropertySchema, childPath, breaks);
22
+ findStringConstraintNarrowing(beforePropertySchema, afterPropertySchema, childPath, breaks);
23
+ }
24
+ }
25
+ const beforeItems = beforeSchema.items;
26
+ const afterItems = afterSchema.items;
27
+ // Recurse into latest nested array items.
28
+ if (afterItems && typeof afterItems === 'object' && !Array.isArray(afterItems)) {
29
+ const itemsPath = path ? `${path}[]` : '[]';
30
+ const beforeItemSchema = beforeItems && typeof beforeItems === 'object' && !Array.isArray(beforeItems) ? beforeItems : undefined;
31
+ // Only compare string constraints on items that existed in the before schema. New items are skipped.
32
+ if (beforeItemSchema) {
33
+ checkStringConstraintNarrowing(beforeItemSchema, afterItems, itemsPath, breaks);
34
+ findStringConstraintNarrowing(beforeItemSchema, afterItems, itemsPath, breaks);
35
+ }
36
+ }
37
+ }
38
+ /** Returns true when a schema represents a string field. */
39
+ function isStringFieldSchema(schema) {
40
+ const type = schema.type;
41
+ if (type === 'string') {
42
+ return true;
43
+ }
44
+ // Type can be defined as a union of strings e.g. ['string', 'number'], so check if 'string' is included.
45
+ if (Array.isArray(type) && type.includes('string')) {
46
+ return true;
47
+ }
48
+ return (schema.minLength !== undefined ||
49
+ schema.maxLength !== undefined ||
50
+ schema.format !== undefined ||
51
+ schema.pattern !== undefined);
52
+ }
53
+ /** Returns true when afterSchema requires a longer string than beforeSchema. */
54
+ function hasMinLengthIncreased(beforeSchema, afterSchema) {
55
+ var _a, _b;
56
+ const beforeMinLength = (_a = beforeSchema.minLength) !== null && _a !== void 0 ? _a : 0;
57
+ const afterMinLength = (_b = afterSchema.minLength) !== null && _b !== void 0 ? _b : 0;
58
+ return afterMinLength > beforeMinLength;
59
+ }
60
+ /** Returns true when afterSchema allows a shorter string than beforeSchema. */
61
+ function hasMaxLengthLowered(beforeSchema, afterSchema) {
62
+ const beforeMaxLength = beforeSchema.maxLength;
63
+ const afterMaxLength = afterSchema.maxLength;
64
+ if (afterMaxLength === undefined) {
65
+ return false;
66
+ }
67
+ if (beforeMaxLength === undefined) {
68
+ return true;
69
+ }
70
+ return afterMaxLength < beforeMaxLength;
71
+ }
72
+ /** Returns true when afterSchema adds or changes a format constraint. */
73
+ function hasFormatChanged(beforeSchema, afterSchema) {
74
+ const afterFormat = afterSchema.format;
75
+ if (afterFormat === undefined) {
76
+ return false;
77
+ }
78
+ return beforeSchema.format !== afterFormat;
79
+ }
80
+ /** Returns true when afterSchema adds or changes a pattern constraint. */
81
+ function hasPatternChanged(beforeSchema, afterSchema) {
82
+ const afterPattern = afterSchema.pattern;
83
+ if (afterPattern === undefined) {
84
+ return false;
85
+ }
86
+ return beforeSchema.pattern !== afterPattern;
87
+ }
88
+ /** Checks string constraint keywords on a single schema for narrowing changes. */
89
+ function checkStringConstraintNarrowing(beforeSchema, afterSchema, path, breaks) {
90
+ if (!isStringFieldSchema(beforeSchema) && !isStringFieldSchema(afterSchema)) {
91
+ return;
92
+ }
93
+ if (hasMinLengthIncreased(beforeSchema, afterSchema)) {
94
+ (0, types_1.pushBreak)(breaks, path, types_1.BREAK_MESSAGES.minLength);
95
+ }
96
+ if (hasMaxLengthLowered(beforeSchema, afterSchema)) {
97
+ (0, types_1.pushBreak)(breaks, path, types_1.BREAK_MESSAGES.maxLength);
98
+ }
99
+ if (hasFormatChanged(beforeSchema, afterSchema)) {
100
+ (0, types_1.pushBreak)(breaks, path, types_1.BREAK_MESSAGES.format);
101
+ }
102
+ if (hasPatternChanged(beforeSchema, afterSchema)) {
103
+ (0, types_1.pushBreak)(breaks, path, types_1.BREAK_MESSAGES.pattern);
104
+ }
105
+ }
106
+ //# sourceMappingURL=findStringConstraintNarrowing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"findStringConstraintNarrowing.js","sourceRoot":"","sources":["../../../../src/utils/jsonBreakDetector/checks/findStringConstraintNarrowing.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { JSONSchema } from '@squiz/json-schema-library';
2
+ import { JsonBreak } from './types';
3
+ /**
4
+ * Compares two schemas at the same path using every jsonBreakDetector check,
5
+ * including leaf-level constraints on the current node.
6
+ */
7
+ export declare function compareSubschemas(beforeSchema: JSONSchema, afterSchema: JSONSchema, path: string, breaks: JsonBreak[]): void;
8
+ /** Compares array `contains` subschemas using the full jsonBreakDetector check suite. */
9
+ export declare function compareContainsSubschemas(beforeArraySchema: JSONSchema, afterArraySchema: JSONSchema, arrayPath: string, breaks: JsonBreak[]): void;
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.compareSubschemas = compareSubschemas;
4
+ exports.compareContainsSubschemas = compareContainsSubschemas;
5
+ const findArrayConstraintNarrowing_1 = require("./checks/findArrayConstraintNarrowing");
6
+ const findConstChanges_1 = require("./checks/findConstChanges");
7
+ const findFieldTypeChanges_1 = require("./checks/findFieldTypeChanges");
8
+ const findNewRequiredFields_1 = require("./checks/findNewRequiredFields");
9
+ const findNumericConstraintNarrowing_1 = require("./checks/findNumericConstraintNarrowing");
10
+ const findEnumNarrowing_1 = require("./checks/findEnumNarrowing");
11
+ const findStringConstraintNarrowing_1 = require("./checks/findStringConstraintNarrowing");
12
+ const types_1 = require("./types");
13
+ /**
14
+ * Compares two schemas at the same path using every jsonBreakDetector check,
15
+ * including leaf-level constraints on the current node.
16
+ */
17
+ function compareSubschemas(beforeSchema, afterSchema, path, breaks) {
18
+ // Only applicable to nested schemas (from `contains` subschemas), not the root schema.
19
+ if (path !== '') {
20
+ if ((0, findFieldTypeChanges_1.hasTypeChange)(beforeSchema, afterSchema)) {
21
+ (0, types_1.pushBreak)(breaks, path, types_1.BREAK_MESSAGES.type);
22
+ }
23
+ (0, findEnumNarrowing_1.checkEnumNarrowingAtNode)(beforeSchema, afterSchema, path, breaks);
24
+ (0, findConstChanges_1.checkConstNarrowingAtNode)(beforeSchema, afterSchema, path, breaks);
25
+ }
26
+ (0, findArrayConstraintNarrowing_1.checkArrayConstraintNarrowing)(beforeSchema, afterSchema, path, breaks);
27
+ (0, findNumericConstraintNarrowing_1.checkNumericConstraintNarrowing)(beforeSchema, afterSchema, path, breaks);
28
+ (0, findStringConstraintNarrowing_1.checkStringConstraintNarrowing)(beforeSchema, afterSchema, path, breaks);
29
+ // Find breaking changes at children properties and items
30
+ (0, findNewRequiredFields_1.findNewRequiredFields)(beforeSchema, afterSchema, path, breaks);
31
+ (0, findFieldTypeChanges_1.findFieldTypeChanges)(beforeSchema, afterSchema, path, breaks);
32
+ (0, findEnumNarrowing_1.findEnumNarrowing)(beforeSchema, afterSchema, path, breaks);
33
+ (0, findConstChanges_1.findConstChanges)(beforeSchema, afterSchema, path, breaks);
34
+ (0, findArrayConstraintNarrowing_1.findArrayConstraintNarrowing)(beforeSchema, afterSchema, path, breaks);
35
+ (0, findNumericConstraintNarrowing_1.findNumericConstraintNarrowing)(beforeSchema, afterSchema, path, breaks);
36
+ (0, findStringConstraintNarrowing_1.findStringConstraintNarrowing)(beforeSchema, afterSchema, path, breaks);
37
+ }
38
+ /** Compares array `contains` subschemas using the full jsonBreakDetector check suite. */
39
+ function compareContainsSubschemas(beforeArraySchema, afterArraySchema, arrayPath, breaks) {
40
+ const afterContains = afterArraySchema.contains;
41
+ if (!afterContains || typeof afterContains !== 'object') {
42
+ return;
43
+ }
44
+ const beforeContains = beforeArraySchema.contains;
45
+ const containsPath = arrayPath ? `${arrayPath}.{contains}` : '{contains}';
46
+ const beforeSubschema = beforeContains && typeof beforeContains === 'object' ? beforeContains : {};
47
+ compareSubschemas(beforeSubschema, afterContains, containsPath, breaks);
48
+ }
49
+ //# sourceMappingURL=compareSubschemas.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compareSubschemas.js","sourceRoot":"","sources":["../../../src/utils/jsonBreakDetector/compareSubschemas.ts"],"names":[],"mappings":";;AAkBA,8CA4BC;AAGD,8DAiBC;AAhED,wFAAoH;AACpH,gEAAwF;AACxF,wEAAoF;AACpF,0EAAuE;AACvE,4FAGiD;AACjD,kEAAyF;AACzF,0FAAuH;AACvH,mCAA+D;AAE/D;;;GAGG;AACH,SAAgB,iBAAiB,CAC/B,YAAwB,EACxB,WAAuB,EACvB,IAAY,EACZ,MAAmB;IAEnB,uFAAuF;IACvF,IAAI,IAAI,KAAK,EAAE,EAAE,CAAC;QAChB,IAAI,IAAA,oCAAa,EAAC,YAAY,EAAE,WAAW,CAAC,EAAE,CAAC;YAC7C,IAAA,iBAAS,EAAC,MAAM,EAAE,IAAI,EAAE,sBAAc,CAAC,IAAI,CAAC,CAAC;QAC/C,CAAC;QAED,IAAA,4CAAwB,EAAC,YAAY,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;QAClE,IAAA,4CAAyB,EAAC,YAAY,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;IACrE,CAAC;IAED,IAAA,4DAA6B,EAAC,YAAY,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;IACvE,IAAA,gEAA+B,EAAC,YAAY,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;IACzE,IAAA,8DAA8B,EAAC,YAAY,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;IAExE,yDAAyD;IACzD,IAAA,6CAAqB,EAAC,YAAY,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;IAC/D,IAAA,2CAAoB,EAAC,YAAY,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;IAC9D,IAAA,qCAAiB,EAAC,YAAY,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;IAC3D,IAAA,mCAAgB,EAAC,YAAY,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;IAC1D,IAAA,2DAA4B,EAAC,YAAY,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;IACtE,IAAA,+DAA8B,EAAC,YAAY,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;IACxE,IAAA,6DAA6B,EAAC,YAAY,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;AACzE,CAAC;AAED,yFAAyF;AACzF,SAAgB,yBAAyB,CACvC,iBAA6B,EAC7B,gBAA4B,EAC5B,SAAiB,EACjB,MAAmB;IAEnB,MAAM,aAAa,GAAG,gBAAgB,CAAC,QAAQ,CAAC;IAEhD,IAAI,CAAC,aAAa,IAAI,OAAO,aAAa,KAAK,QAAQ,EAAE,CAAC;QACxD,OAAO;IACT,CAAC;IAED,MAAM,cAAc,GAAG,iBAAiB,CAAC,QAAQ,CAAC;IAClD,MAAM,YAAY,GAAG,SAAS,CAAC,CAAC,CAAC,GAAG,SAAS,aAAa,CAAC,CAAC,CAAC,YAAY,CAAC;IAC1E,MAAM,eAAe,GAAG,cAAc,IAAI,OAAO,cAAc,KAAK,QAAQ,CAAC,CAAC,CAAE,cAA6B,CAAC,CAAC,CAAC,EAAE,CAAC;IAEnH,iBAAiB,CAAC,eAAe,EAAE,aAA2B,EAAE,YAAY,EAAE,MAAM,CAAC,CAAC;AACxF,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { JSONSchema } from '@squiz/json-schema-library';
2
+ export type GenericSchema = Record<string, any>;
3
+ /**
4
+ * Synchronously dereferences internal ($ref: "#/...") JSON schema references.
5
+ */
6
+ export declare function dereferenceLocal<T extends GenericSchema = JSONSchema>(schema: T): T;
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.dereferenceLocal = dereferenceLocal;
4
+ /**
5
+ * Synchronously dereferences internal ($ref: "#/...") JSON schema references.
6
+ */
7
+ function dereferenceLocal(schema) {
8
+ function resolvePointer(root, pointer) {
9
+ if (!pointer.startsWith('#/')) {
10
+ throw new Error(`Only internal references starting with "#/" are supported. Received: "${pointer}"`);
11
+ }
12
+ const pathSegments = pointer.replace(/^#\//, '').split('/');
13
+ return pathSegments.reduce((acc, key) => {
14
+ // Decode RFC 6901 JSON Pointer escaped sequences (~1 -> /, ~0 -> ~)
15
+ const unescapedKey = key.replace(/~1/g, '/').replace(/~0/g, '~');
16
+ if (acc && typeof acc === 'object' && unescapedKey in acc) {
17
+ return acc[unescapedKey];
18
+ }
19
+ throw new Error(`Could not resolve JSON pointer reference: "${pointer}" at segment "${key}"`);
20
+ }, root);
21
+ }
22
+ function walk(node, root, seen = new WeakSet()) {
23
+ if (node === null || typeof node !== 'object') {
24
+ return node;
25
+ }
26
+ // Prevent infinite loops on circular references
27
+ if (seen.has(node)) {
28
+ return node;
29
+ }
30
+ seen.add(node);
31
+ if (Array.isArray(node)) {
32
+ return node.map((item) => walk(item, root, seen));
33
+ }
34
+ // Check if current object contains a string $ref property
35
+ if (typeof node.$ref === 'string') {
36
+ const resolvedTarget = resolvePointer(root, node.$ref);
37
+ // Separate $ref from rest of keys (JSON Schema draft 2019-09+ allows sibling properties)
38
+ const { $ref: _ref, ...rest } = node;
39
+ return {
40
+ ...walk(resolvedTarget, root, seen),
41
+ ...walk(rest, root, seen),
42
+ };
43
+ }
44
+ const result = {};
45
+ for (const [key, value] of Object.entries(node)) {
46
+ result[key] = walk(value, root, seen);
47
+ }
48
+ return result;
49
+ }
50
+ return walk(schema, schema);
51
+ }
52
+ //# sourceMappingURL=dereference.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dereference.js","sourceRoot":"","sources":["../../../../src/utils/jsonBreakDetector/dereference/dereference.ts"],"names":[],"mappings":";;AAOA,4CAyDC;AA5DD;;GAEG;AACH,SAAgB,gBAAgB,CAAuC,MAAS;IAC9E,SAAS,cAAc,CAAC,IAAyB,EAAE,OAAe;QAChE,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CAAC,yEAAyE,OAAO,GAAG,CAAC,CAAC;QACvG,CAAC;QAED,MAAM,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAE5D,OAAO,YAAY,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;YACtC,oEAAoE;YACpE,MAAM,YAAY,GAAG,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;YAEjE,IAAI,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,YAAY,IAAI,GAAG,EAAE,CAAC;gBAC1D,OAAO,GAAG,CAAC,YAAY,CAAC,CAAC;YAC3B,CAAC;YAED,MAAM,IAAI,KAAK,CAAC,8CAA8C,OAAO,iBAAiB,GAAG,GAAG,CAAC,CAAC;QAChG,CAAC,EAAE,IAAI,CAAC,CAAC;IACX,CAAC;IAED,SAAS,IAAI,CAAC,IAAS,EAAE,IAAyB,EAAE,OAAO,IAAI,OAAO,EAAU;QAC9E,IAAI,IAAI,KAAK,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC9C,OAAO,IAAI,CAAC;QACd,CAAC;QAED,gDAAgD;QAChD,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACnB,OAAO,IAAI,CAAC;QACd,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAEf,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YACxB,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;QACpD,CAAC;QAED,0DAA0D;QAC1D,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAClC,MAAM,cAAc,GAAG,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;YAEvD,yFAAyF;YACzF,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,CAAC;YAErC,OAAO;gBACL,GAAG,IAAI,CAAC,cAAc,EAAE,IAAI,EAAE,IAAI,CAAC;gBACnC,GAAG,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC;aAC1B,CAAC;QACJ,CAAC;QAED,MAAM,MAAM,GAAwB,EAAE,CAAC;QACvC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YAChD,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;QACxC,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,OAAO,IAAI,CAAC,MAAM,EAAE,MAAM,CAAM,CAAC;AACnC,CAAC"}