ata-validator 1.59.0 → 1.61.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +107 -4
- package/bin/ata.js +84 -0
- package/build.d.ts +29 -0
- package/build.mjs +2 -0
- package/compiled.d.ts +3 -1
- package/index.browser.mjs +2 -2
- package/index.bundle.mjs +2 -2
- package/index.d.ts +9 -0
- package/index.edge.mjs +2 -2
- package/index.js +48 -0
- package/index.mjs +1 -1
- package/index.node.mjs +1 -1
- package/lib/aot-build.js +73 -6
- package/lib/aot-impl.js +28 -27
- package/lib/bun-target.js +612 -0
- package/lib/codegen-engine.js +9 -3
- package/lib/combined-runtime.js +1 -1
- package/lib/compiled.js +6 -0
- package/lib/formats.js +1 -1
- package/lib/js-compiler-errors.js +45 -10
- package/lib/js-compiler.js +92 -13
- package/lib/public-api.js +1 -0
- package/lib/standard-schema.js +145 -0
- package/lib/tier0.js +1 -1
- package/lib/validator-core.js +44 -138
- package/lib/verify.js +321 -0
- package/lib/version.js +1 -1
- package/lite.js +1 -0
- package/lite.mjs +1 -1
- package/package.json +10 -9
package/README.md
CHANGED
|
@@ -12,11 +12,17 @@ JSON Schema validation that compiles for speed and still runs where code generat
|
|
|
12
12
|
|
|
13
13
|
## Who uses ata
|
|
14
14
|
|
|
15
|
-
Projects whose code depends on ata, from GitHub's dependency graph,
|
|
16
|
-
its
|
|
15
|
+
Projects whose code depends on ata, from GitHub's dependency graph, a framework that lists its
|
|
16
|
+
plugin, a form library that ships its resolver, and one company whose use is not public code,
|
|
17
|
+
with what each does with it:
|
|
17
18
|
|
|
19
|
+
- [Trendyol](https://github.com/Trendyol) validates configuration with ata in Puzzle, its
|
|
20
|
+
internal config tooling. The package is internal, so it is not in the public dependency
|
|
21
|
+
graph; this line rests on its maintainer.
|
|
18
22
|
- [Socket](https://github.com/SocketDev) uses ata, compiled ahead of time, in the shared build
|
|
19
23
|
tooling of its repositories.
|
|
24
|
+
- [React Hook Form](https://github.com/react-hook-form/resolvers) ships an ata resolver in
|
|
25
|
+
`@hookform/resolvers` (`@hookform/resolvers/ata-validator`), beside its other validators.
|
|
20
26
|
- [Fastify](https://fastify.dev/ecosystem/) lists the
|
|
21
27
|
[`fastify-ata`](https://github.com/ata-core/fastify-ata) plugin in its ecosystem.
|
|
22
28
|
- [react-jsonschema-form](https://github.com/rjsf-team/react-jsonschema-form) ships an ata
|
|
@@ -68,7 +74,7 @@ details, and what Deno Deploy's refusal of dynamic code means for it, are in
|
|
|
68
74
|
|
|
69
75
|
Those four now agree with `validate()` on every case of the official suite, 3365 across three dialects. The native walker behind them does not handle every shape (`contains`, `unevaluatedProperties`, `patternProperties`, tuple `items`, cross-document `$ref`, a few formats), so for schemas using one of those the buffer APIs parse the bytes and answer through `validate()`; the list is in `lib/buffer-gate.js`. Typical request schemas stay on the zero-copy path. `npm test` holds the disagreement count at zero.
|
|
70
76
|
|
|
71
|
-
Where `new Function` is refused altogether, on Cloudflare Workers, Deno Deploy or under a strict Content-Security-Policy, ata drops to the interpreted engine and scores the same 1301 of 1301 with code generation blocked. No flags, and on Workers no `nodejs_compat` either. See [docs/edge-runtimes.md](docs/edge-runtimes.md).
|
|
77
|
+
Where `new Function` is refused altogether, on Cloudflare Workers, Deno Deploy or under a strict Content-Security-Policy, ata drops to the interpreted engine and scores the same 1301 of 1301 with code generation blocked. No flags, and on Workers no `nodejs_compat` either. See [docs/edge-runtimes.md](docs/edge-runtimes.md). Where generated code runs but slowly, as in an ahead-of-time compiled Bun executable, a module from `ata build` is plain JavaScript that imports nothing and calls no `new Function`: on Bun 1.4.0, import plus a first validation takes 0.66 ms with such a module against 10.70 ms with the runtime compiler (medians of 21 runs). [docs/proof-no-code-generation.md](docs/proof-no-code-generation.md) runs one schema in five of these places, Workers and a CSP page included, and shows the same answers from each.
|
|
72
78
|
|
|
73
79
|
Node has a switch for exactly that environment, so this takes thirty seconds to check for yourself, on ata or on whatever you use today:
|
|
74
80
|
|
|
@@ -667,6 +673,102 @@ first request, so counting only registration would overstate the gap. The first
|
|
|
667
673
|
here comes in the same tick as setup; a server that listens first has the code generator
|
|
668
674
|
loaded by then. Reproduce with `node benchmark/bench_fastify_boot.mjs`.
|
|
669
675
|
|
|
676
|
+
A server that listens first also gets the engine warmed: once the event loop is free, if a
|
|
677
|
+
validator was built and not yet called, ata runs one check of a small schema, accepted and
|
|
678
|
+
rejected, so that V8 compiles the generator's functions and the error builders then rather
|
|
679
|
+
than on the first request. Measured on a four-field schema with the generator already
|
|
680
|
+
loaded: the first verdict 3.1 to 3.4 ms without it, 0.5 to 0.6 with it; the first error
|
|
681
|
+
list 6.7 against 0.8; a second route's first verdict 0.9 to 1.0 against 0.7 to 0.9. It costs
|
|
682
|
+
the process 1.5 to 2 ms of CPU once. A script that builds a validator and checks in the
|
|
683
|
+
same tick never runs it, and the timer is unref'd, so a finished script does not stay for
|
|
684
|
+
it; `ATA_NO_WARM=1` turns it off.
|
|
685
|
+
|
|
686
|
+
### Proving the build (`ata verify`)
|
|
687
|
+
|
|
688
|
+
A module written at build time is only a good idea if it answers as the
|
|
689
|
+
runtime it replaced. `ata verify` checks that on the project's own schemas:
|
|
690
|
+
|
|
691
|
+
```bash
|
|
692
|
+
npx ata verify 'schemas/*.json' --samples test/fixtures
|
|
693
|
+
```
|
|
694
|
+
|
|
695
|
+
For each schema it loads the module `ata build` wrote beside it, makes
|
|
696
|
+
documents from the schema (200 by default, half of them with one rule broken),
|
|
697
|
+
reads the project's sample documents (JSON files, JSON Lines, or a directory
|
|
698
|
+
of them), and has both the module and a `Validator` built from the schema now
|
|
699
|
+
answer every one. Verdicts and error lists have to agree; a module whose
|
|
700
|
+
schema hash no longer matches the schema is reported stale. The exit code is
|
|
701
|
+
non-zero on any disagreement, stale module or missing module, so the command
|
|
702
|
+
works as a CI step. This is the check that found the two silent divergences
|
|
703
|
+
fixed in 1.59.0 and 1.60.0, now in a form a project can run on every change.
|
|
704
|
+
It does not run the `.bun.ts` target, which needs Bun's compiler.
|
|
705
|
+
|
|
706
|
+
### Bun, compiled ahead of time
|
|
707
|
+
|
|
708
|
+
Bun's ahead-of-time compiler (`bun build --compile --aot`, an open pull
|
|
709
|
+
request as of October 2026) runs code that a library hands to `new Function`
|
|
710
|
+
through an interpreter. Measured with its pull request build on one schema
|
|
711
|
+
and 1024 parsed documents, nanoseconds per document (`benchmark/proof/aot`):
|
|
712
|
+
|
|
713
|
+
| | JIT | ahead of time |
|
|
714
|
+
|---|---|---|
|
|
715
|
+
| a module from `ata build --target bun` | 25 | 24 |
|
|
716
|
+
| `new Validator(schema)`, generated code | 28 | 492 |
|
|
717
|
+
| `new Validator(schema)`, interpreted engine | 52 | 80 |
|
|
718
|
+
|
|
719
|
+
So, in order of preference:
|
|
720
|
+
|
|
721
|
+
1. Compile the schema at build time. `@ata-project/unplugin/bun` does it in
|
|
722
|
+
`Bun.build`, including `Bun.build({ compile })`; `ata build` writes the
|
|
723
|
+
module by hand. The module is plain JavaScript and compiles with the
|
|
724
|
+
program: 24 ns, the same errors as the runtime.
|
|
725
|
+
2. Where the runtime `Validator` stays, let it take the interpreted engine.
|
|
726
|
+
It does so by itself when Bun reports `Bun.isAOT`, when the executable is
|
|
727
|
+
built with `--disallow-code-generation-from-strings` (the program then
|
|
728
|
+
counts as closed for the compiler, too), or when `ATA_ENGINE=interpreter`
|
|
729
|
+
is set: 80 ns against 492 for the generated code there.
|
|
730
|
+
3. Write the module for the compiler. `ata build schema.json --target bun`
|
|
731
|
+
writes it with a closed object's keys read once and compared with the
|
|
732
|
+
declared list in order (on a ten-item order with 1024 distinct documents,
|
|
733
|
+
10% of them invalid, 105 to 107 ns under the compiler against 223 for the
|
|
734
|
+
form V8 gets; on V8 the module keeps for...in, on Bun's JIT a plain count,
|
|
735
|
+
each the cheaper form there), and answers a rejection with the one-pass
|
|
736
|
+
error function (189 ns with the error list on that order, against 724
|
|
737
|
+
with the older collector), the form every other build takes only with
|
|
738
|
+
`--one-pass` since it is 20% larger gzipped. Beside the module it writes
|
|
739
|
+
`schema.compiled.bun.ts`: the schema as a TypeScript type (kinds,
|
|
740
|
+
properties and which are required, items and fixed tuples, literals,
|
|
741
|
+
local definitions as named types), `validate` and `isValid` with that
|
|
742
|
+
type on them, and `parse(text)`, which declares the type where it parses
|
|
743
|
+
and has the module check the content. Every check is the module's, and
|
|
744
|
+
the file is a type for the program, not a faster path: on that order,
|
|
745
|
+
with the pull request build of 2026-10-25, `isValid` 118 ns through the
|
|
746
|
+
file against 118 to 121 through the module, `parse` 564 to 574 against
|
|
747
|
+
570 to 578 for a plain parse and the module, and reading the parsed
|
|
748
|
+
object after a typed parse 593 to 595 against 587 to 591 after a plain
|
|
749
|
+
one. The file is for executables built with
|
|
750
|
+
`--aot`; a project points that compiler at it with an `"aot"` condition
|
|
751
|
+
in its `package.json` `imports`, which nothing else reads:
|
|
752
|
+
|
|
753
|
+
```json
|
|
754
|
+
{ "imports": { "#schemas/*": { "aot": "./schemas/*.bun.ts", "default": "./schemas/*.js" } } }
|
|
755
|
+
```
|
|
756
|
+
|
|
757
|
+
A schema no type can be written for (a remote `$ref`, `$dynamicRef`, a
|
|
758
|
+
root the type says nothing about) gets a warning and the plain module
|
|
759
|
+
alone.
|
|
760
|
+
|
|
761
|
+
The pull request carried its own typed validator until 2026-10-25, and
|
|
762
|
+
`--target bun` wrote the schema's rules as a type for it; it left the pull
|
|
763
|
+
request to return as a change of its own. `docs/API.md` has what ata keeps
|
|
764
|
+
for it. A schema's `pattern` is a `new RegExp` at run time in the runtime
|
|
765
|
+
`Validator`, which that compiler runs through its regular expression
|
|
766
|
+
interpreter; the module writes each pattern as a literal, which it compiles.
|
|
767
|
+
`--aot` makes TypeScript errors fatal; ata's declarations say `message?:
|
|
768
|
+
string` on an error, so read it as such. The numbers are from the pull
|
|
769
|
+
request build of 2026-10-24 on one machine and will be run again when the
|
|
770
|
+
compiler ships.
|
|
771
|
+
|
|
670
772
|
### Standard Schema V1
|
|
671
773
|
|
|
672
774
|
```javascript
|
|
@@ -745,9 +847,10 @@ Copy-paste recipes for the common frameworks. Most need 10-20 lines of glue. See
|
|
|
745
847
|
| Vite (build-time compile) | dedicated plugin | [`ata-vite`](https://github.com/ata-core/ata-vite), the Vite entry of the plugin above |
|
|
746
848
|
| Next.js (build-time compile) | webpack entry of the plugin above | `@ata-project/unplugin/webpack` in `next.config.js` |
|
|
747
849
|
| Hono | async middleware | [docs/integrations/hono.md](docs/integrations/hono.md) |
|
|
748
|
-
| Elysia |
|
|
850
|
+
| Elysia | Standard Schema V1 in the `body` slot | [docs/integrations/elysia.md](docs/integrations/elysia.md) |
|
|
749
851
|
| tRPC | Standard Schema V1 input | [docs/integrations/trpc.md](docs/integrations/trpc.md) |
|
|
750
852
|
| TanStack Form | Standard Schema V1 validator | [docs/integrations/tanstack-form.md](docs/integrations/tanstack-form.md) |
|
|
853
|
+
| React Hook Form | resolver | [`@hookform/resolvers/ata-validator`](https://github.com/react-hook-form/resolvers/tree/master/ata-validator) |
|
|
751
854
|
| Express | sync middleware | [docs/integrations/express.md](docs/integrations/express.md) |
|
|
752
855
|
| Koa | async ctx middleware | [docs/integrations/koa.md](docs/integrations/koa.md) |
|
|
753
856
|
| NestJS | validation pipe | [docs/integrations/nestjs.md](docs/integrations/nestjs.md) |
|
package/bin/ata.js
CHANGED
|
@@ -13,6 +13,15 @@ Usage:
|
|
|
13
13
|
ata build <glob>... [options] Compile a project's schemas (glob pattern) per file.
|
|
14
14
|
ata validate <schema> <data> [options] Validate a JSON data file against a schema.
|
|
15
15
|
ata migrate [dir] [options] Report what switching from ajv would change; --write applies it.
|
|
16
|
+
ata verify <glob>... [options] Check that each schema's compiled module answers as the runtime
|
|
17
|
+
does, on generated documents and the project's samples.
|
|
18
|
+
|
|
19
|
+
Verify options:
|
|
20
|
+
--generate <n> Documents made from each schema, half with one rule broken. Default: 200
|
|
21
|
+
--samples <path> A JSON, JSON Lines file or a directory of them, checked too (repeatable)
|
|
22
|
+
--seed <n> Seed for the generated documents. Default: 1
|
|
23
|
+
--json Report as JSON
|
|
24
|
+
--out-dir, --suffix, --format Where the modules are, as given to ata build
|
|
16
25
|
|
|
17
26
|
Validate options:
|
|
18
27
|
--pretty Render errors with source frames (default on TTY)
|
|
@@ -65,6 +74,9 @@ Build options:
|
|
|
65
74
|
--cache-file <path> Cache file for incremental builds (default: cache disabled)
|
|
66
75
|
--max-size <bytes> Fail build if any compiled module exceeds this gzipped size
|
|
67
76
|
--strict Treat any AOT-incompatible schema as a build error (default: skip + warn)
|
|
77
|
+
--target bun Write every module for Bun's ahead-of-time compiler, and beside
|
|
78
|
+
each a .bun.ts with the schema as a TypeScript type and a typed
|
|
79
|
+
parse(text); the plain module answers every check
|
|
68
80
|
--strict-schema Fail the build on schema authoring mistakes: unknown
|
|
69
81
|
keywords (with a spelling suggestion), keywords the
|
|
70
82
|
node's type makes inert, unresolvable local $refs,
|
|
@@ -117,6 +129,11 @@ function parseArgs(argv) {
|
|
|
117
129
|
if (a === '--check') { out.opts.check = true; continue; }
|
|
118
130
|
if (a === '--strict') { out.opts.strict = true; continue; }
|
|
119
131
|
if (a === '--strict-schema') { out.opts.strictSchema = true; continue; }
|
|
132
|
+
if (a === '--target') { out.opts.target = argv[++i]; continue; }
|
|
133
|
+
if (a === '--generate') { out.opts.generate = Number(argv[++i]); continue; }
|
|
134
|
+
if (a === '--samples') { (out.opts.samples = out.opts.samples || []).push(argv[++i]); continue; }
|
|
135
|
+
if (a === '--seed') { out.opts.seed = Number(argv[++i]); continue; }
|
|
136
|
+
if (a === '--json') { out.opts.json = true; continue; }
|
|
120
137
|
if (a === '--out-dir') { out.opts.outDir = argv[++i]; continue; }
|
|
121
138
|
if (a === '--suffix') { out.opts.suffix = argv[++i]; continue; }
|
|
122
139
|
if (a === '--cache-file') { out.opts.cacheFile = argv[++i]; continue; }
|
|
@@ -239,6 +256,15 @@ function cmdCompile(args) {
|
|
|
239
256
|
|
|
240
257
|
const { Validator } = require('..');
|
|
241
258
|
const aot = require('../lib/aot');
|
|
259
|
+
// `--target bun`: the module is written for JavaScriptCore, the engine the
|
|
260
|
+
// executable the target is for runs on.
|
|
261
|
+
if (args.opts.target === 'bun') {
|
|
262
|
+
require('../lib/js-compiler').setTargetEngine('jsc-aot');
|
|
263
|
+
// The executable's module answers rejections with the one-pass error
|
|
264
|
+
// function and carries no schema-source frames unless asked for.
|
|
265
|
+
if (args.opts.onePass === undefined) args.opts.onePass = true;
|
|
266
|
+
if (args.opts.source === undefined) args.opts.source = false;
|
|
267
|
+
}
|
|
242
268
|
let v;
|
|
243
269
|
try {
|
|
244
270
|
v = new Validator(schema);
|
|
@@ -277,6 +303,25 @@ function cmdCompile(args) {
|
|
|
277
303
|
const sizeBytes = Buffer.byteLength(src, 'utf8');
|
|
278
304
|
process.stdout.write(`ata: compiled ${input} -> ${output} (${sizeBytes.toLocaleString()} bytes, ${format}${abortEarly ? ', abort-early' : ''})\n`);
|
|
279
305
|
|
|
306
|
+
if (args.opts.target !== undefined) {
|
|
307
|
+
if (args.opts.target !== 'bun') {
|
|
308
|
+
reportCompileError(input, `--target must be bun (got ${JSON.stringify(args.opts.target)})`);
|
|
309
|
+
process.exit(1);
|
|
310
|
+
}
|
|
311
|
+
const { writeBunTarget, Declined } = require('../lib/bun-target');
|
|
312
|
+
const tn = (args.opts.name || path.basename(input, path.extname(input)).replace(/[^A-Za-z0-9_]/g, '_').replace(/^([a-z])/, (m) => m.toUpperCase())) || 'Data';
|
|
313
|
+
try {
|
|
314
|
+
const w = writeBunTarget({ schema, input, output, typeName: tn });
|
|
315
|
+
process.stdout.write(`ata: bun target -> ${w.bunPath} (for bun build --compile --aot)\n`);
|
|
316
|
+
} catch (e) {
|
|
317
|
+
if (!(e instanceof Declined)) throw e;
|
|
318
|
+
// No type can be written; the plain module stands alone.
|
|
319
|
+
const msg = `--target bun: ${e.message}; the plain module stands alone`;
|
|
320
|
+
if (args.opts.strict) { reportCompileError(input, msg); process.exit(1); }
|
|
321
|
+
process.stderr.write(`ata: warning: ${input}: ${msg}\n`);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
280
325
|
// Emit paired declaration file unless --no-types.
|
|
281
326
|
// TypeScript resolution: .mjs -> .d.mts, .cjs -> .d.cts, .js -> .d.ts.
|
|
282
327
|
const emitTypes = args.opts.types !== false;
|
|
@@ -298,6 +343,10 @@ function cmdCompile(args) {
|
|
|
298
343
|
}
|
|
299
344
|
|
|
300
345
|
function cmdBuild(args) {
|
|
346
|
+
if (args.opts.target !== undefined && args.opts.target !== 'bun') {
|
|
347
|
+
process.stderr.write(`error: --target must be bun (got ${JSON.stringify(args.opts.target)})\n`);
|
|
348
|
+
process.exit(1);
|
|
349
|
+
}
|
|
301
350
|
if (args._.length === 0) {
|
|
302
351
|
process.stderr.write('error: missing <glob>\n\n');
|
|
303
352
|
usage();
|
|
@@ -323,6 +372,7 @@ function cmdBuild(args) {
|
|
|
323
372
|
check: !!args.opts.check,
|
|
324
373
|
maxSize: args.opts.maxSize,
|
|
325
374
|
strict: !!args.opts.strict,
|
|
375
|
+
target: args.opts.target,
|
|
326
376
|
types: args.opts.types,
|
|
327
377
|
cacheFile: args.opts.cacheFile,
|
|
328
378
|
// Forward the explicit user choice (true / false / undefined). The
|
|
@@ -337,6 +387,8 @@ function cmdBuild(args) {
|
|
|
337
387
|
}
|
|
338
388
|
for (const c of report.compiled) {
|
|
339
389
|
process.stdout.write(`ata: ${c.input} -> ${c.output} (${c.bytes.toLocaleString()} bytes${c.errors === 'compact' ? ', shared errors' : c.errors === 'schema' ? ', schema module' : ''})\n`);
|
|
390
|
+
for (const t of (report.bunTargets || []).filter((t) => t.input === c.input)) process.stdout.write(`ata: bun target -> ${t.output} (for bun build --compile --aot)\n`);
|
|
391
|
+
for (const d of (report.bunDeclined || []).filter((d) => d.input === c.input)) process.stderr.write(`ata: warning: ${d.input}: ${d.reason}\n`);
|
|
340
392
|
}
|
|
341
393
|
if (report.runtime) {
|
|
342
394
|
process.stdout.write(`ata: error runtime -> ${report.runtime.output} (${report.runtime.bytes.toLocaleString()} bytes, shared by the modules above)\n`);
|
|
@@ -408,6 +460,33 @@ function cmdBuild(args) {
|
|
|
408
460
|
});
|
|
409
461
|
}
|
|
410
462
|
|
|
463
|
+
function cmdVerify (args) {
|
|
464
|
+
if (args._.length === 0) {
|
|
465
|
+
process.stderr.write('error: missing <glob>\n\n');
|
|
466
|
+
usage();
|
|
467
|
+
process.exit(1);
|
|
468
|
+
}
|
|
469
|
+
const buildLib = require('../lib/aot-build');
|
|
470
|
+
const { verifyOne, renderReport, ok } = require('../lib/verify');
|
|
471
|
+
const format = args.opts.format || 'esm';
|
|
472
|
+
(async () => {
|
|
473
|
+
const inputs = await buildLib.expandGlobs(args._);
|
|
474
|
+
if (inputs.length === 0) {
|
|
475
|
+
process.stderr.write(`error: no schema files match ${args._.join(' ')}\n`);
|
|
476
|
+
process.exit(1);
|
|
477
|
+
}
|
|
478
|
+
const reports = [];
|
|
479
|
+
for (const input of inputs) {
|
|
480
|
+
let schema;
|
|
481
|
+
try { schema = buildLib.parseSchemaFile(input); } catch (e) { reports.push({ schema: input, module: '', error: e.message, documents: 0, agree: 0, disagreements: [] }); continue; }
|
|
482
|
+
const moduleFile = buildLib.outputPathFor(input, { format, outDir: args.opts.outDir, suffix: args.opts.suffix });
|
|
483
|
+
reports.push(await verifyOne({ schemaFile: input, moduleFile, schema, generate: Number.isFinite(args.opts.generate) ? args.opts.generate : 200, seed: Number.isFinite(args.opts.seed) ? args.opts.seed : 1, samples: args.opts.samples || [] }));
|
|
484
|
+
}
|
|
485
|
+
process.stdout.write(renderReport(reports, { json: !!args.opts.json }) + '\n');
|
|
486
|
+
process.exit(reports.every(ok) ? 0 : 1);
|
|
487
|
+
})().catch((e) => { process.stderr.write(`error: ${e.message}\n`); process.exit(1); });
|
|
488
|
+
}
|
|
489
|
+
|
|
411
490
|
function cmdValidate (args) {
|
|
412
491
|
if (args._.length < 2) {
|
|
413
492
|
process.stderr.write('error: ata validate <schema> <data-file>\n');
|
|
@@ -508,6 +587,11 @@ function main() {
|
|
|
508
587
|
return;
|
|
509
588
|
}
|
|
510
589
|
|
|
590
|
+
if (cmd === 'verify') {
|
|
591
|
+
cmdVerify(args);
|
|
592
|
+
return;
|
|
593
|
+
}
|
|
594
|
+
|
|
511
595
|
if (cmd === 'migrate') {
|
|
512
596
|
const { migrate, formatReport } = require('../lib/migrate');
|
|
513
597
|
const result = migrate(args._[0] || '.', { write: !!args.opts.write });
|
package/build.d.ts
CHANGED
|
@@ -204,3 +204,32 @@ export function compiledModuleFor(schema: unknown, opts?: { format?: 'esm' | 'cj
|
|
|
204
204
|
* ata-validator 1.37.0, where only calls without options can be.
|
|
205
205
|
*/
|
|
206
206
|
export const compiledOptions: readonly string[];
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* The Bun target, for a build plugin: the schema as a TypeScript type and the
|
|
210
|
+
* `.bun.ts` module `ata build --target bun` writes beside a compiled module.
|
|
211
|
+
* With `tags: true` the type carries Bun's `Schema` tags and `residual` holds
|
|
212
|
+
* the schema of every rule the tagged type does not carry, the split made for
|
|
213
|
+
* Bun's `validate<T>`, which left the compiler's pull request on 2026-10-25
|
|
214
|
+
* and is to return as a change of its own; without tags `residual` is null.
|
|
215
|
+
*/
|
|
216
|
+
export const bunTarget: {
|
|
217
|
+
schemaToBunType(schema: unknown, opts?: { name?: string; aliasPrefix?: string; tags?: boolean; assertFormat?: boolean }): { name: string; type: string; aliases: Array<[string, string]>; residual: unknown | null; carried: string[] };
|
|
218
|
+
toBunModule(args: { schemaFile: string; moduleImport: string; typeName: string; typeSource: string; aliases: Array<[string, string]> }): string;
|
|
219
|
+
writeBunTarget(args: { schema: unknown; input: string; output: string; typeName: string }): { bunPath: string; definitions: number; carried: number };
|
|
220
|
+
Declined: new (reason: string, pointer: string) => Error & { reason: string; pointer: string };
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
/** `ata verify` as functions: a compiled module held against the runtime on generated documents and samples. */
|
|
224
|
+
export const verify: {
|
|
225
|
+
verifyOne(args: { schemaFile: string; moduleFile: string; schema: unknown; generate?: number; seed?: number; samples?: string[] }): Promise<VerifyReport>;
|
|
226
|
+
verifySource(schema: unknown, src: string, opts?: { name?: string; format?: 'esm' | 'cjs'; generate?: number; seed?: number; samples?: string[] }): Promise<VerifyReport>;
|
|
227
|
+
generate(schema: unknown, count: number, seed: number): unknown[];
|
|
228
|
+
renderReport(reports: VerifyReport[], opts?: { json?: boolean }): string;
|
|
229
|
+
ok(report: VerifyReport): boolean;
|
|
230
|
+
};
|
|
231
|
+
export interface VerifyReport {
|
|
232
|
+
schema: string; module: string; documents: number; generated: number; samples: number; valid: number; agree: number;
|
|
233
|
+
disagreements: Array<{ source: string; document: string; runtime: string; module: string; runtimeIsValid: boolean; moduleIsValid: boolean } | { more: number }>;
|
|
234
|
+
stale: boolean; missing: boolean; ataVersion: string | null; error: string | null;
|
|
235
|
+
}
|
package/build.mjs
CHANGED
|
@@ -12,5 +12,7 @@ export const schemaHash = mod.schemaHash;
|
|
|
12
12
|
export const compiledEligible = mod.compiledEligible;
|
|
13
13
|
export const compiledSchemaFor = mod.compiledSchemaFor;
|
|
14
14
|
export const compiledModuleFor = mod.compiledModuleFor;
|
|
15
|
+
export const bunTarget = mod.bunTarget;
|
|
16
|
+
export const verify = mod.verify;
|
|
15
17
|
export const compiledOptions = mod.compiledOptions;
|
|
16
18
|
export default mod;
|
package/compiled.d.ts
CHANGED
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
import type { ValidationResult } from './index.js';
|
|
4
4
|
|
|
5
5
|
export interface CompiledModule {
|
|
6
|
-
|
|
6
|
+
// A module's accepted result is frozen, so the array is read-only here;
|
|
7
|
+
// under Bun's ahead-of-time compiler a type error fails the build.
|
|
8
|
+
validate(data: unknown): { valid: boolean; errors: readonly unknown[] };
|
|
7
9
|
isValid(data: unknown): boolean;
|
|
8
10
|
}
|
|
9
11
|
|
package/index.browser.mjs
CHANGED
|
@@ -15,6 +15,6 @@ import { toTypeScript, renderPretty, renderCompact, toOutput, toRetryMessage, de
|
|
|
15
15
|
|
|
16
16
|
core._registerTiering(tiering.createTiering(() => import('./lib/codegen-engine.js')));
|
|
17
17
|
|
|
18
|
-
export const { Validator, compile, validate, validateAsync, parseAsync, version, createPaddedBuffer, SIMDJSON_PADDING, parseJSON, defineSchema } = core;
|
|
18
|
+
export const { Validator, compile, validate, validateAsync, parseAsync, version, createPaddedBuffer, SIMDJSON_PADDING, parseJSON, defineSchema, schemaOf } = core;
|
|
19
19
|
export { toTypeScript, renderPretty, renderCompact, toOutput, toRetryMessage, describeSchema, renderJSON };
|
|
20
|
-
export default { Validator, compile, validate, validateAsync, parseAsync, version, createPaddedBuffer, SIMDJSON_PADDING, parseJSON, toTypeScript, defineSchema, renderPretty, renderCompact, toOutput, toRetryMessage, describeSchema, renderJSON };
|
|
20
|
+
export default { Validator, compile, validate, validateAsync, parseAsync, version, createPaddedBuffer, SIMDJSON_PADDING, parseJSON, toTypeScript, defineSchema, schemaOf, renderPretty, renderCompact, toOutput, toRetryMessage, describeSchema, renderJSON };
|
package/index.bundle.mjs
CHANGED
|
@@ -10,6 +10,6 @@ import { toTypeScript, renderPretty, renderCompact, toOutput, toRetryMessage, de
|
|
|
10
10
|
|
|
11
11
|
core._registerCodegen(engine);
|
|
12
12
|
|
|
13
|
-
export const { Validator, compile, validate, validateAsync, parseAsync, version, createPaddedBuffer, SIMDJSON_PADDING, parseJSON, defineSchema } = core;
|
|
13
|
+
export const { Validator, compile, validate, validateAsync, parseAsync, version, createPaddedBuffer, SIMDJSON_PADDING, parseJSON, defineSchema, schemaOf } = core;
|
|
14
14
|
export { toTypeScript, renderPretty, renderCompact, toOutput, toRetryMessage, describeSchema, renderJSON };
|
|
15
|
-
export default { Validator, compile, validate, validateAsync, parseAsync, version, createPaddedBuffer, SIMDJSON_PADDING, parseJSON, toTypeScript, defineSchema, renderPretty, renderCompact, toOutput, toRetryMessage, describeSchema, renderJSON };
|
|
15
|
+
export default { Validator, compile, validate, validateAsync, parseAsync, version, createPaddedBuffer, SIMDJSON_PADDING, parseJSON, toTypeScript, defineSchema, schemaOf, renderPretty, renderCompact, toOutput, toRetryMessage, describeSchema, renderJSON };
|
package/index.d.ts
CHANGED
|
@@ -678,3 +678,12 @@ export function toTypeScript(schema: object, options?: { name?: string }): strin
|
|
|
678
678
|
* Requires TypeScript >= 5.0 for the `const` type parameter.
|
|
679
679
|
*/
|
|
680
680
|
export declare function defineSchema<const S extends JSONSchema>(schema: S): S;
|
|
681
|
+
|
|
682
|
+
/**
|
|
683
|
+
* The JSON Schema of a TypeScript type, written in at build time by
|
|
684
|
+
* `@ata-project/unplugin` from the type and the JSDoc tags on its properties
|
|
685
|
+
* (`@format email`, `@minimum 1`, `@pattern`, `@minLength`, `@maxItems`,
|
|
686
|
+
* `@asType integer`). `new Validator(schemaOf<User>())` then compiles like any
|
|
687
|
+
* static schema. Without the plugin the call throws: it has no run-time form.
|
|
688
|
+
*/
|
|
689
|
+
export declare function schemaOf<T>(): JSONSchema;
|
package/index.edge.mjs
CHANGED
|
@@ -8,6 +8,6 @@ import { toTypeScript, renderPretty, renderCompact, toOutput, toRetryMessage, de
|
|
|
8
8
|
|
|
9
9
|
core._registerAot(() => aotBrowser);
|
|
10
10
|
|
|
11
|
-
export const { Validator, compile, validate, validateAsync, parseAsync, version, createPaddedBuffer, SIMDJSON_PADDING, parseJSON, defineSchema } = core;
|
|
11
|
+
export const { Validator, compile, validate, validateAsync, parseAsync, version, createPaddedBuffer, SIMDJSON_PADDING, parseJSON, defineSchema, schemaOf } = core;
|
|
12
12
|
export { toTypeScript, renderPretty, renderCompact, toOutput, toRetryMessage, describeSchema, renderJSON };
|
|
13
|
-
export default { Validator, compile, validate, validateAsync, parseAsync, version, createPaddedBuffer, SIMDJSON_PADDING, parseJSON, toTypeScript, defineSchema, renderPretty, renderCompact, toOutput, toRetryMessage, describeSchema, renderJSON };
|
|
13
|
+
export default { Validator, compile, validate, validateAsync, parseAsync, version, createPaddedBuffer, SIMDJSON_PADDING, parseJSON, toTypeScript, defineSchema, schemaOf, renderPretty, renderCompact, toOutput, toRetryMessage, describeSchema, renderJSON };
|
package/index.js
CHANGED
|
@@ -20,6 +20,53 @@ core._setCodegenLoader(loadCodegen);
|
|
|
20
20
|
const warm = setTimeout(loadCodegen, 0);
|
|
21
21
|
if (typeof warm === 'object' && typeof warm.unref === 'function') warm.unref();
|
|
22
22
|
|
|
23
|
+
// A process whose first check comes after the event loop has turned, a
|
|
24
|
+
// server's first request, pays on that check for V8 compiling the generator's
|
|
25
|
+
// functions and the error builders: on a four-field schema 5 ms for the
|
|
26
|
+
// verdict and 7 to 10 ms for the first error list, measured with the
|
|
27
|
+
// generator already loaded. One check of a small schema, accepted and
|
|
28
|
+
// rejected, run once the loop is free, moves that off the request: 0.5 and
|
|
29
|
+
// 0.7 ms after it (the same warm-up as the browser build's, lib/tiering.js).
|
|
30
|
+
// It runs only where a validator was built and is still uncompiled when the
|
|
31
|
+
// loop turns: a script that builds one and checks in the same tick never runs
|
|
32
|
+
// it, and the timer is unref'd, so a finished script does not stay for it.
|
|
33
|
+
// ATA_NO_WARM=1 turns it off.
|
|
34
|
+
let built = null;
|
|
35
|
+
core._registerBuiltHook((v) => {
|
|
36
|
+
if (built === null) {
|
|
37
|
+
built = [];
|
|
38
|
+
const t = setTimeout(warmUp, 0);
|
|
39
|
+
if (typeof t === 'object' && typeof t.unref === 'function') t.unref();
|
|
40
|
+
}
|
|
41
|
+
if (built.length < 8) built.push(new WeakRef(v));
|
|
42
|
+
});
|
|
43
|
+
function warmUp () {
|
|
44
|
+
const list = built;
|
|
45
|
+
built = [];
|
|
46
|
+
core._registerBuiltHook(null);
|
|
47
|
+
if (process.env.ATA_NO_WARM === '1') return;
|
|
48
|
+
// Untouched: neither compiled for validate() nor a verdict or validate
|
|
49
|
+
// method read off it (the prototype's accessors bind the method on the
|
|
50
|
+
// instance at the first read, a verdict-only compile sets no other mark).
|
|
51
|
+
const untouched = (v) => !v._initialized && !Object.prototype.hasOwnProperty.call(v, 'isValidObject') && !Object.prototype.hasOwnProperty.call(v, 'validate');
|
|
52
|
+
if (!list.some((r) => { const v = r.deref(); return v !== undefined && untouched(v); })) return;
|
|
53
|
+
try {
|
|
54
|
+
const v = new core.Validator({
|
|
55
|
+
type: 'object',
|
|
56
|
+
properties: {
|
|
57
|
+
a: { type: 'string', minLength: 2, maxLength: 9, pattern: '^[a-z]+$', format: 'email' },
|
|
58
|
+
b: { type: 'integer', minimum: 1, maximum: 9 },
|
|
59
|
+
c: { type: 'array', items: { type: 'string' }, maxItems: 3 },
|
|
60
|
+
d: { const: true },
|
|
61
|
+
e: { type: 'object', properties: { f: { type: 'string' } }, required: ['f'] },
|
|
62
|
+
},
|
|
63
|
+
required: ['a', 'b'],
|
|
64
|
+
});
|
|
65
|
+
v.isValidObject({ a: 'ab@c.de', b: 2, c: ['x'], d: true, e: { f: 'x' } });
|
|
66
|
+
void v.validate({ a: '1', b: 0, c: [1], d: false, e: {} }).errors.length;
|
|
67
|
+
} catch { /* a warm-up never reaches the caller */ }
|
|
68
|
+
}
|
|
69
|
+
|
|
23
70
|
// The public names. lib/public-api.js holds the same for index.edge.js; they
|
|
24
71
|
// are written out here rather than required so that loading the package in
|
|
25
72
|
// Node reads one file fewer (tests/test_edge_entry.js and
|
|
@@ -91,6 +138,7 @@ module.exports = {
|
|
|
91
138
|
parseJSON: core.parseJSON,
|
|
92
139
|
toTypeScript,
|
|
93
140
|
defineSchema: core.defineSchema,
|
|
141
|
+
schemaOf: core.schemaOf,
|
|
94
142
|
renderPretty,
|
|
95
143
|
renderCompact,
|
|
96
144
|
toOutput,
|
package/index.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import mod from './index.js';
|
|
2
|
-
export const { Validator, compile, validate, validateAsync, parseAsync, version, createPaddedBuffer, SIMDJSON_PADDING, parseJSON, toTypeScript, defineSchema, renderPretty, renderCompact, toOutput, toRetryMessage, describeSchema, renderJSON } = mod;
|
|
2
|
+
export const { Validator, compile, validate, validateAsync, parseAsync, version, createPaddedBuffer, SIMDJSON_PADDING, parseJSON, toTypeScript, defineSchema, schemaOf, renderPretty, renderCompact, toOutput, toRetryMessage, describeSchema, renderJSON } = mod;
|
|
3
3
|
export default mod;
|
package/index.node.mjs
CHANGED
|
@@ -6,5 +6,5 @@
|
|
|
6
6
|
// static import they can follow.
|
|
7
7
|
import { createRequire } from 'node:module';
|
|
8
8
|
const mod = createRequire(import.meta.url)('./index.js');
|
|
9
|
-
export const { Validator, compile, validate, validateAsync, parseAsync, version, createPaddedBuffer, SIMDJSON_PADDING, parseJSON, toTypeScript, defineSchema, renderPretty, renderCompact, toOutput, toRetryMessage, describeSchema, renderJSON } = mod;
|
|
9
|
+
export const { Validator, compile, validate, validateAsync, parseAsync, version, createPaddedBuffer, SIMDJSON_PADDING, parseJSON, toTypeScript, defineSchema, schemaOf, renderPretty, renderCompact, toOutput, toRetryMessage, describeSchema, renderJSON } = mod;
|
|
10
10
|
export default mod;
|
package/lib/aot-build.js
CHANGED
|
@@ -202,7 +202,29 @@ function pruneRegistry(roots, byId) {
|
|
|
202
202
|
return out;
|
|
203
203
|
}
|
|
204
204
|
|
|
205
|
+
function bunTargetPath (output) {
|
|
206
|
+
const ext = path.extname(output);
|
|
207
|
+
return output.slice(0, output.length - ext.length) + '.bun.ts';
|
|
208
|
+
}
|
|
209
|
+
|
|
205
210
|
async function build(opts) {
|
|
211
|
+
// `--target bun`: every module written for JavaScriptCore, the plain ones
|
|
212
|
+
// included, since the executable the target is for runs on it.
|
|
213
|
+
const { setTargetEngine } = require('./js-compiler');
|
|
214
|
+
const prevEngine = setTargetEngine(opts.target === 'bun' ? 'jsc-aot' : null);
|
|
215
|
+
// An executable compiled ahead of time pays no bundle size and answers
|
|
216
|
+
// rejections: the one-pass error function (3.6x cheaper on a rejection, 20%
|
|
217
|
+
// larger gzipped) is the default there, and schema-source frames, which it
|
|
218
|
+
// does not carry, are off unless asked for.
|
|
219
|
+
if (opts.target === 'bun') opts = { ...opts, onePass: opts.onePass === undefined ? true : opts.onePass, source: opts.source === true ? true : false };
|
|
220
|
+
try {
|
|
221
|
+
return await buildWith(opts);
|
|
222
|
+
} finally {
|
|
223
|
+
setTargetEngine(prevEngine);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
async function buildWith(opts) {
|
|
206
228
|
const globs = opts.globs || [];
|
|
207
229
|
if (globs.length === 0) throw new Error('build: at least one glob required');
|
|
208
230
|
const format = opts.format || 'esm';
|
|
@@ -226,6 +248,10 @@ async function build(opts) {
|
|
|
226
248
|
|
|
227
249
|
const compiled = [];
|
|
228
250
|
const cached = [];
|
|
251
|
+
// --target bun: the .bun.ts written beside a module, and the schemas whose
|
|
252
|
+
// rules a type cannot carry.
|
|
253
|
+
const bunTargets = [];
|
|
254
|
+
const bunDeclined = [];
|
|
229
255
|
const skipped = [];
|
|
230
256
|
const failed = [];
|
|
231
257
|
const warnings = [];
|
|
@@ -345,7 +371,10 @@ async function build(opts) {
|
|
|
345
371
|
// the registry is put together from such modules: always rebuilt.
|
|
346
372
|
!cacheEntry.usesSiblings &&
|
|
347
373
|
fs.existsSync(output) &&
|
|
348
|
-
cacheEntry.outputHash === hashContent(fs.readFileSync(output))
|
|
374
|
+
cacheEntry.outputHash === hashContent(fs.readFileSync(output)) &&
|
|
375
|
+
// The Bun target is written beside the module; when it is asked for
|
|
376
|
+
// and missing, the module is rebuilt so that it gets written.
|
|
377
|
+
(opts.target !== 'bun' || fs.existsSync(bunTargetPath(output)))
|
|
349
378
|
);
|
|
350
379
|
if (opts.check) {
|
|
351
380
|
if (fresh) cached.push({ input, output });
|
|
@@ -460,12 +489,25 @@ async function build(opts) {
|
|
|
460
489
|
continue;
|
|
461
490
|
}
|
|
462
491
|
compiled.push({ input, output, bytes: outBytes, gzipBytes: gzBytes, errors: e.mode });
|
|
492
|
+
const stem = path.basename(input, path.extname(input)).replace(/\.schema$/, '');
|
|
493
|
+
const typeName = stem
|
|
494
|
+
.replace(/[^A-Za-z0-9_]/g, '_')
|
|
495
|
+
.replace(/^([a-z])/, (m) => m.toUpperCase()) || 'Data';
|
|
496
|
+
if (opts.target === 'bun') {
|
|
497
|
+
const { writeBunTarget, Declined } = require('./bun-target');
|
|
498
|
+
try {
|
|
499
|
+
const w = writeBunTarget({ schema: e.schema, input, output, typeName });
|
|
500
|
+
bunTargets.push({ input, output: w.bunPath, definitions: w.definitions });
|
|
501
|
+
} catch (err) {
|
|
502
|
+
if (!(err instanceof Declined)) throw err;
|
|
503
|
+
// No type can be written; the plain module stands alone.
|
|
504
|
+
const reason = `--target bun: ${err.message}; the plain module stands alone`;
|
|
505
|
+
if (opts.strict) { failed.push({ input, error: reason }); continue; }
|
|
506
|
+
bunDeclined.push({ input, reason });
|
|
507
|
+
}
|
|
508
|
+
}
|
|
463
509
|
if (opts.types !== false) {
|
|
464
510
|
const { toTypeScript } = require('./ts-gen');
|
|
465
|
-
const stem = path.basename(input, path.extname(input)).replace(/\.schema$/, '');
|
|
466
|
-
const typeName = stem
|
|
467
|
-
.replace(/[^A-Za-z0-9_]/g, '_')
|
|
468
|
-
.replace(/^([a-z])/, (m) => m.toUpperCase()) || 'Data';
|
|
469
511
|
const dts = toTypeScript(e.schema, { name: typeName, applyDefaults: /\nfunction applyDefaults\(/.test(src) });
|
|
470
512
|
const ext = path.extname(output);
|
|
471
513
|
const dtsExt = ext === '.mjs' ? '.d.mts'
|
|
@@ -514,7 +556,7 @@ async function build(opts) {
|
|
|
514
556
|
// module, whose errors come from the runtime. Only the written one counts.
|
|
515
557
|
const fromRuntime = new Set(entries.filter((e) => e.mode !== 'inline').map((e) => e.input));
|
|
516
558
|
const kept = warnings.filter((w) => !(w.kind === 'error-detail' && fromRuntime.has(w.input)));
|
|
517
|
-
return { compiled, cached, skipped, failed, warnings: kept, runtime: runtimeReport };
|
|
559
|
+
return { compiled, cached, skipped, failed, warnings: kept, runtime: runtimeReport, bunTargets, bunDeclined };
|
|
518
560
|
}
|
|
519
561
|
|
|
520
562
|
async function watch(opts, onReport) {
|
|
@@ -647,6 +689,10 @@ function compiledModuleFor(schema, opts) {
|
|
|
647
689
|
try {
|
|
648
690
|
src = aot.toStandaloneModule(validatorFor(schema), {
|
|
649
691
|
format: (opts && opts.format) || 'esm',
|
|
692
|
+
// The one-pass error function where the caller asks (a plugin writing
|
|
693
|
+
// for a Bun executable): 3.6x cheaper on a rejection, 20% larger gzipped.
|
|
694
|
+
onePass: opts && opts.onePass === true ? true : undefined,
|
|
695
|
+
source: opts && opts.onePass === true ? false : undefined,
|
|
650
696
|
// Errors in the runtime's order, for a reader that does not sort them
|
|
651
697
|
// itself (a form resolver); fromCompiled sorts, so a plugin putting
|
|
652
698
|
// that wrapper around the module leaves it off.
|
|
@@ -664,7 +710,28 @@ function compiledModuleFor(schema, opts) {
|
|
|
664
710
|
// not export this, and a plugin should then replace only calls without options.
|
|
665
711
|
const { COMPILED_OPTIONS: compiledOptions } = require('./compiled');
|
|
666
712
|
|
|
713
|
+
// For a build plugin: the Bun target (lib/bun-target.js) and the verification
|
|
714
|
+
// (lib/verify.js), loaded on first use.
|
|
715
|
+
const bunTarget = {
|
|
716
|
+
get schemaToBunType () { return require('./bun-target').schemaToBunType },
|
|
717
|
+
get toBunModule () { return require('./bun-target').toBunModule },
|
|
718
|
+
get writeBunTarget () { return require('./bun-target').writeBunTarget },
|
|
719
|
+
get Declined () { return require('./bun-target').Declined },
|
|
720
|
+
// The generated code's target engine (lib/js-compiler): a plugin that
|
|
721
|
+
// writes for a Bun executable compiled ahead of time sets 'jsc-aot'.
|
|
722
|
+
setTargetEngine (engine) { return require('./js-compiler').setTargetEngine(engine) },
|
|
723
|
+
}
|
|
724
|
+
const verify = {
|
|
725
|
+
get verifyOne () { return require('./verify').verifyOne },
|
|
726
|
+
get verifySource () { return require('./verify').verifySource },
|
|
727
|
+
get generate () { return require('./verify').generate },
|
|
728
|
+
get renderReport () { return require('./verify').renderReport },
|
|
729
|
+
get ok () { return require('./verify').ok },
|
|
730
|
+
}
|
|
731
|
+
|
|
667
732
|
module.exports = {
|
|
733
|
+
bunTarget,
|
|
734
|
+
verify,
|
|
668
735
|
compiledOptions,
|
|
669
736
|
compiledEligible,
|
|
670
737
|
compiledSchemaFor,
|