@x0k/json-schema-merge 1.0.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 (39) hide show
  1. package/LICENSE +7 -0
  2. package/README.md +181 -0
  3. package/dist/index.d.ts +1 -0
  4. package/dist/index.js +1 -0
  5. package/dist/lib/array.d.ts +19 -0
  6. package/dist/lib/array.js +133 -0
  7. package/dist/lib/function.d.ts +1 -0
  8. package/dist/lib/function.js +3 -0
  9. package/dist/lib/json-schema/compare/compare.d.ts +9 -0
  10. package/dist/lib/json-schema/compare/compare.js +205 -0
  11. package/dist/lib/json-schema/compare/index.d.ts +1 -0
  12. package/dist/lib/json-schema/compare/index.js +1 -0
  13. package/dist/lib/json-schema/index.d.ts +5 -0
  14. package/dist/lib/json-schema/index.js +5 -0
  15. package/dist/lib/json-schema/json-schema.d.ts +37 -0
  16. package/dist/lib/json-schema/json-schema.js +56 -0
  17. package/dist/lib/json-schema/merge/all-of-merge.d.ts +3 -0
  18. package/dist/lib/json-schema/merge/all-of-merge.js +29 -0
  19. package/dist/lib/json-schema/merge/index.d.ts +3 -0
  20. package/dist/lib/json-schema/merge/index.js +3 -0
  21. package/dist/lib/json-schema/merge/merge.d.ts +91 -0
  22. package/dist/lib/json-schema/merge/merge.js +554 -0
  23. package/dist/lib/json-schema/merge/patterns.d.ts +2 -0
  24. package/dist/lib/json-schema/merge/patterns.js +6 -0
  25. package/dist/lib/json-schema/transform.d.ts +4 -0
  26. package/dist/lib/json-schema/transform.js +72 -0
  27. package/dist/lib/json-schema/traverse.d.ts +26 -0
  28. package/dist/lib/json-schema/traverse.js +1 -0
  29. package/dist/lib/math.d.ts +2 -0
  30. package/dist/lib/math.js +2 -0
  31. package/dist/lib/memoize.d.ts +7 -0
  32. package/dist/lib/memoize.js +11 -0
  33. package/dist/lib/object.d.ts +2 -0
  34. package/dist/lib/object.js +12 -0
  35. package/dist/lib/ord.d.ts +9 -0
  36. package/dist/lib/ord.js +7 -0
  37. package/dist/lib/traverser.d.ts +4 -0
  38. package/dist/lib/traverser.js +1 -0
  39. package/package.json +59 -0
