zod-aot 0.5.0 → 0.6.0

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
@@ -7,22 +7,22 @@
7
7
  [![npm](https://img.shields.io/npm/v/zod-aot)](https://www.npmjs.com/package/zod-aot)
8
8
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
9
9
 
10
- No code changes required — keep your existing Zod schemas and get **2-64x faster** validation.
10
+ No code changes required — keep your existing Zod schemas and get **2-80x faster** validation.
11
11
 
12
12
  ## Why
13
13
 
14
14
  Zod v4 is already fast, but runtime schema traversal still costs ~10x compared to ahead-of-time (AOT) compiled approaches. Existing AOT solutions like [Typia](https://typia.io/) require rewriting your schemas as TypeScript types. **zod-aot** bridges this gap — it takes your existing Zod schemas and generates optimized, plain JavaScript validation functions at build time.
15
15
 
16
- | | zod-aot | Typia | AJV standalone | Zod v4 |
17
- |---|---|---|---|---|
18
- | **Input** | Zod schemas | TS types | JSON Schema | Zod schemas |
19
- | **Existing code changes** | None | Full rewrite | Full rewrite | N/A |
20
- | **Type inference** | Inherited from Zod | Native | External | Native |
21
- | **Runtime dependency** | None (generated code) | Typia runtime | AJV runtime | Zod |
16
+ | | Zod AOT | Typia | AJV standalone | Zod v3 | Zod v4 |
17
+ |---|---------------------|---|---|---|---|
18
+ | **Input** | Zod schemas | TS types | JSON Schema | Zod schemas | Zod schemas |
19
+ | **Existing code changes** | None | Full rewrite | Full rewrite | N/A | N/A |
20
+ | **Type inference** | Inherited from Zod | Native | External | Native | Native |
21
+ | **Runtime dependency** | None (generated code) | Typia runtime | AJV runtime | Zod | Zod |
22
22
 
23
23
  ## Benchmarks
24
24
 
25
- Measured with `vitest bench` on Node.js (Apple M-series). The benchmark suite compares **zod**, **zod-aot**, **[ajv](https://ajv.js.org/)**, and **[typia](https://typia.io/)** across primitives, objects, collections, unions, recursive schemas, and real-world scenarios.
25
+ Measured with `vitest bench` on Node.js (Apple M-series). The benchmark suite compares **Zod v3**, **Zod v4**, **zod-aot**, **[ajv](https://ajv.js.org/)**, and **[typia](https://typia.io/)** across primitives, objects, collections, unions, recursive schemas, and real-world scenarios.
26
26
 
27
27
  Run benchmarks locally:
28
28
 
@@ -30,27 +30,29 @@ Run benchmarks locally:
30
30
  pnpm bench
31
31
  ```
32
32
 
33
- ### safeParse (zod vs zod-aot)
34
-
35
- | Scenario | Zod v4 | zod-aot | Speedup |
36
- |---|---|---|----------|
37
- | simple string | 11.1M ops/s | 19.6M ops/s | **1.8x** |
38
- | string (min/max) | 5.5M ops/s | 20.0M ops/s | **3.6x** |
39
- | number (int+positive) | 5.5M ops/s | 18.7M ops/s | **3.4x** |
40
- | enum | 9.1M ops/s | 17.2M ops/s | **1.9x** |
41
- | tuple [string, int, boolean] | 4.3M ops/s | 18.1M ops/s | **4.2x** |
42
- | record\<string, number\> (5 keys) | 1.9M ops/s | 7.1M ops/s | **3.7x** |
43
- | discriminatedUnion (3 variants) | 3.0M ops/s | 17.3M ops/s | **5.8x** |
44
- | medium object (7 props, valid) | 1.6M ops/s | 6.6M ops/s | **4.1x** |
45
- | medium object (7 props, invalid) | 63K ops/s | 474K ops/s | **7.5x** |
46
- | large object (10 nested items) | 107K ops/s | 5.0M ops/s | **46x** |
47
- | large object (100 nested items) | 11.6K ops/s | 740K ops/s | **64x** |
48
- | event log (combined) | 442K ops/s | 5.5M ops/s | **12x** |
49
- | partial fallback object (transform) | 1.7M ops/s | 3.9M ops/s | **2.3x** |
50
- | partial fallback array 10 (transform) | 139K ops/s | 577K ops/s | **4.1x** |
51
- | partial fallback array 50 (transform) | 28K ops/s | 119K ops/s | **4.2x** |
52
-
53
- Performance gains scale with schema complexity. The `discriminatedUnion` optimization uses an O(1) `switch` dispatch instead of Zod's sequential trial approach. Partial fallback schemas (containing `transform`/`refine`) still show 2.5-4.7x speedups by compiling the optimizable portions.
33
+ ### safeParse
34
+
35
+ | Scenario | Zod v3 | Zod v4 | Zod AOT | vs v3 | vs v4 |
36
+ |---|---|---|-----------|---|---|
37
+ | simple string | 8.2M ops/s | 9.6M ops/s | 10.4M ops/s | **1.3x** | **1.1x** |
38
+ | string (min/max) | 7.8M ops/s | 5.4M ops/s | 10.5M ops/s | **1.4x** | **2.0x** |
39
+ | number (int+positive) | 7.8M ops/s | 5.7M ops/s | 10.5M ops/s | **1.3x** | **1.8x** |
40
+ | enum | 7.5M ops/s | 9.1M ops/s | 10.0M ops/s | **1.3x** | **1.1x** |
41
+ | tuple [string, int, boolean] | 4.2M ops/s | 4.6M ops/s | 10.5M ops/s | **2.5x** | **2.3x** |
42
+ | record\<string, number\> (5 keys) | 2.3M ops/s | 1.9M ops/s | 5.6M ops/s | **2.4x** | **2.9x** |
43
+ | discriminatedUnion (3 variants) | 2.3M ops/s | 2.9M ops/s | 9.3M ops/s | **4.1x** | **3.3x** |
44
+ | medium object (7 props, valid) | 1.3M ops/s | 1.7M ops/s | 5.2M ops/s | **4.0x** | **3.0x** |
45
+ | medium object (7 props, invalid) | 346K ops/s | 62K ops/s | 467K ops/s | **1.4x** | **7.5x** |
46
+ | large object (10 nested items) | 83K ops/s | 110K ops/s | 4.0M ops/s | **48x** | **36x** |
47
+ | large object (100 nested items) | 8.5K ops/s | 11.3K ops/s | 680K ops/s | **80x** | **60x** |
48
+ | recursive tree (7 nodes) | 398K ops/s | 1.5M ops/s | 6.3M ops/s | **16x** | **4.2x** |
49
+ | recursive tree (121 nodes) | 23K ops/s | 101K ops/s | 749K ops/s | **33x** | **7.4x** |
50
+ | event log (combined) | 265K ops/s | 440K ops/s | 4.4M ops/s | **17x** | **10x** |
51
+ | partial fallback object (transform) | 822K ops/s | 1.4M ops/s | 3.5M ops/s | **4.2x** | **2.4x** |
52
+ | partial fallback array 10 (transform) | 85K ops/s | 144K ops/s | 1.1M ops/s | **13x** | **7.7x** |
53
+ | partial fallback array 50 (transform) | 18K ops/s | 30K ops/s | 237K ops/s | **13x** | **7.8x** |
54
+
55
+ Performance gains scale with schema complexity. The `discriminatedUnion` optimization uses an O(1) `switch` dispatch instead of Zod's sequential trial approach. Partial fallback schemas (containing `transform`/`refine`) still show 2-8x speedups by compiling the optimizable portions.
54
56
 
55
57
  ## Runtime Support
56
58
 
@@ -302,7 +304,7 @@ interface CompiledSchema<T> {
302
304
 
303
305
  | Type | Supported Checks |
304
306
  |---|---|
305
- | `string` | `min`, `max`, `length`, `email`, `url`, `uuid`, `regex` |
307
+ | `string` | `min`, `max`, `length`, `email`, `url`, `uuid`, `regex`, `includes`, `startsWith`, `endsWith` |
306
308
  | `number` | `int`, `positive`, `negative`, `nonnegative`, `nonpositive`, `min`, `max`, `multipleOf` |
307
309
  | `bigint` | `min`, `max`, `positive`, `negative`, `nonnegative`, `nonpositive`, `multipleOf` |
308
310
  | `boolean` | — |
@@ -327,6 +329,7 @@ interface CompiledSchema<T> {
327
329
  | `nullable` | wraps any supported type |
328
330
  | `readonly` | validates inner type (TS-only concept) |
329
331
  | `default` | replaces `undefined` with default value, then validates inner |
332
+ | `lazy` (self-recursive) | cycle detection → self-recursive codegen |
330
333
 
331
334
  ### Automatic Fallback to Zod
332
335
 
@@ -336,7 +339,7 @@ These schema types contain JavaScript closures or runtime-dependent logic that c
336
339
  - `refine` / `superRefine` — custom validation with closures
337
340
  - `custom` — arbitrary validation logic
338
341
  - `preprocess` — input preprocessing
339
- - `lazy` — deferred schema resolution (getter function not serializable)
342
+ - `lazy` (non-recursive) — deferred schema resolution where inner type cannot be resolved
340
343
 
341
344
  #### Partial Fallback
342
345
 
@@ -353,7 +356,7 @@ pnpm install
353
356
  # Run tests
354
357
  pnpm test
355
358
 
356
- # Run benchmarks (zod vs zod-aot vs ajv vs typia)
359
+ # Run benchmarks (zod v3 vs zod v4 vs zod-aot vs ajv vs typia)
357
360
  pnpm bench
358
361
 
359
362
  # Lint (Biome)
@@ -373,7 +376,6 @@ zod-aot/
373
376
  ├── packages/zod-aot/ # Main npm package
374
377
  │ ├── src/
375
378
  │ │ ├── index.ts # Public API exports (zod-aot)
376
- │ │ ├── internals.ts # Internal API exports (zod-aot/internals)
377
379
  │ │ ├── discovery.ts # Schema discovery (shared by CLI & unplugin)
378
380
  │ │ ├── loader.ts # Runtime-aware file loader
379
381
  │ │ ├── core/ # Pure logic (no CLI/unplugin deps)
@@ -385,7 +387,7 @@ zod-aot/
385
387
  │ │ ├── cli/ # CLI commands (generate, check, watch)
386
388
  │ │ └── unplugin/ # Build plugin (Vite/webpack/esbuild/Rollup/Rolldown/Bun)
387
389
  │ └── tests/
388
- ├── benchmarks/ # vitest bench (zod vs zod-aot vs ajv vs typia)
390
+ ├── benchmarks/ # vitest bench (zod v3 vs v4 vs zod-aot vs ajv vs typia)
389
391
  └── .github/workflows/ # CI + release automation
390
392
  ```
391
393
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zod-aot",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "Compile Zod schemas into zero-overhead validation functions at build time",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -74,12 +74,6 @@
74
74
  "source": "./src/unplugin/bun.ts",
75
75
  "import": "./dist/unplugin/bun.js",
76
76
  "default": "./dist/unplugin/bun.js"
77
- },
78
- "./internals": {
79
- "types": "./dist/internals.d.ts",
80
- "source": "./src/internals.ts",
81
- "import": "./dist/internals.js",
82
- "default": "./dist/internals.js"
83
77
  }
84
78
  },
85
79
  "dependencies": {
@@ -1,7 +0,0 @@
1
- export type { CodeGenResult } from "#src/core/codegen/index.js";
2
- export { generateValidator } from "#src/core/codegen/index.js";
3
- export type { FallbackEntry } from "#src/core/extract/index.js";
4
- export { extractSchema } from "#src/core/extract/index.js";
5
- export { createFallback } from "#src/core/runtime.js";
6
- export type { CheckIR, DateCheckIR, SchemaIR } from "#src/core/types.js";
7
- //# sourceMappingURL=internals.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"internals.d.ts","sourceRoot":"","sources":["../src/internals.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAC/D,YAAY,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,YAAY,EAAE,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC"}
package/dist/internals.js DELETED
@@ -1,4 +0,0 @@
1
- export { generateValidator } from "#src/core/codegen/index.js";
2
- export { extractSchema } from "#src/core/extract/index.js";
3
- export { createFallback } from "#src/core/runtime.js";
4
- //# sourceMappingURL=internals.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"internals.js","sourceRoot":"","sources":["../src/internals.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAE/D,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC"}