@squiz/dx-json-schema-lib 1.86.1 → 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 (73) hide show
  1. package/CHANGELOG.md +12 -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/manifest/v1/v1.d.ts +1 -1
  11. package/lib/manifest/v1/v1.json +3 -3
  12. package/lib/manifest/v1/v1.spec.js +12 -0
  13. package/lib/manifest/v1/v1.spec.js.map +1 -1
  14. package/lib/utils/jsonBreakDetector/checks/findArrayConstraintNarrowing.d.ts +6 -0
  15. package/lib/utils/jsonBreakDetector/checks/findArrayConstraintNarrowing.js +93 -0
  16. package/lib/utils/jsonBreakDetector/checks/findArrayConstraintNarrowing.js.map +1 -0
  17. package/lib/utils/jsonBreakDetector/checks/findConstChanges.d.ts +6 -0
  18. package/lib/utils/jsonBreakDetector/checks/findConstChanges.js +75 -0
  19. package/lib/utils/jsonBreakDetector/checks/findConstChanges.js.map +1 -0
  20. package/lib/utils/jsonBreakDetector/checks/findEnumNarrowing.d.ts +6 -0
  21. package/lib/utils/jsonBreakDetector/checks/findEnumNarrowing.js +90 -0
  22. package/lib/utils/jsonBreakDetector/checks/findEnumNarrowing.js.map +1 -0
  23. package/lib/utils/jsonBreakDetector/checks/findFieldTypeChanges.d.ts +8 -0
  24. package/lib/utils/jsonBreakDetector/checks/findFieldTypeChanges.js +86 -0
  25. package/lib/utils/jsonBreakDetector/checks/findFieldTypeChanges.js.map +1 -0
  26. package/lib/utils/jsonBreakDetector/checks/findNewRequiredFields.d.ts +6 -0
  27. package/lib/utils/jsonBreakDetector/checks/findNewRequiredFields.js +68 -0
  28. package/lib/utils/jsonBreakDetector/checks/findNewRequiredFields.js.map +1 -0
  29. package/lib/utils/jsonBreakDetector/checks/findNumericConstraintNarrowing.d.ts +6 -0
  30. package/lib/utils/jsonBreakDetector/checks/findNumericConstraintNarrowing.js +179 -0
  31. package/lib/utils/jsonBreakDetector/checks/findNumericConstraintNarrowing.js.map +1 -0
  32. package/lib/utils/jsonBreakDetector/checks/findStringConstraintNarrowing.d.ts +6 -0
  33. package/lib/utils/jsonBreakDetector/checks/findStringConstraintNarrowing.js +106 -0
  34. package/lib/utils/jsonBreakDetector/checks/findStringConstraintNarrowing.js.map +1 -0
  35. package/lib/utils/jsonBreakDetector/compareSubschemas.d.ts +9 -0
  36. package/lib/utils/jsonBreakDetector/compareSubschemas.js +49 -0
  37. package/lib/utils/jsonBreakDetector/compareSubschemas.js.map +1 -0
  38. package/lib/utils/jsonBreakDetector/dereference/dereference.d.ts +6 -0
  39. package/lib/utils/jsonBreakDetector/dereference/dereference.js +52 -0
  40. package/lib/utils/jsonBreakDetector/dereference/dereference.js.map +1 -0
  41. package/lib/utils/jsonBreakDetector/dereference/dereference.spec.d.ts +1 -0
  42. package/lib/utils/jsonBreakDetector/dereference/dereference.spec.js +225 -0
  43. package/lib/utils/jsonBreakDetector/dereference/dereference.spec.js.map +1 -0
  44. package/lib/utils/jsonBreakDetector/jsonBreakDetector.d.ts +8 -0
  45. package/lib/utils/jsonBreakDetector/jsonBreakDetector.js +35 -0
  46. package/lib/utils/jsonBreakDetector/jsonBreakDetector.js.map +1 -0
  47. package/lib/utils/jsonBreakDetector/jsonBreakDetector.spec.d.ts +1 -0
  48. package/lib/utils/jsonBreakDetector/jsonBreakDetector.spec.js +2761 -0
  49. package/lib/utils/jsonBreakDetector/jsonBreakDetector.spec.js.map +1 -0
  50. package/lib/utils/jsonBreakDetector/types.d.ts +25 -0
  51. package/lib/utils/jsonBreakDetector/types.js +28 -0
  52. package/lib/utils/jsonBreakDetector/types.js.map +1 -0
  53. package/package.json +1 -1
  54. package/src/formatted-text/v1/resolveFormattedTextNodes.spec.ts +70 -0
  55. package/src/formatted-text/v1/resolveFormattedTextNodes.ts +18 -3
  56. package/src/index.ts +2 -0
  57. package/src/manifest/v1/v1.json +3 -3
  58. package/src/manifest/v1/v1.spec.ts +15 -0
  59. package/src/manifest/v1/v1.ts +1 -1
  60. package/src/utils/jsonBreakDetector/checks/findArrayConstraintNarrowing.ts +121 -0
  61. package/src/utils/jsonBreakDetector/checks/findConstChanges.ts +97 -0
  62. package/src/utils/jsonBreakDetector/checks/findEnumNarrowing.ts +124 -0
  63. package/src/utils/jsonBreakDetector/checks/findFieldTypeChanges.ts +105 -0
  64. package/src/utils/jsonBreakDetector/checks/findNewRequiredFields.ts +97 -0
  65. package/src/utils/jsonBreakDetector/checks/findNumericConstraintNarrowing.ts +243 -0
  66. package/src/utils/jsonBreakDetector/checks/findStringConstraintNarrowing.ts +139 -0
  67. package/src/utils/jsonBreakDetector/compareSubschemas.ts +67 -0
  68. package/src/utils/jsonBreakDetector/dereference/dereference.spec.ts +245 -0
  69. package/src/utils/jsonBreakDetector/dereference/dereference.ts +65 -0
  70. package/src/utils/jsonBreakDetector/jsonBreakDetector.spec.ts +3041 -0
  71. package/src/utils/jsonBreakDetector/jsonBreakDetector.ts +36 -0
  72. package/src/utils/jsonBreakDetector/types.ts +29 -0
  73. package/tsconfig.tsbuildinfo +1 -1
