ata-validator 1.17.1 → 1.17.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 +6 -0
- package/index.js +47 -25
- package/lib/version.js +1 -1
- package/package.json +9 -9
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,12 @@
|
|
|
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.17.2 - 2026-09-13
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
|
|
9
|
+
- `new Validator(schema)` no longer walks the schema. Normalization (the draft-07 rewrites, `nullable`, `format` removal under `assertFormat: false`) and the scan that decides whether any of it is needed now run on the first read of the schema, which is the first compile. Construction is the instance and its fields. Measured on the schema-benchmarks product schema built fresh each time: 4.28 to 0.91 µs; with the `@ata-project/keywords` wrapper (0.3.1, which reads the schema lazily too) 6.70 to 2.81 µs. Nothing observable changes for a schema that is used: the same normalized document reaches the engines, and the identity cache, `keywords`, `assertFormat` and `source` options behave as before. `tests/test_lazy_normalization.js` counts property reads on the schema during construction and holds them at the dialect lookup alone.
|
|
10
|
+
|
|
5
11
|
## 1.17.1 - 2026-09-13
|
|
6
12
|
|
|
7
13
|
### Changed
|
package/index.js
CHANGED
|
@@ -797,6 +797,26 @@ function resolveSchemaForPreprocess(schema, schemaMap) {
|
|
|
797
797
|
return cloned || s
|
|
798
798
|
}
|
|
799
799
|
|
|
800
|
+
// `_schemaObj` and `_usesKeywords` are materialized together on first read:
|
|
801
|
+
// the caller's schema normalized on a clone (the caller's object is never
|
|
802
|
+
// touched), `format` stripped under `assertFormat: false`, and the custom
|
|
803
|
+
// keyword scan. The accessors then step aside for own data properties, so
|
|
804
|
+
// every later read is a plain field.
|
|
805
|
+
function _materializeSchema(self) {
|
|
806
|
+
const raw = self._rawSchema;
|
|
807
|
+
const options = self._options;
|
|
808
|
+
let schemaObj = _normalizeCallerSchema(raw);
|
|
809
|
+
const isCallers = self._rawIsCallers && schemaObj === raw;
|
|
810
|
+
if (options.assertFormat === false) {
|
|
811
|
+
schemaObj = stripFormatAssertions(isCallers ? _deepCloneWithSymbols(schemaObj) : schemaObj);
|
|
812
|
+
}
|
|
813
|
+
const usesKeywords = self._keywords !== null && schemaUsesKeywords(schemaObj, self._keywords);
|
|
814
|
+
Object.defineProperty(self, '_schemaObj', { value: schemaObj, writable: true, configurable: true, enumerable: true });
|
|
815
|
+
Object.defineProperty(self, '_usesKeywords', { value: usesKeywords, writable: true, configurable: true, enumerable: true });
|
|
816
|
+
Object.defineProperty(self, '_schemaIsCallers', { value: isCallers && schemaObj === raw, writable: true, configurable: true, enumerable: true });
|
|
817
|
+
return schemaObj;
|
|
818
|
+
}
|
|
819
|
+
|
|
800
820
|
class Validator {
|
|
801
821
|
constructor(schema, opts) {
|
|
802
822
|
const options = opts || {};
|
|
@@ -809,22 +829,16 @@ class Validator {
|
|
|
809
829
|
if (hit) return hit;
|
|
810
830
|
}
|
|
811
831
|
|
|
832
|
+
// The schema is not walked here. Normalization (draft-07 rewrites,
|
|
833
|
+
// nullable, `assertFormat: false`) and the scan that decides whether any
|
|
834
|
+
// of it is needed run on the first read of `_schemaObj`, which is the
|
|
835
|
+
// first compile. Construction is the object and its fields; a server
|
|
836
|
+
// building a validator per request pays nothing for a schema it never
|
|
837
|
+
// uses, and a benchmark timing construction measures construction.
|
|
812
838
|
// When schema is a string, JSON.parse already produces a fresh object.
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
? _normalizeCallerSchema(JSON.parse(schema))
|
|
817
|
-
: _normalizeCallerSchema(schema);
|
|
818
|
-
const rootIsDraft7 = !!(schemaObj && typeof schemaObj === 'object' && typeof schemaObj.$schema === 'string' &&
|
|
819
|
-
(schemaObj.$schema === 'http://json-schema.org/draft-07/schema#' || schemaObj.$schema === 'http://json-schema.org/draft-07/schema'));
|
|
820
|
-
|
|
821
|
-
// assertFormat: false makes `format` annotation-only. Strip it on a clone
|
|
822
|
-
// so the caller's schema keeps the keyword.
|
|
823
|
-
if (options.assertFormat === false) {
|
|
824
|
-
schemaObj = stripFormatAssertions(
|
|
825
|
-
schemaObj === schema ? _deepCloneWithSymbols(schemaObj) : schemaObj,
|
|
826
|
-
);
|
|
827
|
-
}
|
|
839
|
+
const raw = typeof schema === "string" ? JSON.parse(schema) : schema;
|
|
840
|
+
const rootIsDraft7 = !!(raw && typeof raw === 'object' && typeof raw.$schema === 'string' &&
|
|
841
|
+
(raw.$schema === 'http://json-schema.org/draft-07/schema#' || raw.$schema === 'http://json-schema.org/draft-07/schema'));
|
|
828
842
|
|
|
829
843
|
// Built here rather than below because `$vocabulary` is resolved against
|
|
830
844
|
// it, and that resolution waits until compilation so a meta-schema
|
|
@@ -832,21 +846,17 @@ class Validator {
|
|
|
832
846
|
const shared = buildSchemaMap(options.schemas, rootIsDraft7);
|
|
833
847
|
const schemaMap = shared || new Map();
|
|
834
848
|
this._schemaMapShared = shared !== null;
|
|
835
|
-
this._schemaIsCallers = schemaObj === schema;
|
|
836
849
|
this._vocabulariesApplied = false;
|
|
837
850
|
|
|
838
|
-
// Custom keywords, normalized once. `_usesKeywords`
|
|
839
|
-
// schema to the interpreted engine and keeps
|
|
840
|
-
// compile cache; a schema that registers keywords
|
|
841
|
-
// takes the ordinary path.
|
|
851
|
+
// Custom keywords, normalized once. `_usesKeywords` (resolved with the
|
|
852
|
+
// schema) is what routes the schema to the interpreted engine and keeps
|
|
853
|
+
// it out of the shared compile cache; a schema that registers keywords
|
|
854
|
+
// but uses none of them takes the ordinary path.
|
|
842
855
|
this._keywords = normalizeKeywords(options.keywords);
|
|
843
|
-
this._usesKeywords = false;
|
|
844
|
-
if (this._keywords !== null && schemaUsesKeywords(schemaObj, this._keywords)) {
|
|
845
|
-
this._usesKeywords = true;
|
|
846
|
-
}
|
|
847
856
|
|
|
848
857
|
this._schemaStr = null; // lazy: computed on first use
|
|
849
|
-
this.
|
|
858
|
+
this._rawSchema = raw;
|
|
859
|
+
this._rawIsCallers = typeof schema !== "string";
|
|
850
860
|
this._options = options;
|
|
851
861
|
this._noOpts = !opts;
|
|
852
862
|
this._initialized = false;
|
|
@@ -2162,6 +2172,18 @@ function _defineLazyMethod(name, maker) {
|
|
|
2162
2172
|
});
|
|
2163
2173
|
}
|
|
2164
2174
|
|
|
2175
|
+
for (const [name, pick] of [
|
|
2176
|
+
['_schemaObj', (self) => _materializeSchema(self)],
|
|
2177
|
+
['_usesKeywords', (self) => { _materializeSchema(self); return self._usesKeywords; }],
|
|
2178
|
+
['_schemaIsCallers', (self) => { _materializeSchema(self); return self._schemaIsCallers; }],
|
|
2179
|
+
]) {
|
|
2180
|
+
Object.defineProperty(Validator.prototype, name, {
|
|
2181
|
+
configurable: true,
|
|
2182
|
+
get() { return pick(this); },
|
|
2183
|
+
set(v) { Object.defineProperty(this, name, { value: v, writable: true, configurable: true, enumerable: true }); },
|
|
2184
|
+
});
|
|
2185
|
+
}
|
|
2186
|
+
|
|
2165
2187
|
_defineLazyMethod('validate', (self) => (data) => {
|
|
2166
2188
|
self._ensureCompiled();
|
|
2167
2189
|
return self.validate(data);
|
package/lib/version.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ata-validator",
|
|
3
|
-
"version": "1.17.
|
|
3
|
+
"version": "1.17.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",
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"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",
|
|
52
52
|
"build": "cmake-js build --target ata",
|
|
53
53
|
"rebuild": "cmake-js rebuild --target ata",
|
|
54
|
-
"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_buffer_gate.js && node tests/test_buffer_reject_cost.js && node tests/test_nan_verdict.js && node tests/test_remove_additional_nested.js && node tests/test_aot_parse.js && node tests/test_draft7_semantics.js && node tests/test_metaschema_ref.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_native_loaded.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_format_mode.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_engine_diagnostic.js && node tests/test_format_engine_parity.js && node tests/test_formats_single_pass.js && node tests/test_format_single_error.js && node tests/test_defs_pointer_alias.js && node tests/test_cross_doc_root_ref.js && node tests/test_codegen_entrypoint_agreement.js && node tests/test_hybrid_agreement.js && node tests/test_codegen_edge_shapes.js && node tests/test_ajv_errors.js && node tests/test_custom_keywords.js && node tests/test_ajv_parity.js && node tests/test_user_format_error_path.js && node tests/test_unevaluated_error_path.js && node tests/test_pattern_properties_errors.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_error_order_ordinal.js && node tests/test_rejection_shape.js && node tests/test_value_equality.js && node tests/test_vocabulary.js && node tests/test_schema_scan.js && node tests/test_lazy_errors.js && node tests/test_lazy_instance.js && node tests/test_cyclic_input.js && node tests/test_native_error_codes.js && node tests/test_verdict_preprocess.js && node tests/test_plan_compiler.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_additive_fields.js && node tests/test_diagnostic_source.js && node tests/test_diagnose.js && node tests/test_correlate.js && node tests/test_diagnostics_score.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",
|
|
54
|
+
"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_buffer_gate.js && node tests/test_buffer_reject_cost.js && node tests/test_nan_verdict.js && node tests/test_remove_additional_nested.js && node tests/test_aot_parse.js && node tests/test_draft7_semantics.js && node tests/test_metaschema_ref.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_native_loaded.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_format_mode.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_engine_diagnostic.js && node tests/test_format_engine_parity.js && node tests/test_formats_single_pass.js && node tests/test_format_single_error.js && node tests/test_defs_pointer_alias.js && node tests/test_cross_doc_root_ref.js && node tests/test_codegen_entrypoint_agreement.js && node tests/test_hybrid_agreement.js && node tests/test_codegen_edge_shapes.js && node tests/test_ajv_errors.js && node tests/test_custom_keywords.js && node tests/test_ajv_parity.js && node tests/test_user_format_error_path.js && node tests/test_unevaluated_error_path.js && node tests/test_pattern_properties_errors.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_error_order_ordinal.js && node tests/test_rejection_shape.js && node tests/test_lazy_normalization.js && node tests/test_value_equality.js && node tests/test_vocabulary.js && node tests/test_schema_scan.js && node tests/test_lazy_errors.js && node tests/test_lazy_instance.js && node tests/test_cyclic_input.js && node tests/test_native_error_codes.js && node tests/test_verdict_preprocess.js && node tests/test_plan_compiler.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_additive_fields.js && node tests/test_diagnostic_source.js && node tests/test_diagnose.js && node tests/test_correlate.js && node tests/test_diagnostics_score.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",
|
|
55
55
|
"bench:size": "node benchmark/bench_aot_size.mjs",
|
|
56
56
|
"test:suite": "node tests/run_suite.js && node tests/run_suite.js draft7 && node tests/run_suite.js v1",
|
|
57
57
|
"test:compat": "node tests/test_compat.js",
|
|
@@ -122,13 +122,13 @@
|
|
|
122
122
|
"LICENSE"
|
|
123
123
|
],
|
|
124
124
|
"optionalDependencies": {
|
|
125
|
-
"@ata-validator/native-darwin-arm64": "1.17.
|
|
126
|
-
"@ata-validator/native-darwin-x64": "1.17.
|
|
127
|
-
"@ata-validator/native-linux-arm64-gnu": "1.17.
|
|
128
|
-
"@ata-validator/native-linux-arm64-musl": "1.17.
|
|
129
|
-
"@ata-validator/native-linux-x64-gnu": "1.17.
|
|
130
|
-
"@ata-validator/native-linux-x64-musl": "1.17.
|
|
131
|
-
"@ata-validator/native-win32-x64": "1.17.
|
|
125
|
+
"@ata-validator/native-darwin-arm64": "1.17.2",
|
|
126
|
+
"@ata-validator/native-darwin-x64": "1.17.2",
|
|
127
|
+
"@ata-validator/native-linux-arm64-gnu": "1.17.2",
|
|
128
|
+
"@ata-validator/native-linux-arm64-musl": "1.17.2",
|
|
129
|
+
"@ata-validator/native-linux-x64-gnu": "1.17.2",
|
|
130
|
+
"@ata-validator/native-linux-x64-musl": "1.17.2",
|
|
131
|
+
"@ata-validator/native-win32-x64": "1.17.2"
|
|
132
132
|
},
|
|
133
133
|
"peerDependencies": {
|
|
134
134
|
"yaml": "^2.0.0"
|