ata-validator 0.18.0 → 0.18.2
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 +29 -38
- package/index.browser.mjs +1 -1
- package/index.js +17 -10
- package/package.json +3 -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.2 - 2026-05-26
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- The browser and edge build no longer touches the filesystem at import. The safe-regex engine source was embedded into standalone output through a `fs.readFileSync` that ran at module load, which crashed bundlers that stub `fs`/`path` for the browser (a regression from 0.17.3). The read is deferred to the first standalone compile that actually embeds the engine, so importing ata, validating, generating types, and compiling pattern-free schemas now run with no filesystem access in browsers and Cloudflare Workers. Added a regression test that bundles the browser entry and runs it with `fs`/`path` stubbed.
|
|
10
|
+
|
|
11
|
+
## 0.18.1 - 2026-05-26
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- The browser entry (`index.browser.mjs`) re-exports `toTypeScript`, so the inferred TypeScript type for a schema can be generated client-side (for example in a web playground) alongside `Validator.toStandaloneModule()`. Pure re-export, no runtime change.
|
|
16
|
+
|
|
5
17
|
## 0.18.0 - 2026-05-25
|
|
6
18
|
|
|
7
19
|
### Added
|
package/README.md
CHANGED
|
@@ -127,40 +127,7 @@ v.countValid(ndjson); // number
|
|
|
127
127
|
|
|
128
128
|
### Type-safe schemas
|
|
129
129
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
```ts
|
|
133
|
-
import { Type, type Static } from '@sinclair/typebox'
|
|
134
|
-
import { Validator } from 'ata-validator'
|
|
135
|
-
|
|
136
|
-
const UserSchema = Type.Object({
|
|
137
|
-
id: Type.Integer({ minimum: 1 }),
|
|
138
|
-
name: Type.String({ minLength: 1 }),
|
|
139
|
-
email: Type.String({ format: 'email' }),
|
|
140
|
-
})
|
|
141
|
-
|
|
142
|
-
type User = Static<typeof UserSchema>
|
|
143
|
-
|
|
144
|
-
const v = new Validator<User>(UserSchema)
|
|
145
|
-
|
|
146
|
-
if (v.isValidObject(data)) {
|
|
147
|
-
// data is narrowed to User, no cast needed
|
|
148
|
-
console.log(data.name)
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
const result = v.validate(data)
|
|
152
|
-
if (result.valid) {
|
|
153
|
-
// result.data is User
|
|
154
|
-
} else {
|
|
155
|
-
// result.errors: ValidationError[]
|
|
156
|
-
}
|
|
157
|
-
```
|
|
158
|
-
|
|
159
|
-
The same pattern works with Zod-from-JSON-Schema, Valibot, or a hand-written `type User = {...}` alongside a JSON Schema literal. `Validator<T>` makes no library-specific assumption.
|
|
160
|
-
|
|
161
|
-
#### Authoring a schema inline: `defineSchema`
|
|
162
|
-
|
|
163
|
-
If you would rather write a plain JSON Schema object than reach for a schema library, wrap it in `defineSchema`. It returns the schema untouched at runtime, but in TypeScript it gives you keyword autocomplete and an error when a value has the wrong shape, with no `as const` needed.
|
|
130
|
+
ata infers TypeScript types straight from plain JSON Schema. Write the schema once with `defineSchema`, and both runtime validation and the static type come from it, with no builder DSL and no second type declaration to keep in sync.
|
|
164
131
|
|
|
165
132
|
```ts
|
|
166
133
|
import { defineSchema, Validator } from 'ata-validator'
|
|
@@ -174,15 +141,21 @@ const userSchema = defineSchema({
|
|
|
174
141
|
required: ['id'],
|
|
175
142
|
})
|
|
176
143
|
|
|
177
|
-
// type: 123 or required: 'id' would be a compile error here.
|
|
178
144
|
const v = new Validator(userSchema)
|
|
145
|
+
const result = v.validate(data)
|
|
146
|
+
if (result.valid) {
|
|
147
|
+
result.data.id // number
|
|
148
|
+
result.data.role // 'admin' | 'user' | undefined
|
|
149
|
+
} else {
|
|
150
|
+
// result.errors: ValidationError[]
|
|
151
|
+
}
|
|
179
152
|
```
|
|
180
153
|
|
|
181
|
-
|
|
154
|
+
`defineSchema` returns the schema untouched at runtime; in TypeScript it gives keyword autocomplete and an error when a value has the wrong shape, with no `as const` needed. `new Validator(schema)` carries the inferred type, so a successful `validate` narrows `result.data` with no manual annotation.
|
|
182
155
|
|
|
183
156
|
#### Extracting the type: `Infer`
|
|
184
157
|
|
|
185
|
-
|
|
158
|
+
You can also pull the type out directly with `Infer`, with no second declaration to keep in sync.
|
|
186
159
|
|
|
187
160
|
```ts
|
|
188
161
|
import { defineSchema, type Infer } from 'ata-validator'
|
|
@@ -208,7 +181,25 @@ type Event = Infer<typeof event>
|
|
|
208
181
|
// }
|
|
209
182
|
```
|
|
210
183
|
|
|
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.
|
|
184
|
+
`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. An external or unresolvable `$ref` resolves to `unknown` rather than erroring. The exported `JSONSchema` type is available if you want to annotate a schema by hand; custom and vendor keywords are allowed. Requires TypeScript >= 5.0.
|
|
185
|
+
|
|
186
|
+
#### Composes with TypeBox, Zod, or your own types
|
|
187
|
+
|
|
188
|
+
`Validator<T>` is generic, so if you already author schemas with a library, pass the type and ata narrows to it. No library-specific assumption.
|
|
189
|
+
|
|
190
|
+
```ts
|
|
191
|
+
import { Type, type Static } from '@sinclair/typebox'
|
|
192
|
+
import { Validator } from 'ata-validator'
|
|
193
|
+
|
|
194
|
+
const UserSchema = Type.Object({
|
|
195
|
+
id: Type.Integer({ minimum: 1 }),
|
|
196
|
+
name: Type.String({ minLength: 1 }),
|
|
197
|
+
})
|
|
198
|
+
|
|
199
|
+
const v = new Validator<Static<typeof UserSchema>>(UserSchema)
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
The same works with Zod-from-JSON-Schema, Valibot, or a hand-written `type User = {...}` alongside a JSON Schema literal.
|
|
212
203
|
|
|
213
204
|
### Cross-Schema `$ref`
|
|
214
205
|
|
package/index.browser.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
// Browser ESM entry — same code, native addon stubbed out by bundler via "browser" field.
|
|
2
2
|
import mod from './index.js';
|
|
3
|
-
export const { Validator, validate, version, createPaddedBuffer, SIMDJSON_PADDING, renderPretty, renderCompact, renderJSON } = mod;
|
|
3
|
+
export const { Validator, validate, version, createPaddedBuffer, SIMDJSON_PADDING, renderPretty, renderCompact, renderJSON, toTypeScript } = mod;
|
|
4
4
|
export default mod;
|
package/index.js
CHANGED
|
@@ -305,19 +305,26 @@ const _CP_LEN_SOURCE = `function _cpLen(s) {
|
|
|
305
305
|
// directive and CommonJS exports stripped, plus the `__ataSafeRe` alias the
|
|
306
306
|
// emitted code calls. The engine has no eval/new Function, so the embed is
|
|
307
307
|
// CSP-safe.
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
308
|
+
// Lazy so merely importing ata never touches the filesystem. Bundlers that stub
|
|
309
|
+
// `fs`/`path` for the browser would otherwise crash at module load; the read is
|
|
310
|
+
// deferred to the first standalone compile that actually embeds the engine.
|
|
311
|
+
let _safeRegexEmbed = null;
|
|
312
|
+
function getSafeRegexEmbed() {
|
|
313
|
+
if (_safeRegexEmbed === null) {
|
|
314
|
+
const raw = require("fs").readFileSync(require("path").join(__dirname, "lib", "safe-regex.js"), "utf8");
|
|
315
|
+
const body = raw
|
|
316
|
+
.replace(/^'use strict'\s*\n/, "")
|
|
317
|
+
.replace(/\nmodule\.exports[^\n]*\n?/, "\n");
|
|
318
|
+
_safeRegexEmbed = body.trimEnd() + "\nconst __ataSafeRe = compileSafe;";
|
|
319
|
+
}
|
|
320
|
+
return _safeRegexEmbed;
|
|
321
|
+
}
|
|
315
322
|
|
|
316
323
|
// Returns the engine embed when any supplied compiled function references the
|
|
317
324
|
// safe matcher (jsFn._usesSafeRe), else an empty string so non-pattern modules
|
|
318
325
|
// pay zero bytes.
|
|
319
326
|
function safeRePrelude(...fns) {
|
|
320
|
-
return fns.some((f) => f && f._usesSafeRe) ?
|
|
327
|
+
return fns.some((f) => f && f._usesSafeRe) ? getSafeRegexEmbed() + "\n" : "";
|
|
321
328
|
}
|
|
322
329
|
|
|
323
330
|
// Above this size, simdjson On Demand (selective field access) beats JSON.parse
|
|
@@ -1561,7 +1568,7 @@ Validator.bundleStandalone = function (schemas, opts) {
|
|
|
1561
1568
|
return `(function(R){${preamble}var E=function(d){var _all=true;${errBody}};return function(d){${jsFn._hybridSource}}})(R)`;
|
|
1562
1569
|
});
|
|
1563
1570
|
const arr = `[${fns.join(",")}]`;
|
|
1564
|
-
const safeEmbed = bundleUsesSafeRe ?
|
|
1571
|
+
const safeEmbed = bundleUsesSafeRe ? getSafeRegexEmbed() + "\n" : "";
|
|
1565
1572
|
if (format === 'esm') {
|
|
1566
1573
|
return `// Auto-generated by ata-validator — do not edit\n${safeEmbed}const R=${R};\nconst validators=${arr};\nexport default validators;\nexport { validators };\n`;
|
|
1567
1574
|
}
|
|
@@ -1632,7 +1639,7 @@ Validator.bundleCompact = function (schemas, opts) {
|
|
|
1632
1639
|
let out = isEsm
|
|
1633
1640
|
? "// Auto-generated by ata-validator — do not edit\n"
|
|
1634
1641
|
: "'use strict';\n";
|
|
1635
|
-
if (bundleUsesSafeRe) out +=
|
|
1642
|
+
if (bundleUsesSafeRe) out += getSafeRegexEmbed() + "\n";
|
|
1636
1643
|
const declKW = isEsm ? "const" : "var";
|
|
1637
1644
|
out += `${declKW} R=Object.freeze({valid:true,errors:Object.freeze([])});\n`;
|
|
1638
1645
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ata-validator",
|
|
3
|
-
"version": "0.18.
|
|
3
|
+
"version": "0.18.2",
|
|
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_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",
|
|
45
|
+
"test": "node test.js && node tests/test_no_native.js && node tests/test_browser_nofs.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",
|
|
@@ -130,6 +130,7 @@
|
|
|
130
130
|
"@sinclair/typebox": "^0.34.49",
|
|
131
131
|
"@types/node": "^25.8.0",
|
|
132
132
|
"cmake-js": "^8.0.0",
|
|
133
|
+
"esbuild": "^0.28.0",
|
|
133
134
|
"jsonc-parser": "^3.3.1",
|
|
134
135
|
"mitata": "^1.0.34",
|
|
135
136
|
"typebox": "^1.1.7",
|