ata-validator 0.11.0 → 0.11.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/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Ultra-fast JSON Schema validator powered by [simdjson](https://github.com/simdjson/simdjson). Multi-core parallel validation, RE2 regex, codegen bytecode engine. Standard Schema V1 compatible.
4
4
 
5
- **[ata-validator.com](https://ata-validator.com)** | **[API Docs](docs/API.md)** | **[Contributing](CONTRIBUTING.md)**
5
+ **[ata-validator.com](https://ata-validator.com)** | **[API Docs](docs/API.md)** | **[Migrate from ajv](docs/migration-from-ajv.md)** | **[Contributing](CONTRIBUTING.md)**
6
6
 
7
7
  ## Performance
8
8
 
package/index.d.ts CHANGED
@@ -123,3 +123,11 @@ export function createPaddedBuffer(jsonStr: string): { buffer: Buffer; length: n
123
123
 
124
124
  /** Required padding size for simdjson buffers. */
125
125
  export const SIMDJSON_PADDING: number;
126
+
127
+ /**
128
+ * Generate a TypeScript declaration (.d.ts source) for the given JSON Schema.
129
+ * Returns a string containing the generated type plus `isValid` / `validate`
130
+ * signatures. Used internally by the `ata compile` CLI and exposed for
131
+ * build-time integrations (Vite plugin, custom build steps).
132
+ */
133
+ export function toTypeScript(schema: object, options?: { name?: string }): string;
package/index.js CHANGED
@@ -1216,6 +1216,8 @@ function compile(schema, opts) {
1216
1216
  return fn;
1217
1217
  }
1218
1218
 
1219
+ const { toTypeScript } = require("./lib/ts-gen");
1220
+
1219
1221
  module.exports = {
1220
1222
  Validator,
1221
1223
  compile,
@@ -1224,4 +1226,5 @@ module.exports = {
1224
1226
  createPaddedBuffer,
1225
1227
  SIMDJSON_PADDING,
1226
1228
  parseJSON,
1229
+ toTypeScript,
1227
1230
  };
@@ -675,8 +675,14 @@ function codegenSafe(schema, schemaMap) {
675
675
  if (siblings.length > 0 && schema.unevaluatedProperties === undefined && schema.unevaluatedItems === undefined) return false
676
676
  }
677
677
 
678
- // additionalProperties as schema — bail entirely, too many edge cases with allOf interaction
679
- if (typeof schema.additionalProperties === 'object') return false
678
+ // additionalProperties as schema — supported when no composition (allOf/oneOf/anyOf)
679
+ // is in play, and no patternProperties (unified loop does not emit the
680
+ // per-key sub-schema walk yet). Closure path handles those cases.
681
+ if (typeof schema.additionalProperties === 'object' && schema.additionalProperties !== null) {
682
+ if (schema.allOf || schema.oneOf || schema.anyOf) return false
683
+ if (schema.patternProperties) return false
684
+ if (!codegenSafe(schema.additionalProperties, schemaMap)) return false
685
+ }
680
686
  if (schema.additionalProperties === false && !schema.properties) return false
681
687
 
682
688
  // propertyNames: false — codegen doesn't handle this
@@ -729,6 +735,37 @@ function codegenSafe(schema, schemaMap) {
729
735
  return true
730
736
  }
731
737
 
738
+ // Returns true if the schema (or any nested sub-schema reachable through the
739
+ // usual keywords) has additionalProperties as a schema value. Used by the
740
+ // combined-codegen bail since that path does not emit the per-key loop yet.
741
+ function hasAdditionalPropertiesSchema(schema) {
742
+ if (typeof schema !== 'object' || schema === null) return false
743
+ if (typeof schema.additionalProperties === 'object' && schema.additionalProperties !== null) return true
744
+ const objSubs = ['properties', 'patternProperties', '$defs', 'definitions', 'dependentSchemas']
745
+ for (const key of objSubs) {
746
+ if (schema[key] && typeof schema[key] === 'object') {
747
+ for (const v of Object.values(schema[key])) {
748
+ if (hasAdditionalPropertiesSchema(v)) return true
749
+ }
750
+ }
751
+ }
752
+ const arrSubs = ['allOf', 'anyOf', 'oneOf', 'prefixItems']
753
+ for (const key of arrSubs) {
754
+ if (Array.isArray(schema[key])) {
755
+ for (const s of schema[key]) {
756
+ if (hasAdditionalPropertiesSchema(s)) return true
757
+ }
758
+ }
759
+ }
760
+ const singleSubs = ['items', 'contains', 'not', 'if', 'then', 'else', 'propertyNames']
761
+ for (const key of singleSubs) {
762
+ if (typeof schema[key] === 'object' && schema[key] !== null) {
763
+ if (hasAdditionalPropertiesSchema(schema[key])) return true
764
+ }
765
+ }
766
+ return false
767
+ }
768
+
732
769
  // --- Codegen mode: generates a single Function (NOT CSP-safe) ---
733
770
  // This matches ajv's approach: one monolithic function, V8 JIT fully inlines it
734
771
  function compileToJSCodegen(schema, schemaMap) {
@@ -1274,6 +1311,25 @@ function genCode(schema, v, lines, ctx, knownType) {
1274
1311
  _deferOrInline(ctx, lines, v, isObj ? inner : `if(typeof ${v}==='object'&&${v}!==null&&!Array.isArray(${v})){${inner}}`)
1275
1312
  }
1276
1313
 
1314
+ // additionalProperties as a schema: validate every non-declared property
1315
+ // against that sub-schema. Skip if patternProperties is present (handled by
1316
+ // the unified loop). Composition cases are filtered out by codegenSafe.
1317
+ if (typeof schema.additionalProperties === 'object' && schema.additionalProperties !== null && !schema.patternProperties) {
1318
+ const declared = schema.properties ? Object.keys(schema.properties) : []
1319
+ const skipCheck = declared.length === 0
1320
+ ? null
1321
+ : declared.map(k => `_k===${JSON.stringify(k)}`).join('||')
1322
+ const subLines = []
1323
+ genCode(schema.additionalProperties, '_av', subLines, ctx)
1324
+ if (subLines.length > 0) {
1325
+ const body = subLines.join(';')
1326
+ const loop = skipCheck
1327
+ ? `for(var _k in ${v}){if(${skipCheck})continue;const _av=${v}[_k];${body}}`
1328
+ : `for(var _k in ${v}){const _av=${v}[_k];${body}}`
1329
+ _deferOrInline(ctx, lines, v, isObj ? loop : `if(typeof ${v}==='object'&&${v}!==null&&!Array.isArray(${v})){${loop}}`)
1330
+ }
1331
+ }
1332
+
1277
1333
  // dependentRequired
1278
1334
  if (schema.dependentRequired) {
1279
1335
  for (const [key, deps] of Object.entries(schema.dependentRequired)) {
@@ -2251,6 +2307,9 @@ function compileToJSCodegenWithErrors(schema, schemaMap) {
2251
2307
  if (s.includes('unevaluatedProperties') || s.includes('unevaluatedItems')) return null
2252
2308
  // Bail on self-referencing schemas — error codegen doesn't support recursion
2253
2309
  if (s.includes('"$ref":"#"')) return null
2310
+ // Bail on additionalProperties as a schema — genCodeE does not emit the
2311
+ // per-key sub-schema loop. Let the closure path handle detailed errors.
2312
+ if (hasAdditionalPropertiesSchema(schema)) return null
2254
2313
  }
2255
2314
  if (typeof schema === 'boolean') {
2256
2315
  return schema
@@ -2752,6 +2811,9 @@ function compileToJSCombined(schema, VALID_RESULT, schemaMap) {
2752
2811
  if (s.includes('unevaluatedProperties') || s.includes('unevaluatedItems')) return null
2753
2812
  // Bail on self-referencing schemas — combined codegen doesn't support recursion
2754
2813
  if (s.includes('"$ref":"#"')) return null
2814
+ // Bail on additionalProperties as a schema — combined path doesn't emit the
2815
+ // per-key sub-schema loop yet. The jsFn + errFn fallback handles it correctly.
2816
+ if (hasAdditionalPropertiesSchema(schema)) return null
2755
2817
  }
2756
2818
  if (typeof schema === 'boolean') {
2757
2819
  return schema
package/lib/ts-gen.js CHANGED
@@ -125,8 +125,11 @@ function toTypeScript(schema, opts) {
125
125
  }
126
126
 
127
127
  const rootType = renderValueType(schema, defs, 0);
128
- const isObjectShape = rootType.startsWith('{') || rootType.startsWith('Record<');
129
- const rootDecl = isObjectShape && !rootType.includes(' | ')
128
+ // Use `interface` only for a pure object literal; otherwise fall back to
129
+ // `type`. Catches cases like `{...}[]` (array of object) and `Record<...>`
130
+ // which are valid TS but cannot be expressed as an interface body.
131
+ const isPureObjectLiteral = rootType.startsWith('{') && rootType.endsWith('}') && !rootType.includes(' | ');
132
+ const rootDecl = isPureObjectLiteral
130
133
  ? `export interface ${rootName} ${rootType}`
131
134
  : `export type ${rootName} = ${rootType};`;
132
135
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ata-validator",
3
- "version": "0.11.0",
3
+ "version": "0.11.1",
4
4
  "description": "Ultra-fast JSON Schema validator. 4.7x faster validation, 1,800x faster compilation. Works without native addon. Cross-schema $ref, Draft 2020-12 + Draft 7, V8-optimized JS codegen, simdjson, RE2, multi-core. Standard Schema V1 compatible.",
5
5
  "main": "index.js",
6
6
  "module": "index.mjs",
@@ -40,6 +40,7 @@
40
40
  "test:compat": "node tests/test_compat.js",
41
41
  "test:standard-schema": "node tests/test_standard_schema.js",
42
42
  "test:browser": "node tests/test_browser.js",
43
+ "test:ts": "node tests/test_ts_gen.js",
43
44
  "bench": "node benchmark/bench_large.js",
44
45
  "fuzz": "node tests/fuzz_differential.js",
45
46
  "fuzz:long": "FUZZ_ITERATIONS=100000 node tests/fuzz_differential.js",
@@ -60,7 +61,7 @@
60
61
  "standard-schema",
61
62
  "fastify"
62
63
  ],
63
- "author": "Mert Can Altin <mertcanaltin01@gmail.com>",
64
+ "author": "Mert Can Altin <mertgold60@gmail.com>",
64
65
  "license": "MIT",
65
66
  "repository": {
66
67
  "type": "git",
@@ -103,6 +104,7 @@
103
104
  "cmake-js": "^8.0.0",
104
105
  "mitata": "^1.0.34",
105
106
  "typebox": "^1.1.7",
107
+ "typescript": "^6.0.3",
106
108
  "valibot": "^1.3.1",
107
109
  "zod": "^4.3.6"
108
110
  },