ata-validator 0.18.1 → 0.20.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 +44 -0
- package/build.d.ts +28 -0
- package/build.mjs +3 -0
- package/index.d.ts +8 -2
- package/index.js +26 -363
- package/lib/aot-build.js +30 -1
- package/lib/aot.js +410 -0
- package/lib/native-load.browser.js +8 -0
- package/lib/native-load.js +21 -0
- package/lib/safe-regex-source.js +8 -0
- package/lib/t.js +140 -0
- package/lib/version.js +10 -0
- package/package.json +15 -5
- package/scripts/regen-safe-regex-source.js +33 -0
- package/t.d.ts +186 -0
- package/t.js +9 -0
- package/t.mjs +6 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ata-validator",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.20.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",
|
|
@@ -25,6 +25,11 @@
|
|
|
25
25
|
"import": "./build.mjs",
|
|
26
26
|
"require": "./build.js"
|
|
27
27
|
},
|
|
28
|
+
"./t": {
|
|
29
|
+
"types": "./t.d.ts",
|
|
30
|
+
"import": "./t.mjs",
|
|
31
|
+
"require": "./t.js"
|
|
32
|
+
},
|
|
28
33
|
"./package.json": "./package.json"
|
|
29
34
|
},
|
|
30
35
|
"sideEffects": false,
|
|
@@ -32,17 +37,18 @@
|
|
|
32
37
|
"ata": "bin/ata.js"
|
|
33
38
|
},
|
|
34
39
|
"browser": {
|
|
35
|
-
"pkg-prebuilds": false
|
|
40
|
+
"pkg-prebuilds": false,
|
|
41
|
+
"./lib/native-load.js": "./lib/native-load.browser.js"
|
|
36
42
|
},
|
|
37
43
|
"scripts": {
|
|
38
44
|
"install": "node scripts/install.js",
|
|
39
|
-
"prepublishOnly": "node scripts/check-prebuilds.js && ATA_ALLOW_DOC_PLACEHOLDERS=1 node scripts/check-doc-coverage.js && node tests/test_error_codes_lock.js",
|
|
40
|
-
"release:check": "node scripts/check-prebuilds.js && node scripts/check-doc-coverage.js && node tests/test_error_codes_lock.js",
|
|
45
|
+
"prepublishOnly": "node scripts/regen-safe-regex-source.js && node scripts/check-prebuilds.js && ATA_ALLOW_DOC_PLACEHOLDERS=1 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",
|
|
46
|
+
"release:check": "node scripts/regen-safe-regex-source.js && node scripts/check-prebuilds.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",
|
|
41
47
|
"build": "cmake-js build --target ata",
|
|
42
48
|
"rebuild": "cmake-js rebuild --target ata",
|
|
43
49
|
"prebuild": "pkg-prebuilds-copy --baseDir build/Release --source ata.node --name=ata --strip --napi_version=10",
|
|
44
50
|
"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_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",
|
|
51
|
+
"test": "node test.js && node tests/test_no_native.js && node tests/test_browser_nofs.js && node tests/test_browser_imports_guard.js && node tests/test_version_sync.js && node tests/test_safe_regex_source_sync.js && node tests/test_t_builder.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
52
|
"bench:size": "node benchmark/bench_aot_size.mjs",
|
|
47
53
|
"test:suite": "node tests/run_suite.js",
|
|
48
54
|
"test:compat": "node tests/test_compat.js",
|
|
@@ -101,6 +107,9 @@
|
|
|
101
107
|
"build.js",
|
|
102
108
|
"build.mjs",
|
|
103
109
|
"build.d.ts",
|
|
110
|
+
"t.js",
|
|
111
|
+
"t.mjs",
|
|
112
|
+
"t.d.ts",
|
|
104
113
|
"binding-options.js",
|
|
105
114
|
"binding/",
|
|
106
115
|
"include/",
|
|
@@ -130,6 +139,7 @@
|
|
|
130
139
|
"@sinclair/typebox": "^0.34.49",
|
|
131
140
|
"@types/node": "^25.8.0",
|
|
132
141
|
"cmake-js": "^8.0.0",
|
|
142
|
+
"esbuild": "^0.28.0",
|
|
133
143
|
"jsonc-parser": "^3.3.1",
|
|
134
144
|
"mitata": "^1.0.34",
|
|
135
145
|
"typebox": "^1.1.7",
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// Bake `lib/safe-regex.js` into `lib/safe-regex-source.js` as a plain string
|
|
4
|
+
// export so the AOT path (`lib/aot.js`) can embed the engine into generated
|
|
5
|
+
// modules without reading from disk at runtime. The runtime read used to be
|
|
6
|
+
// the reason browser bundles broke on first AOT call (and the reason the
|
|
7
|
+
// default entry had to carry `__dirname`/`fs`/`path`).
|
|
8
|
+
//
|
|
9
|
+
// Run from `prepublishOnly` and from a sync test so the bundled string never
|
|
10
|
+
// drifts from the engine source.
|
|
11
|
+
|
|
12
|
+
const fs = require('fs');
|
|
13
|
+
const path = require('path');
|
|
14
|
+
|
|
15
|
+
const root = path.resolve(__dirname, '..');
|
|
16
|
+
const src = fs.readFileSync(path.join(root, 'lib', 'safe-regex.js'), 'utf8');
|
|
17
|
+
|
|
18
|
+
const out =
|
|
19
|
+
"'use strict';\n\n" +
|
|
20
|
+
"// Auto-generated by scripts/regen-safe-regex-source.js — do not edit.\n" +
|
|
21
|
+
"// Mirrors `lib/safe-regex.js` verbatim so `lib/aot.js` can embed the engine\n" +
|
|
22
|
+
"// into standalone output without a runtime `fs` read. Kept in sync by\n" +
|
|
23
|
+
"// `tests/test_safe_regex_source_sync.js`.\n\n" +
|
|
24
|
+
'module.exports = ' + JSON.stringify(src) + ';\n';
|
|
25
|
+
|
|
26
|
+
const outPath = path.join(root, 'lib', 'safe-regex-source.js');
|
|
27
|
+
const prev = fs.existsSync(outPath) ? fs.readFileSync(outPath, 'utf8') : '';
|
|
28
|
+
if (prev === out) {
|
|
29
|
+
console.log('lib/safe-regex-source.js: up to date');
|
|
30
|
+
} else {
|
|
31
|
+
fs.writeFileSync(outPath, out);
|
|
32
|
+
console.log('lib/safe-regex-source.js: regenerated');
|
|
33
|
+
}
|
package/t.d.ts
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
// Chainable builder for ata. Each function returns a plain JSON Schema
|
|
2
|
+
// literal, so `Infer<typeof X>` from the main entry resolves the inferred
|
|
3
|
+
// TypeScript type with no additional plumbing.
|
|
4
|
+
//
|
|
5
|
+
// import { t } from 'ata-validator/t'
|
|
6
|
+
// import { Validator, Infer } from 'ata-validator'
|
|
7
|
+
//
|
|
8
|
+
// const User = t.object({
|
|
9
|
+
// name: t.string({ minLength: 1 }),
|
|
10
|
+
// age: t.integer({ minimum: 0 }),
|
|
11
|
+
// email: t.optional(t.string({ format: 'email' })),
|
|
12
|
+
// })
|
|
13
|
+
// type User = Infer<typeof User>
|
|
14
|
+
// // { name: string; age: number; email?: string }
|
|
15
|
+
//
|
|
16
|
+
// const v = new Validator(User) // schema is plain JSON Schema
|
|
17
|
+
|
|
18
|
+
import type { JSONSchema } from './index.js';
|
|
19
|
+
|
|
20
|
+
export declare const OPTIONAL: unique symbol;
|
|
21
|
+
|
|
22
|
+
export type TOptional<S> = S & { readonly [OPTIONAL]: true };
|
|
23
|
+
|
|
24
|
+
export type TSchema = JSONSchema;
|
|
25
|
+
|
|
26
|
+
export interface StringOptions {
|
|
27
|
+
minLength?: number;
|
|
28
|
+
maxLength?: number;
|
|
29
|
+
pattern?: string;
|
|
30
|
+
format?: string;
|
|
31
|
+
description?: string;
|
|
32
|
+
title?: string;
|
|
33
|
+
default?: string;
|
|
34
|
+
examples?: readonly string[];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface NumericOptions {
|
|
38
|
+
minimum?: number;
|
|
39
|
+
maximum?: number;
|
|
40
|
+
exclusiveMinimum?: number;
|
|
41
|
+
exclusiveMaximum?: number;
|
|
42
|
+
multipleOf?: number;
|
|
43
|
+
description?: string;
|
|
44
|
+
title?: string;
|
|
45
|
+
default?: number;
|
|
46
|
+
examples?: readonly number[];
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export interface ArrayOptions {
|
|
50
|
+
minItems?: number;
|
|
51
|
+
maxItems?: number;
|
|
52
|
+
uniqueItems?: boolean;
|
|
53
|
+
description?: string;
|
|
54
|
+
title?: string;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export interface ObjectOptions {
|
|
58
|
+
additionalProperties?: boolean | JSONSchema;
|
|
59
|
+
description?: string;
|
|
60
|
+
title?: string;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export interface RecordOptions {
|
|
64
|
+
minProperties?: number;
|
|
65
|
+
maxProperties?: number;
|
|
66
|
+
description?: string;
|
|
67
|
+
title?: string;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// `Omit` against an `OPTIONAL`-branded schema collapses literal property types
|
|
71
|
+
// through the JSONSchema index signature, which breaks downstream `Infer`. The
|
|
72
|
+
// branded property is a Symbol key, so it doesn't intersect with any string
|
|
73
|
+
// index lookup; we leave it in place and just compute `RequiredKeys` from it.
|
|
74
|
+
// Infer reads `type`, `properties`, etc. and ignores extra phantom keys.
|
|
75
|
+
|
|
76
|
+
type RequiredKeysOf<T> = {
|
|
77
|
+
[K in keyof T]: T[K] extends { readonly [OPTIONAL]: true } ? never : K;
|
|
78
|
+
}[keyof T];
|
|
79
|
+
|
|
80
|
+
type StrippedProperties<T> = { [K in keyof T]: T[K] };
|
|
81
|
+
|
|
82
|
+
export interface TString extends JSONSchema {
|
|
83
|
+
type: 'string';
|
|
84
|
+
minLength?: number;
|
|
85
|
+
maxLength?: number;
|
|
86
|
+
pattern?: string;
|
|
87
|
+
format?: string;
|
|
88
|
+
description?: string;
|
|
89
|
+
title?: string;
|
|
90
|
+
default?: string;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export interface TNumber extends JSONSchema {
|
|
94
|
+
type: 'number';
|
|
95
|
+
minimum?: number;
|
|
96
|
+
maximum?: number;
|
|
97
|
+
exclusiveMinimum?: number;
|
|
98
|
+
exclusiveMaximum?: number;
|
|
99
|
+
multipleOf?: number;
|
|
100
|
+
description?: string;
|
|
101
|
+
title?: string;
|
|
102
|
+
default?: number;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export interface TInteger extends JSONSchema {
|
|
106
|
+
type: 'integer';
|
|
107
|
+
minimum?: number;
|
|
108
|
+
maximum?: number;
|
|
109
|
+
exclusiveMinimum?: number;
|
|
110
|
+
exclusiveMaximum?: number;
|
|
111
|
+
multipleOf?: number;
|
|
112
|
+
description?: string;
|
|
113
|
+
title?: string;
|
|
114
|
+
default?: number;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export interface TBoolean extends JSONSchema { type: 'boolean' }
|
|
118
|
+
export interface TNull extends JSONSchema { type: 'null' }
|
|
119
|
+
|
|
120
|
+
export interface TLiteral<V extends string | number | boolean | null> extends JSONSchema { const: V }
|
|
121
|
+
export interface TEnum<V extends readonly (string | number | boolean | null)[]> extends JSONSchema { enum: V }
|
|
122
|
+
|
|
123
|
+
export interface TArray<S extends JSONSchema> extends JSONSchema {
|
|
124
|
+
type: 'array';
|
|
125
|
+
items: S;
|
|
126
|
+
minItems?: number;
|
|
127
|
+
maxItems?: number;
|
|
128
|
+
uniqueItems?: boolean;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export interface TTuple<S extends ReadonlyArray<JSONSchema>> extends JSONSchema {
|
|
132
|
+
type: 'array';
|
|
133
|
+
prefixItems: S;
|
|
134
|
+
items: false;
|
|
135
|
+
minItems?: number;
|
|
136
|
+
maxItems?: number;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export interface TRecord<S extends JSONSchema> extends JSONSchema {
|
|
140
|
+
type: 'object';
|
|
141
|
+
additionalProperties: S;
|
|
142
|
+
minProperties?: number;
|
|
143
|
+
maxProperties?: number;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export interface TObject<T extends Record<string, JSONSchema>> extends JSONSchema {
|
|
147
|
+
type: 'object';
|
|
148
|
+
properties: StrippedProperties<T>;
|
|
149
|
+
required: ReadonlyArray<Extract<RequiredKeysOf<T>, string>>;
|
|
150
|
+
additionalProperties?: boolean | JSONSchema;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export interface TUnion<S extends ReadonlyArray<JSONSchema>> extends JSONSchema { anyOf: S }
|
|
154
|
+
export interface TIntersect<S extends ReadonlyArray<JSONSchema>> extends JSONSchema { allOf: S }
|
|
155
|
+
export interface TRef extends JSONSchema { $ref: string }
|
|
156
|
+
export interface TAny extends JSONSchema {}
|
|
157
|
+
export interface TNever extends JSONSchema { not: {} }
|
|
158
|
+
|
|
159
|
+
export interface TBuilder {
|
|
160
|
+
string(opts?: StringOptions): TString;
|
|
161
|
+
number(opts?: NumericOptions): TNumber;
|
|
162
|
+
integer(opts?: NumericOptions): TInteger;
|
|
163
|
+
boolean(): TBoolean;
|
|
164
|
+
null(): TNull;
|
|
165
|
+
|
|
166
|
+
literal<const V extends string | number | boolean | null>(value: V): TLiteral<V>;
|
|
167
|
+
const<const V extends string | number | boolean | null>(value: V): TLiteral<V>;
|
|
168
|
+
enum<const V extends readonly (string | number | boolean | null)[]>(values: V): TEnum<V>;
|
|
169
|
+
|
|
170
|
+
array<S extends JSONSchema>(items: S, opts?: ArrayOptions): TArray<S>;
|
|
171
|
+
tuple<const S extends ReadonlyArray<JSONSchema>>(items: S, opts?: ArrayOptions): TTuple<S>;
|
|
172
|
+
record<S extends JSONSchema>(values: S, opts?: RecordOptions): TRecord<S>;
|
|
173
|
+
|
|
174
|
+
object<const T extends Record<string, JSONSchema>>(properties: T, opts?: ObjectOptions): TObject<T>;
|
|
175
|
+
optional<S extends JSONSchema>(schema: S): TOptional<S>;
|
|
176
|
+
|
|
177
|
+
union<const S extends ReadonlyArray<JSONSchema>>(schemas: S): TUnion<S>;
|
|
178
|
+
intersect<const S extends ReadonlyArray<JSONSchema>>(schemas: S): TIntersect<S>;
|
|
179
|
+
ref(pointer: string): TRef;
|
|
180
|
+
|
|
181
|
+
any(): TAny;
|
|
182
|
+
unknown(): TAny;
|
|
183
|
+
never(): TNever;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
export declare const t: TBuilder;
|
package/t.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// CJS entry for `ata-validator/t`. The implementation lives in `lib/t.js`
|
|
4
|
+
// so the default entry can lazy-require it for users who never touch the
|
|
5
|
+
// builder. Re-export shape matches the `TBuilder` interface in `t.d.ts`.
|
|
6
|
+
|
|
7
|
+
const t = require('./lib/t');
|
|
8
|
+
|
|
9
|
+
module.exports = { t, OPTIONAL: t.OPTIONAL };
|