ata-validator 1.16.2 → 1.17.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 +9 -0
- package/index.js +53 -70
- package/lib/js-compiler.js +30 -18
- package/lib/schema-order.js +128 -0
- package/lib/version.js +1 -1
- package/package.json +9 -9
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to ata-validator are documented here. The format follows [Keep a Changelog](https://keepachangelog.com/), and this project adheres to semantic versioning.
|
|
4
4
|
|
|
5
|
+
## 1.17.0 - 2026-09-13
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
|
|
9
|
+
- Errors are put in schema declaration order by an integer computed when the schema is compiled, not by walking each error's schemaPath at read time. The rank of a path is its pre-order position in the schema tree, which is exactly the order the old array-of-indexes comparison produced; the code generator now writes that position into each error literal (`_o`, an internal field), the reader compares integers, and a list that already arrives in order is returned without sorting or allocating. Errors without a position (an appended custom-keyword error, a path into another document) keep their place next to the error before them. The ordinal logic lives in `lib/schema-order.js`; `tests/test_error_order_ordinal.js` holds the ordinal to the array rank on a set of paths and holds the public error order unchanged.
|
|
10
|
+
- The Standard Schema bridge caches parsed issue paths per instancePath string (bounded, entries frozen), instead of splitting the string for every issue of every rejection.
|
|
11
|
+
- Measured on the schema-benchmarks harness locally, before and after on the same machine: standard invalid 3.57 to 2.83 µs (21 percent less); every other row within noise. On the raw error list of that schema, 15 errors: 1.88 to 1.50 µs; through the Standard Schema bridge 3.30 to 1.99 µs. Verdict paths are untouched.
|
|
12
|
+
- `richErrors: false` keeps the v0.14 key set: the ordering field is dropped from that shape.
|
|
13
|
+
|
|
5
14
|
## 1.16.2 - 2026-09-12
|
|
6
15
|
|
|
7
16
|
### Fixed
|
package/index.js
CHANGED
|
@@ -423,83 +423,64 @@ function resolveSchemaByPath(rootSchema, schemaPath) {
|
|
|
423
423
|
// A failing route sees the same handful of schemaPaths over and over, which is
|
|
424
424
|
// what makes the first one worth having.
|
|
425
425
|
const _rankCache = new WeakMap();
|
|
426
|
-
const
|
|
427
|
-
|
|
428
|
-
function keyIndex(node, seg) {
|
|
429
|
-
let index = _keyIndexCache.get(node);
|
|
430
|
-
if (index === undefined) {
|
|
431
|
-
index = new Map();
|
|
432
|
-
const keys = Object.keys(node);
|
|
433
|
-
for (let i = 0; i < keys.length; i++) index.set(keys[i], i);
|
|
434
|
-
_keyIndexCache.set(node, index);
|
|
435
|
-
}
|
|
436
|
-
const at = index.get(seg);
|
|
437
|
-
return at === undefined ? -1 : at;
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
// `~1` and `~0` are the only escapes a JSON pointer has, and almost no schema
|
|
441
|
-
// key contains a tilde. Looking for one is far cheaper than two regex passes
|
|
442
|
-
// over every segment of every path.
|
|
443
|
-
function unescapePointerSegment(seg) {
|
|
444
|
-
return seg.indexOf('~') < 0 ? seg : seg.replace(/~1/g, '/').replace(/~0/g, '~');
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
function schemaOrderRank(rootSchema, schemaPath) {
|
|
448
|
-
if (!schemaPath || typeof schemaPath !== 'string' || !schemaPath.startsWith('#')) return null;
|
|
449
|
-
if (rootSchema === null || typeof rootSchema !== 'object') return null;
|
|
426
|
+
const { rankFor: schemaOrderRank, ordinalFor: schemaOrdinal } = require('./lib/schema-order');
|
|
450
427
|
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
byPath.set(schemaPath, rank);
|
|
458
|
-
return rank;
|
|
428
|
+
// A raw error without the `_o` ordering key, for the legacy error shape.
|
|
429
|
+
function stripOrdinal(e) {
|
|
430
|
+
if (e === null || typeof e !== 'object' || e._o === undefined) return e;
|
|
431
|
+
const out = {};
|
|
432
|
+
for (const k in e) if (k !== '_o') out[k] = e[k];
|
|
433
|
+
return out;
|
|
459
434
|
}
|
|
460
435
|
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
if (idx < 0) break;
|
|
481
|
-
rank.push(idx);
|
|
482
|
-
node = node[seg];
|
|
483
|
-
}
|
|
436
|
+
// Errors in schema declaration order. Each error's key is its schemaPath's
|
|
437
|
+
// pre-order ordinal in the root schema: written into the literal by the code
|
|
438
|
+
// generator (`_o`), looked up once per path otherwise. Most rejections come
|
|
439
|
+
// out already ordered, and those return without sorting or allocating.
|
|
440
|
+
function sortErrorsBySchemaOrder(rootSchema, errors) {
|
|
441
|
+
const n = errors.length;
|
|
442
|
+
const keys = new Array(n);
|
|
443
|
+
let sorted = true;
|
|
444
|
+
let prev = -1;
|
|
445
|
+
for (let i = 0; i < n; i++) {
|
|
446
|
+
const e = errors[i];
|
|
447
|
+
let o = typeof e._o === 'number' ? e._o : schemaOrdinal(rootSchema, e.schemaPath);
|
|
448
|
+
// An error with no place in this document (an appended custom-keyword
|
|
449
|
+
// error, a path into another schema) stays next to the error before it,
|
|
450
|
+
// which is where the rank comparison left it too.
|
|
451
|
+
if (o === null) o = prev < 0 ? 0 : prev;
|
|
452
|
+
keys[i] = o;
|
|
453
|
+
if (o < prev) sorted = false;
|
|
454
|
+
prev = o;
|
|
484
455
|
}
|
|
485
|
-
return
|
|
456
|
+
if (sorted) return errors;
|
|
457
|
+
const idx = new Array(n);
|
|
458
|
+
for (let i = 0; i < n; i++) idx[i] = i;
|
|
459
|
+
idx.sort((a, b) => keys[a] - keys[b] || a - b);
|
|
460
|
+
const out = new Array(n);
|
|
461
|
+
for (let i = 0; i < n; i++) out[i] = errors[idx[i]];
|
|
462
|
+
return out;
|
|
486
463
|
}
|
|
487
464
|
|
|
488
|
-
function sortErrorsBySchemaOrder(rootSchema, errors) {
|
|
489
|
-
const ranked = errors.map((e, i) => ({ e, i, rank: schemaOrderRank(rootSchema, e.schemaPath) }));
|
|
490
|
-
ranked.sort((a, b) => {
|
|
491
|
-
if (!a.rank || !b.rank) return a.i - b.i;
|
|
492
|
-
const n = Math.min(a.rank.length, b.rank.length);
|
|
493
|
-
for (let k = 0; k < n; k++) {
|
|
494
|
-
if (a.rank[k] !== b.rank[k]) return a.rank[k] - b.rank[k];
|
|
495
|
-
}
|
|
496
|
-
return a.i - b.i;
|
|
497
|
-
});
|
|
498
|
-
return ranked.map((r) => r.e);
|
|
499
|
-
}
|
|
500
465
|
|
|
466
|
+
// Paths repeat across rejections of the same shape, so the parsed segment
|
|
467
|
+
// list is cached per path string. Entries are frozen: the same array is
|
|
468
|
+
// handed to every issue that names the path. The cache is bounded so a
|
|
469
|
+
// stream of array indexes cannot grow it without limit.
|
|
470
|
+
const _pathCache = new Map();
|
|
471
|
+
const PATH_CACHE_MAX = 4096;
|
|
501
472
|
function parsePointerPath(path) {
|
|
502
|
-
if (!path) return
|
|
473
|
+
if (!path) return EMPTY_PATH;
|
|
474
|
+
const hit = _pathCache.get(path);
|
|
475
|
+
if (hit !== undefined) return hit;
|
|
476
|
+
const segs = Object.freeze(parsePointerPathUncached(path));
|
|
477
|
+
if (_pathCache.size >= PATH_CACHE_MAX) _pathCache.clear();
|
|
478
|
+
_pathCache.set(path, segs);
|
|
479
|
+
return segs;
|
|
480
|
+
}
|
|
481
|
+
const EMPTY_PATH = Object.freeze([]);
|
|
482
|
+
|
|
483
|
+
function parsePointerPathUncached(path) {
|
|
503
484
|
// One pass, no intermediate arrays. Per Standard Schema V1 an array index
|
|
504
485
|
// is emitted as a number and an object key as a string; a segment is an
|
|
505
486
|
// index when it is all digits with no leading zero.
|
|
@@ -1463,7 +1444,9 @@ class Validator {
|
|
|
1463
1444
|
schemaPositions: self._schemaPositions,
|
|
1464
1445
|
schemaFile: self._source ? self._source.path : undefined,
|
|
1465
1446
|
}))
|
|
1466
|
-
|
|
1447
|
+
// The v0.14 shape is a fixed key set; the ordering key the
|
|
1448
|
+
// generated code carries is dropped from it here.
|
|
1449
|
+
: raw.map(stripOrdinal);
|
|
1467
1450
|
// Correlation is published, never applied. Both halves of a
|
|
1468
1451
|
// typo pair stay in the array; `related` only says they are
|
|
1469
1452
|
// one mistake, so a wrong pairing costs a sentence rather
|
package/lib/js-compiler.js
CHANGED
|
@@ -73,6 +73,7 @@ function enumCondition(ctx, vals, v) {
|
|
|
73
73
|
|
|
74
74
|
|
|
75
75
|
const { codeFor } = require('./error-codes')
|
|
76
|
+
const { ordinalFor } = require('./schema-order')
|
|
76
77
|
const { compileSafe, patternIsSafe } = require('./safe-regex')
|
|
77
78
|
|
|
78
79
|
// Closure value for a patternProperties/propertyNames regex: the linear-time
|
|
@@ -94,6 +95,14 @@ const DOC_BASE = 'https://ata-validator.com/e/'
|
|
|
94
95
|
// like ",schemaSource:Object.freeze({...})" or "" if no source map hit.
|
|
95
96
|
// The fragment always starts with a leading comma when non-empty so callers
|
|
96
97
|
// can splice it inside an existing object literal.
|
|
98
|
+
// The error's position in schema declaration order, as a literal field the
|
|
99
|
+
// reader sorts by without deriving it from the path. Empty when the path is
|
|
100
|
+
// not into the root document.
|
|
101
|
+
function ordinalField (ctx, schemaPath) {
|
|
102
|
+
const o = ctx && ctx.rootSchema ? ordinalFor(ctx.rootSchema, schemaPath) : null
|
|
103
|
+
return o === null ? '' : `,_o:${o}`
|
|
104
|
+
}
|
|
105
|
+
|
|
97
106
|
function buildErrorLiteral (opts) {
|
|
98
107
|
const { keyword, format, schemaPath, sourceMap } = opts
|
|
99
108
|
let code = (keyword === 'format' && format) ? codeFor('format', format) : codeFor(keyword)
|
|
@@ -3213,7 +3222,7 @@ function compileToJSCodegenWithErrors(schema, schemaMap, userFormats, sourceOpts
|
|
|
3213
3222
|
// AOT output small for schemas that don't compose. Standalone modules can't
|
|
3214
3223
|
// require('./branch-collapse'), so the helper body is embedded verbatim.
|
|
3215
3224
|
if (ctx.usesBranchCollapse) {
|
|
3216
|
-
ctx.helperCode.push("const __ATA_SEVERITY={type:10,const:8,enum:8,required:5,format:3,minLength:3,maxLength:3,minimum:3,maximum:3,pattern:3,additionalProperties:2,unevaluatedProperties:2,unevaluatedItems:2};function __ataScore(errs){if(!errs||!errs.length)return 0;let s=0;for(const e of errs)s+=__ATA_SEVERITY[e.keyword]||4;return errs.length*100+s}function __ataCollapse(kw,br,pp,sp){const pass=br.filter(b=>b.valid);if(kw==='oneOf'){if(pass.length===1)return null;if(pass.length>1)return{code:'ATA4002',keyword:'oneOf',instancePath:pp||'',path:pp||'',schemaPath:sp,message:'value matched '+pass.length+' of '+br.length+' oneOf variants, expected exactly one',params:{matched:pass.length,total:br.length}}}else{if(pass.length>=1)return null}let bi=0,bs=Infinity;for(let i=0;i<br.length;i++){const s=__ataScore(br[i].errors);if(s<bs){bs=s;bi=i}}const code=kw==='oneOf'?'ATA4001':'ATA4003';const best=br[bi];return{code,keyword:kw,instancePath:pp||'',path:pp||'',schemaPath:sp,message:'value matched 0 of '+br.length+' '+kw+' variants',params:{variants:br.length,closest:bi,closestName:best.title||('variant '+(bi+1))},branchErrors:best.errors}}")
|
|
3225
|
+
ctx.helperCode.push("const __ATA_SEVERITY={type:10,const:8,enum:8,required:5,format:3,minLength:3,maxLength:3,minimum:3,maximum:3,pattern:3,additionalProperties:2,unevaluatedProperties:2,unevaluatedItems:2};function __ataScore(errs){if(!errs||!errs.length)return 0;let s=0;for(const e of errs)s+=__ATA_SEVERITY[e.keyword]||4;return errs.length*100+s}function __ataCollapse(kw,br,pp,sp,o){const pass=br.filter(b=>b.valid);if(kw==='oneOf'){if(pass.length===1)return null;if(pass.length>1)return{code:'ATA4002',keyword:'oneOf',instancePath:pp||'',path:pp||'',schemaPath:sp,_o:o,message:'value matched '+pass.length+' of '+br.length+' oneOf variants, expected exactly one',params:{matched:pass.length,total:br.length}}}else{if(pass.length>=1)return null}let bi=0,bs=Infinity;for(let i=0;i<br.length;i++){const s=__ataScore(br[i].errors);if(s<bs){bs=s;bi=i}}const code=kw==='oneOf'?'ATA4001':'ATA4003';const best=br[bi];return{code,keyword:kw,instancePath:pp||'',path:pp||'',schemaPath:sp,_o:o,message:'value matched 0 of '+br.length+' '+kw+' variants',params:{variants:br.length,closest:bi,closestName:best.title||('variant '+(bi+1))},branchErrors:best.errors}}")
|
|
3217
3226
|
}
|
|
3218
3227
|
if (lines.length === 0) return (d) => ({ valid: true, errors: [] })
|
|
3219
3228
|
|
|
@@ -3299,7 +3308,7 @@ function emitBranchCollapse (branches, keyword, v, pathExpr, lines, ctx, schemaP
|
|
|
3299
3308
|
} else if (sub === false) {
|
|
3300
3309
|
// A false branch never matches; it reports the same error the
|
|
3301
3310
|
// interpreter attaches to a false schema.
|
|
3302
|
-
subLines.push(`_e.push({keyword:'not',instancePath:${pathExpr||'""'},schemaPath:'${subSp}',params:{},message:'boolean schema is false'})`)
|
|
3311
|
+
subLines.push(`_e.push({keyword:'not',instancePath:${pathExpr||'""'},schemaPath:'${subSp}'${ordinalField(ctx, `${subSp}`)},params:{},message:'boolean schema is false'})`)
|
|
3303
3312
|
}
|
|
3304
3313
|
const title = (sub && typeof sub === 'object' && typeof sub.title === 'string') ? sub.title : ''
|
|
3305
3314
|
titles.push(title)
|
|
@@ -3313,7 +3322,7 @@ function emitBranchCollapse (branches, keyword, v, pathExpr, lines, ctx, schemaP
|
|
|
3313
3322
|
const titleArr = JSON.stringify(titles)
|
|
3314
3323
|
const collapsed = `_brc${fi}`
|
|
3315
3324
|
const pp = pathExpr || '""'
|
|
3316
|
-
lines.push(`{const ${fnArr}=[${fns.join(',')}];const _bt${fi}=${titleArr};const ${resArr}=[];for(let _bi=0;_bi<${fnArr}.length;_bi++){const _br=${fnArr}[_bi](${v});${resArr}.push({valid:_br.valid,errors:_br.errors,title:_bt${fi}[_bi]})}const ${collapsed}=__ataCollapse('${branchKw}',${resArr},${pp},'${branchSp}');if(${collapsed}){_e.push(${collapsed});if(!_all)return{valid:false,errors:_e}}}`)
|
|
3325
|
+
lines.push(`{const ${fnArr}=[${fns.join(',')}];const _bt${fi}=${titleArr};const ${resArr}=[];for(let _bi=0;_bi<${fnArr}.length;_bi++){const _br=${fnArr}[_bi](${v});${resArr}.push({valid:_br.valid,errors:_br.errors,title:_bt${fi}[_bi]})}const ${collapsed}=__ataCollapse('${branchKw}',${resArr},${pp},'${branchSp}',${(() => { const o = ordinalFor(ctx.rootSchema, branchSp); return o === null ? 'null' : o })()});if(${collapsed}){_e.push(${collapsed});if(!_all)return{valid:false,errors:_e}}}`)
|
|
3317
3326
|
}
|
|
3318
3327
|
|
|
3319
3328
|
// Error-collecting code generator.
|
|
@@ -3327,7 +3336,7 @@ function genCodeE(schema, v, pathExpr, lines, ctx, schemaPrefix) {
|
|
|
3327
3336
|
// name this keyword `false schema`; changing it here would change output
|
|
3328
3337
|
// the interpreter path already produces, so both engines say `not`.
|
|
3329
3338
|
if (schema === false) {
|
|
3330
|
-
lines.push(`;_e.push({keyword:'not',instancePath:${pathExpr||'""'},schemaPath:'${schemaPrefix}',params:{},message:'boolean schema is false'});if(!_all)return{valid:false,errors:_e}`)
|
|
3339
|
+
lines.push(`;_e.push({keyword:'not',instancePath:${pathExpr||'""'},schemaPath:'${schemaPrefix}'${ordinalField(ctx, `${schemaPrefix}`)},params:{},message:'boolean schema is false'});if(!_all)return{valid:false,errors:_e}`)
|
|
3331
3340
|
return
|
|
3332
3341
|
}
|
|
3333
3342
|
if (schema === true) return
|
|
@@ -3442,7 +3451,7 @@ function genCodeE(schema, v, pathExpr, lines, ctx, schemaPrefix) {
|
|
|
3442
3451
|
{
|
|
3443
3452
|
const typeSp = `${schemaPrefix}/type`
|
|
3444
3453
|
const lit = buildErrorLiteral({ keyword: 'type', schemaPath: typeSp, sourceMap: ctx.sourceMap })
|
|
3445
|
-
lines.push(`if(!(${conds.join('||')})){_e.push({code:'${lit.codeStr}',keyword:'type',instancePath:${pathExpr||'""'},schemaPath:'${typeSp}',params:{type:'${expected}'},message:'must be ${expected}',docUrl:'${lit.docUrl}'${lit.frame}});if(!_all)return{valid:false,errors:_e}}`)
|
|
3454
|
+
lines.push(`if(!(${conds.join('||')})){_e.push({code:'${lit.codeStr}',keyword:'type',instancePath:${pathExpr||'""'},schemaPath:'${typeSp}'${ordinalField(ctx, `${typeSp}`)},params:{type:'${expected}'},message:'must be ${expected}',docUrl:'${lit.docUrl}'${lit.frame}});if(!_all)return{valid:false,errors:_e}}`)
|
|
3446
3455
|
}
|
|
3447
3456
|
}
|
|
3448
3457
|
|
|
@@ -3455,7 +3464,7 @@ function genCodeE(schema, v, pathExpr, lines, ctx, schemaPrefix) {
|
|
|
3455
3464
|
const fail = (keyword, schemaSuffix, paramsCode, msgCode, fmt) => {
|
|
3456
3465
|
const sp = schemaPrefix + '/' + schemaSuffix
|
|
3457
3466
|
const lit = buildErrorLiteral({ keyword, format: fmt, schemaPath: sp, sourceMap: ctx.sourceMap })
|
|
3458
|
-
return `_e.push({code:'${lit.codeStr}',keyword:'${keyword}',instancePath:${pathExpr||'""'},schemaPath:'${sp}',params:${paramsCode},message:${msgCode},docUrl:'${lit.docUrl}'${lit.frame}});if(!_all)return{valid:false,errors:_e}`
|
|
3467
|
+
return `_e.push({code:'${lit.codeStr}',keyword:'${keyword}',instancePath:${pathExpr||'""'},schemaPath:'${sp}',params:${paramsCode},message:${msgCode},docUrl:'${lit.docUrl}'${lit.frame}${ordinalField(ctx, sp)}});if(!_all)return{valid:false,errors:_e}`
|
|
3459
3468
|
}
|
|
3460
3469
|
|
|
3461
3470
|
// enum
|
|
@@ -3480,7 +3489,7 @@ function genCodeE(schema, v, pathExpr, lines, ctx, schemaPrefix) {
|
|
|
3480
3489
|
const reqSp = `${schemaPrefix}/required`
|
|
3481
3490
|
const reqLit = buildErrorLiteral({ keyword: 'required', schemaPath: reqSp, sourceMap: ctx.sourceMap })
|
|
3482
3491
|
for (const key of schema.required) {
|
|
3483
|
-
lines.push(`if(typeof ${v}==='object'&&${v}!==null&&!Array.isArray(${v})&&!(${JSON.stringify(key)} in ${v})){_e.push({code:'${reqLit.codeStr}',keyword:'required',instancePath:${pathExpr||'""'},schemaPath:'${reqSp}',params:{missingProperty:'${esc(key)}'},message:"must have required property '${esc(key)}'",docUrl:'${reqLit.docUrl}'${reqLit.frame}});if(!_all)return{valid:false,errors:_e}}`)
|
|
3492
|
+
lines.push(`if(typeof ${v}==='object'&&${v}!==null&&!Array.isArray(${v})&&!(${JSON.stringify(key)} in ${v})){_e.push({code:'${reqLit.codeStr}',keyword:'required',instancePath:${pathExpr||'""'},schemaPath:'${reqSp}'${ordinalField(ctx, `${reqSp}`)},params:{missingProperty:'${esc(key)}'},message:"must have required property '${esc(key)}'",docUrl:'${reqLit.docUrl}'${reqLit.frame}});if(!_all)return{valid:false,errors:_e}}`)
|
|
3484
3493
|
}
|
|
3485
3494
|
}
|
|
3486
3495
|
|
|
@@ -3550,7 +3559,7 @@ function genCodeE(schema, v, pathExpr, lines, ctx, schemaPrefix) {
|
|
|
3550
3559
|
const fc = FORMAT_CODEGEN[schema.format]
|
|
3551
3560
|
const fmtSp = `${schemaPrefix}/format`
|
|
3552
3561
|
const fmtLit = buildErrorLiteral({ keyword: 'format', format: schema.format, schemaPath: fmtSp, sourceMap: ctx.sourceMap })
|
|
3553
|
-
const failPush = `_e.push({code:'${fmtLit.codeStr}',keyword:'format',instancePath:${pathExpr||'""'},schemaPath:'${fmtSp}',params:{format:'${esc(schema.format)}'},message:'must match format "${esc(schema.format)}"',docUrl:'${fmtLit.docUrl}'${fmtLit.frame}});if(!_all)return{valid:false,errors:_e}`
|
|
3562
|
+
const failPush = `_e.push({code:'${fmtLit.codeStr}',keyword:'format',instancePath:${pathExpr||'""'},schemaPath:'${fmtSp}'${ordinalField(ctx, `${fmtSp}`)},params:{format:'${esc(schema.format)}'},message:'must match format "${esc(schema.format)}"',docUrl:'${fmtLit.docUrl}'${fmtLit.frame}});if(!_all)return{valid:false,errors:_e}`
|
|
3554
3563
|
// Format errors use the boolean codegen, each `return false` becoming an
|
|
3555
3564
|
// error push. One violation reports once: the first failing statement
|
|
3556
3565
|
// pushes and leaves the labeled block, where it used to fall through and
|
|
@@ -3634,7 +3643,7 @@ function genCodeE(schema, v, pathExpr, lines, ctx, schemaPrefix) {
|
|
|
3634
3643
|
patChecks.push(`_re${ctx.regExpMap.get(pattern)}.test(_k${ci}[_i])`)
|
|
3635
3644
|
}
|
|
3636
3645
|
const isAdditional = patChecks.length ? `!_a${ci}.has(_k${ci}[_i])&&!(${patChecks.join('||')})` : `!_a${ci}.has(_k${ci}[_i])`
|
|
3637
|
-
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}}}`
|
|
3646
|
+
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}'${ordinalField(ctx, `${apSp}`)},params:{additionalProperty:_k${ci}[_i]},message:'must NOT have additional properties',docUrl:'${apLit.docUrl}'${apLit.frame}});if(!_all)return{valid:false,errors:_e}}}`
|
|
3638
3647
|
lines.push(isObj ? `{${inner}}` : `if(typeof ${v}==='object'&&${v}!==null&&!Array.isArray(${v})){${inner}}`)
|
|
3639
3648
|
}
|
|
3640
3649
|
|
|
@@ -3644,7 +3653,7 @@ function genCodeE(schema, v, pathExpr, lines, ctx, schemaPrefix) {
|
|
|
3644
3653
|
const drLit = buildErrorLiteral({ keyword: 'dependentRequired', schemaPath: drSp, sourceMap: ctx.sourceMap })
|
|
3645
3654
|
for (const [key, deps] of Object.entries(schema.dependentRequired)) {
|
|
3646
3655
|
for (const dep of deps) {
|
|
3647
|
-
lines.push(`if(typeof ${v}==='object'&&${v}!==null&&${JSON.stringify(key)} in ${v}&&!(${JSON.stringify(dep)} in ${v})){_e.push({code:'${drLit.codeStr}',keyword:'required',instancePath:${pathExpr||'""'},schemaPath:'${drSp}',params:{missingProperty:'${esc(dep)}'},message:"must have required property '${esc(dep)}'",docUrl:'${drLit.docUrl}'${drLit.frame}});if(!_all)return{valid:false,errors:_e}}`)
|
|
3656
|
+
lines.push(`if(typeof ${v}==='object'&&${v}!==null&&${JSON.stringify(key)} in ${v}&&!(${JSON.stringify(dep)} in ${v})){_e.push({code:'${drLit.codeStr}',keyword:'required',instancePath:${pathExpr||'""'},schemaPath:'${drSp}'${ordinalField(ctx, `${drSp}`)},params:{missingProperty:'${esc(dep)}'},message:"must have required property '${esc(dep)}'",docUrl:'${drLit.docUrl}'${drLit.frame}});if(!_all)return{valid:false,errors:_e}}`)
|
|
3648
3657
|
}
|
|
3649
3658
|
}
|
|
3650
3659
|
}
|
|
@@ -3731,7 +3740,7 @@ function genCodeE(schema, v, pathExpr, lines, ctx, schemaPrefix) {
|
|
|
3731
3740
|
if (schema.propertyNames === false) {
|
|
3732
3741
|
const ki = ctx.varCounter++
|
|
3733
3742
|
const p = pathExpr ? `${pathExpr}+'/'+_k${ki}` : `'/'+_k${ki}`
|
|
3734
|
-
lines.push(`if(typeof ${v}==='object'&&${v}!==null&&!Array.isArray(${v})){for(const _k${ki} in ${v}){_e.push({keyword:'not',instancePath:${p},schemaPath:'${schemaPrefix}/propertyNames',params:{},message:'boolean schema is false'});if(!_all)return{valid:false,errors:_e}}}`)
|
|
3743
|
+
lines.push(`if(typeof ${v}==='object'&&${v}!==null&&!Array.isArray(${v})){for(const _k${ki} in ${v}){_e.push({keyword:'not',instancePath:${p},schemaPath:'${schemaPrefix}/propertyNames'${ordinalField(ctx, `${schemaPrefix}/propertyNames`)},params:{},message:'boolean schema is false'});if(!_all)return{valid:false,errors:_e}}}`)
|
|
3735
3744
|
}
|
|
3736
3745
|
|
|
3737
3746
|
// propertyNames
|
|
@@ -3973,7 +3982,7 @@ function genCodeC(schema, v, pathExpr, lines, ctx, schemaPrefix) {
|
|
|
3973
3982
|
if (schema === false) {
|
|
3974
3983
|
// Leading semicolon: the previous generated line may end in an
|
|
3975
3984
|
// expression, and a line starting with `(` would be parsed as a call.
|
|
3976
|
-
lines.push(`;(_e||(_e=[])).push({keyword:'not',instancePath:${pathExpr||'""'},schemaPath:'${schemaPrefix}',params:{},message:'boolean schema is false'})`)
|
|
3985
|
+
lines.push(`;(_e||(_e=[])).push({keyword:'not',instancePath:${pathExpr||'""'},schemaPath:'${schemaPrefix}'${ordinalField(ctx, `${schemaPrefix}`)},params:{},message:'boolean schema is false'})`)
|
|
3977
3986
|
return
|
|
3978
3987
|
}
|
|
3979
3988
|
if (schema === true) return
|
|
@@ -4061,12 +4070,15 @@ function genCodeC(schema, v, pathExpr, lines, ctx, schemaPrefix) {
|
|
|
4061
4070
|
const pathVal = pathExpr ? pathExpr.slice(1, -1) : ''
|
|
4062
4071
|
const msgVal = msgCode.slice(1, -1)
|
|
4063
4072
|
ctx.closureVars.push(errVar)
|
|
4064
|
-
|
|
4073
|
+
const o = ordinalFor(ctx.rootSchema, sp)
|
|
4074
|
+
const lit = {keyword, instancePath: pathVal, schemaPath: sp, params: Object.freeze(paramsVal), message: msgVal}
|
|
4075
|
+
if (o !== null) lit._o = o
|
|
4076
|
+
ctx.closureVals.push(Object.freeze(lit))
|
|
4065
4077
|
return `(_e||(_e=[])).push(${errVar})`
|
|
4066
4078
|
}
|
|
4067
4079
|
}
|
|
4068
4080
|
// Dynamic path (e.g., array index): inline as before
|
|
4069
|
-
return `(_e||(_e=[])).push({keyword:'${keyword}',instancePath:${pathExpr||'""'},schemaPath:'${sp}',params:${paramsCode},message:${msgCode}})`
|
|
4081
|
+
return `(_e||(_e=[])).push({keyword:'${keyword}',instancePath:${pathExpr||'""'},schemaPath:'${sp}',params:${paramsCode},message:${msgCode}${ordinalField(ctx, sp)}})`
|
|
4070
4082
|
}
|
|
4071
4083
|
|
|
4072
4084
|
if (types) {
|
|
@@ -4135,7 +4147,7 @@ function genCodeC(schema, v, pathExpr, lines, ctx, schemaPrefix) {
|
|
|
4135
4147
|
ctx.closureVals.push(Object.freeze({keyword: 'required', instancePath: pathVal, schemaPath: `${schemaPrefix}/required`, params: Object.freeze({missingProperty: key}), message: `must have required property '${key}'`}))
|
|
4136
4148
|
lines.push(`if(${check}){(_e||(_e=[])).push(${errVar})}`)
|
|
4137
4149
|
} else {
|
|
4138
|
-
lines.push(`if(${check}){(_e||(_e=[])).push({keyword:'required',instancePath:${pathExpr||'""'},schemaPath:'${schemaPrefix}/required',params:{missingProperty:'${esc(key)}'},message:"must have required property '${esc(key)}'"})}`)
|
|
4150
|
+
lines.push(`if(${check}){(_e||(_e=[])).push({keyword:'required',instancePath:${pathExpr||'""'},schemaPath:'${schemaPrefix}/required'${ordinalField(ctx, `${schemaPrefix}/required`)},params:{missingProperty:'${esc(key)}'},message:"must have required property '${esc(key)}'"})}`)
|
|
4139
4151
|
}
|
|
4140
4152
|
}
|
|
4141
4153
|
} else if (schema.required) {
|
|
@@ -4149,7 +4161,7 @@ function genCodeC(schema, v, pathExpr, lines, ctx, schemaPrefix) {
|
|
|
4149
4161
|
ctx.closureVals.push(Object.freeze({keyword: 'required', instancePath: pathVal, schemaPath: `${schemaPrefix}/required`, params: Object.freeze({missingProperty: key}), message: `must have required property '${key}'`}))
|
|
4150
4162
|
lines.push(`if(typeof ${v}==='object'&&${v}!==null&&!Array.isArray(${v})&&!(${JSON.stringify(key)} in ${v})){(_e||(_e=[])).push(${errVar})}`)
|
|
4151
4163
|
} else {
|
|
4152
|
-
lines.push(`if(typeof ${v}==='object'&&${v}!==null&&!Array.isArray(${v})&&!(${JSON.stringify(key)} in ${v})){(_e||(_e=[])).push({keyword:'required',instancePath:${pathExpr||'""'},schemaPath:'${schemaPrefix}/required',params:{missingProperty:'${esc(key)}'},message:"must have required property '${esc(key)}'"})}`)
|
|
4164
|
+
lines.push(`if(typeof ${v}==='object'&&${v}!==null&&!Array.isArray(${v})&&!(${JSON.stringify(key)} in ${v})){(_e||(_e=[])).push({keyword:'required',instancePath:${pathExpr||'""'},schemaPath:'${schemaPrefix}/required'${ordinalField(ctx, `${schemaPrefix}/required`)},params:{missingProperty:'${esc(key)}'},message:"must have required property '${esc(key)}'"})}`)
|
|
4153
4165
|
}
|
|
4154
4166
|
}
|
|
4155
4167
|
}
|
|
@@ -4271,7 +4283,7 @@ function genCodeC(schema, v, pathExpr, lines, ctx, schemaPrefix) {
|
|
|
4271
4283
|
ctx.closureVals.push(Object.freeze({keyword: 'required', instancePath: pathVal, schemaPath: `${schemaPrefix}/dependentRequired`, params: Object.freeze({missingProperty: dep}), message: `must have required property '${dep}'`}))
|
|
4272
4284
|
lines.push(`if(typeof ${v}==='object'&&${v}!==null&&${JSON.stringify(key)} in ${v}&&!(${JSON.stringify(dep)} in ${v})){(_e||(_e=[])).push(${errVar})}`)
|
|
4273
4285
|
} else {
|
|
4274
|
-
lines.push(`if(typeof ${v}==='object'&&${v}!==null&&${JSON.stringify(key)} in ${v}&&!(${JSON.stringify(dep)} in ${v})){(_e||(_e=[])).push({keyword:'required',instancePath:${pathExpr||'""'},schemaPath:'${schemaPrefix}/dependentRequired',params:{missingProperty:'${esc(dep)}'},message:"must have required property '${esc(dep)}'"})}`)
|
|
4286
|
+
lines.push(`if(typeof ${v}==='object'&&${v}!==null&&${JSON.stringify(key)} in ${v}&&!(${JSON.stringify(dep)} in ${v})){(_e||(_e=[])).push({keyword:'required',instancePath:${pathExpr||'""'},schemaPath:'${schemaPrefix}/dependentRequired'${ordinalField(ctx, `${schemaPrefix}/dependentRequired`)},params:{missingProperty:'${esc(dep)}'},message:"must have required property '${esc(dep)}'"})}`)
|
|
4275
4287
|
}
|
|
4276
4288
|
}
|
|
4277
4289
|
}
|
|
@@ -4417,7 +4429,7 @@ function genCodeC(schema, v, pathExpr, lines, ctx, schemaPrefix) {
|
|
|
4417
4429
|
if (schema.propertyNames === false) {
|
|
4418
4430
|
const ki = ctx.varCounter++
|
|
4419
4431
|
const p = pathExpr ? `${pathExpr}+'/'+_k${ki}` : `'/'+_k${ki}`
|
|
4420
|
-
lines.push(`;if(typeof ${v}==='object'&&${v}!==null&&!Array.isArray(${v})){for(const _k${ki} in ${v}){(_e||(_e=[])).push({keyword:'not',instancePath:${p},schemaPath:'${schemaPrefix}/propertyNames',params:{},message:'boolean schema is false'})}}`)
|
|
4432
|
+
lines.push(`;if(typeof ${v}==='object'&&${v}!==null&&!Array.isArray(${v})){for(const _k${ki} in ${v}){(_e||(_e=[])).push({keyword:'not',instancePath:${p},schemaPath:'${schemaPrefix}/propertyNames'${ordinalField(ctx, `${schemaPrefix}/propertyNames`)},params:{},message:'boolean schema is false'})}}`)
|
|
4421
4433
|
}
|
|
4422
4434
|
|
|
4423
4435
|
// propertyNames — skip if already merged into patternProperties loop
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// Declaration order of a schemaPath within its root schema.
|
|
4
|
+
//
|
|
5
|
+
// `rankFor` is the path of child indexes from the root to the node the
|
|
6
|
+
// schemaPath names (or to the deepest node it can reach), which sorts errors
|
|
7
|
+
// in the order their keywords appear in the schema. `ordinalFor` is the same
|
|
8
|
+
// order as one integer: the node's pre-order position in the schema tree.
|
|
9
|
+
// Comparing two ranks segment by segment gives exactly the pre-order
|
|
10
|
+
// relation, so the integer can stand in for the array, and the code
|
|
11
|
+
// generator can compute it once per error site instead of the reader
|
|
12
|
+
// deriving it from the path string on every rejection.
|
|
13
|
+
//
|
|
14
|
+
// Both are memoized per root schema; a validator's root never changes.
|
|
15
|
+
|
|
16
|
+
const _keyIndexCache = new WeakMap();
|
|
17
|
+
const _rankCache = new WeakMap();
|
|
18
|
+
const _ordinalCache = new WeakMap();
|
|
19
|
+
|
|
20
|
+
function keyIndex(node, seg) {
|
|
21
|
+
let index = _keyIndexCache.get(node);
|
|
22
|
+
if (index === undefined) {
|
|
23
|
+
index = new Map();
|
|
24
|
+
const keys = Object.keys(node);
|
|
25
|
+
for (let i = 0; i < keys.length; i++) index.set(keys[i], i);
|
|
26
|
+
_keyIndexCache.set(node, index);
|
|
27
|
+
}
|
|
28
|
+
const at = index.get(seg);
|
|
29
|
+
return at === undefined ? -1 : at;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// `~1` and `~0` are the only escapes a JSON pointer has, and almost no schema
|
|
33
|
+
// key contains a tilde. Looking for one is far cheaper than two regex passes
|
|
34
|
+
// over every segment of every path.
|
|
35
|
+
function unescapePointerSegment(seg) {
|
|
36
|
+
return seg.indexOf('~') < 0 ? seg : seg.replace(/~1/g, '/').replace(/~0/g, '~');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function escapePointerSegment(seg) {
|
|
40
|
+
return seg.indexOf('~') < 0 && seg.indexOf('/') < 0 ? seg : seg.replace(/~/g, '~0').replace(/\//g, '~1');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function rankFor(rootSchema, schemaPath) {
|
|
44
|
+
if (!schemaPath || typeof schemaPath !== 'string' || !schemaPath.startsWith('#')) return null;
|
|
45
|
+
if (rootSchema === null || typeof rootSchema !== 'object') return null;
|
|
46
|
+
let byPath = _rankCache.get(rootSchema);
|
|
47
|
+
if (byPath === undefined) { byPath = new Map(); _rankCache.set(rootSchema, byPath); }
|
|
48
|
+
const hit = byPath.get(schemaPath);
|
|
49
|
+
if (hit !== undefined) return hit;
|
|
50
|
+
const rank = computeRank(rootSchema, schemaPath);
|
|
51
|
+
byPath.set(schemaPath, rank);
|
|
52
|
+
return rank;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function computeRank(rootSchema, schemaPath) {
|
|
56
|
+
const rank = [];
|
|
57
|
+
let node = rootSchema;
|
|
58
|
+
let start = 1;
|
|
59
|
+
while (start <= schemaPath.length) {
|
|
60
|
+
let end = schemaPath.indexOf('/', start);
|
|
61
|
+
if (end < 0) end = schemaPath.length;
|
|
62
|
+
if (end === start) { start = end + 1; continue; }
|
|
63
|
+
const seg = unescapePointerSegment(schemaPath.slice(start, end));
|
|
64
|
+
start = end + 1;
|
|
65
|
+
if (node == null || typeof node !== 'object') break;
|
|
66
|
+
if (Array.isArray(node)) {
|
|
67
|
+
const idx = Number(seg);
|
|
68
|
+
if (!Number.isInteger(idx) || idx < 0 || idx >= node.length) break;
|
|
69
|
+
rank.push(idx);
|
|
70
|
+
node = node[idx];
|
|
71
|
+
} else {
|
|
72
|
+
const idx = keyIndex(node, seg);
|
|
73
|
+
if (idx < 0) break;
|
|
74
|
+
rank.push(idx);
|
|
75
|
+
node = node[seg];
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return rank;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Pre-order numbering of every node in the schema, keyed by its pointer as
|
|
82
|
+
// it appears in a schemaPath (segments escaped). Built once per root, on the
|
|
83
|
+
// first ask. Cyclic structures are guarded; a schema object can contain
|
|
84
|
+
// itself only through references, which are strings.
|
|
85
|
+
function ordinals(rootSchema) {
|
|
86
|
+
let map = _ordinalCache.get(rootSchema);
|
|
87
|
+
if (map !== undefined) return map;
|
|
88
|
+
map = new Map();
|
|
89
|
+
const seen = new Set();
|
|
90
|
+
let next = 0;
|
|
91
|
+
const walk = (node, pointer) => {
|
|
92
|
+
map.set(pointer, next++);
|
|
93
|
+
if (node === null || typeof node !== 'object') return;
|
|
94
|
+
if (seen.has(node)) return;
|
|
95
|
+
seen.add(node);
|
|
96
|
+
if (Array.isArray(node)) {
|
|
97
|
+
for (let i = 0; i < node.length; i++) walk(node[i], pointer + '/' + i);
|
|
98
|
+
} else {
|
|
99
|
+
for (const key of Object.keys(node)) walk(node[key], pointer + '/' + escapePointerSegment(key));
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
walk(rootSchema, '#');
|
|
103
|
+
_ordinalCache.set(rootSchema, map);
|
|
104
|
+
return map;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// The ordinal of the deepest node the schemaPath reaches; null when the path
|
|
108
|
+
// is not into this document.
|
|
109
|
+
function ordinalFor(rootSchema, schemaPath) {
|
|
110
|
+
if (!schemaPath || typeof schemaPath !== 'string' || schemaPath.charCodeAt(0) !== 35) return null;
|
|
111
|
+
if (rootSchema === null || typeof rootSchema !== 'object') return null;
|
|
112
|
+
const map = ordinals(rootSchema);
|
|
113
|
+
const hit = map.get(schemaPath);
|
|
114
|
+
if (hit !== undefined) return hit;
|
|
115
|
+
// Walk back to the longest prefix that exists. Paths through a keyword's
|
|
116
|
+
// value that is a primitive, or through a key the schema does not have,
|
|
117
|
+
// land on the nearest enclosing node.
|
|
118
|
+
let p = schemaPath;
|
|
119
|
+
while (true) {
|
|
120
|
+
const cut = p.lastIndexOf('/');
|
|
121
|
+
if (cut < 0) return 0;
|
|
122
|
+
p = p.slice(0, cut);
|
|
123
|
+
const o = map.get(p);
|
|
124
|
+
if (o !== undefined) return o;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
module.exports = { rankFor, ordinalFor, unescapePointerSegment };
|
package/lib/version.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ata-validator",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.17.0",
|
|
4
4
|
"description": "JSON Schema validation with first-class TypeScript and zero runtime cost. AOT compile to per-schema ESM modules with zero validator dependency. Generic Validator<T> for TypeBox/Zod/Valibot composition. Optional runtime API. Standard Schema V1 compatible.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"module": "index.mjs",
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"release:check": "node scripts/regen-safe-regex-source.js && node tests/test_pack_purity.js && node scripts/check-doc-coverage.js && node tests/test_error_codes_lock.js && node tests/test_safe_regex_source_sync.js && node tests/test_version_sync.js",
|
|
52
52
|
"build": "cmake-js build --target ata",
|
|
53
53
|
"rebuild": "cmake-js rebuild --target ata",
|
|
54
|
-
"test": "node test.js && node tests/test_removed_aot_methods.js && node tests/test_no_native.js && node tests/test_no_eval.js && node tests/test_property_dependencies.js && node tests/test_v1_dialect.js && node tests/test_buffer_path_parity.js && node tests/test_buffer_gate.js && node tests/test_buffer_reject_cost.js && node tests/test_nan_verdict.js && node tests/test_remove_additional_nested.js && node tests/test_aot_parse.js && node tests/test_draft7_semantics.js && node tests/test_metaschema_ref.js && node tests/test_pure_js_unsupported.js && node tests/test_native_load_order.js && node tests/test_pack_purity.js && node tests/test_make_native_package.js && node tests/test_browser_nofs.js && node tests/test_browser_imports_guard.js && node tests/test_version_sync.js && node tests/test_native_loaded.js && node tests/test_safe_regex_source_sync.js && node tests/test_t_builder.js && node tests/test_async_refine.js && node tests/test_safe_regex.js && node tests/test_safe_regex_integration.js && node tests/test_aot_build.js && node tests/test_aot_differential.js && node tests/test_aot_cli_build.js && node tests/test_aot_cli_smoke.js && node tests/test_bundle_standalone.js && node tests/test_standalone_anyof.js && node tests/test_standalone_formats.js && node tests/test_aot_format_mode.js && node tests/test_aot_additional_props_errors.js && node tests/test_id_anchor_refs.js && node tests/test_engine_routing.js && node tests/test_engine_diagnostic.js && node tests/test_format_engine_parity.js && node tests/test_formats_single_pass.js && node tests/test_format_single_error.js && node tests/test_defs_pointer_alias.js && node tests/test_cross_doc_root_ref.js && node tests/test_codegen_entrypoint_agreement.js && node tests/test_hybrid_agreement.js && node tests/test_codegen_edge_shapes.js && node tests/test_ajv_errors.js && node tests/test_custom_keywords.js && node tests/test_ajv_parity.js && node tests/test_user_format_error_path.js && node tests/test_unevaluated_error_path.js && node tests/test_pattern_properties_errors.js && node tests/test_no_input_mutation.js && node tests/test_typed_validator_runner.js && node tests/test_define_schema.js && node tests/test_error_codes_lock.js && node tests/test_error_code_lookup.js && node tests/test_error_order.js && node tests/test_value_equality.js && node tests/test_vocabulary.js && node tests/test_schema_scan.js && node tests/test_lazy_errors.js && node tests/test_lazy_instance.js && node tests/test_cyclic_input.js && node tests/test_native_error_codes.js && node tests/test_verdict_preprocess.js && node tests/test_plan_compiler.js && node tests/test_nullable.js && node tests/test_validate_and_parse.js && node tests/test_validate_data.js && node tests/test_enrich_error.js && node tests/test_enrich_received.js && node tests/test_rich_errors_optout.js && node tests/test_error_messages.js && node tests/test_source_positions.js && node tests/fuzz_positions.js && node tests/test_data_positions.js && node tests/test_render_shared.js && node tests/test_renderers.js && node tests/test_additive_fields.js && node tests/test_diagnostic_source.js && node tests/test_diagnose.js && node tests/test_correlate.js && node tests/test_diagnostics_score.js && node tests/test_runtime_error_dx.js && node tests/test_aot_error_dx.js && node tests/test_abort_early.js && node tests/test_branch_collapse.js && node tests/test_suggestions.js && node tests/test_cli_validate.js && node tests/test_cli_version.js && node benchmark/bench_aot_size.mjs",
|
|
54
|
+
"test": "node test.js && node tests/test_removed_aot_methods.js && node tests/test_no_native.js && node tests/test_no_eval.js && node tests/test_property_dependencies.js && node tests/test_v1_dialect.js && node tests/test_buffer_path_parity.js && node tests/test_buffer_gate.js && node tests/test_buffer_reject_cost.js && node tests/test_nan_verdict.js && node tests/test_remove_additional_nested.js && node tests/test_aot_parse.js && node tests/test_draft7_semantics.js && node tests/test_metaschema_ref.js && node tests/test_pure_js_unsupported.js && node tests/test_native_load_order.js && node tests/test_pack_purity.js && node tests/test_make_native_package.js && node tests/test_browser_nofs.js && node tests/test_browser_imports_guard.js && node tests/test_version_sync.js && node tests/test_native_loaded.js && node tests/test_safe_regex_source_sync.js && node tests/test_t_builder.js && node tests/test_async_refine.js && node tests/test_safe_regex.js && node tests/test_safe_regex_integration.js && node tests/test_aot_build.js && node tests/test_aot_differential.js && node tests/test_aot_cli_build.js && node tests/test_aot_cli_smoke.js && node tests/test_bundle_standalone.js && node tests/test_standalone_anyof.js && node tests/test_standalone_formats.js && node tests/test_aot_format_mode.js && node tests/test_aot_additional_props_errors.js && node tests/test_id_anchor_refs.js && node tests/test_engine_routing.js && node tests/test_engine_diagnostic.js && node tests/test_format_engine_parity.js && node tests/test_formats_single_pass.js && node tests/test_format_single_error.js && node tests/test_defs_pointer_alias.js && node tests/test_cross_doc_root_ref.js && node tests/test_codegen_entrypoint_agreement.js && node tests/test_hybrid_agreement.js && node tests/test_codegen_edge_shapes.js && node tests/test_ajv_errors.js && node tests/test_custom_keywords.js && node tests/test_ajv_parity.js && node tests/test_user_format_error_path.js && node tests/test_unevaluated_error_path.js && node tests/test_pattern_properties_errors.js && node tests/test_no_input_mutation.js && node tests/test_typed_validator_runner.js && node tests/test_define_schema.js && node tests/test_error_codes_lock.js && node tests/test_error_code_lookup.js && node tests/test_error_order.js && node tests/test_error_order_ordinal.js && node tests/test_value_equality.js && node tests/test_vocabulary.js && node tests/test_schema_scan.js && node tests/test_lazy_errors.js && node tests/test_lazy_instance.js && node tests/test_cyclic_input.js && node tests/test_native_error_codes.js && node tests/test_verdict_preprocess.js && node tests/test_plan_compiler.js && node tests/test_nullable.js && node tests/test_validate_and_parse.js && node tests/test_validate_data.js && node tests/test_enrich_error.js && node tests/test_enrich_received.js && node tests/test_rich_errors_optout.js && node tests/test_error_messages.js && node tests/test_source_positions.js && node tests/fuzz_positions.js && node tests/test_data_positions.js && node tests/test_render_shared.js && node tests/test_renderers.js && node tests/test_additive_fields.js && node tests/test_diagnostic_source.js && node tests/test_diagnose.js && node tests/test_correlate.js && node tests/test_diagnostics_score.js && node tests/test_runtime_error_dx.js && node tests/test_aot_error_dx.js && node tests/test_abort_early.js && node tests/test_branch_collapse.js && node tests/test_suggestions.js && node tests/test_cli_validate.js && node tests/test_cli_version.js && node benchmark/bench_aot_size.mjs",
|
|
55
55
|
"bench:size": "node benchmark/bench_aot_size.mjs",
|
|
56
56
|
"test:suite": "node tests/run_suite.js && node tests/run_suite.js draft7 && node tests/run_suite.js v1",
|
|
57
57
|
"test:compat": "node tests/test_compat.js",
|
|
@@ -122,13 +122,13 @@
|
|
|
122
122
|
"LICENSE"
|
|
123
123
|
],
|
|
124
124
|
"optionalDependencies": {
|
|
125
|
-
"@ata-validator/native-darwin-arm64": "1.
|
|
126
|
-
"@ata-validator/native-darwin-x64": "1.
|
|
127
|
-
"@ata-validator/native-linux-arm64-gnu": "1.
|
|
128
|
-
"@ata-validator/native-linux-arm64-musl": "1.
|
|
129
|
-
"@ata-validator/native-linux-x64-gnu": "1.
|
|
130
|
-
"@ata-validator/native-linux-x64-musl": "1.
|
|
131
|
-
"@ata-validator/native-win32-x64": "1.
|
|
125
|
+
"@ata-validator/native-darwin-arm64": "1.17.0",
|
|
126
|
+
"@ata-validator/native-darwin-x64": "1.17.0",
|
|
127
|
+
"@ata-validator/native-linux-arm64-gnu": "1.17.0",
|
|
128
|
+
"@ata-validator/native-linux-arm64-musl": "1.17.0",
|
|
129
|
+
"@ata-validator/native-linux-x64-gnu": "1.17.0",
|
|
130
|
+
"@ata-validator/native-linux-x64-musl": "1.17.0",
|
|
131
|
+
"@ata-validator/native-win32-x64": "1.17.0"
|
|
132
132
|
},
|
|
133
133
|
"peerDependencies": {
|
|
134
134
|
"yaml": "^2.0.0"
|