ata-validator 1.6.1 → 1.6.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 +9 -0
- package/README.md +27 -10
- package/index.d.ts +9 -4
- package/lib/enrich-error.js +14 -4
- package/lib/error-codes.js +16 -9
- package/lib/js-compiler.js +56 -9
- package/lib/version.js +1 -1
- package/package.json +8 -8
- package/t.d.ts +16 -5
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,15 @@
|
|
|
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
|
+
## 1.6.2 - 2026-08-19
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- The Standard Schema surface carried no output type. `~standard.validate()` returned `{ value: unknown }` and the `types` carrier the specification defines for inference was missing, so every consumer that reads the validated type off `~standard` (Fastify, tRPC, TanStack Form, Drizzle) saw `unknown` and needed a cast. `~standard` is now typed against the validator's own data type, and `types.output` carries it. Type-only: the runtime object is unchanged, and the specification defines `types` as never present at runtime.
|
|
10
|
+
- Boolean schemas were rejected by the `Validator` constructor's TypeScript signature. `true` and `false` are schemas anywhere JSON Schema allows one, and both have always worked at runtime; only the types disagreed, which made a schema of unknown shape (`object | boolean`) impossible to pass without a cast. Nested boolean subschemas are still typed as objects, so `{ properties: { a: true } }` needs `defineSchema` or a cast.
|
|
11
|
+
- The `t` builder's option bags rejected vendor keywords. `t.object({}, { instanceof: 'Date' })` is what a custom keyword package expects to be given, and the option types only allowed the keywords the builder itself emits, so callers wrote `as never`. Every option bag now accepts unknown keywords alongside the typed ones.
|
|
12
|
+
- `tests/test_interop_types.ts` covers all three under `tsc --noEmit`.
|
|
13
|
+
|
|
5
14
|
## 1.6.1 - 2026-08-09
|
|
6
15
|
|
|
7
16
|
### Fixed
|
package/README.md
CHANGED
|
@@ -43,15 +43,29 @@ The `.compiled.mjs` modules are self-contained: zero runtime dependency on ata-v
|
|
|
43
43
|
|
|
44
44
|
| Dimension | Schema | ata-AOT | AJV-runtime | Difference |
|
|
45
45
|
|---|---|---|---|---|
|
|
46
|
-
| Bundle (gzipped) | simple |
|
|
47
|
-
| Bundle (gzipped) | complex |
|
|
48
|
-
|
|
|
49
|
-
|
|
|
50
|
-
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
46
|
+
| Bundle (gzipped) | simple | 1.0 KB | 52.7 KB | 50.5x smaller |
|
|
47
|
+
| Bundle (gzipped) | complex | 4.8 KB | 52.7 KB | 11.0x smaller |
|
|
48
|
+
| Bundle (gzipped) | nested | 2.3 KB | 52.7 KB | 23.1x smaller |
|
|
49
|
+
| Cold start | simple | 21 ms | 40 ms | 1.9x faster |
|
|
50
|
+
| Throughput (1M ops) | simple | 258 Mops/s | 102 Mops/s | 2.5x faster |
|
|
51
|
+
| Compile time | simple | 8 µs | 1.61 ms | 191x faster |
|
|
52
|
+
|
|
53
|
+
Reproduce on your machine with `npm run bench:aot-vs-ajv`. Numbers from one run on Apple
|
|
54
|
+
M4 Pro, Node 25.2.1, 2026-08-13. Across three runs throughput moved between 258 and 278
|
|
55
|
+
Mops/s and the compile ratio between 150x and 199x, so treat the last two rows as an order
|
|
56
|
+
of magnitude rather than a constant.
|
|
57
|
+
|
|
58
|
+
The wins are largest on bundle size and compile time because AOT moves work from runtime to
|
|
59
|
+
build time. Throughput and cold start are also faster because the compiled validator is a
|
|
60
|
+
tight straight-line function with no schema-walk overhead.
|
|
61
|
+
|
|
62
|
+
What the table does not cover is data that fails. It measures compiled modules on input that
|
|
63
|
+
passes, and a rejection costs more than a verdict: ata builds an error carrying a code, the
|
|
64
|
+
offending value, a documentation link and a suggestion. On a five-field object schema a
|
|
65
|
+
passing payload costs about 17 ns and a rejected one about 155 ns. `abortEarly: true` or
|
|
66
|
+
`isValidObject()` skips that work when only the verdict matters. Schemas ata declines to
|
|
67
|
+
compile, mostly cross-document `$ref`, `$dynamicRef` and `unevaluated*`, run on the
|
|
68
|
+
interpreted engine and are slower again.
|
|
55
69
|
|
|
56
70
|
## Error messages
|
|
57
71
|
|
|
@@ -385,7 +399,10 @@ const { toStandaloneModule } = require('ata-validator/build');
|
|
|
385
399
|
fs.writeFileSync('./user.validator.mjs', toStandaloneModule(schema, { format: 'esm' }));
|
|
386
400
|
```
|
|
387
401
|
|
|
388
|
-
**Fastify startup
|
|
402
|
+
**Fastify startup, 10 route schemas, from a cold process to the first validated request:
|
|
403
|
+
ajv 19.6 ms, ata 3.1 ms, no build step required.** ata registers in 1.1 ms of that and
|
|
404
|
+
compiles on the first request, so counting only registration would overstate the gap.
|
|
405
|
+
Reproduce with `node benchmark/bench_fastify_boot.mjs`.
|
|
389
406
|
|
|
390
407
|
### Standard Schema V1
|
|
391
408
|
|
package/index.d.ts
CHANGED
|
@@ -364,13 +364,13 @@ export interface BundleStandaloneOptions extends ValidatorOptions {
|
|
|
364
364
|
format?: 'esm' | 'cjs';
|
|
365
365
|
}
|
|
366
366
|
|
|
367
|
-
export interface StandardSchemaV1Props {
|
|
367
|
+
export interface StandardSchemaV1Props<Output = unknown, Input = unknown> {
|
|
368
368
|
version: 1;
|
|
369
369
|
vendor: "ata-validator";
|
|
370
370
|
validate(
|
|
371
371
|
value: unknown
|
|
372
372
|
):
|
|
373
|
-
| { value:
|
|
373
|
+
| { value: Output }
|
|
374
374
|
| {
|
|
375
375
|
issues: Array<{
|
|
376
376
|
message: string;
|
|
@@ -378,6 +378,11 @@ export interface StandardSchemaV1Props {
|
|
|
378
378
|
path?: ReadonlyArray<{ key: PropertyKey }>;
|
|
379
379
|
}>;
|
|
380
380
|
};
|
|
381
|
+
/**
|
|
382
|
+
* Type-only carrier the Standard Schema spec uses for inference: consumers
|
|
383
|
+
* read the validated type off `types.output`. Never present at runtime.
|
|
384
|
+
*/
|
|
385
|
+
readonly types?: { readonly input: Input; readonly output: Output } | undefined;
|
|
381
386
|
}
|
|
382
387
|
|
|
383
388
|
export interface StandaloneModule {
|
|
@@ -425,7 +430,7 @@ export interface Validator<T = unknown> {
|
|
|
425
430
|
isValidNDJSON(ndjsonBuffer: Buffer): boolean[];
|
|
426
431
|
|
|
427
432
|
/** Standard Schema V1 interface, compatible with Fastify, tRPC, TanStack, etc. */
|
|
428
|
-
readonly "~standard": StandardSchemaV1Props
|
|
433
|
+
readonly "~standard": StandardSchemaV1Props<T>;
|
|
429
434
|
}
|
|
430
435
|
|
|
431
436
|
/** Constructor + statics for {@link Validator}. */
|
|
@@ -433,7 +438,7 @@ export interface ValidatorConstructor {
|
|
|
433
438
|
/** Construct from a JSON Schema literal; the validated data type is inferred. */
|
|
434
439
|
new <const S extends JSONSchema>(schema: S, options?: ValidatorOptions): Validator<Infer<S>>;
|
|
435
440
|
/** Construct from a plain object/string schema, or with an explicit data type. */
|
|
436
|
-
new <T = unknown>(schema: object | string, options?: ValidatorOptions): Validator<T>;
|
|
441
|
+
new <T = unknown>(schema: object | string | boolean, options?: ValidatorOptions): Validator<T>;
|
|
437
442
|
|
|
438
443
|
/** Load a pre-compiled standalone module. Zero schema compilation at startup. */
|
|
439
444
|
fromStandalone<T = unknown>(mod: StandaloneModule, schema: object | string, options?: ValidatorOptions): Validator<T>;
|
package/lib/enrich-error.js
CHANGED
|
@@ -46,14 +46,24 @@ function expectedFor (err) {
|
|
|
46
46
|
|
|
47
47
|
function pickReceived (err, data) {
|
|
48
48
|
if (!data && data !== 0 && data !== false) return undefined;
|
|
49
|
-
// Walk JSON pointer to extract the actual offending value
|
|
49
|
+
// Walk JSON pointer to extract the actual offending value. This runs for
|
|
50
|
+
// every error on every rejected payload, so the walk reads segments straight
|
|
51
|
+
// out of the pointer: no leading-slash regex, no parts array, and no unescape
|
|
52
|
+
// pass on the segments that carry no `~`.
|
|
50
53
|
const p = err.instancePath || err.path || '';
|
|
51
54
|
if (!p) return reprValue(data);
|
|
52
|
-
const
|
|
55
|
+
const len = p.length;
|
|
53
56
|
let cur = data;
|
|
54
|
-
|
|
57
|
+
let i = p.charCodeAt(0) === 47 ? 1 : 0; // 47 is '/'
|
|
58
|
+
for (;;) {
|
|
59
|
+
let j = p.indexOf('/', i);
|
|
60
|
+
if (j === -1) j = len;
|
|
61
|
+
let seg = p.slice(i, j);
|
|
62
|
+
if (seg.indexOf('~') !== -1) seg = seg.replace(/~1/g, '/').replace(/~0/g, '~');
|
|
55
63
|
if (cur == null) return undefined;
|
|
56
|
-
cur = cur[
|
|
64
|
+
cur = cur[seg];
|
|
65
|
+
if (j === len) break;
|
|
66
|
+
i = j + 1;
|
|
57
67
|
}
|
|
58
68
|
return reprValue(cur);
|
|
59
69
|
}
|
package/lib/error-codes.js
CHANGED
|
@@ -77,20 +77,27 @@ function all () {
|
|
|
77
77
|
return Object.keys(CODES).sort();
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
+
// Reverse lookups, built once. codeFor runs per error on every failing
|
|
81
|
+
// validation, so walking the table there showed up as most of the cost of
|
|
82
|
+
// enriching a rejected payload. Insertion follows sorted code order, so the
|
|
83
|
+
// first writer wins and each keyword keeps the lowest code that carries it.
|
|
84
|
+
const BY_KEYWORD = new Map();
|
|
85
|
+
const BY_FORMAT = new Map();
|
|
86
|
+
for (const c of Object.keys(CODES).sort()) {
|
|
87
|
+
const meta = CODES[c];
|
|
88
|
+
if (!BY_KEYWORD.has(meta.keyword)) BY_KEYWORD.set(meta.keyword, c);
|
|
89
|
+
if (meta.keyword === 'format' && meta.format && !BY_FORMAT.has(meta.format)) BY_FORMAT.set(meta.format, c);
|
|
90
|
+
}
|
|
91
|
+
|
|
80
92
|
// Map a (keyword, optional format) tuple back to a code. Used by the codegen
|
|
81
93
|
// integration to attach codes to existing error sites without rewriting them all.
|
|
82
94
|
function codeFor (keyword, format) {
|
|
83
95
|
if (keyword === 'format' && format) {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
if (meta.keyword === 'format' && meta.format === format) return c;
|
|
87
|
-
}
|
|
88
|
-
return 'ATA3099';
|
|
89
|
-
}
|
|
90
|
-
for (const c of all()) {
|
|
91
|
-
if (CODES[c].keyword === keyword) return c;
|
|
96
|
+
const hit = BY_FORMAT.get(format);
|
|
97
|
+
return hit === undefined ? 'ATA3099' : hit;
|
|
92
98
|
}
|
|
93
|
-
|
|
99
|
+
const hit = BY_KEYWORD.get(keyword);
|
|
100
|
+
return hit === undefined ? null : hit;
|
|
94
101
|
}
|
|
95
102
|
|
|
96
103
|
module.exports = { CODES, get, all, codeFor };
|
package/lib/js-compiler.js
CHANGED
|
@@ -845,6 +845,16 @@ function codegenSafe(schema, schemaMap) {
|
|
|
845
845
|
if (typeof schema.unevaluatedProperties === 'object' && schema.unevaluatedProperties !== null) {
|
|
846
846
|
if (!codegenSafe(schema.unevaluatedProperties, schemaMap)) return false
|
|
847
847
|
}
|
|
848
|
+
// When evaluation is both dynamic (branch-dependent) and some branch
|
|
849
|
+
// unconditionally evaluates all properties, static tracking cannot
|
|
850
|
+
// correctly determine which properties are unevaluated at runtime.
|
|
851
|
+
// For example, a oneOf whose branches include both patternProperties
|
|
852
|
+
// and unevaluatedProperties:true requires annotation-aware evaluation
|
|
853
|
+
// that only the interpreted engine provides.
|
|
854
|
+
if (schema.unevaluatedProperties === false || (typeof schema.unevaluatedProperties === 'object' && schema.unevaluatedProperties !== null)) {
|
|
855
|
+
const evalResult = collectEvaluated(schema, schemaMap)
|
|
856
|
+
if (evalResult.dynamic && evalResult.allProps) return false
|
|
857
|
+
}
|
|
848
858
|
}
|
|
849
859
|
// unevaluatedItems: allow boolean and schema values
|
|
850
860
|
if (schema.unevaluatedItems !== undefined) {
|
|
@@ -861,15 +871,52 @@ function codegenSafe(schema, schemaMap) {
|
|
|
861
871
|
const defs = schema.$defs || schema.definitions
|
|
862
872
|
if (defs) {
|
|
863
873
|
const defNames = new Set(Object.keys(defs))
|
|
864
|
-
// Detect cyclic local refs:
|
|
865
|
-
//
|
|
866
|
-
//
|
|
867
|
-
//
|
|
868
|
-
//
|
|
869
|
-
|
|
870
|
-
const
|
|
871
|
-
|
|
872
|
-
|
|
874
|
+
// Detect cyclic local refs: build a directed graph of def->def references and
|
|
875
|
+
// check for cycles using DFS. A plain cross-reference (A -> B where B doesn't
|
|
876
|
+
// refer back to A) is fine; only true cycles (A -> B -> A) must be rejected.
|
|
877
|
+
// The JS codegen returns (() => true) on cycle (permissive), so cyclic schemas
|
|
878
|
+
// must route to the interpreted engine instead.
|
|
879
|
+
const defRefs = {}
|
|
880
|
+
for (const [name, def] of Object.entries(defs)) {
|
|
881
|
+
defRefs[name] = []
|
|
882
|
+
if (typeof def === 'object' && def !== null) {
|
|
883
|
+
const refs = []
|
|
884
|
+
const seen = new WeakSet()
|
|
885
|
+
const collectRefs = (node) => {
|
|
886
|
+
if (typeof node !== 'object' || node === null) return
|
|
887
|
+
if (seen.has(node)) return
|
|
888
|
+
seen.add(node)
|
|
889
|
+
if (node.$ref) {
|
|
890
|
+
const m = /^#\/(?:\$defs|definitions)\/([^/]+)$/.exec(node.$ref)
|
|
891
|
+
if (m && defNames.has(m[1])) refs.push(m[1])
|
|
892
|
+
}
|
|
893
|
+
for (const val of Object.values(node)) {
|
|
894
|
+
if (typeof val === 'object' && val !== null) {
|
|
895
|
+
if (Array.isArray(val)) { for (const item of val) collectRefs(item) }
|
|
896
|
+
else collectRefs(val)
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
collectRefs(def)
|
|
901
|
+
defRefs[name] = refs
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
const hasCycle = (() => {
|
|
905
|
+
const visited = new Set()
|
|
906
|
+
const inStack = new Set()
|
|
907
|
+
const dfs = (node) => {
|
|
908
|
+
if (inStack.has(node)) return true
|
|
909
|
+
if (visited.has(node)) return false
|
|
910
|
+
visited.add(node)
|
|
911
|
+
inStack.add(node)
|
|
912
|
+
for (const neighbor of (defRefs[node] || [])) {
|
|
913
|
+
if (dfs(neighbor)) return true
|
|
914
|
+
}
|
|
915
|
+
inStack.delete(node)
|
|
916
|
+
return false
|
|
917
|
+
}
|
|
918
|
+
return Object.keys(defRefs).some(dfs)
|
|
919
|
+
})()
|
|
873
920
|
if (hasCycle) return false
|
|
874
921
|
for (const [name, def] of Object.entries(defs)) {
|
|
875
922
|
if (/[~/"']/.test(name)) return false // special chars in def name
|
package/lib/version.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ata-validator",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.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",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"release:check": "node scripts/regen-safe-regex-source.js && node tests/test_pack_purity.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",
|
|
45
45
|
"build": "cmake-js build --target ata",
|
|
46
46
|
"rebuild": "cmake-js rebuild --target ata",
|
|
47
|
-
"test": "node test.js && node tests/test_removed_aot_methods.js && node tests/test_no_native.js && node tests/test_no_eval.js && node tests/test_property_dependencies.js && node tests/test_v1_dialect.js && node tests/test_buffer_path_parity.js && node tests/test_pure_js_unsupported.js && node tests/test_native_load_order.js && node tests/test_pack_purity.js && node tests/test_make_native_package.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_async_refine.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_engine_routing.js && node tests/test_format_engine_parity.js && node tests/test_defs_pointer_alias.js && node tests/test_cross_doc_root_ref.js && node tests/test_no_input_mutation.js && node tests/test_typed_validator_runner.js && node tests/test_define_schema.js && node tests/test_error_codes_lock.js && node tests/test_error_order.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_error_messages.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",
|
|
47
|
+
"test": "node test.js && node tests/test_removed_aot_methods.js && node tests/test_no_native.js && node tests/test_no_eval.js && node tests/test_property_dependencies.js && node tests/test_v1_dialect.js && node tests/test_buffer_path_parity.js && node tests/test_pure_js_unsupported.js && node tests/test_native_load_order.js && node tests/test_pack_purity.js && node tests/test_make_native_package.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_async_refine.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_engine_routing.js && node tests/test_format_engine_parity.js && node tests/test_defs_pointer_alias.js && node tests/test_cross_doc_root_ref.js && node tests/test_no_input_mutation.js && node tests/test_typed_validator_runner.js && node tests/test_define_schema.js && node tests/test_error_codes_lock.js && node tests/test_error_code_lookup.js && node tests/test_error_order.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_enrich_received.js && node tests/test_rich_errors_optout.js && node tests/test_error_messages.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",
|
|
48
48
|
"bench:size": "node benchmark/bench_aot_size.mjs",
|
|
49
49
|
"test:suite": "node tests/run_suite.js && node tests/run_suite.js draft7 && node tests/run_suite.js v1",
|
|
50
50
|
"test:compat": "node tests/test_compat.js",
|
|
@@ -112,12 +112,12 @@
|
|
|
112
112
|
"LICENSE"
|
|
113
113
|
],
|
|
114
114
|
"optionalDependencies": {
|
|
115
|
-
"@ata-validator/native-darwin-arm64": "1.6.
|
|
116
|
-
"@ata-validator/native-linux-x64-gnu": "1.6.
|
|
117
|
-
"@ata-validator/native-linux-arm64-gnu": "1.6.
|
|
118
|
-
"@ata-validator/native-linux-x64-musl": "1.6.
|
|
119
|
-
"@ata-validator/native-linux-arm64-musl": "1.6.
|
|
120
|
-
"@ata-validator/native-win32-x64": "1.6.
|
|
115
|
+
"@ata-validator/native-darwin-arm64": "1.6.2",
|
|
116
|
+
"@ata-validator/native-linux-x64-gnu": "1.6.2",
|
|
117
|
+
"@ata-validator/native-linux-arm64-gnu": "1.6.2",
|
|
118
|
+
"@ata-validator/native-linux-x64-musl": "1.6.2",
|
|
119
|
+
"@ata-validator/native-linux-arm64-musl": "1.6.2",
|
|
120
|
+
"@ata-validator/native-win32-x64": "1.6.2"
|
|
121
121
|
},
|
|
122
122
|
"peerDependencies": {
|
|
123
123
|
"yaml": "^2.0.0"
|
package/t.d.ts
CHANGED
|
@@ -34,7 +34,18 @@ export type TOptional<S> = S & { readonly [OPTIONAL]: true };
|
|
|
34
34
|
|
|
35
35
|
export type TSchema = JSONSchema;
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
/**
|
|
38
|
+
* Shared by every builder option bag. Annotations and vendor keywords (custom
|
|
39
|
+
* keywords outside the JSON Schema vocabulary) are carried through to the
|
|
40
|
+
* emitted schema, so the option types accept them.
|
|
41
|
+
*/
|
|
42
|
+
export interface CommonOptions {
|
|
43
|
+
description?: string;
|
|
44
|
+
title?: string;
|
|
45
|
+
[keyword: string]: unknown;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export interface StringOptions extends CommonOptions {
|
|
38
49
|
minLength?: number;
|
|
39
50
|
maxLength?: number;
|
|
40
51
|
pattern?: string;
|
|
@@ -45,7 +56,7 @@ export interface StringOptions {
|
|
|
45
56
|
examples?: readonly string[];
|
|
46
57
|
}
|
|
47
58
|
|
|
48
|
-
export interface NumericOptions {
|
|
59
|
+
export interface NumericOptions extends CommonOptions {
|
|
49
60
|
minimum?: number;
|
|
50
61
|
maximum?: number;
|
|
51
62
|
exclusiveMinimum?: number;
|
|
@@ -57,7 +68,7 @@ export interface NumericOptions {
|
|
|
57
68
|
examples?: readonly number[];
|
|
58
69
|
}
|
|
59
70
|
|
|
60
|
-
export interface ArrayOptions {
|
|
71
|
+
export interface ArrayOptions extends CommonOptions {
|
|
61
72
|
minItems?: number;
|
|
62
73
|
maxItems?: number;
|
|
63
74
|
uniqueItems?: boolean;
|
|
@@ -65,13 +76,13 @@ export interface ArrayOptions {
|
|
|
65
76
|
title?: string;
|
|
66
77
|
}
|
|
67
78
|
|
|
68
|
-
export interface ObjectOptions {
|
|
79
|
+
export interface ObjectOptions extends CommonOptions {
|
|
69
80
|
additionalProperties?: boolean | JSONSchema;
|
|
70
81
|
description?: string;
|
|
71
82
|
title?: string;
|
|
72
83
|
}
|
|
73
84
|
|
|
74
|
-
export interface RecordOptions {
|
|
85
|
+
export interface RecordOptions extends CommonOptions {
|
|
75
86
|
minProperties?: number;
|
|
76
87
|
maxProperties?: number;
|
|
77
88
|
description?: string;
|