ata-validator 1.18.0 → 1.18.1

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/index.js CHANGED
@@ -10,7 +10,7 @@ const {
10
10
  compileToJSCodegenWithErrors,
11
11
  compileToJSCombined,
12
12
  } = require("./lib/js-compiler");
13
- const { normalizeDraft7, normalizeNullable, stripFormatAssertions } = require("./lib/draft7");
13
+ const { normalizeDraft7, normalizeNullable, normalizeExclusiveBounds, stripFormatAssertions } = require("./lib/draft7");
14
14
  const { enabledKeywords, stripDisabledKeywords } = require("./lib/vocabularies");
15
15
  const { needsNormalization } = require("./lib/schema-scan");
16
16
  const { isV1Dialect } = require("./lib/dialect");
@@ -618,6 +618,7 @@ function _normalizeCallerSchema(s, inheritDraft7) {
618
618
  const copy = _deepCloneWithSymbols(s)
619
619
  if (needsDraft7) normalizeDraft7(copy, true)
620
620
  normalizeNullable(copy)
621
+ normalizeExclusiveBounds(copy)
621
622
  // Return original when normalization produced no change, copy otherwise.
622
623
  // Kept even though the walk has already said there is work, so that a walk
623
624
  // which over-reports still returns exactly what it returned before.
package/lib/draft7.js CHANGED
@@ -105,6 +105,50 @@ function _normalize(schema) {
105
105
  // 'null' (`{ type: 'X', nullable: true }` -> `{ type: ['X', 'null'] }`), the
106
106
  // same shape AJV produces under its `nullable` option. Recurses only through
107
107
  // schema-bearing keywords so it never touches data values (default, const, etc.).
108
+
109
+ // draft-04 spelled the exclusive bounds as booleans modifying `minimum` and
110
+ // `maximum`; every dialect since spells them as the bound itself. The engines
111
+ // read the numeric form, and the codegen path compared the value against the
112
+ // boolean directly, so `true` became 1: a schema saying "below 5, exclusive"
113
+ // rejected 1 and a schema saying "above 3, exclusive" accepted 3. Rewriting
114
+ // the pair here gives every engine the same numeric keyword, which is also
115
+ // what makes the two agree.
116
+ function normalizeExclusiveBounds(schema) {
117
+ _walkExclusive(schema, new Set())
118
+ return schema
119
+ }
120
+
121
+ function _walkExclusive(node, seen) {
122
+ if (typeof node !== 'object' || node === null) return
123
+ if (Array.isArray(node)) {
124
+ for (const item of node) _walkExclusive(item, seen)
125
+ return
126
+ }
127
+ if (seen.has(node)) return
128
+ seen.add(node)
129
+
130
+ if (typeof node.exclusiveMinimum === 'boolean') {
131
+ if (node.exclusiveMinimum === true && typeof node.minimum === 'number') {
132
+ node.exclusiveMinimum = node.minimum
133
+ delete node.minimum
134
+ } else {
135
+ // `false` restates the inclusive bound, and a boolean with no bound
136
+ // beside it says nothing at all.
137
+ delete node.exclusiveMinimum
138
+ }
139
+ }
140
+ if (typeof node.exclusiveMaximum === 'boolean') {
141
+ if (node.exclusiveMaximum === true && typeof node.maximum === 'number') {
142
+ node.exclusiveMaximum = node.maximum
143
+ delete node.maximum
144
+ } else {
145
+ delete node.exclusiveMaximum
146
+ }
147
+ }
148
+
149
+ for (const key of Object.keys(node)) _walkExclusive(node[key], seen)
150
+ }
151
+
108
152
  function normalizeNullable(schema) {
109
153
  if (typeof schema !== 'object' || schema === null) return schema
110
154
  _normalizeNullable(schema)
@@ -190,4 +234,4 @@ function _stripFormat(schema, seen) {
190
234
  }
191
235
  }
192
236
 
193
- module.exports = { isDraft7, normalizeDraft7, normalizeNullable, stripFormatAssertions }
237
+ module.exports = { isDraft7, normalizeDraft7, normalizeNullable, normalizeExclusiveBounds, stripFormatAssertions }
@@ -27,6 +27,7 @@ const ANCHOR_ID = 1 << 2; // a fragment-only `$id`, which is an anchor in
27
27
  const DEFINITIONS = 1 << 3; // `definitions`, renamed to `$defs`
28
28
  const DEPENDENCIES = 1 << 4; // `dependencies`, split into two keywords
29
29
  const TUPLE_ITEMS = 1 << 5; // array-valued `items`, split into `prefixItems`
30
+ const EXCLUSIVE_BOOL = 1 << 6; // draft-04's boolean `exclusiveMinimum`/`exclusiveMaximum`
30
31
 
31
32
  // Everything only draft-07 normalization acts on. A schema of another dialect
32
33
  // can carry these without them meaning anything, so they are read together
@@ -74,6 +75,9 @@ function scan(schema) {
74
75
  if (node.definitions !== undefined && node.$defs === undefined) bits |= DEFINITIONS;
75
76
  if (node.dependencies !== undefined) bits |= DEPENDENCIES;
76
77
  if (Array.isArray(node.items)) bits |= TUPLE_ITEMS;
78
+ if (typeof node.exclusiveMinimum === 'boolean' || typeof node.exclusiveMaximum === 'boolean') {
79
+ bits |= EXCLUSIVE_BOOL;
80
+ }
77
81
  if (typeof node.$id === 'string' && ANCHOR_ID_RE.test(node.$id)) bits |= ANCHOR_ID;
78
82
 
79
83
  // `Object.keys` rather than `for...in`: the prototype chain has nothing
@@ -99,6 +103,10 @@ function scan(schema) {
99
103
  function needsNormalization(schema, isDraft7) {
100
104
  const bits = scan(schema);
101
105
  if (bits & NULLABLE) return true;
106
+ // The boolean form of the exclusive bounds is draft-04's, and it is
107
+ // unambiguous wherever it appears: no later dialect gives a boolean any
108
+ // meaning there. Normalizing it is not gated on the declared dialect.
109
+ if (bits & EXCLUSIVE_BOOL) return true;
102
110
  return isDraft7 ? (bits & DRAFT7_WORK) !== 0 : false;
103
111
  }
104
112
 
@@ -111,5 +119,6 @@ module.exports = {
111
119
  DEFINITIONS,
112
120
  DEPENDENCIES,
113
121
  TUPLE_ITEMS,
122
+ EXCLUSIVE_BOOL,
114
123
  DRAFT7_WORK,
115
124
  };
package/lib/version.js CHANGED
@@ -7,4 +7,4 @@
7
7
  //
8
8
  // Kept in lockstep with package.json by `tests/test_version_sync.js`.
9
9
 
10
- module.exports = '1.18.0';
10
+ module.exports = '1.18.1';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ata-validator",
3
- "version": "1.18.0",
3
+ "version": "1.18.1",
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_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",
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_exclusive_bounds.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.18.0",
126
- "@ata-validator/native-darwin-x64": "1.18.0",
127
- "@ata-validator/native-linux-arm64-gnu": "1.18.0",
128
- "@ata-validator/native-linux-arm64-musl": "1.18.0",
129
- "@ata-validator/native-linux-x64-gnu": "1.18.0",
130
- "@ata-validator/native-linux-x64-musl": "1.18.0",
131
- "@ata-validator/native-win32-x64": "1.18.0"
125
+ "@ata-validator/native-darwin-arm64": "1.18.1",
126
+ "@ata-validator/native-darwin-x64": "1.18.1",
127
+ "@ata-validator/native-linux-arm64-gnu": "1.18.1",
128
+ "@ata-validator/native-linux-arm64-musl": "1.18.1",
129
+ "@ata-validator/native-linux-x64-gnu": "1.18.1",
130
+ "@ata-validator/native-linux-x64-musl": "1.18.1",
131
+ "@ata-validator/native-win32-x64": "1.18.1"
132
132
  },
133
133
  "peerDependencies": {
134
134
  "yaml": "^2.0.0"