ata-validator 1.6.1 → 1.7.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/CHANGELOG.md +35 -0
- package/README.md +32 -14
- package/build.d.ts +12 -0
- package/index.d.ts +16 -4
- package/index.js +58 -13
- package/lib/aot-build.js +1 -0
- package/lib/aot.js +69 -19
- package/lib/buffer-gate.js +132 -0
- package/lib/draft7.js +24 -2
- package/lib/enrich-error.js +14 -4
- package/lib/error-codes.js +16 -9
- package/lib/interpreter.js +432 -200
- package/lib/js-compiler.js +240 -62
- package/lib/metaschemas.js +21 -0
- package/lib/safe-regex-source.js +1 -1
- package/lib/safe-regex.js +209 -29
- package/lib/version.js +1 -1
- package/package.json +8 -8
- package/t.d.ts +16 -5
package/lib/js-compiler.js
CHANGED
|
@@ -108,6 +108,14 @@ function compileToJS(schema, defs, schemaMap) {
|
|
|
108
108
|
}
|
|
109
109
|
|
|
110
110
|
if (!defs && needsBaseTracking(schema, schemaMap, new Set())) return null
|
|
111
|
+
if (!defs && externalDocsNeedInterpreter(schema, schemaMap)) return null
|
|
112
|
+
|
|
113
|
+
// unevaluatedProperties / unevaluatedItems need annotation tracking this
|
|
114
|
+
// path does not do. Decline so the schema reaches an engine that does.
|
|
115
|
+
if (!defs) {
|
|
116
|
+
const str = JSON.stringify(schema)
|
|
117
|
+
if (str.includes('"unevaluatedProperties"') || str.includes('"unevaluatedItems"')) return null
|
|
118
|
+
}
|
|
111
119
|
|
|
112
120
|
// Collect $defs early so sub-schemas can resolve $ref
|
|
113
121
|
const rootDefs = defs || collectDefs(schema)
|
|
@@ -158,13 +166,13 @@ function compileToJS(schema, defs, schemaMap) {
|
|
|
158
166
|
const primitives = vals.filter(v => v === null || typeof v !== 'object')
|
|
159
167
|
const objects = vals.filter(v => v !== null && typeof v === 'object')
|
|
160
168
|
const primSet = new Set(primitives.map(v => v === null ? 'null' : typeof v === 'string' ? 's:' + v : 'n:' + v))
|
|
161
|
-
const objStrs = objects.map(v =>
|
|
169
|
+
const objStrs = objects.map(v => _canonical(v))
|
|
162
170
|
checks.push((d) => {
|
|
163
171
|
// Fast primitive check
|
|
164
172
|
const key = d === null ? 'null' : typeof d === 'string' ? 's:' + d : typeof d === 'number' || typeof d === 'boolean' ? 'n:' + d : null
|
|
165
173
|
if (key !== null && primSet.has(key)) return true
|
|
166
|
-
// Slow object check
|
|
167
|
-
const ds =
|
|
174
|
+
// Slow object check, key order independent
|
|
175
|
+
const ds = _canonical(d)
|
|
168
176
|
for (let i = 0; i < objStrs.length; i++) {
|
|
169
177
|
if (ds === objStrs[i]) return true
|
|
170
178
|
}
|
|
@@ -182,15 +190,15 @@ function compileToJS(schema, defs, schemaMap) {
|
|
|
182
190
|
if (cv === null || typeof cv !== 'object') {
|
|
183
191
|
checks.push((d) => d === cv)
|
|
184
192
|
} else {
|
|
185
|
-
const cs =
|
|
186
|
-
checks.push((d) =>
|
|
193
|
+
const cs = _canonical(cv)
|
|
194
|
+
checks.push((d) => _canonical(d) === cs)
|
|
187
195
|
}
|
|
188
196
|
}
|
|
189
197
|
|
|
190
|
-
// required
|
|
198
|
+
// required applies to objects only; other types are ignored.
|
|
191
199
|
if (schema.required && Array.isArray(schema.required)) {
|
|
192
200
|
for (const key of schema.required) {
|
|
193
|
-
checks.push((d) => typeof d
|
|
201
|
+
checks.push((d) => typeof d !== 'object' || d === null || Array.isArray(d) || d[key] !== undefined)
|
|
194
202
|
}
|
|
195
203
|
}
|
|
196
204
|
|
|
@@ -206,10 +214,10 @@ function compileToJS(schema, defs, schemaMap) {
|
|
|
206
214
|
}
|
|
207
215
|
}
|
|
208
216
|
|
|
209
|
-
// additionalProperties
|
|
210
|
-
if (schema.additionalProperties !== undefined
|
|
217
|
+
// additionalProperties (with or without a properties map)
|
|
218
|
+
if (schema.additionalProperties !== undefined) {
|
|
211
219
|
if (schema.additionalProperties === false) {
|
|
212
|
-
const allowed = new Set(Object.keys(schema.properties))
|
|
220
|
+
const allowed = new Set(Object.keys(schema.properties || {}))
|
|
213
221
|
checks.push((d) => {
|
|
214
222
|
if (typeof d !== 'object' || d === null || Array.isArray(d)) return true
|
|
215
223
|
const keys = Object.keys(d)
|
|
@@ -246,13 +254,14 @@ function compileToJS(schema, defs, schemaMap) {
|
|
|
246
254
|
}
|
|
247
255
|
}
|
|
248
256
|
|
|
249
|
-
// items
|
|
257
|
+
// items, applied after the prefixItems positions
|
|
250
258
|
if (schema.items) {
|
|
251
259
|
const itemCheck = compileToJS(schema.items, rootDefs)
|
|
252
260
|
if (!itemCheck) return null
|
|
261
|
+
const start = Array.isArray(schema.prefixItems) ? schema.prefixItems.length : 0
|
|
253
262
|
checks.push((d) => {
|
|
254
263
|
if (!Array.isArray(d)) return true
|
|
255
|
-
for (let i =
|
|
264
|
+
for (let i = start; i < d.length; i++) {
|
|
256
265
|
if (!itemCheck(d[i])) return false
|
|
257
266
|
}
|
|
258
267
|
return true
|
|
@@ -330,7 +339,11 @@ function compileToJS(schema, defs, schemaMap) {
|
|
|
330
339
|
}
|
|
331
340
|
if (schema.multipleOf !== undefined) {
|
|
332
341
|
const div = schema.multipleOf
|
|
333
|
-
checks.push((d) =>
|
|
342
|
+
checks.push((d) => {
|
|
343
|
+
if (typeof d !== 'number') return true
|
|
344
|
+
const r = d % div
|
|
345
|
+
return Math.abs(r) <= 1e-8 || Math.abs(r - div) <= 1e-8
|
|
346
|
+
})
|
|
334
347
|
}
|
|
335
348
|
|
|
336
349
|
// string
|
|
@@ -352,10 +365,12 @@ function compileToJS(schema, defs, schemaMap) {
|
|
|
352
365
|
}
|
|
353
366
|
}
|
|
354
367
|
|
|
355
|
-
// format — hand-written fast checks
|
|
368
|
+
// format — hand-written fast checks. A format the code generator asserts
|
|
369
|
+
// but this path cannot is a decline, not a pass.
|
|
356
370
|
if (schema.format) {
|
|
357
371
|
const fc = FORMAT_CHECKS[schema.format]
|
|
358
372
|
if (fc) checks.push((d) => typeof d !== 'string' || fc(d))
|
|
373
|
+
else if (FORMAT_CODEGEN[schema.format]) return null
|
|
359
374
|
}
|
|
360
375
|
|
|
361
376
|
// array size
|
|
@@ -371,11 +386,11 @@ function compileToJS(schema, defs, schemaMap) {
|
|
|
371
386
|
// object size
|
|
372
387
|
if (schema.minProperties !== undefined) {
|
|
373
388
|
const min = schema.minProperties
|
|
374
|
-
checks.push((d) => typeof d !== 'object' || d === null || Object.keys(d).length >= min)
|
|
389
|
+
checks.push((d) => typeof d !== 'object' || d === null || Array.isArray(d) || Object.keys(d).length >= min)
|
|
375
390
|
}
|
|
376
391
|
if (schema.maxProperties !== undefined) {
|
|
377
392
|
const max = schema.maxProperties
|
|
378
|
-
checks.push((d) => typeof d !== 'object' || d === null || Object.keys(d).length <= max)
|
|
393
|
+
checks.push((d) => typeof d !== 'object' || d === null || Array.isArray(d) || Object.keys(d).length <= max)
|
|
379
394
|
}
|
|
380
395
|
|
|
381
396
|
// allOf
|
|
@@ -558,7 +573,7 @@ function walkJsonPointer(root, fragment) {
|
|
|
558
573
|
for (const p of parts) {
|
|
559
574
|
if (target == null || typeof target !== 'object') return null
|
|
560
575
|
if (!(p in target)) {
|
|
561
|
-
const alt = p === 'definitions' ? '$defs' : p === '$defs' ? 'definitions' : null
|
|
576
|
+
const alt = p === 'definitions' ? '$defs' : p === '$defs' ? 'definitions' : p === 'items' && Array.isArray(target.prefixItems) ? 'prefixItems' : null
|
|
562
577
|
if (alt !== null && alt in target) { target = target[alt]; continue }
|
|
563
578
|
return null
|
|
564
579
|
}
|
|
@@ -597,8 +612,9 @@ function resolveCrossSchemaRef(ref, schemaMap) {
|
|
|
597
612
|
}
|
|
598
613
|
|
|
599
614
|
function resolveRef(ref, defs, schemaMap) {
|
|
600
|
-
// Self-reference: "#"
|
|
601
|
-
|
|
615
|
+
// Self-reference: "#" cannot be expressed as a closure without a recursion
|
|
616
|
+
// guard. Decline rather than substitute a vacuous check.
|
|
617
|
+
if (ref === '#') return null
|
|
602
618
|
|
|
603
619
|
// 1. Local ref
|
|
604
620
|
if (defs) {
|
|
@@ -660,6 +676,13 @@ const TYPE_CHECKS = {
|
|
|
660
676
|
object: (d) => typeof d === 'object' && d !== null && !Array.isArray(d),
|
|
661
677
|
}
|
|
662
678
|
|
|
679
|
+
// Key-order independent JSON rendering for const/enum comparison.
|
|
680
|
+
function _canonical(x) {
|
|
681
|
+
if (x === null || typeof x !== 'object') return JSON.stringify(x)
|
|
682
|
+
if (Array.isArray(x)) return '[' + x.map(_canonical).join(',') + ']'
|
|
683
|
+
return '{' + Object.keys(x).sort().map((k) => JSON.stringify(k) + ':' + _canonical(x[k])).join(',') + '}'
|
|
684
|
+
}
|
|
685
|
+
|
|
663
686
|
const FORMAT_CHECKS = {
|
|
664
687
|
email: (s) => { const at = s.indexOf('@'); return at > 0 && at < s.length - 1 && s.indexOf('.', at) > at + 1 },
|
|
665
688
|
date: (s) => { if (s.length !== 10 || !/^\d{4}-\d{2}-\d{2}$/.test(s)) return false; const m = +s.slice(5, 7), d = +s.slice(8, 10); return m >= 1 && m <= 12 && d >= 1 && d <= 31 },
|
|
@@ -845,6 +868,16 @@ function codegenSafe(schema, schemaMap) {
|
|
|
845
868
|
if (typeof schema.unevaluatedProperties === 'object' && schema.unevaluatedProperties !== null) {
|
|
846
869
|
if (!codegenSafe(schema.unevaluatedProperties, schemaMap)) return false
|
|
847
870
|
}
|
|
871
|
+
// When evaluation is both dynamic (branch-dependent) and some branch
|
|
872
|
+
// unconditionally evaluates all properties, static tracking cannot
|
|
873
|
+
// correctly determine which properties are unevaluated at runtime.
|
|
874
|
+
// For example, a oneOf whose branches include both patternProperties
|
|
875
|
+
// and unevaluatedProperties:true requires annotation-aware evaluation
|
|
876
|
+
// that only the interpreted engine provides.
|
|
877
|
+
if (schema.unevaluatedProperties === false || (typeof schema.unevaluatedProperties === 'object' && schema.unevaluatedProperties !== null)) {
|
|
878
|
+
const evalResult = collectEvaluated(schema, schemaMap)
|
|
879
|
+
if (evalResult.dynamic && evalResult.allProps) return false
|
|
880
|
+
}
|
|
848
881
|
}
|
|
849
882
|
// unevaluatedItems: allow boolean and schema values
|
|
850
883
|
if (schema.unevaluatedItems !== undefined) {
|
|
@@ -861,15 +894,52 @@ function codegenSafe(schema, schemaMap) {
|
|
|
861
894
|
const defs = schema.$defs || schema.definitions
|
|
862
895
|
if (defs) {
|
|
863
896
|
const defNames = new Set(Object.keys(defs))
|
|
864
|
-
// Detect cyclic local refs:
|
|
865
|
-
//
|
|
866
|
-
//
|
|
867
|
-
//
|
|
868
|
-
//
|
|
869
|
-
|
|
870
|
-
const
|
|
871
|
-
|
|
872
|
-
|
|
897
|
+
// Detect cyclic local refs: build a directed graph of def->def references and
|
|
898
|
+
// check for cycles using DFS. A plain cross-reference (A -> B where B doesn't
|
|
899
|
+
// refer back to A) is fine; only true cycles (A -> B -> A) must be rejected.
|
|
900
|
+
// The JS codegen returns (() => true) on cycle (permissive), so cyclic schemas
|
|
901
|
+
// must route to the interpreted engine instead.
|
|
902
|
+
const defRefs = {}
|
|
903
|
+
for (const [name, def] of Object.entries(defs)) {
|
|
904
|
+
defRefs[name] = []
|
|
905
|
+
if (typeof def === 'object' && def !== null) {
|
|
906
|
+
const refs = []
|
|
907
|
+
const seen = new WeakSet()
|
|
908
|
+
const collectRefs = (node) => {
|
|
909
|
+
if (typeof node !== 'object' || node === null) return
|
|
910
|
+
if (seen.has(node)) return
|
|
911
|
+
seen.add(node)
|
|
912
|
+
if (node.$ref) {
|
|
913
|
+
const m = /^#\/(?:\$defs|definitions)\/([^/]+)$/.exec(node.$ref)
|
|
914
|
+
if (m && defNames.has(m[1])) refs.push(m[1])
|
|
915
|
+
}
|
|
916
|
+
for (const val of Object.values(node)) {
|
|
917
|
+
if (typeof val === 'object' && val !== null) {
|
|
918
|
+
if (Array.isArray(val)) { for (const item of val) collectRefs(item) }
|
|
919
|
+
else collectRefs(val)
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
collectRefs(def)
|
|
924
|
+
defRefs[name] = refs
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
const hasCycle = (() => {
|
|
928
|
+
const visited = new Set()
|
|
929
|
+
const inStack = new Set()
|
|
930
|
+
const dfs = (node) => {
|
|
931
|
+
if (inStack.has(node)) return true
|
|
932
|
+
if (visited.has(node)) return false
|
|
933
|
+
visited.add(node)
|
|
934
|
+
inStack.add(node)
|
|
935
|
+
for (const neighbor of (defRefs[node] || [])) {
|
|
936
|
+
if (dfs(neighbor)) return true
|
|
937
|
+
}
|
|
938
|
+
inStack.delete(node)
|
|
939
|
+
return false
|
|
940
|
+
}
|
|
941
|
+
return Object.keys(defRefs).some(dfs)
|
|
942
|
+
})()
|
|
873
943
|
if (hasCycle) return false
|
|
874
944
|
for (const [name, def] of Object.entries(defs)) {
|
|
875
945
|
if (/[~/"']/.test(name)) return false // special chars in def name
|
|
@@ -1100,14 +1170,85 @@ function hasUnresolvableRef(node, rootDefs, anchors, schemaMap, seen) {
|
|
|
1100
1170
|
return false
|
|
1101
1171
|
}
|
|
1102
1172
|
|
|
1173
|
+
|
|
1174
|
+
// --- The one gate every code generation entry point runs first ---
|
|
1175
|
+
//
|
|
1176
|
+
// Four entry points build four contexts, and three times a bail present in
|
|
1177
|
+
// one was missing from another; each time the generator emitted nothing for
|
|
1178
|
+
// a construct it could not represent and returned the empty program as
|
|
1179
|
+
// always-valid. The checks that do not depend on an entry point's own anchor
|
|
1180
|
+
// map live here, so adding a bail is one edit. Entry-point-specific checks
|
|
1181
|
+
// (hasUnresolvableRef against each path's anchors) still run after this.
|
|
1182
|
+
// tests/test_codegen_entrypoint_agreement.js holds the four to one verdict.
|
|
1183
|
+
|
|
1184
|
+
function collectExternalRefKeys(node, out, seen) {
|
|
1185
|
+
if (typeof node !== 'object' || node === null) return
|
|
1186
|
+
if (seen.has(node)) return
|
|
1187
|
+
seen.add(node)
|
|
1188
|
+
if (Array.isArray(node)) { for (const n of node) collectExternalRefKeys(n, out, seen); return }
|
|
1189
|
+
for (const key of Object.keys(node)) {
|
|
1190
|
+
const v = node[key]
|
|
1191
|
+
if ((key === '$ref' || key === '$dynamicRef') && typeof v === 'string' && !v.startsWith('#')) out.add(v.split('#')[0])
|
|
1192
|
+
else if (typeof v === 'object' && v !== null && key !== 'enum' && key !== 'const' && key !== 'default' && key !== 'examples') collectExternalRefKeys(v, out, seen)
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
|
|
1196
|
+
function lookupExternal(key, schemaMap) {
|
|
1197
|
+
if (schemaMap.has(key)) return schemaMap.get(key)
|
|
1198
|
+
if (!key.includes('://')) {
|
|
1199
|
+
for (const [id, doc] of schemaMap) if (id.endsWith('/' + key)) return doc
|
|
1200
|
+
}
|
|
1201
|
+
return null
|
|
1202
|
+
}
|
|
1203
|
+
|
|
1204
|
+
// Documents reachable from `schema` through cross-document references.
|
|
1205
|
+
function reachableExternalDocs(schema, schemaMap) {
|
|
1206
|
+
const docs = new Set()
|
|
1207
|
+
if (!schemaMap || schemaMap.size === 0) return docs
|
|
1208
|
+
const queue = [schema]
|
|
1209
|
+
const seenDocs = new Set([schema])
|
|
1210
|
+
while (queue.length) {
|
|
1211
|
+
const doc = queue.shift()
|
|
1212
|
+
const keys = new Set()
|
|
1213
|
+
collectExternalRefKeys(doc, keys, new Set())
|
|
1214
|
+
for (const key of keys) {
|
|
1215
|
+
const target = lookupExternal(key, schemaMap)
|
|
1216
|
+
if (target && !seenDocs.has(target)) { seenDocs.add(target); docs.add(target); queue.push(target) }
|
|
1217
|
+
}
|
|
1218
|
+
}
|
|
1219
|
+
return docs
|
|
1220
|
+
}
|
|
1221
|
+
|
|
1222
|
+
// Dynamic scope and annotation tracking across documents is interpreter
|
|
1223
|
+
// work. A referenced document that uses either must decline the whole
|
|
1224
|
+
// schema, or the generator emits a vacuous check for the reference.
|
|
1225
|
+
function externalDocsNeedInterpreter(schema, schemaMap) {
|
|
1226
|
+
for (const doc of reachableExternalDocs(schema, schemaMap)) {
|
|
1227
|
+
const str = JSON.stringify(doc)
|
|
1228
|
+
if (str.includes('"$dynamicRef"') || str.includes('"$dynamicAnchor"') ||
|
|
1229
|
+
str.includes('"unevaluatedProperties"') || str.includes('"unevaluatedItems"')) return true
|
|
1230
|
+
// An embedded $id inside a referenced document opens a resource the
|
|
1231
|
+
// generator never registers, so references to it would be vacuous.
|
|
1232
|
+
if (typeof doc === 'object' && doc !== null && hasNestedIdScope(doc)) return true
|
|
1233
|
+
}
|
|
1234
|
+
return false
|
|
1235
|
+
}
|
|
1236
|
+
|
|
1237
|
+
function sharedCodegenGate(schema, schemaMap) {
|
|
1238
|
+
if (typeof schema !== 'object' || schema === null) return true
|
|
1239
|
+
if (!codegenSafe(schema, schemaMap)) return false
|
|
1240
|
+
if (needsBaseTracking(schema, schemaMap, new Set())) return false
|
|
1241
|
+
if (externalDocsNeedInterpreter(schema, schemaMap)) return false
|
|
1242
|
+
return true
|
|
1243
|
+
}
|
|
1244
|
+
|
|
1103
1245
|
// --- Codegen mode: generates a single Function (NOT CSP-safe) ---
|
|
1104
1246
|
// This matches ajv's approach: one monolithic function, V8 JIT fully inlines it
|
|
1105
1247
|
function compileToJSCodegen(schema, schemaMap, userFormats) {
|
|
1106
1248
|
if (typeof schema === 'boolean') return schema ? () => true : () => false
|
|
1107
1249
|
if (typeof schema !== 'object' || schema === null) return null
|
|
1108
1250
|
|
|
1109
|
-
|
|
1110
|
-
if (!codegenSafe(schema, schemaMap)) return null
|
|
1251
|
+
if (!sharedCodegenGate(schema, schemaMap)) return null
|
|
1111
1252
|
|
|
1112
1253
|
// Collect defs for $ref resolution
|
|
1113
1254
|
const rootDefs = schema.$defs || schema.definitions || null
|
|
@@ -1243,7 +1384,13 @@ function compileToJSCodegen(schema, schemaMap, userFormats) {
|
|
|
1243
1384
|
const fmtEntries = []
|
|
1244
1385
|
for (let i = 0; i < closureNames.length; i++) {
|
|
1245
1386
|
if (closureNames[i].startsWith('_uf_')) {
|
|
1246
|
-
|
|
1387
|
+
// The format's own name, so an emitter can look it up at runtime
|
|
1388
|
+
// instead of embedding the function.
|
|
1389
|
+
let format = null
|
|
1390
|
+
for (const key of Object.keys(ctx.userFormats)) {
|
|
1391
|
+
if (ctx.userFormats[key] === closureValues[i]) { format = key; break }
|
|
1392
|
+
}
|
|
1393
|
+
fmtEntries.push({ name: closureNames[i], fn: closureValues[i], format })
|
|
1247
1394
|
}
|
|
1248
1395
|
}
|
|
1249
1396
|
if (fmtEntries.length) boolFn._formatClosures = fmtEntries
|
|
@@ -1387,7 +1534,7 @@ function tryGenCombined(schema, access, ctx) {
|
|
|
1387
1534
|
if (schema.maximum !== undefined) conds.push(`_v>${schema.maximum}`)
|
|
1388
1535
|
if (schema.exclusiveMinimum !== undefined) conds.push(`_v<=${schema.exclusiveMinimum}`)
|
|
1389
1536
|
if (schema.exclusiveMaximum !== undefined) conds.push(`_v>=${schema.exclusiveMaximum}`)
|
|
1390
|
-
if (schema.multipleOf !== undefined) conds.push(`_v%${schema.multipleOf}
|
|
1537
|
+
if (schema.multipleOf !== undefined) conds.push(`(Math.abs(_v%${schema.multipleOf})>1e-8&&Math.abs(_v%${schema.multipleOf}-${schema.multipleOf})>1e-8)`)
|
|
1391
1538
|
if (conds.length < 2) return null
|
|
1392
1539
|
return bind(conds)
|
|
1393
1540
|
}
|
|
@@ -1398,7 +1545,7 @@ function tryGenCombined(schema, access, ctx) {
|
|
|
1398
1545
|
if (schema.maximum !== undefined) conds.push(`_v>${schema.maximum}`)
|
|
1399
1546
|
if (schema.exclusiveMinimum !== undefined) conds.push(`_v<=${schema.exclusiveMinimum}`)
|
|
1400
1547
|
if (schema.exclusiveMaximum !== undefined) conds.push(`_v>=${schema.exclusiveMaximum}`)
|
|
1401
|
-
if (schema.multipleOf !== undefined) conds.push(`_v%${schema.multipleOf}
|
|
1548
|
+
if (schema.multipleOf !== undefined) conds.push(`(Math.abs(_v%${schema.multipleOf})>1e-8&&Math.abs(_v%${schema.multipleOf}-${schema.multipleOf})>1e-8)`)
|
|
1402
1549
|
if (conds.length < 2) return null
|
|
1403
1550
|
return bind(conds)
|
|
1404
1551
|
}
|
|
@@ -1411,7 +1558,9 @@ function tryGenCombined(schema, access, ctx) {
|
|
|
1411
1558
|
// function is only safe when we're at the root (`v === 'd'`). For nested
|
|
1412
1559
|
// nodes, emit inline so block-scoped variables like `_o0` stay in scope.
|
|
1413
1560
|
function _deferOrInline(ctx, lines, v, check) {
|
|
1414
|
-
|
|
1561
|
+
// Deferring is only sound at the top level of the root function. Inside a
|
|
1562
|
+
// conditional applicator (dependentSchemas) the check must stay in its block.
|
|
1563
|
+
if (v === 'd' && !ctx.condDepth) {
|
|
1415
1564
|
if (!ctx.deferredChecks) ctx.deferredChecks = []
|
|
1416
1565
|
ctx.deferredChecks.push(check)
|
|
1417
1566
|
} else {
|
|
@@ -1552,7 +1701,7 @@ function genCode(schema, v, lines, ctx, knownType) {
|
|
|
1552
1701
|
const isArr = effectiveType === 'array'
|
|
1553
1702
|
const isStr = effectiveType === 'string'
|
|
1554
1703
|
const isNum = effectiveType === 'number' || effectiveType === 'integer'
|
|
1555
|
-
const objGuard = isObj ? '' : `typeof ${v}==='object'&&${v}!==null&&`
|
|
1704
|
+
const objGuard = isObj ? '' : `typeof ${v}==='object'&&${v}!==null&&!Array.isArray(${v})&&`
|
|
1556
1705
|
const objCheck = isObj ? '' : `if(typeof ${v}!=='object'||${v}===null)return false;`
|
|
1557
1706
|
|
|
1558
1707
|
// enum
|
|
@@ -1572,7 +1721,12 @@ function genCode(schema, v, lines, ctx, knownType) {
|
|
|
1572
1721
|
if (cv === null || typeof cv !== 'object') {
|
|
1573
1722
|
lines.push(`if(${v}!==${JSON.stringify(cv)})return false`)
|
|
1574
1723
|
} else {
|
|
1575
|
-
|
|
1724
|
+
// Key-order independent comparison, defined inline so every emitter
|
|
1725
|
+
// (runtime, hybrid, standalone) carries it.
|
|
1726
|
+
const ci = ctx.varCounter++
|
|
1727
|
+
const canonFn = `_cnB${ci}`
|
|
1728
|
+
const expected = _canonical(cv)
|
|
1729
|
+
lines.push(`{const ${canonFn}=function(x){if(x===null||typeof x!=='object')return JSON.stringify(x);if(Array.isArray(x))return'['+x.map(${canonFn}).join(',')+']';return'{'+Object.keys(x).sort().map(function(k){return JSON.stringify(k)+':'+${canonFn}(x[k])}).join(',')+'}'};if(${canonFn}(${v})!==${JSON.stringify(expected)})return false}`)
|
|
1576
1730
|
}
|
|
1577
1731
|
}
|
|
1578
1732
|
|
|
@@ -1600,9 +1754,9 @@ function genCode(schema, v, lines, ctx, knownType) {
|
|
|
1600
1754
|
const checks = schema.required.map(key => `${v}[${JSON.stringify(key)}]===undefined`)
|
|
1601
1755
|
lines.push(`if(${checks.join('||')})return false`)
|
|
1602
1756
|
} else {
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
}
|
|
1757
|
+
// required applies to objects only; other types are ignored.
|
|
1758
|
+
const checks = schema.required.map(key => `${v}[${JSON.stringify(key)}]===undefined`)
|
|
1759
|
+
lines.push(`if(typeof ${v}==='object'&&${v}!==null&&!Array.isArray(${v})&&(${checks.join('||')}))return false`)
|
|
1606
1760
|
}
|
|
1607
1761
|
}
|
|
1608
1762
|
|
|
@@ -1632,7 +1786,11 @@ function genCode(schema, v, lines, ctx, knownType) {
|
|
|
1632
1786
|
if (schema.maximum !== undefined) lines.push(isNum ? `if(${v}>${schema.maximum})return false` : `if(typeof ${v}==='number'&&${v}>${schema.maximum})return false`)
|
|
1633
1787
|
if (schema.exclusiveMinimum !== undefined) lines.push(isNum ? `if(${v}<=${schema.exclusiveMinimum})return false` : `if(typeof ${v}==='number'&&${v}<=${schema.exclusiveMinimum})return false`)
|
|
1634
1788
|
if (schema.exclusiveMaximum !== undefined) lines.push(isNum ? `if(${v}>=${schema.exclusiveMaximum})return false` : `if(typeof ${v}==='number'&&${v}>=${schema.exclusiveMaximum})return false`)
|
|
1635
|
-
if (schema.multipleOf !== undefined)
|
|
1789
|
+
if (schema.multipleOf !== undefined) {
|
|
1790
|
+
const m = schema.multipleOf
|
|
1791
|
+
const bad = `(Math.abs(${v}%${m})>1e-8&&Math.abs(${v}%${m}-${m})>1e-8)`
|
|
1792
|
+
lines.push(isNum ? `if${bad}return false` : `if(typeof ${v}==='number'&&${bad})return false`)
|
|
1793
|
+
}
|
|
1636
1794
|
|
|
1637
1795
|
// string length — skip type guard if known string.
|
|
1638
1796
|
// s.length (UTF-16 code units) is an upper bound on cpLen, and at least cpLen
|
|
@@ -1891,7 +2049,9 @@ function genCode(schema, v, lines, ctx, knownType) {
|
|
|
1891
2049
|
for (const [key, depSchema] of Object.entries(schema.dependentSchemas)) {
|
|
1892
2050
|
const guard = isObj ? '' : `typeof ${v}==='object'&&${v}!==null&&!Array.isArray(${v})&&`
|
|
1893
2051
|
lines.push(`if(${guard}${JSON.stringify(key)} in ${v}){`)
|
|
2052
|
+
ctx.condDepth = (ctx.condDepth || 0) + 1
|
|
1894
2053
|
genCode(depSchema, v, lines, ctx, effectiveType)
|
|
2054
|
+
ctx.condDepth--
|
|
1895
2055
|
lines.push(`}`)
|
|
1896
2056
|
}
|
|
1897
2057
|
}
|
|
@@ -1968,9 +2128,11 @@ function genCode(schema, v, lines, ctx, knownType) {
|
|
|
1968
2128
|
const idx = `_j${ctx.varCounter}`
|
|
1969
2129
|
const elem = `_e${ctx.varCounter}`
|
|
1970
2130
|
ctx.varCounter++
|
|
2131
|
+
// items applies after the prefixItems positions (Draft 2020-12).
|
|
2132
|
+
const start = Array.isArray(schema.prefixItems) ? schema.prefixItems.length : 0
|
|
1971
2133
|
lines.push(isArr
|
|
1972
|
-
? `for(let ${idx}
|
|
1973
|
-
: `if(Array.isArray(${v})){for(let ${idx}
|
|
2134
|
+
? `for(let ${idx}=${start};${idx}<${v}.length;${idx}++){const ${elem}=${v}[${idx}]`
|
|
2135
|
+
: `if(Array.isArray(${v})){for(let ${idx}=${start};${idx}<${v}.length;${idx}++){const ${elem}=${v}[${idx}]`)
|
|
1974
2136
|
genCode(schema.items, elem, lines, ctx)
|
|
1975
2137
|
lines.push(isArr ? `}` : `}}`)
|
|
1976
2138
|
}
|
|
@@ -2635,6 +2797,9 @@ const FORMAT_CODEGEN = {
|
|
|
2635
2797
|
|
|
2636
2798
|
// Safe key escaping: use JSON.stringify to handle all special chars (newlines, null bytes, etc.)
|
|
2637
2799
|
function esc(s) { return JSON.stringify(s).slice(1, -1) }
|
|
2800
|
+
// A schema pointer segment for a pattern: JSON Pointer escaping, then made
|
|
2801
|
+
// safe for the single-quoted literal the error emitters use.
|
|
2802
|
+
function ptrSeg(s) { return s.replace(/~/g, '~0').replace(/\//g, '~1').replace(/\\/g, '\\\\').replace(/'/g, "\\'") }
|
|
2638
2803
|
|
|
2639
2804
|
// Resolve child path at codegen time when parent is a static string literal.
|
|
2640
2805
|
// This enables frozen pre-allocation for ALL nested error objects.
|
|
@@ -2781,7 +2946,7 @@ function compileToJSCodegenWithErrors(schema, schemaMap, userFormats, sourceOpts
|
|
|
2781
2946
|
: () => ({ valid: false, errors: [{ keyword: 'false schema', instancePath: '', schemaPath: '#', params: {}, message: 'boolean schema is false' }] })
|
|
2782
2947
|
}
|
|
2783
2948
|
if (typeof schema !== 'object' || schema === null) return null
|
|
2784
|
-
if (!
|
|
2949
|
+
if (!sharedCodegenGate(schema, schemaMap)) return null
|
|
2785
2950
|
if (schema.patternProperties) {
|
|
2786
2951
|
for (const [pat, sub] of Object.entries(schema.patternProperties)) {
|
|
2787
2952
|
if (typeof sub === 'boolean') return null
|
|
@@ -3179,13 +3344,30 @@ function genCodeE(schema, v, pathExpr, lines, ctx, schemaPrefix) {
|
|
|
3179
3344
|
lines.push(`if(typeof ${v}==='object'&&${v}!==null&&!Array.isArray(${v})&&Object.keys(${v}).length>${schema.maxProperties}){${fail('maxProperties', 'maxProperties', `{limit:${schema.maxProperties}}`, `'must NOT have more than ${schema.maxProperties} properties'`)}}`)
|
|
3180
3345
|
}
|
|
3181
3346
|
|
|
3182
|
-
// additionalProperties: false
|
|
3183
|
-
|
|
3184
|
-
|
|
3347
|
+
// additionalProperties: false. A key matched by any patternProperties
|
|
3348
|
+
// entry is not additional, so those patterns are consulted here as well.
|
|
3349
|
+
if (schema.additionalProperties === false && (schema.properties || schema.patternProperties)) {
|
|
3350
|
+
const allowed = Object.keys(schema.properties || {}).map(k => `${JSON.stringify(k)}`).join(',')
|
|
3185
3351
|
const ci = ctx.varCounter++
|
|
3186
3352
|
const apSp = `${schemaPrefix}/additionalProperties`
|
|
3187
3353
|
const apLit = buildErrorLiteral({ keyword: 'additionalProperties', schemaPath: apSp, sourceMap: ctx.sourceMap })
|
|
3188
|
-
const
|
|
3354
|
+
const patChecks = []
|
|
3355
|
+
for (const pat of Object.keys(schema.patternProperties || {})) {
|
|
3356
|
+
const pattern = JSON.stringify(pat)
|
|
3357
|
+
if (!ctx.regExpMap.has(pattern)) {
|
|
3358
|
+
const ri = ctx.varCounter++
|
|
3359
|
+
ctx.regExpMap.set(pattern, ri)
|
|
3360
|
+
if (patternIsSafe(pat)) {
|
|
3361
|
+
ctx.helperCode.push(`const _re${ri}=__ataSafeRe(${pattern})`)
|
|
3362
|
+
ctx.usesSafeRe = true
|
|
3363
|
+
} else {
|
|
3364
|
+
ctx.helperCode.push(`const _re${ri}=new RegExp(${pattern})`)
|
|
3365
|
+
}
|
|
3366
|
+
}
|
|
3367
|
+
patChecks.push(`_re${ctx.regExpMap.get(pattern)}.test(_k${ci}[_i])`)
|
|
3368
|
+
}
|
|
3369
|
+
const isAdditional = patChecks.length ? `!_a${ci}.has(_k${ci}[_i])&&!(${patChecks.join('||')})` : `!_a${ci}.has(_k${ci}[_i])`
|
|
3370
|
+
const inner = `const _k${ci}=Object.keys(${v});const _a${ci}=new Set([${allowed}]);for(let _i=0;_i<_k${ci}.length;_i++){if(${isAdditional}){_e.push({code:'${apLit.codeStr}',keyword:'additionalProperties',instancePath:${pathExpr||'""'},schemaPath:'${apSp}',params:{additionalProperty:_k${ci}[_i]},message:'must NOT have additional properties',docUrl:'${apLit.docUrl}'${apLit.frame}});if(!_all)return{valid:false,errors:_e}}}`
|
|
3189
3371
|
lines.push(isObj ? `{${inner}}` : `if(typeof ${v}==='object'&&${v}!==null&&!Array.isArray(${v})){${inner}}`)
|
|
3190
3372
|
}
|
|
3191
3373
|
|
|
@@ -3228,7 +3410,8 @@ function genCodeE(schema, v, pathExpr, lines, ctx, schemaPrefix) {
|
|
|
3228
3410
|
const ki = ctx.varCounter++
|
|
3229
3411
|
lines.push(`if(typeof ${v}==='object'&&${v}!==null&&!Array.isArray(${v})){for(const _k${ki} in ${v}){if(_re${ri}.test(_k${ki})){`)
|
|
3230
3412
|
const p = pathExpr ? `${pathExpr}+'/'+_k${ki}` : `'/'+_k${ki}`
|
|
3231
|
-
|
|
3413
|
+
// The real pointer, so source maps can locate the failing keyword.
|
|
3414
|
+
genCodeE(sub, `${v}[_k${ki}]`, p, lines, ctx, schemaPrefix + '/patternProperties/' + pat.replace(/~/g, '~0').replace(/\//g, '~1'))
|
|
3232
3415
|
lines.push(`}}}`)
|
|
3233
3416
|
}
|
|
3234
3417
|
}
|
|
@@ -3407,7 +3590,7 @@ function compileToJSCombined(schema, VALID_RESULT, schemaMap, userFormats) {
|
|
|
3407
3590
|
: () => ({ valid: false, errors: [{ keyword: 'false schema', instancePath: '', schemaPath: '#', params: {}, message: 'boolean schema is false' }] })
|
|
3408
3591
|
}
|
|
3409
3592
|
if (typeof schema !== 'object' || schema === null) return null
|
|
3410
|
-
if (!
|
|
3593
|
+
if (!sharedCodegenGate(schema, schemaMap)) return null
|
|
3411
3594
|
if (schema.patternProperties) {
|
|
3412
3595
|
for (const [pat, sub] of Object.entries(schema.patternProperties)) {
|
|
3413
3596
|
if (typeof sub === 'boolean') return null
|
|
@@ -3841,17 +4024,6 @@ function genCodeC(schema, v, pathExpr, lines, ctx, schemaPrefix) {
|
|
|
3841
4024
|
}
|
|
3842
4025
|
}
|
|
3843
4026
|
|
|
3844
|
-
// Build sub-schema validators as closure vars
|
|
3845
|
-
for (let i = 0; i < ppEntries.length; i++) {
|
|
3846
|
-
const [, sub] = ppEntries[i]
|
|
3847
|
-
const subLines = []
|
|
3848
|
-
genCode(sub, `_ppv`, subLines, ctx)
|
|
3849
|
-
const fnBody = subLines.length === 0 ? `return true` : `${subLines.join(';')};return true`
|
|
3850
|
-
const fnVar = `_ppf${pi}_${i}`
|
|
3851
|
-
ctx.closureVars.push(fnVar)
|
|
3852
|
-
ctx.closureVals.push(new Function('_ppv', fnBody))
|
|
3853
|
-
}
|
|
3854
|
-
|
|
3855
4027
|
const guard = isObj ? '' : `if(typeof ${v}==='object'&&${v}!==null&&!Array.isArray(${v}))`
|
|
3856
4028
|
const kVar = `_k${pi}`
|
|
3857
4029
|
|
|
@@ -3895,7 +4067,11 @@ function genCodeC(schema, v, pathExpr, lines, ctx, schemaPrefix) {
|
|
|
3895
4067
|
const matchExpr = keyCheck || `_as${pi}.has(${kVar})`
|
|
3896
4068
|
lines.push(`let _m${pi}=${matchExpr}`)
|
|
3897
4069
|
for (let i = 0; i < ppEntries.length; i++) {
|
|
3898
|
-
|
|
4070
|
+
// The subschema is generated in place so its own keywords report
|
|
4071
|
+
// the real instance path and schema pointer.
|
|
4072
|
+
lines.push(`if(${matchers[i].check}){_m${pi}=true;{const _ppv${pi}_${i}=${v}[${kVar}]`)
|
|
4073
|
+
genCodeC(ppEntries[i][1], `_ppv${pi}_${i}`, childPathDynExpr(pathExpr, kVar), lines, ctx, schemaPrefix + '/patternProperties/' + ptrSeg(ppEntries[i][0]))
|
|
4074
|
+
lines.push(`}}`)
|
|
3899
4075
|
}
|
|
3900
4076
|
lines.push(`if(!_m${pi}){${fail('additionalProperties', 'additionalProperties', `{additionalProperty:${kVar}}`, "'must NOT have additional properties'")}}`)
|
|
3901
4077
|
lines.push(`}}`)
|
|
@@ -3925,7 +4101,9 @@ function genCodeC(schema, v, pathExpr, lines, ctx, schemaPrefix) {
|
|
|
3925
4101
|
}
|
|
3926
4102
|
}
|
|
3927
4103
|
for (let i = 0; i < ppEntries.length; i++) {
|
|
3928
|
-
lines.push(`if(${matchers[i].check}
|
|
4104
|
+
lines.push(`if(${matchers[i].check}){const _ppv${pi}_${i}=${v}[${kVar}]`)
|
|
4105
|
+
genCodeC(ppEntries[i][1], `_ppv${pi}_${i}`, childPathDynExpr(pathExpr, kVar), lines, ctx, schemaPrefix + '/patternProperties/' + ptrSeg(ppEntries[i][0]))
|
|
4106
|
+
lines.push(`}`)
|
|
3929
4107
|
}
|
|
3930
4108
|
lines.push(`}}`)
|
|
3931
4109
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// The official meta-schemas, vendored so a `$ref` to one of them resolves
|
|
4
|
+
// without a network. Draft 2020-12 is eight documents joined by $dynamicRef;
|
|
5
|
+
// draft-07 is one. Sources: https://json-schema.org/draft/2020-12/schema and
|
|
6
|
+
// http://json-schema.org/draft-07/schema, fetched 2026-08-23, unmodified.
|
|
7
|
+
// Keyed by $id; index.js also registers the http/https and trailing-# spellings.
|
|
8
|
+
|
|
9
|
+
const METASCHEMAS = new Map([
|
|
10
|
+
["https://json-schema.org/draft/2020-12/schema", {"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://json-schema.org/draft/2020-12/schema","$vocabulary":{"https://json-schema.org/draft/2020-12/vocab/core":true,"https://json-schema.org/draft/2020-12/vocab/applicator":true,"https://json-schema.org/draft/2020-12/vocab/unevaluated":true,"https://json-schema.org/draft/2020-12/vocab/validation":true,"https://json-schema.org/draft/2020-12/vocab/meta-data":true,"https://json-schema.org/draft/2020-12/vocab/format-annotation":true,"https://json-schema.org/draft/2020-12/vocab/content":true},"$dynamicAnchor":"meta","title":"Core and Validation specifications meta-schema","allOf":[{"$ref":"meta/core"},{"$ref":"meta/applicator"},{"$ref":"meta/unevaluated"},{"$ref":"meta/validation"},{"$ref":"meta/meta-data"},{"$ref":"meta/format-annotation"},{"$ref":"meta/content"}],"type":["object","boolean"],"$comment":"This meta-schema also defines keywords that have appeared in previous drafts in order to prevent incompatible extensions as they remain in common use.","properties":{"definitions":{"$comment":"\"definitions\" has been replaced by \"$defs\".","type":"object","additionalProperties":{"$dynamicRef":"#meta"},"deprecated":true,"default":{}},"dependencies":{"$comment":"\"dependencies\" has been split and replaced by \"dependentSchemas\" and \"dependentRequired\" in order to serve their differing semantics.","type":"object","additionalProperties":{"anyOf":[{"$dynamicRef":"#meta"},{"$ref":"meta/validation#/$defs/stringArray"}]},"deprecated":true,"default":{}},"$recursiveAnchor":{"$comment":"\"$recursiveAnchor\" has been replaced by \"$dynamicAnchor\".","$ref":"meta/core#/$defs/anchorString","deprecated":true},"$recursiveRef":{"$comment":"\"$recursiveRef\" has been replaced by \"$dynamicRef\".","$ref":"meta/core#/$defs/uriReferenceString","deprecated":true}}}],
|
|
11
|
+
["https://json-schema.org/draft/2020-12/meta/core", {"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://json-schema.org/draft/2020-12/meta/core","$dynamicAnchor":"meta","title":"Core vocabulary meta-schema","type":["object","boolean"],"properties":{"$id":{"$ref":"#/$defs/uriReferenceString","$comment":"Non-empty fragments not allowed.","pattern":"^[^#]*#?$"},"$schema":{"$ref":"#/$defs/uriString"},"$ref":{"$ref":"#/$defs/uriReferenceString"},"$anchor":{"$ref":"#/$defs/anchorString"},"$dynamicRef":{"$ref":"#/$defs/uriReferenceString"},"$dynamicAnchor":{"$ref":"#/$defs/anchorString"},"$vocabulary":{"type":"object","propertyNames":{"$ref":"#/$defs/uriString"},"additionalProperties":{"type":"boolean"}},"$comment":{"type":"string"},"$defs":{"type":"object","additionalProperties":{"$dynamicRef":"#meta"}}},"$defs":{"anchorString":{"type":"string","pattern":"^[A-Za-z_][-A-Za-z0-9._]*$"},"uriString":{"type":"string","format":"uri"},"uriReferenceString":{"type":"string","format":"uri-reference"}}}],
|
|
12
|
+
["https://json-schema.org/draft/2020-12/meta/applicator", {"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://json-schema.org/draft/2020-12/meta/applicator","$dynamicAnchor":"meta","title":"Applicator vocabulary meta-schema","type":["object","boolean"],"properties":{"prefixItems":{"$ref":"#/$defs/schemaArray"},"items":{"$dynamicRef":"#meta"},"contains":{"$dynamicRef":"#meta"},"additionalProperties":{"$dynamicRef":"#meta"},"properties":{"type":"object","additionalProperties":{"$dynamicRef":"#meta"},"default":{}},"patternProperties":{"type":"object","additionalProperties":{"$dynamicRef":"#meta"},"propertyNames":{"format":"regex"},"default":{}},"dependentSchemas":{"type":"object","additionalProperties":{"$dynamicRef":"#meta"},"default":{}},"propertyNames":{"$dynamicRef":"#meta"},"if":{"$dynamicRef":"#meta"},"then":{"$dynamicRef":"#meta"},"else":{"$dynamicRef":"#meta"},"allOf":{"$ref":"#/$defs/schemaArray"},"anyOf":{"$ref":"#/$defs/schemaArray"},"oneOf":{"$ref":"#/$defs/schemaArray"},"not":{"$dynamicRef":"#meta"}},"$defs":{"schemaArray":{"type":"array","minItems":1,"items":{"$dynamicRef":"#meta"}}}}],
|
|
13
|
+
["https://json-schema.org/draft/2020-12/meta/validation", {"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://json-schema.org/draft/2020-12/meta/validation","$dynamicAnchor":"meta","title":"Validation vocabulary meta-schema","type":["object","boolean"],"properties":{"type":{"anyOf":[{"$ref":"#/$defs/simpleTypes"},{"type":"array","items":{"$ref":"#/$defs/simpleTypes"},"minItems":1,"uniqueItems":true}]},"const":true,"enum":{"type":"array","items":true},"multipleOf":{"type":"number","exclusiveMinimum":0},"maximum":{"type":"number"},"exclusiveMaximum":{"type":"number"},"minimum":{"type":"number"},"exclusiveMinimum":{"type":"number"},"maxLength":{"$ref":"#/$defs/nonNegativeInteger"},"minLength":{"$ref":"#/$defs/nonNegativeIntegerDefault0"},"pattern":{"type":"string","format":"regex"},"maxItems":{"$ref":"#/$defs/nonNegativeInteger"},"minItems":{"$ref":"#/$defs/nonNegativeIntegerDefault0"},"uniqueItems":{"type":"boolean","default":false},"maxContains":{"$ref":"#/$defs/nonNegativeInteger"},"minContains":{"$ref":"#/$defs/nonNegativeInteger","default":1},"maxProperties":{"$ref":"#/$defs/nonNegativeInteger"},"minProperties":{"$ref":"#/$defs/nonNegativeIntegerDefault0"},"required":{"$ref":"#/$defs/stringArray"},"dependentRequired":{"type":"object","additionalProperties":{"$ref":"#/$defs/stringArray"}}},"$defs":{"nonNegativeInteger":{"type":"integer","minimum":0},"nonNegativeIntegerDefault0":{"$ref":"#/$defs/nonNegativeInteger","default":0},"simpleTypes":{"enum":["array","boolean","integer","null","number","object","string"]},"stringArray":{"type":"array","items":{"type":"string"},"uniqueItems":true,"default":[]}}}],
|
|
14
|
+
["https://json-schema.org/draft/2020-12/meta/meta-data", {"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://json-schema.org/draft/2020-12/meta/meta-data","$dynamicAnchor":"meta","title":"Meta-data vocabulary meta-schema","type":["object","boolean"],"properties":{"title":{"type":"string"},"description":{"type":"string"},"default":true,"deprecated":{"type":"boolean","default":false},"readOnly":{"type":"boolean","default":false},"writeOnly":{"type":"boolean","default":false},"examples":{"type":"array","items":true}}}],
|
|
15
|
+
["https://json-schema.org/draft/2020-12/meta/format-annotation", {"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://json-schema.org/draft/2020-12/meta/format-annotation","$dynamicAnchor":"meta","title":"Format vocabulary meta-schema for annotation results","type":["object","boolean"],"properties":{"format":{"type":"string"}}}],
|
|
16
|
+
["https://json-schema.org/draft/2020-12/meta/content", {"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://json-schema.org/draft/2020-12/meta/content","$dynamicAnchor":"meta","title":"Content vocabulary meta-schema","type":["object","boolean"],"properties":{"contentEncoding":{"type":"string"},"contentMediaType":{"type":"string"},"contentSchema":{"$dynamicRef":"#meta"}}}],
|
|
17
|
+
["https://json-schema.org/draft/2020-12/meta/unevaluated", {"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://json-schema.org/draft/2020-12/meta/unevaluated","$dynamicAnchor":"meta","title":"Unevaluated applicator vocabulary meta-schema","type":["object","boolean"],"properties":{"unevaluatedItems":{"$dynamicRef":"#meta"},"unevaluatedProperties":{"$dynamicRef":"#meta"}}}],
|
|
18
|
+
["http://json-schema.org/draft-07/schema#", {"$schema":"http://json-schema.org/draft-07/schema#","$id":"http://json-schema.org/draft-07/schema#","title":"Core schema meta-schema","definitions":{"schemaArray":{"type":"array","minItems":1,"items":{"$ref":"#"}},"nonNegativeInteger":{"type":"integer","minimum":0},"nonNegativeIntegerDefault0":{"allOf":[{"$ref":"#/definitions/nonNegativeInteger"},{"default":0}]},"simpleTypes":{"enum":["array","boolean","integer","null","number","object","string"]},"stringArray":{"type":"array","items":{"type":"string"},"uniqueItems":true,"default":[]}},"type":["object","boolean"],"properties":{"$id":{"type":"string","format":"uri-reference"},"$schema":{"type":"string","format":"uri"},"$ref":{"type":"string","format":"uri-reference"},"$comment":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"default":true,"readOnly":{"type":"boolean","default":false},"writeOnly":{"type":"boolean","default":false},"examples":{"type":"array","items":true},"multipleOf":{"type":"number","exclusiveMinimum":0},"maximum":{"type":"number"},"exclusiveMaximum":{"type":"number"},"minimum":{"type":"number"},"exclusiveMinimum":{"type":"number"},"maxLength":{"$ref":"#/definitions/nonNegativeInteger"},"minLength":{"$ref":"#/definitions/nonNegativeIntegerDefault0"},"pattern":{"type":"string","format":"regex"},"additionalItems":{"$ref":"#"},"items":{"anyOf":[{"$ref":"#"},{"$ref":"#/definitions/schemaArray"}],"default":true},"maxItems":{"$ref":"#/definitions/nonNegativeInteger"},"minItems":{"$ref":"#/definitions/nonNegativeIntegerDefault0"},"uniqueItems":{"type":"boolean","default":false},"contains":{"$ref":"#"},"maxProperties":{"$ref":"#/definitions/nonNegativeInteger"},"minProperties":{"$ref":"#/definitions/nonNegativeIntegerDefault0"},"required":{"$ref":"#/definitions/stringArray"},"additionalProperties":{"$ref":"#"},"definitions":{"type":"object","additionalProperties":{"$ref":"#"},"default":{}},"properties":{"type":"object","additionalProperties":{"$ref":"#"},"default":{}},"patternProperties":{"type":"object","additionalProperties":{"$ref":"#"},"propertyNames":{"format":"regex"},"default":{}},"dependencies":{"type":"object","additionalProperties":{"anyOf":[{"$ref":"#"},{"$ref":"#/definitions/stringArray"}]}},"propertyNames":{"$ref":"#"},"const":true,"enum":{"type":"array","items":true,"minItems":1,"uniqueItems":true},"type":{"anyOf":[{"$ref":"#/definitions/simpleTypes"},{"type":"array","items":{"$ref":"#/definitions/simpleTypes"},"minItems":1,"uniqueItems":true}]},"format":{"type":"string"},"contentMediaType":{"type":"string"},"contentEncoding":{"type":"string"},"if":{"$ref":"#"},"then":{"$ref":"#"},"else":{"$ref":"#"},"allOf":{"$ref":"#/definitions/schemaArray"},"anyOf":{"$ref":"#/definitions/schemaArray"},"oneOf":{"$ref":"#/definitions/schemaArray"},"not":{"$ref":"#"}},"default":true}],
|
|
19
|
+
]);
|
|
20
|
+
|
|
21
|
+
module.exports = { METASCHEMAS };
|