package/LICENSE ADDED
@@ -0,0 +1,7 @@
1
+ Copyright (c) 2025 Roman Krasilnikov
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,181 @@
1
+ # JSON Schema merge
2
+
3
+ A minimal JSON Schema merging library.
4
+
5
+ ```shell
6
+ npm i @x0k/json-schema-merge
7
+ ```
8
+
9
+ **Goals**
10
+
11
+ - Fast and correct merging of JSON Schemas Draft-07
12
+ - Shallow merging of the `allOf` keyword
13
+
14
+ **Non-goals**
15
+
16
+ - Support for drafts other than Draft-07
17
+ - Deep merging of the `allOf` keyword (possible, but not optimal)
18
+ - Handling invalid or incorrect JSON Schemas (the merge result is undefined)
19
+ - Resolving `$ref` references (see [json-schema-ref-parser](https://github.com/APIDevTools/json-schema-ref-parser))
20
+
21
+ ## Usage
22
+
23
+ ```ts
24
+ import {
25
+ createDeduplicator,
26
+ createIntersector,
27
+ } from "@x0k/json-schema-merge/lib/array";
28
+ import {
29
+ createMerger,
30
+ createComparator,
31
+ createShallowAllOfMerge,
32
+ } from "@x0k/json-schema-merge";
33
+
34
+ const { compareSchemaDefinitions, compareSchemaValues } = createComparator();
35
+
36
+ const { mergeArrayOfSchemaDefinitions } = createMerger({
37
+ intersectJson: createIntersector(compareSchemaValues),
38
+ deduplicateJsonSchemaDef: createDeduplicator(compareSchemaDefinitions),
39
+ });
40
+
41
+ const shallowAllOfMerge = createShallowAllOfMerge(
42
+ mergeArrayOfSchemaDefinitions
43
+ );
44
+
45
+ const merged = shallowAllOfMerge({
46
+ /* your schema with `allOf` keyword */
47
+ });
48
+ ```
49
+
50
+ ### Options
51
+
52
+ ```ts
53
+ /**
54
+ * Function type for removing duplicates from an array.
55
+ * Should return a new array with unique elements only.
56
+ */
57
+ export type Deduplicator<T> = (data: T[]) => T[];
58
+
59
+ /**
60
+ * Function type for intersecting two arrays of the same type.
61
+ */
62
+ export type Intersector<T> = (a: T[], b: T[]) => T[];
63
+
64
+ /**
65
+ * A merger function combines two values for a specific JSON Schema keyword.
66
+ */
67
+ export type Merger<T> = (a: T, b: T) => T;
68
+
69
+ /**
70
+ * An assigner function operates at the schema-object level.
71
+ * It receives the partially merged `target` and the original
72
+ * `left` and `right` schemas.
73
+ *
74
+ * In most cases, it modifies and returns the `target` object,
75
+ * but it may also return a completely new schema object if needed.
76
+ *
77
+ * Assigners are used for keywords that cannot be merged by simple
78
+ * value-level functions, often because they interact with other
79
+ * keywords or require holistic decisions.
80
+ */
81
+ export type Assigner<R extends {}> = (target: R, l: R, r: R) => R;
82
+
83
+ /**
84
+ * A validation function that ensures consistency between two schema keywords.
85
+ */
86
+ export type Check<K extends SchemaKey> = (
87
+ target: Required<Pick<JSONSchema7, K>>
88
+ ) => boolean;
89
+
90
+ export type CheckEntry<A extends SchemaKey, B extends SchemaKey> = readonly [
91
+ A,
92
+ B,
93
+ Check<A | B>,
94
+ ];
95
+
96
+ export interface MergeOptions {
97
+ /**
98
+ * Custom function to test whether a regular expression `subExpr`
99
+ * is considered a subset of another `superExpr`.
100
+ * @default Object.is
101
+ */
102
+ isSubRegExp?: (subExpr: string, superExpr: string) => boolean;
103
+
104
+ /**
105
+ * Merger function for combining regular expression patterns
106
+ * @default simplePatternsMerger
107
+ */
108
+ mergePatterns?: Merger<string>;
109
+
110
+ /**
111
+ * Intersector function for merging JSON values (enum keyword)
112
+ * @default intersection
113
+ */
114
+ intersectJson?: Intersector<JSONSchema7Type>;
115
+
116
+ /**
117
+ * Deduplication strategy for JSON Schema definitions.
118
+ * @default identity
119
+ */
120
+ deduplicateJsonSchemaDef?: Deduplicator<JSONSchema7Definition>;
121
+
122
+ /**
123
+ * Fallback merger applied when no keyword-specific merger is defined.
124
+ * @default identity
125
+ */
126
+ defaultMerger?: Merger<any>;
127
+
128
+ /**
129
+ * A mapping of schema keywords to merger functions.
130
+ *
131
+ * - A merger operates on **values of a single keyword** (`a`, `b` → merged value).
132
+ * - When provided, a custom merger **overrides the default merger** for that keyword.
133
+ */
134
+ mergers?: Partial<{
135
+ [K in SchemaKey]: Merger<Exclude<JSONSchema7[K], undefined>>;
136
+ }>;
137
+
138
+ /**
139
+ * A collection of keyword groups with associated assigner functions.
140
+ *
141
+ * - An assigner operates at the **schema-object level** (`target`, `left`, `right`).
142
+ * - Custom assigners are **appended** to the default assigners,
143
+ * but can also **replace behavior** for specific keywords if they overlap.
144
+ */
145
+ assigners?: Iterable<[SchemaKey[], Assigner<JSONSchema7>]>;
146
+
147
+ /**
148
+ * Consistency checks to validate relationships between
149
+ * pairs of schema keywords (e.g. `minimum` ≤ `maximum`).
150
+ *
151
+ * - A check ensures that two related keywords do not conflict.
152
+ * - Providing this option **replaces the default checks** completely.
153
+ *
154
+ * @default DEFAULT_CHECKS
155
+ */
156
+ checks?: Iterable<CheckEntry<SchemaKey, SchemaKey>>;
157
+ }
158
+ ```
159
+
160
+ ## Compatibility
161
+
162
+ This library was originally developed as part of the [svelte-jsonschema-form](https://github.com/x0k/svelte-jsonschema-form) project to replace [json-schema-merge-allof](https://github.com/mokkabonna/json-schema-merge-allof) and [json-schema-compare](https://github.com/mokkabonna/json-schema-compare).
163
+
164
+ It can be used as a drop-in alternative with the following differences:
165
+
166
+ ### Compared to `json-schema-compare`
167
+
168
+ - See the usage of the `DOES_NOT_MATCH` constant in the [comparison test](./src/lib/json-schema/compare/compare.test.ts)
169
+
170
+ ### Compared to `json-schema-merge-allof`
171
+
172
+ - Uses a different algorithm for sorting JSON values — order in array-like structures may differ
173
+ - More precise merging of the `properties`, `patternProperties`, and `additionalProperties` keywords
174
+ - Support for merging `number` and `integer` types
175
+ - Support for merging `if`, `then` and `else` keywords
176
+ - Fixed merging of regular expressions (see [comparison test](./src/lib/json-schema/merge/patterns.test.ts))
177
+ - Built-in schema consistency checks (e.g. `minimum` ≤ `maximum`)
178
+
179
+ ## License
180
+
181
+ MIT
@@ -0,0 +1 @@
1
+ export * from "./lib/json-schema/index.ts";
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ export * from "./lib/json-schema/index.js";
@@ -0,0 +1,19 @@
1
+ import type { Comparator } from "./ord.ts";
2
+ export declare function union<T>(larger: T[], smaller: T[]): T[];
3
+ export declare function intersection<T>(a: T[], b: T[]): T[];
4
+ export declare function isArrayEmpty<T>(arr: T[]): arr is [];
5
+ export declare function createArrayComparator<T>(compare: (a: T, b: T) => number): (a: T[], b: T[]) => number;
6
+ /**
7
+ * Function type for removing duplicates from an array.
8
+ */
9
+ export type Deduplicator<T> = (data: T[]) => T[];
10
+ export interface DeduplicatorOptions {
11
+ /** @default 12 */
12
+ threshold?: number;
13
+ }
14
+ export declare function createDeduplicator<T>(compare: Comparator<T>, { threshold }?: DeduplicatorOptions): Deduplicator<T>;
15
+ /**
16
+ * Function type for intersecting two arrays of the same type.
17
+ */
18
+ export type Intersector<T> = (a: T[], b: T[]) => T[];
19
+ export declare function createIntersector<T>(compare: Comparator<T>): Intersector<T>;
@@ -0,0 +1,133 @@
1
+ export function union(larger, smaller) {
2
+ const ll = larger.length;
3
+ if (ll === 0) {
4
+ return smaller;
5
+ }
6
+ let sl = smaller.length;
7
+ if (sl === 0) {
8
+ return larger;
9
+ }
10
+ if (ll < sl) {
11
+ const tmp = larger;
12
+ larger = smaller;
13
+ smaller = tmp;
14
+ sl = ll;
15
+ }
16
+ const data = new Set(larger);
17
+ for (let i = 0; i < sl; i++) {
18
+ data.add(smaller[i]);
19
+ }
20
+ return Array.from(data);
21
+ }
22
+ export function intersection(a, b) {
23
+ const result = [];
24
+ if (a.length === 0 || b.length === 0) {
25
+ return result;
26
+ }
27
+ if (a.length > b.length) {
28
+ const tmp = a;
29
+ a = b;
30
+ b = tmp;
31
+ }
32
+ const setB = new Set(b);
33
+ for (let i = 0; i < a.length && setB.size > 0; i++) {
34
+ const val = a[i];
35
+ if (setB.delete(val)) {
36
+ result.push(val);
37
+ }
38
+ }
39
+ return result;
40
+ }
41
+ export function isArrayEmpty(arr) {
42
+ return arr.length === 0;
43
+ }
44
+ export function createArrayComparator(compare) {
45
+ return (a, b) => {
46
+ const d = a.length - b.length;
47
+ if (d !== 0) {
48
+ return d;
49
+ }
50
+ for (let i = 0; i < a.length; i++) {
51
+ if (a[i] !== b[i]) {
52
+ const d = compare(a[i], b[i]);
53
+ if (d !== 0) {
54
+ return d;
55
+ }
56
+ }
57
+ }
58
+ return 0;
59
+ };
60
+ }
61
+ export function createDeduplicator(compare, { threshold = 12 } = {}) {
62
+ return (arr) => {
63
+ const al = arr.length;
64
+ if (al === 0) {
65
+ return arr;
66
+ }
67
+ if (al <= threshold) {
68
+ const result = [];
69
+ let rl = 0;
70
+ outer: for (let i = 0; i < al; i++) {
71
+ const item = arr[i];
72
+ for (let j = 0; j < rl; j++) {
73
+ if (compare(item, result[j]) === 0) {
74
+ continue outer;
75
+ }
76
+ }
77
+ rl = result.push(item);
78
+ }
79
+ return result;
80
+ }
81
+ const sorted = arr.slice().sort(compare);
82
+ let wIndex = 0;
83
+ for (let rIndex = 1; rIndex < al; rIndex++) {
84
+ if (compare(sorted[wIndex], sorted[rIndex]) !== 0) {
85
+ if (++wIndex !== rIndex) {
86
+ sorted[wIndex] = sorted[rIndex];
87
+ }
88
+ }
89
+ }
90
+ sorted.length = wIndex + 1;
91
+ return sorted;
92
+ };
93
+ }
94
+ export function createIntersector(compare) {
95
+ return (a, b) => {
96
+ const result = [];
97
+ let al = a.length;
98
+ let bl = b.length;
99
+ if (al === 0 || bl === 0) {
100
+ return result;
101
+ }
102
+ if (al > bl) {
103
+ const tmpArr = a;
104
+ a = b;
105
+ b = tmpArr;
106
+ const tmpL = al;
107
+ al = bl;
108
+ bl = tmpL;
109
+ }
110
+ const aSorted = [...a].sort(compare);
111
+ const bSorted = [...b].sort(compare);
112
+ let i = 0, j = 0;
113
+ while (i < al && j < bl) {
114
+ const cmp = compare(aSorted[i], bSorted[j]);
115
+ if (cmp === 0) {
116
+ // Only push if result is empty OR last pushed value is different
117
+ if (result.length === 0 ||
118
+ compare(result[result.length - 1], aSorted[i]) !== 0) {
119
+ result.push(aSorted[i]);
120
+ }
121
+ i++;
122
+ j++;
123
+ }
124
+ else if (cmp < 0) {
125
+ i++;
126
+ }
127
+ else {
128
+ j++;
129
+ }
130
+ }
131
+ return result;
132
+ };
133
+ }
@@ -0,0 +1 @@
1
+ export declare function identity<T>(v: T): T;
@@ -0,0 +1,3 @@
1
+ export function identity(v) {
2
+ return v;
3
+ }
@@ -0,0 +1,9 @@
1
+ import type { JSONSchema7Type as SchemaValue, JSONSchema7Definition } from "json-schema";
2
+ export interface ComparatorOptions {
3
+ deduplicationCache?: WeakMap<any[], any[]>;
4
+ sortedKeysCache?: WeakMap<Record<string, any>, string[]>;
5
+ }
6
+ export declare function createComparator({ deduplicationCache, sortedKeysCache, }?: ComparatorOptions): {
7
+ compareSchemaValues: (a: SchemaValue, b: SchemaValue) => number;
8
+ compareSchemaDefinitions: (a: JSONSchema7Definition, b: JSONSchema7Definition) => number;
9
+ };
@@ -0,0 +1,205 @@
1
+ import { ascComparator } from "../../ord.js";
2
+ import { createArrayComparator, createDeduplicator, isArrayEmpty, } from "../../array.js";
3
+ import { isRecordEmpty } from "../../object.js";
4
+ import { weakMemoize } from "../../memoize.js";
5
+ import { isAllowAnySchema, isSchemaObject } from "../json-schema.js";
6
+ const zero = () => 0;
7
+ const isUndefined = (v) => v === undefined;
8
+ const isSchemaPrimitiveExceptNull = (value) => typeof value !== "object";
9
+ const PRIMITIVE_TYPE_ORDER = {
10
+ boolean: 0,
11
+ number: 1,
12
+ string: 2,
13
+ };
14
+ function compareSchemaPrimitive(a, b) {
15
+ const ta = typeof a;
16
+ const tb = typeof b;
17
+ return ta === tb
18
+ ? ascComparator(a, b)
19
+ : PRIMITIVE_TYPE_ORDER[ta] - PRIMITIVE_TYPE_ORDER[tb];
20
+ }
21
+ function insertUniqueValues(mutableTarget, mutableSource) {
22
+ const tl = mutableTarget.length;
23
+ if (tl === 0)
24
+ return mutableSource;
25
+ const sl = mutableSource.length;
26
+ if (sl === 0)
27
+ return mutableTarget;
28
+ if (sl > tl) {
29
+ const t = mutableTarget;
30
+ mutableTarget = mutableSource;
31
+ mutableSource = t;
32
+ }
33
+ const seen = new Set(mutableTarget);
34
+ const l = mutableSource.length;
35
+ for (let i = 0; i < l; i++) {
36
+ const key = mutableSource[i];
37
+ if (!seen.has(key)) {
38
+ mutableTarget.push(key);
39
+ }
40
+ }
41
+ return mutableTarget;
42
+ }
43
+ function createCmpMatcher(isEmpty, compare, compareEmpty = zero) {
44
+ return (a, b) => {
45
+ if (isEmpty(a)) {
46
+ if (isEmpty(b)) {
47
+ return compareEmpty(a, b);
48
+ }
49
+ return -1;
50
+ }
51
+ if (isEmpty(b)) {
52
+ return 1;
53
+ }
54
+ return compare(a, b);
55
+ };
56
+ }
57
+ function createOptionalComparator(compare) {
58
+ return createCmpMatcher(isUndefined, compare);
59
+ }
60
+ function createNarrowingOptionalComparator(isEmpty, compare) {
61
+ return createCmpMatcher((v) => v === undefined || isEmpty(v), compare);
62
+ }
63
+ function createArrayOrItemComparator(compare, compareArray) {
64
+ return createCmpMatcher(Array.isArray, compare, compareArray);
65
+ }
66
+ const compareOptionalSameTypeSchemaPrimitives = createOptionalComparator(ascComparator);
67
+ const compareNumbersWithZeroDefault = createNarrowingOptionalComparator((v) => v === 0, (a, b) => a - b);
68
+ export function createComparator({ deduplicationCache = new WeakMap(), sortedKeysCache = new WeakMap(), } = {}) {
69
+ const getSortedKeys = weakMemoize(sortedKeysCache, (obj) => Object.keys(obj).sort());
70
+ function createRecordsComparator(compare) {
71
+ return (a, b) => {
72
+ const aKeys = getSortedKeys(a);
73
+ const bKeys = getSortedKeys(b);
74
+ const l = Math.min(aKeys.length, bKeys.length);
75
+ for (let i = 0; i < l; i++) {
76
+ const cmp = ascComparator(aKeys[i], bKeys[i]);
77
+ if (cmp !== 0) {
78
+ return cmp;
79
+ }
80
+ }
81
+ if (aKeys.length !== bKeys.length) {
82
+ return aKeys.length - bKeys.length;
83
+ }
84
+ for (let i = 0; i < l; i++) {
85
+ const key = aKeys[i];
86
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
87
+ const cmp = compare(a[key], b[key]);
88
+ if (cmp !== 0) {
89
+ return cmp;
90
+ }
91
+ }
92
+ return 0;
93
+ };
94
+ }
95
+ function createArrayComparatorWithDeduplication(compare) {
96
+ const cmp = createArrayComparator(compare);
97
+ const deduplicate = weakMemoize(deduplicationCache,
98
+ // NOTE: Always sort output
99
+ createDeduplicator(compare, { threshold: 0 }));
100
+ return (a, b) => cmp(deduplicate(a), deduplicate(b));
101
+ }
102
+ const compareArrayOfSameTypePrimitivesWithDeduplication = createArrayComparatorWithDeduplication(ascComparator);
103
+ function compareSchemaDefinitions(a, b) {
104
+ if (isSchemaObject(a)) {
105
+ if (isSchemaObject(b)) {
106
+ const aKeys = Object.keys(a);
107
+ const bKeys = Object.keys(b);
108
+ const allKeys = insertUniqueValues(aKeys, bKeys);
109
+ const l = allKeys.length;
110
+ for (let i = 0; i < l; i++) {
111
+ const key = allKeys[i];
112
+ if (a[key] === b[key]) {
113
+ continue;
114
+ }
115
+ const cmp = COMPARATORS[key] ?? compareOptionalSchemaValues;
116
+ const d = cmp(a[key], b[key]);
117
+ if (d !== 0) {
118
+ return d;
119
+ }
120
+ }
121
+ return 0;
122
+ }
123
+ return b === true && isRecordEmpty(a) ? 0 : 1;
124
+ }
125
+ if (isSchemaObject(b)) {
126
+ return a === true && isRecordEmpty(b) ? 0 : -1;
127
+ }
128
+ return ascComparator(a, b);
129
+ }
130
+ const compareOptionalSchemaValues = createOptionalComparator(compareSchemaValues);
131
+ const compareNonNullSchemaValue = createCmpMatcher(isSchemaPrimitiveExceptNull, createArrayOrItemComparator(createRecordsComparator(compareOptionalSchemaValues), createArrayComparator(compareSchemaValues)), compareSchemaPrimitive);
132
+ function compareSchemaValues(a, b) {
133
+ if (a === null) {
134
+ return -1;
135
+ }
136
+ if (b === null) {
137
+ return 1;
138
+ }
139
+ return compareNonNullSchemaValue(a, b);
140
+ }
141
+ const compareOptionalSchemaDefinitions = createOptionalComparator(compareSchemaDefinitions);
142
+ const compareRecordOfOptionalSchemasWithEmptyRecordDefault = createNarrowingOptionalComparator(isRecordEmpty, createRecordsComparator(compareOptionalSchemaDefinitions));
143
+ const compareOptionalArrayOfSchemasWithDeduplication = createOptionalComparator(createArrayComparatorWithDeduplication(compareSchemaDefinitions));
144
+ const compareSchemaDefinitionsWithEmptyDefinitionDefault = createNarrowingOptionalComparator(isAllowAnySchema, compareSchemaDefinitions);
145
+ const COMPARATORS = {
146
+ $id: compareOptionalSameTypeSchemaPrimitives,
147
+ $comment: compareOptionalSameTypeSchemaPrimitives,
148
+ $defs: compareRecordOfOptionalSchemasWithEmptyRecordDefault,
149
+ $ref: compareOptionalSameTypeSchemaPrimitives,
150
+ $schema: compareOptionalSameTypeSchemaPrimitives,
151
+ const: compareOptionalSchemaValues,
152
+ contains: compareOptionalSchemaDefinitions,
153
+ contentEncoding: compareOptionalSameTypeSchemaPrimitives,
154
+ contentMediaType: compareOptionalSameTypeSchemaPrimitives,
155
+ default: compareOptionalSchemaValues,
156
+ definitions: compareRecordOfOptionalSchemasWithEmptyRecordDefault,
157
+ description: compareOptionalSameTypeSchemaPrimitives,
158
+ else: compareOptionalSchemaDefinitions,
159
+ examples: compareOptionalSchemaValues,
160
+ exclusiveMaximum: compareOptionalSameTypeSchemaPrimitives,
161
+ exclusiveMinimum: compareOptionalSameTypeSchemaPrimitives,
162
+ format: compareOptionalSameTypeSchemaPrimitives,
163
+ if: compareOptionalSchemaDefinitions,
164
+ maximum: compareOptionalSameTypeSchemaPrimitives,
165
+ maxItems: compareOptionalSameTypeSchemaPrimitives,
166
+ maxLength: compareOptionalSameTypeSchemaPrimitives,
167
+ maxProperties: compareOptionalSameTypeSchemaPrimitives,
168
+ minimum: compareOptionalSameTypeSchemaPrimitives,
169
+ multipleOf: compareOptionalSameTypeSchemaPrimitives,
170
+ not: compareOptionalSchemaDefinitions,
171
+ pattern: compareOptionalSameTypeSchemaPrimitives,
172
+ propertyNames: compareOptionalSchemaDefinitions,
173
+ readOnly: compareOptionalSameTypeSchemaPrimitives,
174
+ then: compareOptionalSchemaDefinitions,
175
+ title: compareOptionalSameTypeSchemaPrimitives,
176
+ writeOnly: compareOptionalSameTypeSchemaPrimitives,
177
+ uniqueItems: createNarrowingOptionalComparator((v) => v === false, zero),
178
+ minLength: compareNumbersWithZeroDefault,
179
+ minItems: compareNumbersWithZeroDefault,
180
+ minProperties: compareNumbersWithZeroDefault,
181
+ required: createNarrowingOptionalComparator(isArrayEmpty, compareArrayOfSameTypePrimitivesWithDeduplication),
182
+ enum: createNarrowingOptionalComparator(isArrayEmpty, createArrayComparatorWithDeduplication(compareSchemaValues)),
183
+ type: createOptionalComparator((a, b) => {
184
+ const isAArr = Array.isArray(a);
185
+ const isBArr = Array.isArray(b);
186
+ if (!isAArr && !isBArr) {
187
+ return ascComparator(a, b);
188
+ }
189
+ return compareArrayOfSameTypePrimitivesWithDeduplication(isAArr ? a : [a], isBArr ? b : [b]);
190
+ }),
191
+ items: createNarrowingOptionalComparator((v) => !Array.isArray(v) && isAllowAnySchema(v), createArrayOrItemComparator(compareSchemaDefinitions, createArrayComparator(compareSchemaDefinitions))),
192
+ anyOf: compareOptionalArrayOfSchemasWithDeduplication,
193
+ allOf: compareOptionalArrayOfSchemasWithDeduplication,
194
+ oneOf: compareOptionalArrayOfSchemasWithDeduplication,
195
+ properties: compareRecordOfOptionalSchemasWithEmptyRecordDefault,
196
+ patternProperties: compareRecordOfOptionalSchemasWithEmptyRecordDefault,
197
+ additionalProperties: compareSchemaDefinitionsWithEmptyDefinitionDefault,
198
+ additionalItems: compareSchemaDefinitionsWithEmptyDefinitionDefault,
199
+ dependencies: createNarrowingOptionalComparator(isRecordEmpty, createRecordsComparator(createOptionalComparator(createArrayOrItemComparator(compareSchemaDefinitions, compareArrayOfSameTypePrimitivesWithDeduplication)))),
200
+ };
201
+ return {
202
+ compareSchemaValues,
203
+ compareSchemaDefinitions,
204
+ };
205
+ }
@@ -0,0 +1 @@
1
+ export * from "./compare.ts";
@@ -0,0 +1 @@
1
+ export * from "./compare.js";
@@ -0,0 +1,5 @@
1
+ export * from "./json-schema.ts";
2
+ export * from "./transform.ts";
3
+ export * from "./traverse.ts";
4
+ export * from "./compare/index.ts";
5
+ export * from "./merge/index.ts";
@@ -0,0 +1,5 @@
1
+ export * from "./json-schema.js";
2
+ export * from "./transform.js";
3
+ export * from "./traverse.js";
4
+ export * from "./compare/index.js";
5
+ export * from "./merge/index.js";
@@ -0,0 +1,37 @@
1
+ import type { JSONSchema7TypeName, JSONSchema7Definition } from "json-schema";
2
+ export declare const JSON_SCHEMA_TYPE_NAMES: string[];
3
+ export declare const SET_OF_JSON_SCHEMA_TYPE_NAMES: Set<string>;
4
+ export declare function isJsonSchemaType(type: string): type is JSONSchema7TypeName;
5
+ export declare const RECORDS_OF_SUB_SCHEMAS: ["$defs", "definitions", "properties", "patternProperties", "dependencies"];
6
+ export declare const SET_OF_RECORDS_OF_SUB_SCHEMAS: Set<"$defs" | "properties" | "patternProperties" | "dependencies" | "definitions">;
7
+ export type SubSchemasRecordKey = (typeof RECORDS_OF_SUB_SCHEMAS)[number];
8
+ export declare const ARRAYS_OF_SUB_SCHEMAS: ["items", "allOf", "oneOf", "anyOf"];
9
+ export declare const SET_OF_ARRAYS_OF_SUB_SCHEMAS: Set<"items" | "allOf" | "anyOf" | "oneOf">;
10
+ export type SubSchemasArrayKey = (typeof ARRAYS_OF_SUB_SCHEMAS)[number];
11
+ export declare const SUB_SCHEMAS: ["items", "additionalItems", "additionalProperties", "propertyNames", "contains", "if", "then", "else", "not"];
12
+ export declare const SET_OF_SUB_SCHEMAS: Set<"items" | "additionalItems" | "contains" | "additionalProperties" | "propertyNames" | "if" | "then" | "else" | "not">;
13
+ export type SubSchemaKey = (typeof SUB_SCHEMAS)[number];
14
+ export declare const ALL_SUB_SCHEMA_KEYS: ("$defs" | "items" | "additionalItems" | "contains" | "properties" | "patternProperties" | "additionalProperties" | "dependencies" | "propertyNames" | "if" | "then" | "else" | "allOf" | "anyOf" | "oneOf" | "not" | "definitions")[];
15
+ export type AnySubSchemaKey = (typeof ALL_SUB_SCHEMA_KEYS)[number];
16
+ export type TransformedSchema<R, S> = Omit<S, AnySubSchemaKey> & {
17
+ items?: R | R[] | undefined;
18
+ additionalItems?: R | undefined;
19
+ contains?: R | undefined;
20
+ additionalProperties?: R | undefined;
21
+ propertyNames?: R | undefined;
22
+ if?: R | undefined;
23
+ then?: R | undefined;
24
+ else?: R | undefined;
25
+ not?: R | undefined;
26
+ $defs?: Record<string, R> | undefined;
27
+ properties?: Record<string, R> | undefined;
28
+ patternProperties?: Record<string, R> | undefined;
29
+ dependencies?: Record<string, R | string[]> | undefined;
30
+ definitions?: Record<string, R> | undefined;
31
+ allOf?: R[] | undefined;
32
+ anyOf?: R[] | undefined;
33
+ oneOf?: R[] | undefined;
34
+ };
35
+ export type TransformedSchemaDefinition<R, S> = TransformedSchema<R, S> | boolean;
36
+ export declare function isSchemaObject<D extends JSONSchema7Definition>(schemaDef: D): schemaDef is Exclude<D, boolean>;
37
+ export declare function isAllowAnySchema(def: JSONSchema7Definition): def is true | Record<string, never>;