ata-validator 0.17.4 → 0.18.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 +12 -0
- package/README.md +30 -0
- package/index.d.ts +74 -27
- package/lib/js-compiler.js +14 -25
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,18 @@
|
|
|
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
|
+
## 0.18.0 - 2026-05-25
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- `Infer<S>` resolves the shapes 0.17.0 left as `unknown`. `anyOf` and `oneOf` map to unions, `allOf` to an intersection, `prefixItems` to a tuple, and a `$ref` to a local `#/$defs/...` or `#/definitions/...` entry resolves to the referenced type, including recursive references. An external or otherwise unresolvable `$ref` still resolves to `unknown` rather than erroring. `new Validator(schema)` carries the wider inference, so handlers narrow `result.data` for these schemas with no manual annotation, and the same applies to the Fastify type provider that builds on `Infer`. Pure `.d.ts` change, no runtime impact.
|
|
10
|
+
|
|
11
|
+
## 0.17.5 - 2026-05-25
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
|
|
15
|
+
- Compiled validators resolve draft-07 plain-name anchors. A `$defs`/`definitions` entry that declares an anchor with `$id: "#name"` and is referenced by `$ref: "#name"` now compiles through the codegen on every path (boolean, error, combined) instead of bailing. The bail forced a fallback that could not resolve sibling cross-schema refs, which surfaced as `cannot resolve $ref`. This is how shared schemas are referenced under Fastify.
|
|
16
|
+
|
|
5
17
|
## 0.17.4 - 2026-05-25
|
|
6
18
|
|
|
7
19
|
### Fixed
|
package/README.md
CHANGED
|
@@ -180,6 +180,36 @@ const v = new Validator(userSchema)
|
|
|
180
180
|
|
|
181
181
|
The exported `JSONSchema` type is also available directly if you want to annotate a schema yourself. Custom and vendor keywords are allowed, so exotic schemas still type-check. Requires TypeScript >= 5.0.
|
|
182
182
|
|
|
183
|
+
#### Extracting the type: `Infer`
|
|
184
|
+
|
|
185
|
+
Because `defineSchema` leaves the schema as a plain object, you can pull a TypeScript type straight out of it with `Infer`, with no second type declaration to keep in sync.
|
|
186
|
+
|
|
187
|
+
```ts
|
|
188
|
+
import { defineSchema, type Infer } from 'ata-validator'
|
|
189
|
+
|
|
190
|
+
const event = defineSchema({
|
|
191
|
+
$defs: {
|
|
192
|
+
Point: { type: 'object', properties: { x: { type: 'number' }, y: { type: 'number' } }, required: ['x', 'y'] },
|
|
193
|
+
},
|
|
194
|
+
type: 'object',
|
|
195
|
+
properties: {
|
|
196
|
+
kind: { enum: ['click', 'scroll'] },
|
|
197
|
+
at: { $ref: '#/$defs/Point' },
|
|
198
|
+
path: { type: 'array', prefixItems: [{ type: 'string' }, { type: 'integer' }] },
|
|
199
|
+
},
|
|
200
|
+
required: ['kind', 'at'],
|
|
201
|
+
})
|
|
202
|
+
|
|
203
|
+
type Event = Infer<typeof event>
|
|
204
|
+
// {
|
|
205
|
+
// kind: 'click' | 'scroll'
|
|
206
|
+
// at: { x: number; y: number }
|
|
207
|
+
// path?: [string, number]
|
|
208
|
+
// }
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
`Infer` resolves `const`/`enum` to literals, `anyOf`/`oneOf` to unions, `allOf` to intersections, `prefixItems` to tuples, and local `$ref` into `#/$defs` or `#/definitions`, including recursive references. `new Validator(schema)` carries the same type, so a successful `validate` narrows `result.data` without a manual annotation. An external or unresolvable `$ref` resolves to `unknown` rather than erroring.
|
|
212
|
+
|
|
183
213
|
### Cross-Schema `$ref`
|
|
184
214
|
|
|
185
215
|
```javascript
|
package/index.d.ts
CHANGED
|
@@ -177,26 +177,55 @@ type RequiredKeys<S> = S extends { required: infer R }
|
|
|
177
177
|
: never
|
|
178
178
|
: never;
|
|
179
179
|
|
|
180
|
+
/** Collapse a union of types into their intersection (used for `allOf`). */
|
|
181
|
+
type UnionToIntersection<U> =
|
|
182
|
+
(U extends unknown ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
|
|
183
|
+
|
|
184
|
+
/** The root `$defs`/`definitions` map, threaded through inference for `$ref` resolution. */
|
|
185
|
+
type RootDefs<S> = S extends { $defs: infer D }
|
|
186
|
+
? D
|
|
187
|
+
: S extends { definitions: infer D }
|
|
188
|
+
? D
|
|
189
|
+
: {};
|
|
190
|
+
|
|
191
|
+
/** Extract the definition name from a local `#/$defs/...` or `#/definitions/...` pointer. */
|
|
192
|
+
type RefName<R> = R extends `#/$defs/${infer N}`
|
|
193
|
+
? N
|
|
194
|
+
: R extends `#/definitions/${infer N}`
|
|
195
|
+
? N
|
|
196
|
+
: never;
|
|
197
|
+
|
|
198
|
+
/** Resolve a `$ref` against the root defs map; external/unresolvable refs -> unknown. */
|
|
199
|
+
type ResolveRef<R, D> = [RefName<R>] extends [never]
|
|
200
|
+
? unknown
|
|
201
|
+
: RefName<R> extends keyof D
|
|
202
|
+
? InferWith<D[RefName<R>], D>
|
|
203
|
+
: unknown;
|
|
204
|
+
|
|
180
205
|
/** Object shape: required keys are required, all other declared keys optional. */
|
|
181
|
-
type InferObject<S> = S extends { properties: infer P }
|
|
206
|
+
type InferObject<S, D> = S extends { properties: infer P }
|
|
182
207
|
? Simplify<
|
|
183
|
-
{ [K in keyof P as K extends RequiredKeys<S> ? K : never]:
|
|
184
|
-
{ [K in keyof P as K extends RequiredKeys<S> ? never : K]?:
|
|
208
|
+
{ [K in keyof P as K extends RequiredKeys<S> ? K : never]: InferWith<P[K], D> } &
|
|
209
|
+
{ [K in keyof P as K extends RequiredKeys<S> ? never : K]?: InferWith<P[K], D> }
|
|
185
210
|
>
|
|
186
211
|
: Record<string, unknown>;
|
|
187
212
|
|
|
188
|
-
/** Array shape: `
|
|
189
|
-
type InferArray<S> = S extends {
|
|
190
|
-
?
|
|
191
|
-
?
|
|
192
|
-
:
|
|
193
|
-
:
|
|
213
|
+
/** Array shape: `prefixItems` -> tuple; `items` (single schema) -> element type; otherwise unknown[]. */
|
|
214
|
+
type InferArray<S, D> = S extends { prefixItems: infer P }
|
|
215
|
+
? P extends ReadonlyArray<unknown>
|
|
216
|
+
? { -readonly [K in keyof P]: InferWith<P[K], D> }
|
|
217
|
+
: unknown[]
|
|
218
|
+
: S extends { items: infer I }
|
|
219
|
+
? I extends ReadonlyArray<unknown>
|
|
220
|
+
? unknown[]
|
|
221
|
+
: InferWith<I, D>[]
|
|
222
|
+
: unknown[];
|
|
194
223
|
|
|
195
224
|
/** Map a single JSON Schema type name (+ its schema) to a TS type. */
|
|
196
|
-
type InferByTypeName<N, S> = N extends 'object'
|
|
197
|
-
? InferObject<S>
|
|
225
|
+
type InferByTypeName<N, S, D> = N extends 'object'
|
|
226
|
+
? InferObject<S, D>
|
|
198
227
|
: N extends 'array'
|
|
199
|
-
? InferArray<S>
|
|
228
|
+
? InferArray<S, D>
|
|
200
229
|
: N extends 'string'
|
|
201
230
|
? string
|
|
202
231
|
: N extends 'number'
|
|
@@ -209,28 +238,46 @@ type InferByTypeName<N, S> = N extends 'object'
|
|
|
209
238
|
? null
|
|
210
239
|
: unknown;
|
|
211
240
|
|
|
241
|
+
/** Core inference with the root defs map `D` threaded for `$ref` resolution. */
|
|
242
|
+
type InferWith<S, D> = S extends { $ref: infer R }
|
|
243
|
+
? ResolveRef<R, D>
|
|
244
|
+
: S extends { const: infer C }
|
|
245
|
+
? C
|
|
246
|
+
: S extends { enum: infer E }
|
|
247
|
+
? E extends ReadonlyArray<infer U>
|
|
248
|
+
? U
|
|
249
|
+
: unknown
|
|
250
|
+
: S extends { allOf: infer A }
|
|
251
|
+
? A extends ReadonlyArray<unknown>
|
|
252
|
+
? Simplify<UnionToIntersection<{ [K in keyof A]: InferWith<A[K], D> }[number]>>
|
|
253
|
+
: unknown
|
|
254
|
+
: S extends { anyOf: infer A }
|
|
255
|
+
? A extends ReadonlyArray<unknown>
|
|
256
|
+
? { [K in keyof A]: InferWith<A[K], D> }[number]
|
|
257
|
+
: unknown
|
|
258
|
+
: S extends { oneOf: infer A }
|
|
259
|
+
? A extends ReadonlyArray<unknown>
|
|
260
|
+
? { [K in keyof A]: InferWith<A[K], D> }[number]
|
|
261
|
+
: unknown
|
|
262
|
+
: S extends { type: infer T }
|
|
263
|
+
? T extends ReadonlyArray<infer N>
|
|
264
|
+
? InferByTypeName<N, S, D>
|
|
265
|
+
: InferByTypeName<T, S, D>
|
|
266
|
+
: unknown;
|
|
267
|
+
|
|
212
268
|
/**
|
|
213
|
-
* Infer the TypeScript data type a JSON Schema literal describes
|
|
269
|
+
* Infer the TypeScript data type a JSON Schema literal describes.
|
|
214
270
|
*
|
|
215
271
|
* Handles: primitives, `type` arrays (union), `const`, `enum`, objects
|
|
216
|
-
* (`properties` + `required` -> required/optional keys),
|
|
217
|
-
* (`
|
|
218
|
-
* `
|
|
272
|
+
* (`properties` + `required` -> required/optional keys), arrays (`items`),
|
|
273
|
+
* tuples (`prefixItems`), `anyOf`/`oneOf` (union), `allOf` (intersection),
|
|
274
|
+
* and `$ref` to local `#/$defs/...` or `#/definitions/...`. External or
|
|
275
|
+
* unresolvable `$ref` resolves to `unknown` rather than erroring.
|
|
219
276
|
*
|
|
220
277
|
* Pair with {@link defineSchema}:
|
|
221
278
|
* `const s = defineSchema({...}); type T = Infer<typeof s>;`
|
|
222
279
|
*/
|
|
223
|
-
export type Infer<S> = S
|
|
224
|
-
? C
|
|
225
|
-
: S extends { enum: infer E }
|
|
226
|
-
? E extends ReadonlyArray<infer U>
|
|
227
|
-
? U
|
|
228
|
-
: unknown
|
|
229
|
-
: S extends { type: infer T }
|
|
230
|
-
? T extends ReadonlyArray<infer N>
|
|
231
|
-
? InferByTypeName<N, S>
|
|
232
|
-
: InferByTypeName<T, S>
|
|
233
|
-
: unknown;
|
|
280
|
+
export type Infer<S> = InferWith<S, RootDefs<S>>;
|
|
234
281
|
|
|
235
282
|
export type ValidationResult<T = unknown> =
|
|
236
283
|
| { valid: true; data: T; errors: ValidationError[] }
|
package/lib/js-compiler.js
CHANGED
|
@@ -699,23 +699,6 @@ function canResolveDynamicRefs(target, callingSchema, schemaMap) {
|
|
|
699
699
|
|
|
700
700
|
// Recursively check if a schema can be safely compiled to JS codegen.
|
|
701
701
|
// Returns false if any sub-schema contains features codegen gets wrong.
|
|
702
|
-
// Does the schema (recursively) contain an anchor-style `$ref` equal to anchorId
|
|
703
|
-
// (e.g. `$ref: '#address'`)? Used to keep codegen away from anchor refs it can't
|
|
704
|
-
// resolve in the combined/error paths.
|
|
705
|
-
function schemaHasAnchorRef(node, anchorId) {
|
|
706
|
-
if (!node || typeof node !== 'object') return false
|
|
707
|
-
if (Array.isArray(node)) {
|
|
708
|
-
for (const x of node) if (schemaHasAnchorRef(x, anchorId)) return true
|
|
709
|
-
return false
|
|
710
|
-
}
|
|
711
|
-
if (node.$ref === anchorId) return true
|
|
712
|
-
for (const k in node) {
|
|
713
|
-
if (k === '$ref') continue
|
|
714
|
-
if (schemaHasAnchorRef(node[k], anchorId)) return true
|
|
715
|
-
}
|
|
716
|
-
return false
|
|
717
|
-
}
|
|
718
|
-
|
|
719
702
|
function codegenSafe(schema, schemaMap) {
|
|
720
703
|
if (typeof schema === 'boolean') return true
|
|
721
704
|
if (typeof schema !== 'object' || schema === null) return true
|
|
@@ -826,14 +809,10 @@ function codegenSafe(schema, schemaMap) {
|
|
|
826
809
|
if (typeof def === 'boolean') return false
|
|
827
810
|
if (typeof def === 'object' && def !== null) {
|
|
828
811
|
// A non-fragment $id (e.g. 'sub.json', 'http://...') opens a new base URI
|
|
829
|
-
// scope — bail. A fragment-only $id ('#name') is a draft-07 anchor;
|
|
830
|
-
//
|
|
831
|
-
//
|
|
832
|
-
|
|
833
|
-
if (def.$id) {
|
|
834
|
-
if (!def.$id.startsWith('#')) return false
|
|
835
|
-
if (schemaHasAnchorRef(schema, def.$id)) return false
|
|
836
|
-
}
|
|
812
|
+
// scope — bail. A fragment-only $id ('#name') is a draft-07 anchor; the
|
|
813
|
+
// codegen anchor maps register it (see "Build anchors map"), so anchor
|
|
814
|
+
// refs (`$ref: '#name'`) resolve to it on all paths.
|
|
815
|
+
if (def.$id && !def.$id.startsWith('#')) return false
|
|
837
816
|
if (def.$ref) return false // nested ref chain — bail
|
|
838
817
|
if (!codegenSafe(def, schemaMap)) return false
|
|
839
818
|
}
|
|
@@ -933,12 +912,15 @@ function compileToJSCodegen(schema, schemaMap, userFormats) {
|
|
|
933
912
|
// Root schema's own $dynamicAnchor / $anchor
|
|
934
913
|
if (schema.$dynamicAnchor) anchors['#' + schema.$dynamicAnchor] = schema
|
|
935
914
|
if (schema.$anchor) anchors['#' + schema.$anchor] = schema
|
|
915
|
+
// Draft-07 plain-name anchor: declared as `$id: "#name"`.
|
|
916
|
+
if (typeof schema.$id === 'string' && schema.$id.startsWith('#')) anchors[schema.$id] = schema
|
|
936
917
|
// Anchors from $defs
|
|
937
918
|
if (rootDefs) {
|
|
938
919
|
for (const def of Object.values(rootDefs)) {
|
|
939
920
|
if (def && typeof def === 'object') {
|
|
940
921
|
if (def.$dynamicAnchor) anchors['#' + def.$dynamicAnchor] = def
|
|
941
922
|
if (def.$anchor) anchors['#' + def.$anchor] = def
|
|
923
|
+
if (typeof def.$id === 'string' && def.$id.startsWith('#')) anchors[def.$id] = def
|
|
942
924
|
}
|
|
943
925
|
}
|
|
944
926
|
}
|
|
@@ -948,6 +930,7 @@ function compileToJSCodegen(schema, schemaMap, userFormats) {
|
|
|
948
930
|
if (ext && typeof ext === 'object') {
|
|
949
931
|
if (ext.$dynamicAnchor && !anchors['#' + ext.$dynamicAnchor]) anchors['#' + ext.$dynamicAnchor] = ext
|
|
950
932
|
if (ext.$anchor && !anchors['#' + ext.$anchor]) anchors['#' + ext.$anchor] = ext
|
|
933
|
+
if (typeof ext.$id === 'string' && ext.$id.startsWith('#') && !anchors[ext.$id]) anchors[ext.$id] = ext
|
|
951
934
|
}
|
|
952
935
|
}
|
|
953
936
|
}
|
|
@@ -2592,11 +2575,13 @@ function compileToJSCodegenWithErrors(schema, schemaMap, userFormats, sourceOpts
|
|
|
2592
2575
|
const eAnchors = {}
|
|
2593
2576
|
if (schema.$dynamicAnchor) eAnchors['#' + schema.$dynamicAnchor] = schema
|
|
2594
2577
|
if (schema.$anchor) eAnchors['#' + schema.$anchor] = schema
|
|
2578
|
+
if (typeof schema.$id === 'string' && schema.$id.startsWith('#')) eAnchors[schema.$id] = schema
|
|
2595
2579
|
if (eRootDefs) {
|
|
2596
2580
|
for (const def of Object.values(eRootDefs)) {
|
|
2597
2581
|
if (def && typeof def === 'object') {
|
|
2598
2582
|
if (def.$dynamicAnchor) eAnchors['#' + def.$dynamicAnchor] = def
|
|
2599
2583
|
if (def.$anchor) eAnchors['#' + def.$anchor] = def
|
|
2584
|
+
if (typeof def.$id === 'string' && def.$id.startsWith('#')) eAnchors[def.$id] = def
|
|
2600
2585
|
}
|
|
2601
2586
|
}
|
|
2602
2587
|
}
|
|
@@ -2605,6 +2590,7 @@ function compileToJSCodegenWithErrors(schema, schemaMap, userFormats, sourceOpts
|
|
|
2605
2590
|
if (ext && typeof ext === 'object') {
|
|
2606
2591
|
if (ext.$dynamicAnchor && !eAnchors['#' + ext.$dynamicAnchor]) eAnchors['#' + ext.$dynamicAnchor] = ext
|
|
2607
2592
|
if (ext.$anchor && !eAnchors['#' + ext.$anchor]) eAnchors['#' + ext.$anchor] = ext
|
|
2593
|
+
if (typeof ext.$id === 'string' && ext.$id.startsWith('#') && !eAnchors[ext.$id]) eAnchors[ext.$id] = ext
|
|
2608
2594
|
}
|
|
2609
2595
|
}
|
|
2610
2596
|
}
|
|
@@ -3210,11 +3196,13 @@ function compileToJSCombined(schema, VALID_RESULT, schemaMap, userFormats) {
|
|
|
3210
3196
|
const cAnchors = {}
|
|
3211
3197
|
if (schema.$dynamicAnchor) cAnchors['#' + schema.$dynamicAnchor] = schema
|
|
3212
3198
|
if (schema.$anchor) cAnchors['#' + schema.$anchor] = schema
|
|
3199
|
+
if (typeof schema.$id === 'string' && schema.$id.startsWith('#')) cAnchors[schema.$id] = schema
|
|
3213
3200
|
if (cRootDefs) {
|
|
3214
3201
|
for (const def of Object.values(cRootDefs)) {
|
|
3215
3202
|
if (def && typeof def === 'object') {
|
|
3216
3203
|
if (def.$dynamicAnchor) cAnchors['#' + def.$dynamicAnchor] = def
|
|
3217
3204
|
if (def.$anchor) cAnchors['#' + def.$anchor] = def
|
|
3205
|
+
if (typeof def.$id === 'string' && def.$id.startsWith('#')) cAnchors[def.$id] = def
|
|
3218
3206
|
}
|
|
3219
3207
|
}
|
|
3220
3208
|
}
|
|
@@ -3223,6 +3211,7 @@ function compileToJSCombined(schema, VALID_RESULT, schemaMap, userFormats) {
|
|
|
3223
3211
|
if (ext && typeof ext === 'object') {
|
|
3224
3212
|
if (ext.$dynamicAnchor && !cAnchors['#' + ext.$dynamicAnchor]) cAnchors['#' + ext.$dynamicAnchor] = ext
|
|
3225
3213
|
if (ext.$anchor && !cAnchors['#' + ext.$anchor]) cAnchors['#' + ext.$anchor] = ext
|
|
3214
|
+
if (typeof ext.$id === 'string' && ext.$id.startsWith('#') && !cAnchors[ext.$id]) cAnchors[ext.$id] = ext
|
|
3226
3215
|
}
|
|
3227
3216
|
}
|
|
3228
3217
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ata-validator",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.18.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",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"rebuild": "cmake-js rebuild --target ata",
|
|
43
43
|
"prebuild": "pkg-prebuilds-copy --baseDir build/Release --source ata.node --name=ata --strip --napi_version=10",
|
|
44
44
|
"prebuild-all": "npm run prebuild -- --arch x64 && npm run prebuild -- --arch arm64",
|
|
45
|
-
"test": "node test.js && node tests/test_no_native.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_additional_props_errors.js && node tests/test_typed_validator_runner.js && node tests/test_define_schema.js && node tests/test_error_codes_lock.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_rich_errors_optout.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_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",
|
|
45
|
+
"test": "node test.js && node tests/test_no_native.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_additional_props_errors.js && node tests/test_id_anchor_refs.js && node tests/test_typed_validator_runner.js && node tests/test_define_schema.js && node tests/test_error_codes_lock.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_rich_errors_optout.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_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",
|
|
46
46
|
"bench:size": "node benchmark/bench_aot_size.mjs",
|
|
47
47
|
"test:suite": "node tests/run_suite.js",
|
|
48
48
|
"test:compat": "node tests/test_compat.js",
|