@@ -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"}
@@ -0,0 +1,225 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const dereference_1 = require("./dereference");
4
+ describe('dereferenceLocal', () => {
5
+ describe('JSON Schema Draft 7', () => {
6
+ it('dereferences a top-level $ref to a definition', () => {
7
+ const schema = {
8
+ $schema: 'http://json-schema.org/draft-07/schema#',
9
+ $ref: '#/definitions/Person',
10
+ definitions: {
11
+ Person: {
12
+ type: 'object',
13
+ properties: {
14
+ name: { type: 'string' },
15
+ },
16
+ required: ['name'],
17
+ },
18
+ },
19
+ };
20
+ expect((0, dereference_1.dereferenceLocal)(schema)).toEqual({
21
+ $schema: 'http://json-schema.org/draft-07/schema#',
22
+ definitions: {
23
+ Person: {
24
+ type: 'object',
25
+ properties: {
26
+ name: { type: 'string' },
27
+ },
28
+ required: ['name'],
29
+ },
30
+ },
31
+ type: 'object',
32
+ properties: {
33
+ name: { type: 'string' },
34
+ },
35
+ required: ['name'],
36
+ });
37
+ });
38
+ it('dereferences nested $refs in properties', () => {
39
+ const schema = {
40
+ $schema: 'http://json-schema.org/draft-07/schema#',
41
+ type: 'object',
42
+ properties: {
43
+ address: { $ref: '#/definitions/Address' },
44
+ },
45
+ definitions: {
46
+ Address: {
47
+ type: 'object',
48
+ properties: {
49
+ city: { $ref: '#/definitions/City' },
50
+ },
51
+ },
52
+ City: {
53
+ type: 'string',
54
+ minLength: 1,
55
+ },
56
+ },
57
+ };
58
+ expect((0, dereference_1.dereferenceLocal)(schema)).toEqual({
59
+ $schema: 'http://json-schema.org/draft-07/schema#',
60
+ type: 'object',
61
+ properties: {
62
+ address: {
63
+ type: 'object',
64
+ properties: {
65
+ city: {
66
+ type: 'string',
67
+ minLength: 1,
68
+ },
69
+ },
70
+ },
71
+ },
72
+ definitions: {
73
+ Address: {
74
+ type: 'object',
75
+ properties: {
76
+ city: { $ref: '#/definitions/City' },
77
+ },
78
+ },
79
+ City: {
80
+ type: 'string',
81
+ minLength: 1,
82
+ },
83
+ },
84
+ });
85
+ });
86
+ it('dereferences $refs inside combinators', () => {
87
+ const schema = {
88
+ $schema: 'http://json-schema.org/draft-07/schema#',
89
+ oneOf: [{ $ref: '#/definitions/StringValue' }, { $ref: '#/definitions/NumberValue' }],
90
+ definitions: {
91
+ StringValue: { type: 'string' },
92
+ NumberValue: { type: 'number' },
93
+ },
94
+ };
95
+ expect((0, dereference_1.dereferenceLocal)(schema)).toEqual({
96
+ $schema: 'http://json-schema.org/draft-07/schema#',
97
+ oneOf: [{ type: 'string' }, { type: 'number' }],
98
+ definitions: {
99
+ StringValue: { type: 'string' },
100
+ NumberValue: { type: 'number' },
101
+ },
102
+ });
103
+ });
104
+ it('dereferences chained $refs', () => {
105
+ const schema = {
106
+ $schema: 'http://json-schema.org/draft-07/schema#',
107
+ $ref: '#/definitions/Outer',
108
+ definitions: {
109
+ Outer: { $ref: '#/definitions/Inner' },
110
+ Inner: {
111
+ type: 'boolean',
112
+ },
113
+ },
114
+ };
115
+ expect((0, dereference_1.dereferenceLocal)(schema)).toEqual({
116
+ $schema: 'http://json-schema.org/draft-07/schema#',
117
+ definitions: {
118
+ Outer: { $ref: '#/definitions/Inner' },
119
+ Inner: {
120
+ type: 'boolean',
121
+ },
122
+ },
123
+ type: 'boolean',
124
+ });
125
+ });
126
+ it('merges sibling properties alongside a $ref', () => {
127
+ const schema = {
128
+ $schema: 'http://json-schema.org/draft-07/schema#',
129
+ properties: {
130
+ title: {
131
+ $ref: '#/definitions/NonEmptyString',
132
+ description: 'A human-readable title',
133
+ },
134
+ },
135
+ definitions: {
136
+ NonEmptyString: {
137
+ type: 'string',
138
+ minLength: 1,
139
+ },
140
+ },
141
+ };
142
+ expect((0, dereference_1.dereferenceLocal)(schema)).toEqual({
143
+ $schema: 'http://json-schema.org/draft-07/schema#',
144
+ properties: {
145
+ title: {
146
+ type: 'string',
147
+ minLength: 1,
148
+ description: 'A human-readable title',
149
+ },
150
+ },
151
+ definitions: {
152
+ NonEmptyString: {
153
+ type: 'string',
154
+ minLength: 1,
155
+ },
156
+ },
157
+ });
158
+ });
159
+ it('resolves JSON pointer escaped property names', () => {
160
+ const schema = {
161
+ $schema: 'http://json-schema.org/draft-07/schema#',
162
+ properties: {
163
+ 'foo/bar': { $ref: '#/definitions/foo~1bar' },
164
+ },
165
+ definitions: {
166
+ 'foo/bar': {
167
+ type: 'string',
168
+ },
169
+ },
170
+ };
171
+ expect((0, dereference_1.dereferenceLocal)(schema)).toEqual({
172
+ $schema: 'http://json-schema.org/draft-07/schema#',
173
+ properties: {
174
+ 'foo/bar': {
175
+ type: 'string',
176
+ },
177
+ },
178
+ definitions: {
179
+ 'foo/bar': {
180
+ type: 'string',
181
+ },
182
+ },
183
+ });
184
+ });
185
+ it('does not infinitely recurse on circular definitions', () => {
186
+ const schema = {
187
+ $schema: 'http://json-schema.org/draft-07/schema#',
188
+ $ref: '#/definitions/Node',
189
+ definitions: {
190
+ Node: {
191
+ type: 'object',
192
+ properties: {
193
+ child: { $ref: '#/definitions/Node' },
194
+ },
195
+ },
196
+ },
197
+ };
198
+ const result = (0, dereference_1.dereferenceLocal)(schema);
199
+ expect(result.type).toBe('object');
200
+ expect(result.properties.child).toEqual({
201
+ type: 'object',
202
+ properties: {
203
+ child: { $ref: '#/definitions/Node' },
204
+ },
205
+ });
206
+ });
207
+ it('throws when a reference is not internal', () => {
208
+ const schema = {
209
+ $schema: 'http://json-schema.org/draft-07/schema#',
210
+ $ref: 'https://example.com/schema.json',
211
+ };
212
+ expect(() => (0, dereference_1.dereferenceLocal)(schema)).toThrow('Only internal references starting with "#/" are supported. Received: "https://example.com/schema.json"');
213
+ });
214
+ it('throws when a JSON pointer cannot be resolved', () => {
215
+ const schema = {
216
+ $schema: 'http://json-schema.org/draft-07/schema#',
217
+ properties: {
218
+ missing: { $ref: '#/definitions/DoesNotExist' },
219
+ },
220
+ };
221
+ expect(() => (0, dereference_1.dereferenceLocal)(schema)).toThrow('Could not resolve JSON pointer reference: "#/definitions/DoesNotExist" at segment "definitions"');
222
+ });
223
+ });
224
+ });
225
+ //# sourceMappingURL=dereference.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dereference.spec.js","sourceRoot":"","sources":["../../../../src/utils/jsonBreakDetector/dereference/dereference.spec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { JSONSchema } from '@squiz/json-schema-library';
2
+ import { JsonBreak } from './types';
3
+ /**
4
+ * Detects breaking schema changes between beforeSchema and afterSchema.
5
+ * Returns each break with a dotted path location, e.g. `subtitle`, `image.width`, `tags[]`,
6
+ * `tags.{contains}`, and a message identifying the kind of break.
7
+ */
8
+ export default function jsonBreakDetector(beforeSchema: JSONSchema, afterSchema: JSONSchema): JsonBreak[];
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = jsonBreakDetector;
4
+ const dereference_1 = require("./dereference/dereference");
5
+ const compareSubschemas_1 = require("./compareSubschemas");
6
+ const types_1 = require("./types");
7
+ /**
8
+ * Detects breaking schema changes between beforeSchema and afterSchema.
9
+ * Returns each break with a dotted path location, e.g. `subtitle`, `image.width`, `tags[]`,
10
+ * `tags.{contains}`, and a message identifying the kind of break.
11
+ */
12
+ function jsonBreakDetector(beforeSchema, afterSchema) {
13
+ const breaks = [];
14
+ // Unfold $refs so inline schemas and $defs references can be compared on equal footing.
15
+ let processedBeforeSchema;
16
+ try {
17
+ processedBeforeSchema = (0, dereference_1.dereferenceLocal)(beforeSchema);
18
+ }
19
+ catch (error) {
20
+ (0, types_1.pushBreak)(breaks, '', error instanceof Error ? error.message : 'Could not dereference schema');
21
+ }
22
+ let processedAfterSchema;
23
+ try {
24
+ processedAfterSchema = (0, dereference_1.dereferenceLocal)(afterSchema);
25
+ }
26
+ catch (error) {
27
+ (0, types_1.pushBreak)(breaks, '', error instanceof Error ? error.message : 'Could not dereference schema');
28
+ }
29
+ if (processedBeforeSchema === undefined || processedAfterSchema === undefined) {
30
+ return breaks;
31
+ }
32
+ (0, compareSubschemas_1.compareSubschemas)(processedBeforeSchema, processedAfterSchema, '', breaks);
33
+ return breaks;
34
+ }
35
+ //# sourceMappingURL=jsonBreakDetector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsonBreakDetector.js","sourceRoot":"","sources":["../../../src/utils/jsonBreakDetector/jsonBreakDetector.ts"],"names":[],"mappings":";;AAWA,oCAwBC;AAjCD,2DAA6D;AAC7D,2DAAwD;AACxD,mCAA+C;AAE/C;;;;GAIG;AACH,SAAwB,iBAAiB,CAAC,YAAwB,EAAE,WAAuB;IACzF,MAAM,MAAM,GAAgB,EAAE,CAAC;IAE/B,wFAAwF;IACxF,IAAI,qBAA6C,CAAC;IAClD,IAAI,CAAC;QACH,qBAAqB,GAAG,IAAA,8BAAgB,EAAC,YAAY,CAAC,CAAC;IACzD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAA,iBAAS,EAAC,MAAM,EAAE,EAAE,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,8BAA8B,CAAC,CAAC;IACjG,CAAC;IAED,IAAI,oBAA4C,CAAC;IACjD,IAAI,CAAC;QACH,oBAAoB,GAAG,IAAA,8BAAgB,EAAC,WAAW,CAAC,CAAC;IACvD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAA,iBAAS,EAAC,MAAM,EAAE,EAAE,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,8BAA8B,CAAC,CAAC;IACjG,CAAC;IAED,IAAI,qBAAqB,KAAK,SAAS,IAAI,oBAAoB,KAAK,SAAS,EAAE,CAAC;QAC9E,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,IAAA,qCAAiB,EAAC,qBAAqB,EAAE,oBAAoB,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC;IAC3E,OAAO,MAAM,CAAC;AAChB,CAAC"}