ata-validator 1.49.0 → 1.50.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.
@@ -0,0 +1,80 @@
1
+ 'use strict';
2
+
3
+ // The public names of the package, shared by index.js (with the code
4
+ // generator) and index.edge.js (without it), so the two entries export the
5
+ // same thing.
6
+ const core = require('./validator-core.js');
7
+
8
+
9
+
10
+ // The parts no Validator calls: TypeScript generation, the error renderers,
11
+ // the spec output format, the retry message for language models, the schema
12
+ // description and the suggestion helper. ata-validator/lite leaves them out.
13
+ // Each loads its module on first call. None of them is on the path to a first
14
+ // validated request, and together they were about a sixth of what requiring
15
+ // the package cost.
16
+ function toTypeScript (...a) { return require('./ts-gen').toTypeScript(...a); }
17
+ function renderPretty (...a) { return require('./render-pretty').renderPretty(...a); }
18
+ function renderCompact (...a) { return require('./render-compact').renderCompact(...a); }
19
+ function toOutput (...a) { return require('./output-format').toOutput(...a); }
20
+ function toRetryMessage (...a) { return require('./retry-message').toRetryMessage(...a); }
21
+ function describeSchema (...a) { return require('./describe-schema').describeSchema(...a); }
22
+ function renderJSON (...a) { return require('./render-json').renderJSON(...a); }
23
+
24
+ // Walk a JSON pointer (RFC 6901 escapes) into a data tree. Mirrors the helper
25
+ // inside lib/suggestions.js, kept local to avoid exporting an internal.
26
+ function _walkPointer (root, pointer) {
27
+ if (!pointer) return root;
28
+ const parts = pointer.replace(/^\//, '').split('/').map(s => s.replace(/~1/g, '/').replace(/~0/g, '~'));
29
+ let cur = root;
30
+ for (const p of parts) { if (cur == null) return undefined; cur = cur[p]; }
31
+ return cur;
32
+ }
33
+
34
+ // Post-hoc suggestion enrichment for AOT-compiled validators. The standalone
35
+ // modules do not embed the suggestion engine, so consumers who want
36
+ // suggestions pass the error array through this after validation.
37
+ function attachSuggestions (errors, data) {
38
+ if (!errors) return errors;
39
+ const { suggestFor } = require('./suggestions');
40
+ const { reprValue } = require('./enrich-error');
41
+ for (const e of errors) {
42
+ if (!e || e.suggestion) continue;
43
+ let received = e.received;
44
+ if (received === undefined && data !== undefined) {
45
+ const ptr = e.instancePath != null ? e.instancePath : (e.path || '');
46
+ const raw = _walkPointer(data, ptr);
47
+ if (raw !== undefined || ptr === '') received = reprValue(raw);
48
+ }
49
+ const probe = received !== undefined && e.received === undefined
50
+ ? Object.assign({}, e, { received })
51
+ : e;
52
+ const s = suggestFor(probe, data);
53
+ if (s) e.suggestion = s;
54
+ }
55
+ // AOT modules import nothing, so this is their only route to a frame. The
56
+ // caller holds the original object and ran no preprocessing through here.
57
+ require('./diagnostic-source').setDiagnosticSource(errors, { data, mutatesInput: false });
58
+ return errors;
59
+ }
60
+
61
+ module.exports = {
62
+ Validator: core.Validator,
63
+ compile: core.compile,
64
+ validate: core.validate,
65
+ validateAsync: core.validateAsync,
66
+ parseAsync: core.parseAsync,
67
+ version: core.version,
68
+ createPaddedBuffer: core.createPaddedBuffer,
69
+ SIMDJSON_PADDING: core.SIMDJSON_PADDING,
70
+ parseJSON: core.parseJSON,
71
+ toTypeScript,
72
+ defineSchema: core.defineSchema,
73
+ renderPretty,
74
+ renderCompact,
75
+ toOutput,
76
+ toRetryMessage,
77
+ describeSchema,
78
+ renderJSON,
79
+ attachSuggestions, // internal: used by the renderers; not public API
80
+ };
@@ -0,0 +1,21 @@
1
+ 'use strict';
2
+
3
+ // The runtime a schema module (`ata build --mode schema`) imports: the verdict
4
+ // and the errors both come from the interpreted engine walking the embedded
5
+ // schema, so a module is its schema and a few lines. Smaller and quicker to
6
+ // load than generated code, slower per check once warm; see docs/API.md.
7
+ // One interpreter per schema answers both, so the schema is prepared once.
8
+ // It loads lib/interpreter.js, which brings the plan compiler for schemas
9
+ // used often (TIER in lib/interpreter-core.js).
10
+ const { createInterpreter } = require('./interpreter');
11
+ const { errorsOf, interpreterOptions } = require('./error-runtime-entry');
12
+
13
+ function createValidator(schema, codeOf, options) {
14
+ const interp = createInterpreter(schema, interpreterOptions(options));
15
+ return {
16
+ isValid: (data) => interp.isValid(data),
17
+ errors: (data) => errorsOf(interp, schema, codeOf, data),
18
+ };
19
+ }
20
+
21
+ module.exports = { createValidator };
@@ -0,0 +1,115 @@
1
+ 'use strict';
2
+
3
+ // A copy of a schema without the keywords that only describe it (title,
4
+ // description, examples and the like), for a compact module that embeds its
5
+ // schema so the shared error runtime can walk it. Validation never reads
6
+ // these, and in a typical published schema they are most of the bytes.
7
+ //
8
+ // Only schema positions are touched. An `enum`, a `const` or any keyword this
9
+ // file does not know is copied as it is, so a value that happens to hold a
10
+ // "description" key keeps it. If a local `$ref` points through a keyword that
11
+ // would be removed, nothing is removed: the reference has to land where it
12
+ // did.
13
+
14
+ const DROP = new Set([
15
+ 'title', 'description', '$comment', 'examples', 'default', 'deprecated',
16
+ 'readOnly', 'writeOnly', 'markdownDescription', 'deprecationMessage',
17
+ 'enumDescriptions', 'markdownEnumDescriptions', 'defaultSnippets',
18
+ ]);
19
+
20
+ const SINGLE = new Set([
21
+ 'additionalProperties', 'contains', 'propertyNames', 'if', 'then', 'else', 'not',
22
+ 'items', 'unevaluatedItems', 'unevaluatedProperties', 'additionalItems', 'contentSchema',
23
+ ]);
24
+ const MAPS = new Set(['$defs', 'definitions', 'properties', 'patternProperties', 'dependentSchemas']);
25
+ const LISTS = new Set(['allOf', 'anyOf', 'oneOf', 'prefixItems']);
26
+
27
+ function dropped(key) {
28
+ return DROP.has(key) || key.startsWith('x-');
29
+ }
30
+
31
+ function setOwn(o, k, v) {
32
+ // A key named __proto__ has to stay an own property.
33
+ if (k === '__proto__') Object.defineProperty(o, k, { value: v, enumerable: true, writable: true, configurable: true });
34
+ else o[k] = v;
35
+ }
36
+
37
+ function unescape(seg) {
38
+ return seg.replace(/~1/g, '/').replace(/~0/g, '~');
39
+ }
40
+
41
+ // True when some local reference walks through a key that would be dropped.
42
+ function refsIntoDropped(node, seen) {
43
+ if (node === null || typeof node !== 'object') return false;
44
+ if (seen.has(node)) return false;
45
+ seen.add(node);
46
+ if (Array.isArray(node)) {
47
+ for (const x of node) if (refsIntoDropped(x, seen)) return true;
48
+ return false;
49
+ }
50
+ for (const k of ['$ref', '$dynamicRef', '$recursiveRef']) {
51
+ const r = node[k];
52
+ if (typeof r !== 'string') continue;
53
+ const hash = r.indexOf('#');
54
+ if (hash < 0) continue;
55
+ let frag;
56
+ try { frag = decodeURIComponent(r.slice(hash + 1)); } catch { return true; }
57
+ if (!frag.startsWith('/')) continue;
58
+ for (const seg of frag.slice(1).split('/')) if (dropped(unescape(seg))) return true;
59
+ }
60
+ for (const k of Object.keys(node)) if (refsIntoDropped(node[k], seen)) return true;
61
+ return false;
62
+ }
63
+
64
+ // keepTitle: the node is a branch of anyOf or oneOf, whose title names the
65
+ // branch in the collapsed error (params.closestName).
66
+ function stripSchema(node, keepTitle) {
67
+ if (node === null || typeof node !== 'object' || Array.isArray(node)) return node;
68
+ const out = {};
69
+ for (const k of Object.keys(node)) {
70
+ if (dropped(k) && !(keepTitle === true && k === 'title')) continue;
71
+ const v = node[k];
72
+ if (SINGLE.has(k)) {
73
+ setOwn(out, k, Array.isArray(v) ? v.map((x) => stripSchema(x, false)) : stripSchema(v, false));
74
+ } else if (MAPS.has(k) && v !== null && typeof v === 'object' && !Array.isArray(v)) {
75
+ const m = {};
76
+ for (const name of Object.keys(v)) setOwn(m, name, stripSchema(v[name], false));
77
+ setOwn(out, k, m);
78
+ } else if (LISTS.has(k) && Array.isArray(v)) {
79
+ const branches = k === 'anyOf' || k === 'oneOf';
80
+ setOwn(out, k, v.map((x) => stripSchema(x, branches)));
81
+ } else if (k === 'dependencies' && v !== null && typeof v === 'object' && !Array.isArray(v)) {
82
+ const m = {};
83
+ for (const name of Object.keys(v)) setOwn(m, name, Array.isArray(v[name]) ? v[name] : stripSchema(v[name], false));
84
+ setOwn(out, k, m);
85
+ } else if (k === 'propertyDependencies' && v !== null && typeof v === 'object' && !Array.isArray(v)) {
86
+ const m = {};
87
+ for (const name of Object.keys(v)) {
88
+ const inner = v[name];
89
+ if (inner === null || typeof inner !== 'object' || Array.isArray(inner)) { setOwn(m, name, inner); continue; }
90
+ const mi = {};
91
+ for (const val of Object.keys(inner)) setOwn(mi, val, stripSchema(inner[val], false));
92
+ setOwn(m, name, mi);
93
+ }
94
+ setOwn(out, k, m);
95
+ } else {
96
+ setOwn(out, k, v);
97
+ }
98
+ }
99
+ return out;
100
+ }
101
+
102
+ // A compact or schema module strips its schema three times on the way out
103
+ // (the reference check, the module, the flat-index check): once per schema
104
+ // object. A validator's schema object does not change after it compiles.
105
+ const _stripped = new WeakMap();
106
+ function stripAnnotations(schema) {
107
+ if (schema === null || typeof schema !== 'object') return schema;
108
+ const hit = _stripped.get(schema);
109
+ if (hit !== undefined) return hit;
110
+ const out = refsIntoDropped(schema, new Set()) ? schema : stripSchema(schema, false);
111
+ _stripped.set(schema, out);
112
+ return out;
113
+ }
114
+
115
+ module.exports = { stripAnnotations };
package/lib/tools.mjs ADDED
@@ -0,0 +1,21 @@
1
+ // The package's tools as ES modules, one import each, for the entries a
2
+ // bundler reads (index.browser.mjs, index.edge.mjs): an application that
3
+ // imports only Validator leaves TypeScript generation, the renderers, the
4
+ // output format, the retry message and the schema description out of its
5
+ // bundle. Through index.js they load on first call instead, which a bundler
6
+ // cannot see, so it kept all of them.
7
+ import tsGen from './ts-gen.js';
8
+ import renderPrettyMod from './render-pretty.js';
9
+ import renderCompactMod from './render-compact.js';
10
+ import outputFormat from './output-format.js';
11
+ import retryMessage from './retry-message.js';
12
+ import describe from './describe-schema.js';
13
+ import renderJsonMod from './render-json.js';
14
+
15
+ export function toTypeScript (...a) { return tsGen.toTypeScript(...a); }
16
+ export function renderPretty (...a) { return renderPrettyMod.renderPretty(...a); }
17
+ export function renderCompact (...a) { return renderCompactMod.renderCompact(...a); }
18
+ export function toOutput (...a) { return outputFormat.toOutput(...a); }
19
+ export function toRetryMessage (...a) { return retryMessage.toRetryMessage(...a); }
20
+ export function describeSchema (...a) { return describe.describeSchema(...a); }
21
+ export function renderJSON (...a) { return renderJsonMod.renderJSON(...a); }
@@ -25,6 +25,14 @@ function _registerCodegen(engine) {
25
25
  _codegen = engine;
26
26
  ({ compileToJS, compileToJSCodegen, compileToJSCodegenWithErrors, compileToJSCombined } = engine.jsCompiler);
27
27
  }
28
+ // The ahead-of-time loaders without the code generator: the edge entry
29
+ // (index.edge.js) registers lib/aot.browser.js here, so modules written by
30
+ // `ata build` or Validator.bundle() load where generated code cannot run.
31
+ // The emitters stay out, as they do in a browser bundle of the full package.
32
+ let _aotLoader = null;
33
+ function _registerAot(load) {
34
+ _aotLoader = load;
35
+ }
28
36
  const { draftCode, normalizeDraft2019, normalizeDraft7, normalizeNullable, normalizeExclusiveBounds, stripFormatAssertions } = require("./draft7");
29
37
  const { enabledKeywords, stripDisabledKeywords } = require("./vocabularies");
30
38
  const { needsNormalization } = require("./schema-scan");
@@ -1599,7 +1607,7 @@ class Validator {
1599
1607
  static fromStandalone(mod, schema, opts) {
1600
1608
  // It loads what Validator.bundleStandalone() writes, and compiles an error
1601
1609
  // function when the module carries none, so it goes with those methods.
1602
- if (_codegen === null) throw new TypeError('Validator.fromStandalone is not part of ata-validator/lite, like the bundle methods it loads for. Import it from ata-validator, or import a module from `ata build` directly.');
1610
+ if (_codegen === null && _aotLoader === null) throw new TypeError('Validator.fromStandalone is not part of ata-validator/lite, like the bundle methods it loads for. Import it from ata-validator, or import a module from `ata build` directly.');
1603
1611
  const options = opts || {};
1604
1612
  const schemaObj = typeof schema === "string" ? JSON.parse(schema) : schema;
1605
1613
 
@@ -1635,7 +1643,9 @@ class Validator {
1635
1643
  });
1636
1644
  if (mod.errFn) {
1637
1645
  errFn = (d) => mod.errFn(d, true);
1638
- } else {
1646
+ } else if (compileToJSCodegenWithErrors !== undefined) {
1647
+ // Without the code generator (the edge entry) a module that carries no
1648
+ // error function reports the stub above.
1639
1649
  const jsErrFn = compileToJSCodegenWithErrors(schemaObj);
1640
1650
  if (jsErrFn) {
1641
1651
  try {
@@ -1783,8 +1793,9 @@ function version() {
1783
1793
  // generated module shapes; browser bundles get `lib/aot.browser.js` (a stub
1784
1794
  // that throws) via the package.json `browser` field.
1785
1795
  function _aot() {
1786
- if (_codegen === null) throw new TypeError('The ahead-of-time bundle methods are not part of ata-validator/lite. Import them from ata-validator.');
1787
- return _codegen.aot();
1796
+ if (_codegen !== null) return _codegen.aot();
1797
+ if (_aotLoader !== null) return _aotLoader();
1798
+ throw new TypeError('The ahead-of-time bundle methods are not part of ata-validator/lite. Import them from ata-validator.');
1788
1799
  }
1789
1800
  Validator.bundle = function (schemas, opts) {
1790
1801
  return _aot().bundle(Validator, schemas, opts);
@@ -2195,7 +2206,7 @@ function _buildParse(self) {
2195
2206
  // isValidObject, which runs them, and a property they check with instanceof
2196
2207
  // is carried over as it is (see clone-emit).
2197
2208
  const extended = self._verdictTail !== null || self._validateTail !== null;
2198
- if (_codegen === null) return decline('ata-validator/lite has no code generator to build the copy with', 'Use parse() from ata-validator, or validate(); a valid result carries the input as it is.');
2209
+ if (_codegen === null) return decline('this entry has no code generator to build the copy with', 'Use validate(); a valid result carries the input as it is.');
2199
2210
  return _codegen.buildParse(self, decline, extended);
2200
2211
  }
2201
2212
 
@@ -2369,5 +2380,6 @@ module.exports = {
2369
2380
  // How an entry registers the code generator. Not enumerable, so the exported
2370
2381
  // surface of `require('ata-validator')` is what it was.
2371
2382
  Object.defineProperty(module.exports, '_registerCodegen', { value: _registerCodegen, enumerable: false });
2383
+ Object.defineProperty(module.exports, '_registerAot', { value: _registerAot, enumerable: false });
2372
2384
  // What the compiled paths in index.js need from this module.
2373
2385
  Object.defineProperty(module.exports, '_internals', { value: { _jsonSyntaxRejection, ABORT_EARLY_RESULT, HYBRID_TIER_CALLS, SIMDJSON_THRESHOLD, VALID_RESULT, _bindEntry, _bindVerdict, _compileCache, _compileCacheSet, _mustReject, _rememberInstance, _verboseWrap, compileCacheKey, getNative, isV1Dialect, resolveSchemaByPath }, enumerable: false });
package/lib/version.js CHANGED
@@ -7,4 +7,4 @@
7
7
  //
8
8
  // Kept in lockstep with package.json by `tests/test_version_sync.js`.
9
9
 
10
- module.exports = '1.49.0';
10
+ module.exports = '1.50.0';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ata-validator",
3
- "version": "1.49.0",
3
+ "version": "1.50.0",
4
4
  "description": "JSON Schema validator that compiles to plain JavaScript, still runs where code generation is blocked, and can be compiled away at build time. Passes the full official test suite.",
5
5
  "type": "commonjs",
6
6
  "main": "index.js",
@@ -8,6 +8,16 @@
8
8
  "types": "index.d.ts",
9
9
  "exports": {
10
10
  ".": {
11
+ "workerd": {
12
+ "types": "./index.d.ts",
13
+ "import": "./index.edge.mjs",
14
+ "require": "./index.edge.js"
15
+ },
16
+ "edge-light": {
17
+ "types": "./index.d.ts",
18
+ "import": "./index.edge.mjs",
19
+ "require": "./index.edge.js"
20
+ },
11
21
  "types": "./index.d.ts",
12
22
  "browser": {
13
23
  "import": "./index.browser.mjs",
@@ -54,6 +64,11 @@
54
64
  "import": "./lite.mjs",
55
65
  "require": "./lite.js"
56
66
  },
67
+ "./error-runtime": {
68
+ "types": "./error-runtime.d.ts",
69
+ "import": "./error-runtime.mjs",
70
+ "require": "./error-runtime.js"
71
+ },
57
72
  "./package.json": "./package.json"
58
73
  },
59
74
  "sideEffects": false,
@@ -123,6 +138,8 @@
123
138
  "index.mjs",
124
139
  "index.node.mjs",
125
140
  "index.browser.mjs",
141
+ "index.edge.js",
142
+ "index.edge.mjs",
126
143
  "index.d.ts",
127
144
  "aot.js",
128
145
  "aot.mjs",
@@ -147,18 +164,21 @@
147
164
  "lite.js",
148
165
  "lite.mjs",
149
166
  "lite.d.ts",
167
+ "error-runtime.js",
168
+ "error-runtime.mjs",
169
+ "error-runtime.d.ts",
150
170
  "bin/",
151
171
  "README.md",
152
172
  "LICENSE"
153
173
  ],
154
174
  "optionalDependencies": {
155
- "@ata-validator/native-darwin-arm64": "1.49.0",
156
- "@ata-validator/native-darwin-x64": "1.49.0",
157
- "@ata-validator/native-linux-arm64-gnu": "1.49.0",
158
- "@ata-validator/native-linux-arm64-musl": "1.49.0",
159
- "@ata-validator/native-linux-x64-gnu": "1.49.0",
160
- "@ata-validator/native-linux-x64-musl": "1.49.0",
161
- "@ata-validator/native-win32-x64": "1.49.0"
175
+ "@ata-validator/native-darwin-arm64": "1.50.0",
176
+ "@ata-validator/native-darwin-x64": "1.50.0",
177
+ "@ata-validator/native-linux-arm64-gnu": "1.50.0",
178
+ "@ata-validator/native-linux-arm64-musl": "1.50.0",
179
+ "@ata-validator/native-linux-x64-gnu": "1.50.0",
180
+ "@ata-validator/native-linux-x64-musl": "1.50.0",
181
+ "@ata-validator/native-win32-x64": "1.50.0"
162
182
  },
163
183
  "peerDependencies": {
164
184
  "yaml": "^2.0.0"