@amritk/generate-parsers 0.23.0 → 0.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +37 -463
- package/dist/index.d.ts +22 -2
- package/dist/index.js +18 -1
- package/package.json +15 -40
- package/AI.md +0 -52
- package/dist/generators/assert-supported-keywords.d.ts +0 -30
- package/dist/generators/assert-supported-keywords.js +0 -87
- package/dist/generators/build-schema.d.ts +0 -111
- package/dist/generators/build-schema.js +0 -74
- package/dist/generators/generate-deep-equal-check.d.ts +0 -24
- package/dist/generators/generate-deep-equal-check.js +0 -35
- package/dist/generators/generate-default-from-pattern.d.ts +0 -26
- package/dist/generators/generate-default-from-pattern.js +0 -223
- package/dist/generators/generate-discriminated-union-validation.d.ts +0 -15
- package/dist/generators/generate-discriminated-union-validation.js +0 -28
- package/dist/generators/generate-enum-check.d.ts +0 -35
- package/dist/generators/generate-enum-check.js +0 -31
- package/dist/generators/generate-files.d.ts +0 -138
- package/dist/generators/generate-files.js +0 -79
- package/dist/generators/generate-non-discriminated-union-validation.d.ts +0 -6
- package/dist/generators/generate-non-discriminated-union-validation.js +0 -26
- package/dist/generators/generate-parser-function.d.ts +0 -120
- package/dist/generators/generate-parser-function.js +0 -1955
- package/dist/generators/generate-schema-checks.d.ts +0 -5
- package/dist/generators/generate-schema-checks.js +0 -260
- package/dist/generators/generate-strict-assertion.d.ts +0 -155
- package/dist/generators/generate-strict-assertion.js +0 -759
- package/dist/generators/generate-type-checks.d.ts +0 -148
- package/dist/generators/generate-type-checks.js +0 -454
- package/dist/generators/generate-unique-items-check.d.ts +0 -16
- package/dist/generators/generate-unique-items-check.js +0 -32
- package/dist/generators/generate-validation-expression.d.ts +0 -79
- package/dist/generators/generate-validation-expression.js +0 -416
- package/dist/generators/subschema-match.d.ts +0 -48
- package/dist/generators/subschema-match.js +0 -485
- package/dist/generators/unevaluated-match.d.ts +0 -19
- package/dist/generators/unevaluated-match.js +0 -206
- package/dist/helpers/apply-schema-extensions.d.ts +0 -35
- package/dist/helpers/apply-schema-extensions.js +0 -20
- package/dist/helpers/collect-helpers.d.ts +0 -15
- package/dist/helpers/collect-helpers.js +0 -64
- package/dist/helpers/collect-imports.d.ts +0 -93
- package/dist/helpers/collect-imports.js +0 -197
- package/dist/helpers/find-discriminator.d.ts +0 -6
- package/dist/helpers/find-discriminator.js +0 -27
- package/dist/helpers/get-default-value.d.ts +0 -7
- package/dist/helpers/get-default-value.js +0 -155
- package/dist/helpers/get-discriminator-value.d.ts +0 -6
- package/dist/helpers/get-discriminator-value.js +0 -18
- package/dist/types/schema-extensions.d.ts +0 -34
- package/dist/types/schema-extensions.js +0 -0
|
@@ -1,485 +0,0 @@
|
|
|
1
|
-
import { regexLiteral } from "@amritk/helpers/escape-regex-pattern";
|
|
2
|
-
import { multipleOfPassExpr } from "@amritk/helpers/multiple-of-check";
|
|
3
|
-
import { resolveRef } from "@amritk/helpers/resolve-ref";
|
|
4
|
-
import { hasOwnCheck, missingCheck, safeAccessor } from "@amritk/helpers/safe-accessor";
|
|
5
|
-
import { hasConst, hasEnum, hasExclusiveMaximum, hasExclusiveMinimum, hasItems, hasMaxItems, hasMaximum, hasMaxLength, hasMaxProperties, hasMinItems, hasMinimum, hasMinLength, hasMinProperties, hasMultipleOf, hasPattern, hasProperties, hasRequired, hasType, hasUniqueItems, isSchemaObject } from "@amritk/helpers/schema-guards";
|
|
6
|
-
import { maxLengthPassExpr, minLengthPassExpr } from "@amritk/helpers/string-length-check";
|
|
7
|
-
import { generateDeepEqualCheck } from "./generate-deep-equal-check.js";
|
|
8
|
-
import { generateEnumCheck } from "./generate-enum-check.js";
|
|
9
|
-
import { generateUniqueItemsCheck } from "./generate-unique-items-check.js";
|
|
10
|
-
import { unevaluatedItemsExpr, unevaluatedPropertiesExpr } from "./unevaluated-match.js";
|
|
11
|
-
const HANDLED_KEYWORDS = /* @__PURE__ */ new Set([
|
|
12
|
-
"type",
|
|
13
|
-
"enum",
|
|
14
|
-
"const",
|
|
15
|
-
"pattern",
|
|
16
|
-
"minLength",
|
|
17
|
-
"maxLength",
|
|
18
|
-
"minimum",
|
|
19
|
-
"maximum",
|
|
20
|
-
"exclusiveMinimum",
|
|
21
|
-
"exclusiveMaximum",
|
|
22
|
-
"multipleOf",
|
|
23
|
-
"minItems",
|
|
24
|
-
"maxItems",
|
|
25
|
-
"uniqueItems",
|
|
26
|
-
"items",
|
|
27
|
-
"prefixItems",
|
|
28
|
-
"additionalItems",
|
|
29
|
-
"contains",
|
|
30
|
-
"minContains",
|
|
31
|
-
"maxContains",
|
|
32
|
-
"required",
|
|
33
|
-
"properties",
|
|
34
|
-
"patternProperties",
|
|
35
|
-
"propertyNames",
|
|
36
|
-
"dependentRequired",
|
|
37
|
-
"dependentSchemas",
|
|
38
|
-
"minProperties",
|
|
39
|
-
"maxProperties",
|
|
40
|
-
"additionalProperties",
|
|
41
|
-
"unevaluatedProperties",
|
|
42
|
-
"unevaluatedItems",
|
|
43
|
-
"$ref",
|
|
44
|
-
"allOf",
|
|
45
|
-
"anyOf",
|
|
46
|
-
"oneOf",
|
|
47
|
-
"not",
|
|
48
|
-
"if",
|
|
49
|
-
"then",
|
|
50
|
-
"else"
|
|
51
|
-
]);
|
|
52
|
-
const ANNOTATION_KEYWORDS = /* @__PURE__ */ new Set([
|
|
53
|
-
"title",
|
|
54
|
-
"description",
|
|
55
|
-
"$comment",
|
|
56
|
-
"$id",
|
|
57
|
-
"$schema",
|
|
58
|
-
"$anchor",
|
|
59
|
-
"$dynamicAnchor",
|
|
60
|
-
"$vocabulary",
|
|
61
|
-
"$defs",
|
|
62
|
-
"definitions",
|
|
63
|
-
"examples",
|
|
64
|
-
"default",
|
|
65
|
-
"deprecated",
|
|
66
|
-
"readOnly",
|
|
67
|
-
"writeOnly",
|
|
68
|
-
"format",
|
|
69
|
-
"contentMediaType",
|
|
70
|
-
"contentEncoding",
|
|
71
|
-
"contentSchema"
|
|
72
|
-
]);
|
|
73
|
-
const depthOf = (ctx) => ctx.depth ?? 0;
|
|
74
|
-
const nest = (ctx) => ({ ...ctx, depth: depthOf(ctx) + 1 });
|
|
75
|
-
const isObjectExpr = (acc) => `typeof ${acc} === "object" && ${acc} !== null && !Array.isArray(${acc})`;
|
|
76
|
-
const recordOf = (acc) => `(${acc} as Record<string, any>)`;
|
|
77
|
-
const patternEntriesOf = (schema) => {
|
|
78
|
-
const source = schema["patternProperties"];
|
|
79
|
-
if (typeof source !== "object" || source === null || Array.isArray(source))
|
|
80
|
-
return null;
|
|
81
|
-
return Object.entries(source);
|
|
82
|
-
};
|
|
83
|
-
const stringConstraints = (acc, schema) => {
|
|
84
|
-
const c = [];
|
|
85
|
-
if (hasPattern(schema))
|
|
86
|
-
c.push(`${regexLiteral(schema.pattern)}.test(${acc})`);
|
|
87
|
-
if (hasMinLength(schema))
|
|
88
|
-
c.push(minLengthPassExpr(acc, schema.minLength));
|
|
89
|
-
if (hasMaxLength(schema))
|
|
90
|
-
c.push(maxLengthPassExpr(acc, schema.maxLength));
|
|
91
|
-
return c;
|
|
92
|
-
};
|
|
93
|
-
const numberConstraints = (acc, schema, integer) => {
|
|
94
|
-
const c = [];
|
|
95
|
-
if (integer)
|
|
96
|
-
c.push(`Number.isInteger(${acc})`);
|
|
97
|
-
if (hasMinimum(schema))
|
|
98
|
-
c.push(`${acc} >= ${schema.minimum}`);
|
|
99
|
-
if (hasMaximum(schema))
|
|
100
|
-
c.push(`${acc} <= ${schema.maximum}`);
|
|
101
|
-
if (hasExclusiveMinimum(schema))
|
|
102
|
-
c.push(`${acc} > ${schema.exclusiveMinimum}`);
|
|
103
|
-
if (hasExclusiveMaximum(schema))
|
|
104
|
-
c.push(`${acc} < ${schema.exclusiveMaximum}`);
|
|
105
|
-
if (hasMultipleOf(schema))
|
|
106
|
-
c.push(multipleOfPassExpr(acc, schema.multipleOf));
|
|
107
|
-
return c;
|
|
108
|
-
};
|
|
109
|
-
const tupleShape = (schema) => {
|
|
110
|
-
const s = schema;
|
|
111
|
-
const declared = s["prefixItems"];
|
|
112
|
-
if (Array.isArray(declared))
|
|
113
|
-
return { prefix: declared, tail: s["items"] };
|
|
114
|
-
if (Array.isArray(s["items"]))
|
|
115
|
-
return { prefix: s["items"], tail: s["additionalItems"] };
|
|
116
|
-
return { prefix: null, tail: void 0 };
|
|
117
|
-
};
|
|
118
|
-
const arrayConstraints = (acc, schema, ctx) => {
|
|
119
|
-
const c = [];
|
|
120
|
-
const d = depthOf(ctx);
|
|
121
|
-
const elements = `(${acc} as any[])`;
|
|
122
|
-
if (hasMinItems(schema))
|
|
123
|
-
c.push(`${acc}.length >= ${schema.minItems}`);
|
|
124
|
-
if (hasMaxItems(schema))
|
|
125
|
-
c.push(`${acc}.length <= ${schema.maxItems}`);
|
|
126
|
-
if (hasUniqueItems(schema) && schema.uniqueItems === true) {
|
|
127
|
-
c.push(generateUniqueItemsCheck(acc, schema));
|
|
128
|
-
}
|
|
129
|
-
const { prefix, tail } = tupleShape(schema);
|
|
130
|
-
if (prefix) {
|
|
131
|
-
for (let i = 0; i < prefix.length; i++) {
|
|
132
|
-
const positional = subschemaMatchExpr(`${elements}[${i}]`, prefix[i], nest(ctx));
|
|
133
|
-
if (positional === null)
|
|
134
|
-
return null;
|
|
135
|
-
if (positional === "true")
|
|
136
|
-
continue;
|
|
137
|
-
c.push(`(${acc}.length <= ${i} || ${positional})`);
|
|
138
|
-
}
|
|
139
|
-
if (tail === false) {
|
|
140
|
-
c.push(`${acc}.length <= ${prefix.length}`);
|
|
141
|
-
} else if (tail !== void 0 && tail !== true) {
|
|
142
|
-
const el = `_i${d}`;
|
|
143
|
-
const tailMatch = subschemaMatchExpr(el, tail, nest(ctx));
|
|
144
|
-
if (tailMatch === null)
|
|
145
|
-
return null;
|
|
146
|
-
if (tailMatch !== "true")
|
|
147
|
-
c.push(`${elements}.every((${el}, _x${d}) => _x${d} < ${prefix.length} || ${tailMatch})`);
|
|
148
|
-
}
|
|
149
|
-
} else if ("items" in schema) {
|
|
150
|
-
if (schema["items"] === false) {
|
|
151
|
-
c.push(`${acc}.length === 0`);
|
|
152
|
-
} else if (hasItems(schema)) {
|
|
153
|
-
const el = `_i${d}`;
|
|
154
|
-
const itemMatch = subschemaMatchExpr(el, schema.items, nest(ctx));
|
|
155
|
-
if (itemMatch === null)
|
|
156
|
-
return null;
|
|
157
|
-
if (itemMatch !== "true")
|
|
158
|
-
c.push(`${elements}.every((${el}) => ${itemMatch})`);
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
const contains = containsConstraint(acc, schema, ctx);
|
|
162
|
-
if (contains === null)
|
|
163
|
-
return null;
|
|
164
|
-
c.push(...contains);
|
|
165
|
-
const unevaluated = unevaluatedItemsExpr(acc, schema, ctx, subschemaMatchExpr);
|
|
166
|
-
if (unevaluated === null)
|
|
167
|
-
return null;
|
|
168
|
-
if (unevaluated !== void 0)
|
|
169
|
-
c.push(unevaluated);
|
|
170
|
-
return c;
|
|
171
|
-
};
|
|
172
|
-
const containsConstraint = (acc, schema, ctx) => {
|
|
173
|
-
const s = schema;
|
|
174
|
-
if (!("contains" in s))
|
|
175
|
-
return [];
|
|
176
|
-
const d = depthOf(ctx);
|
|
177
|
-
const min = typeof s["minContains"] === "number" ? s["minContains"] : 1;
|
|
178
|
-
const max = typeof s["maxContains"] === "number" ? s["maxContains"] : void 0;
|
|
179
|
-
if (min === 0 && max === void 0)
|
|
180
|
-
return [];
|
|
181
|
-
const el = `_c${d}`;
|
|
182
|
-
const match = subschemaMatchExpr(el, s["contains"], nest(ctx));
|
|
183
|
-
if (match === null)
|
|
184
|
-
return null;
|
|
185
|
-
const count = `(${acc} as any[]).filter((${el}) => ${match}).length`;
|
|
186
|
-
const bounds = [];
|
|
187
|
-
if (min > 0)
|
|
188
|
-
bounds.push(`${count} >= ${min}`);
|
|
189
|
-
if (max !== void 0)
|
|
190
|
-
bounds.push(`${count} <= ${max}`);
|
|
191
|
-
return bounds;
|
|
192
|
-
};
|
|
193
|
-
const objectConstraints = (acc, schema, ctx) => {
|
|
194
|
-
const c = [];
|
|
195
|
-
const d = depthOf(ctx);
|
|
196
|
-
const required = new Set(hasRequired(schema) ? schema.required : []);
|
|
197
|
-
const rec = recordOf(acc);
|
|
198
|
-
if (hasProperties(schema)) {
|
|
199
|
-
for (const [key, propSchema] of Object.entries(schema.properties)) {
|
|
200
|
-
const propAcc = safeAccessor(rec, key);
|
|
201
|
-
const propMatch = subschemaMatchExpr(propAcc, propSchema, nest(ctx));
|
|
202
|
-
if (propMatch === null)
|
|
203
|
-
return null;
|
|
204
|
-
if (required.has(key)) {
|
|
205
|
-
c.push(propMatch === "true" ? hasOwnCheck(rec, key) : `(${hasOwnCheck(rec, key)} && ${propMatch})`);
|
|
206
|
-
} else if (propMatch !== "true") {
|
|
207
|
-
c.push(`(${propAcc} === undefined || ${propMatch})`);
|
|
208
|
-
}
|
|
209
|
-
required.delete(key);
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
for (const key of required)
|
|
213
|
-
c.push(hasOwnCheck(rec, key));
|
|
214
|
-
if (hasMinProperties(schema))
|
|
215
|
-
c.push(`Object.keys(${rec}).length >= ${schema.minProperties}`);
|
|
216
|
-
if (hasMaxProperties(schema))
|
|
217
|
-
c.push(`Object.keys(${rec}).length <= ${schema.maxProperties}`);
|
|
218
|
-
const keyTerms = keyWalkTerms(`_k${d}`, `_v${d}`, schema, ctx);
|
|
219
|
-
if (keyTerms === null)
|
|
220
|
-
return null;
|
|
221
|
-
if (keyTerms.length > 0) {
|
|
222
|
-
const needsValue = keyTerms.some((term) => term.usesValue);
|
|
223
|
-
const body = keyTerms.map((term) => term.expr).join(" && ");
|
|
224
|
-
c.push(needsValue ? `Object.keys(${rec}).every((_k${d}) => { const _v${d} = ${rec}[_k${d}]; return ${body}; })` : `Object.keys(${rec}).every((_k${d}) => ${body})`);
|
|
225
|
-
}
|
|
226
|
-
const dependent = dependentTerms(rec, acc, schema, ctx);
|
|
227
|
-
if (dependent === null)
|
|
228
|
-
return null;
|
|
229
|
-
c.push(...dependent);
|
|
230
|
-
const unevaluated = unevaluatedPropertiesExpr(acc, schema, ctx, subschemaMatchExpr);
|
|
231
|
-
if (unevaluated === null)
|
|
232
|
-
return null;
|
|
233
|
-
if (unevaluated !== void 0)
|
|
234
|
-
c.push(unevaluated);
|
|
235
|
-
return c;
|
|
236
|
-
};
|
|
237
|
-
const keyWalkTerms = (keyVar, valueVar, schema, ctx) => {
|
|
238
|
-
const terms = [];
|
|
239
|
-
const patterns = patternEntriesOf(schema);
|
|
240
|
-
const declared = hasProperties(schema) ? Object.keys(schema.properties) : [];
|
|
241
|
-
if (patterns) {
|
|
242
|
-
for (const [pattern, sub] of patterns) {
|
|
243
|
-
const match = subschemaMatchExpr(valueVar, sub, nest(ctx));
|
|
244
|
-
if (match === null)
|
|
245
|
-
return null;
|
|
246
|
-
if (match === "true")
|
|
247
|
-
continue;
|
|
248
|
-
terms.push({ expr: `(!${regexLiteral(pattern)}.test(${keyVar}) || ${match})`, usesValue: true });
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
const additional = schema["additionalProperties"];
|
|
252
|
-
if (additional !== void 0 && additional !== true) {
|
|
253
|
-
const guards = [];
|
|
254
|
-
if (declared.length > 0)
|
|
255
|
-
guards.push(`!${JSON.stringify(declared)}.includes(${keyVar})`);
|
|
256
|
-
if (patterns)
|
|
257
|
-
for (const [pattern] of patterns)
|
|
258
|
-
guards.push(`!${regexLiteral(pattern)}.test(${keyVar})`);
|
|
259
|
-
const unclaimed = guards.length > 0 ? guards.join(" && ") : null;
|
|
260
|
-
if (additional === false) {
|
|
261
|
-
terms.push({ expr: unclaimed === null ? "false" : `!(${unclaimed})`, usesValue: false });
|
|
262
|
-
} else {
|
|
263
|
-
const match = subschemaMatchExpr(valueVar, additional, nest(ctx));
|
|
264
|
-
if (match === null)
|
|
265
|
-
return null;
|
|
266
|
-
if (match !== "true") {
|
|
267
|
-
terms.push({ expr: unclaimed === null ? match : `(!(${unclaimed}) || ${match})`, usesValue: true });
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
const names = schema["propertyNames"];
|
|
272
|
-
if (names !== void 0) {
|
|
273
|
-
const match = subschemaMatchExpr(keyVar, names, nest(ctx));
|
|
274
|
-
if (match === null)
|
|
275
|
-
return null;
|
|
276
|
-
if (match !== "true")
|
|
277
|
-
terms.push({ expr: match, usesValue: false });
|
|
278
|
-
}
|
|
279
|
-
return terms;
|
|
280
|
-
};
|
|
281
|
-
const dependentTerms = (rec, acc, schema, ctx) => {
|
|
282
|
-
const s = schema;
|
|
283
|
-
const terms = [];
|
|
284
|
-
const dependentRequired = s["dependentRequired"];
|
|
285
|
-
if (typeof dependentRequired === "object" && dependentRequired !== null && !Array.isArray(dependentRequired)) {
|
|
286
|
-
for (const [trigger, deps] of Object.entries(dependentRequired)) {
|
|
287
|
-
if (!Array.isArray(deps) || deps.length === 0)
|
|
288
|
-
continue;
|
|
289
|
-
const present = deps.map((dep) => hasOwnCheck(rec, dep)).join(" && ");
|
|
290
|
-
terms.push(`(${missingCheck(rec, trigger)} || ${deps.length === 1 ? present : `(${present})`})`);
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
const dependentSchemas = s["dependentSchemas"];
|
|
294
|
-
if (typeof dependentSchemas === "object" && dependentSchemas !== null && !Array.isArray(dependentSchemas)) {
|
|
295
|
-
for (const [trigger, sub] of Object.entries(dependentSchemas)) {
|
|
296
|
-
const match = subschemaMatchExpr(acc, sub, nest(ctx));
|
|
297
|
-
if (match === null)
|
|
298
|
-
return null;
|
|
299
|
-
if (match === "true")
|
|
300
|
-
continue;
|
|
301
|
-
terms.push(`(${missingCheck(rec, trigger)} || ${match})`);
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
return terms;
|
|
305
|
-
};
|
|
306
|
-
const subschemaMatchExpr = (accessor, schema, ctx = {}) => {
|
|
307
|
-
if (schema === true)
|
|
308
|
-
return "true";
|
|
309
|
-
if (schema === false)
|
|
310
|
-
return "false";
|
|
311
|
-
if (!isSchemaObject(schema))
|
|
312
|
-
return null;
|
|
313
|
-
for (const key of Object.keys(schema)) {
|
|
314
|
-
if (!HANDLED_KEYWORDS.has(key) && !ANNOTATION_KEYWORDS.has(key))
|
|
315
|
-
return null;
|
|
316
|
-
}
|
|
317
|
-
if (depthOf(ctx) > 8)
|
|
318
|
-
return null;
|
|
319
|
-
const checks = [];
|
|
320
|
-
const refCheck = refMatch(accessor, schema, ctx);
|
|
321
|
-
if (refCheck === null)
|
|
322
|
-
return null;
|
|
323
|
-
if (refCheck !== "true")
|
|
324
|
-
checks.push(refCheck);
|
|
325
|
-
const combinators = combinatorChecks(accessor, schema, ctx);
|
|
326
|
-
if (combinators === null)
|
|
327
|
-
return null;
|
|
328
|
-
checks.push(...combinators);
|
|
329
|
-
if (hasConst(schema))
|
|
330
|
-
checks.push(`(${generateDeepEqualCheck(accessor, schema.const)})`);
|
|
331
|
-
if (hasEnum(schema)) {
|
|
332
|
-
if (schema.enum.length === 0)
|
|
333
|
-
return "false";
|
|
334
|
-
checks.push(generateEnumCheck(accessor, schema.enum));
|
|
335
|
-
}
|
|
336
|
-
if (hasType(schema)) {
|
|
337
|
-
const typeChecks = buildTypedChecks(accessor, schema, ctx);
|
|
338
|
-
if (typeChecks === null)
|
|
339
|
-
return null;
|
|
340
|
-
checks.push(...typeChecks);
|
|
341
|
-
} else if (Array.isArray(schema.type)) {
|
|
342
|
-
const branches = [];
|
|
343
|
-
for (const type of schema.type) {
|
|
344
|
-
const branch = buildTypedChecks(accessor, { ...schema, type }, ctx);
|
|
345
|
-
if (branch === null)
|
|
346
|
-
return null;
|
|
347
|
-
branches.push(branch.length === 1 ? branch[0] : `(${branch.join(" && ")})`);
|
|
348
|
-
}
|
|
349
|
-
checks.push(branches.length === 0 ? "false" : branches.length === 1 ? branches[0] : `(${branches.join(" || ")})`);
|
|
350
|
-
} else {
|
|
351
|
-
const typeless = buildTypelessChecks(accessor, schema, ctx);
|
|
352
|
-
if (typeless === null)
|
|
353
|
-
return null;
|
|
354
|
-
checks.push(...typeless);
|
|
355
|
-
}
|
|
356
|
-
if (checks.length === 0)
|
|
357
|
-
return "true";
|
|
358
|
-
return checks.length === 1 ? checks[0] : `(${checks.join(" && ")})`;
|
|
359
|
-
};
|
|
360
|
-
const refMatch = (accessor, schema, ctx) => {
|
|
361
|
-
const ref = schema["$ref"];
|
|
362
|
-
if (typeof ref !== "string")
|
|
363
|
-
return "true";
|
|
364
|
-
if (ctx.rootSchema === void 0)
|
|
365
|
-
return null;
|
|
366
|
-
if (ctx.seen?.has(ref))
|
|
367
|
-
return null;
|
|
368
|
-
const target = resolveRef(ref, ctx.rootSchema);
|
|
369
|
-
if (target === void 0)
|
|
370
|
-
return null;
|
|
371
|
-
const seen = new Set(ctx.seen ?? []);
|
|
372
|
-
seen.add(ref);
|
|
373
|
-
return subschemaMatchExpr(accessor, target, { ...nest(ctx), seen });
|
|
374
|
-
};
|
|
375
|
-
const combinatorChecks = (accessor, schema, ctx) => {
|
|
376
|
-
const record = schema;
|
|
377
|
-
const checks = [];
|
|
378
|
-
for (const keyword of ["allOf", "anyOf", "oneOf"]) {
|
|
379
|
-
const members = record[keyword];
|
|
380
|
-
if (members === void 0)
|
|
381
|
-
continue;
|
|
382
|
-
if (!Array.isArray(members) || members.length === 0)
|
|
383
|
-
return null;
|
|
384
|
-
const matches = [];
|
|
385
|
-
for (const member of members) {
|
|
386
|
-
const match = subschemaMatchExpr(accessor, member, nest(ctx));
|
|
387
|
-
if (match === null)
|
|
388
|
-
return null;
|
|
389
|
-
matches.push(match);
|
|
390
|
-
}
|
|
391
|
-
if (keyword === "allOf") {
|
|
392
|
-
const constraining = matches.filter((match) => match !== "true");
|
|
393
|
-
if (constraining.length > 0)
|
|
394
|
-
checks.push(joinAnd(constraining));
|
|
395
|
-
} else if (keyword === "anyOf") {
|
|
396
|
-
if (matches.some((match) => match === "true"))
|
|
397
|
-
continue;
|
|
398
|
-
checks.push(matches.length === 1 ? matches[0] : `(${matches.join(" || ")})`);
|
|
399
|
-
} else {
|
|
400
|
-
checks.push(matches.length === 1 ? matches[0] : `((${matches.map((match) => `(${match} ? 1 : 0)`).join(" + ")}) === 1)`);
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
|
-
if ("not" in record) {
|
|
404
|
-
const match = subschemaMatchExpr(accessor, record["not"], nest(ctx));
|
|
405
|
-
if (match === null)
|
|
406
|
-
return null;
|
|
407
|
-
if (match !== "false")
|
|
408
|
-
checks.push(`!(${match})`);
|
|
409
|
-
}
|
|
410
|
-
if ("if" in record) {
|
|
411
|
-
const ifMatch = subschemaMatchExpr(accessor, record["if"], nest(ctx));
|
|
412
|
-
if (ifMatch === null)
|
|
413
|
-
return null;
|
|
414
|
-
const branch = (keyword) => keyword in record ? subschemaMatchExpr(accessor, record[keyword], nest(ctx)) : void 0;
|
|
415
|
-
const thenMatch = branch("then");
|
|
416
|
-
const elseMatch = branch("else");
|
|
417
|
-
if (thenMatch === null || elseMatch === null)
|
|
418
|
-
return null;
|
|
419
|
-
if (thenMatch !== void 0 && thenMatch !== "true")
|
|
420
|
-
checks.push(`(!(${ifMatch}) || ${thenMatch})`);
|
|
421
|
-
if (elseMatch !== void 0 && elseMatch !== "true")
|
|
422
|
-
checks.push(`((${ifMatch}) || ${elseMatch})`);
|
|
423
|
-
}
|
|
424
|
-
return checks;
|
|
425
|
-
};
|
|
426
|
-
const buildTypedChecks = (accessor, schema, ctx) => {
|
|
427
|
-
switch (schema.type) {
|
|
428
|
-
case "string":
|
|
429
|
-
return [`typeof ${accessor} === "string"`, ...stringConstraints(accessor, schema)];
|
|
430
|
-
case "number":
|
|
431
|
-
return [`typeof ${accessor} === "number"`, ...numberConstraints(accessor, schema, false)];
|
|
432
|
-
case "integer":
|
|
433
|
-
return [`typeof ${accessor} === "number"`, ...numberConstraints(accessor, schema, true)];
|
|
434
|
-
case "boolean":
|
|
435
|
-
return [`typeof ${accessor} === "boolean"`];
|
|
436
|
-
case "null":
|
|
437
|
-
return [`${accessor} === null`];
|
|
438
|
-
case "array": {
|
|
439
|
-
const constraints = arrayConstraints(accessor, schema, ctx);
|
|
440
|
-
if (constraints === null)
|
|
441
|
-
return null;
|
|
442
|
-
return [`Array.isArray(${accessor})`, ...constraints];
|
|
443
|
-
}
|
|
444
|
-
case "object": {
|
|
445
|
-
const constraints = objectConstraints(accessor, schema, ctx);
|
|
446
|
-
if (constraints === null)
|
|
447
|
-
return null;
|
|
448
|
-
return [isObjectExpr(accessor), ...constraints];
|
|
449
|
-
}
|
|
450
|
-
default:
|
|
451
|
-
return null;
|
|
452
|
-
}
|
|
453
|
-
};
|
|
454
|
-
const buildTypelessChecks = (accessor, schema, ctx) => {
|
|
455
|
-
const checks = [];
|
|
456
|
-
const strChecks = stringConstraints(accessor, schema);
|
|
457
|
-
if (strChecks.length > 0)
|
|
458
|
-
checks.push(`(typeof ${accessor} !== "string" || ${joinAnd(strChecks)})`);
|
|
459
|
-
const numChecks = numberConstraints(accessor, schema, false);
|
|
460
|
-
if (numChecks.length > 0)
|
|
461
|
-
checks.push(`(typeof ${accessor} !== "number" || ${joinAnd(numChecks)})`);
|
|
462
|
-
const arrChecks = arrayConstraints(accessor, schema, ctx);
|
|
463
|
-
if (arrChecks === null)
|
|
464
|
-
return null;
|
|
465
|
-
if (arrChecks.length > 0)
|
|
466
|
-
checks.push(`(!Array.isArray(${accessor}) || ${joinAnd(arrChecks)})`);
|
|
467
|
-
const objChecks = objectConstraints(accessor, schema, ctx);
|
|
468
|
-
if (objChecks === null)
|
|
469
|
-
return null;
|
|
470
|
-
if (objChecks.length > 0)
|
|
471
|
-
checks.push(`(!(${isObjectExpr(accessor)}) || ${joinAnd(objChecks)})`);
|
|
472
|
-
return checks;
|
|
473
|
-
};
|
|
474
|
-
const joinAnd = (checks) => checks.length === 1 ? checks[0] : `(${checks.join(" && ")})`;
|
|
475
|
-
const hasConstrainingRefSibling = (schema) => {
|
|
476
|
-
if (!isSchemaObject(schema) || !("$ref" in schema))
|
|
477
|
-
return false;
|
|
478
|
-
return Object.keys(schema).some((key) => key !== "$ref" && !ANNOTATION_KEYWORDS.has(key));
|
|
479
|
-
};
|
|
480
|
-
const canMatchSubschema = (schema, rootSchema) => subschemaMatchExpr("_x", schema, rootSchema ? { rootSchema } : {}) !== null;
|
|
481
|
-
export {
|
|
482
|
-
canMatchSubschema,
|
|
483
|
-
hasConstrainingRefSibling,
|
|
484
|
-
subschemaMatchExpr
|
|
485
|
-
};
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import type { JSONSchema } from 'json-schema-typed/draft-2020-12';
|
|
2
|
-
import type { MatchContext } from './subschema-match.js';
|
|
3
|
-
type MatchFn = (accessor: string, schema: JSONSchema, ctx: MatchContext) => string | null;
|
|
4
|
-
/**
|
|
5
|
-
* The `unevaluatedProperties` conjunct for an object accessor: every own key the
|
|
6
|
-
* schema's other keywords did not evaluate must satisfy the unevaluated
|
|
7
|
-
* subschema (and `false` means there must be no such key).
|
|
8
|
-
*
|
|
9
|
-
* Returns `undefined` when the keyword is absent or constrains nothing (a `true`
|
|
10
|
-
* schema, or a node whose other keywords already sweep every key), and `null`
|
|
11
|
-
* when it cannot be proven inline.
|
|
12
|
-
*/
|
|
13
|
-
export declare const unevaluatedPropertiesExpr: (acc: string, schema: JSONSchema, ctx: MatchContext, match: MatchFn) => string | null | undefined;
|
|
14
|
-
/**
|
|
15
|
-
* The `unevaluatedItems` conjunct for an array accessor — the index counterpart
|
|
16
|
-
* of {@link unevaluatedPropertiesExpr}.
|
|
17
|
-
*/
|
|
18
|
-
export declare const unevaluatedItemsExpr: (acc: string, schema: JSONSchema, ctx: MatchContext, match: MatchFn) => string | null | undefined;
|
|
19
|
-
export {};
|