zod-aot 0.0.3 → 0.0.5
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 +102 -54
- package/dist/cli/commands/check.d.ts +6 -0
- package/dist/cli/commands/check.d.ts.map +1 -0
- package/dist/cli/commands/check.js +97 -0
- package/dist/cli/commands/check.js.map +1 -0
- package/dist/cli/commands/generate.d.ts +7 -0
- package/dist/cli/commands/generate.d.ts.map +1 -0
- package/dist/cli/commands/generate.js +99 -0
- package/dist/cli/commands/generate.js.map +1 -0
- package/dist/cli/discovery.d.ts +11 -0
- package/dist/cli/discovery.d.ts.map +1 -0
- package/dist/cli/discovery.js +17 -0
- package/dist/cli/discovery.js.map +1 -0
- package/dist/cli/emitter.d.ts +19 -0
- package/dist/cli/emitter.d.ts.map +1 -0
- package/dist/cli/emitter.js +77 -0
- package/dist/cli/emitter.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +111 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/loader.d.ts +11 -0
- package/dist/cli/loader.d.ts.map +1 -0
- package/dist/cli/loader.js +52 -0
- package/dist/cli/loader.js.map +1 -0
- package/dist/cli/logger.d.ts +8 -0
- package/dist/cli/logger.d.ts.map +1 -0
- package/dist/cli/logger.js +33 -0
- package/dist/cli/logger.js.map +1 -0
- package/dist/codegen/context.d.ts +5 -0
- package/dist/codegen/context.d.ts.map +1 -1
- package/dist/codegen/context.js +11 -0
- package/dist/codegen/context.js.map +1 -1
- package/dist/compile.d.ts +14 -0
- package/dist/compile.d.ts.map +1 -0
- package/dist/compile.js +21 -0
- package/dist/compile.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/unplugin/esbuild.d.ts +3 -0
- package/dist/unplugin/esbuild.d.ts.map +1 -0
- package/dist/unplugin/esbuild.js +3 -0
- package/dist/unplugin/esbuild.js.map +1 -0
- package/dist/unplugin/index.d.ts +4 -0
- package/dist/unplugin/index.d.ts.map +1 -0
- package/dist/unplugin/index.js +19 -0
- package/dist/unplugin/index.js.map +1 -0
- package/dist/unplugin/rollup.d.ts +3 -0
- package/dist/unplugin/rollup.d.ts.map +1 -0
- package/dist/unplugin/rollup.js +3 -0
- package/dist/unplugin/rollup.js.map +1 -0
- package/dist/unplugin/transform.d.ts +26 -0
- package/dist/unplugin/transform.d.ts.map +1 -0
- package/dist/unplugin/transform.js +134 -0
- package/dist/unplugin/transform.js.map +1 -0
- package/dist/unplugin/types.d.ts +7 -0
- package/dist/unplugin/types.d.ts.map +1 -0
- package/dist/unplugin/types.js +2 -0
- package/dist/unplugin/types.js.map +1 -0
- package/dist/unplugin/vite.d.ts +3 -0
- package/dist/unplugin/vite.d.ts.map +1 -0
- package/dist/unplugin/vite.js +3 -0
- package/dist/unplugin/vite.js.map +1 -0
- package/dist/unplugin/webpack.d.ts +3 -0
- package/dist/unplugin/webpack.d.ts.map +1 -0
- package/dist/unplugin/webpack.js +3 -0
- package/dist/unplugin/webpack.js.map +1 -0
- package/package.json +39 -4
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
[](https://www.npmjs.com/package/zod-aot)
|
|
7
7
|
[](LICENSE)
|
|
8
8
|
|
|
9
|
-
No code changes required — keep your existing Zod schemas and get **2-
|
|
9
|
+
No code changes required — keep your existing Zod schemas and get **2-64x faster** validation.
|
|
10
10
|
|
|
11
11
|
## Why
|
|
12
12
|
|
|
@@ -27,18 +27,18 @@ Measured with `vitest bench` on Node.js (Apple M-series):
|
|
|
27
27
|
|
|
28
28
|
| Scenario | Zod v4 | zod-aot | Speedup |
|
|
29
29
|
|---|---|---|---|
|
|
30
|
-
| simple string | 10.
|
|
31
|
-
| string (min/max) | 5.
|
|
32
|
-
| number (int+positive) | 5.
|
|
33
|
-
| enum | 8.
|
|
34
|
-
| tuple [string, int, boolean] | 4.
|
|
35
|
-
| record\<string, number\> (5 keys) |
|
|
36
|
-
| discriminatedUnion (3 variants) | 3.0M ops/s |
|
|
37
|
-
| medium object (7 props, valid) | 1.7M ops/s | 6.
|
|
38
|
-
| medium object (7 props, invalid) |
|
|
39
|
-
| large object (10 nested items) |
|
|
40
|
-
| large object (100 nested items) | 11.
|
|
41
|
-
| event log (combined) |
|
|
30
|
+
| simple string | 10.4M ops/s | 17.9M ops/s | **1.7x** |
|
|
31
|
+
| string (min/max) | 5.3M ops/s | 17.6M ops/s | **3.3x** |
|
|
32
|
+
| number (int+positive) | 5.2M ops/s | 16.4M ops/s | **3.1x** |
|
|
33
|
+
| enum | 8.7M ops/s | 15.5M ops/s | **1.8x** |
|
|
34
|
+
| tuple [string, int, boolean] | 4.3M ops/s | 17.1M ops/s | **3.9x** |
|
|
35
|
+
| record\<string, number\> (5 keys) | 1.9M ops/s | 8.3M ops/s | **4.3x** |
|
|
36
|
+
| discriminatedUnion (3 variants) | 3.0M ops/s | 15.7M ops/s | **5.3x** |
|
|
37
|
+
| medium object (7 props, valid) | 1.7M ops/s | 6.6M ops/s | **4.0x** |
|
|
38
|
+
| medium object (7 props, invalid) | 65K ops/s | 1.5M ops/s | **23x** |
|
|
39
|
+
| large object (10 nested items) | 111K ops/s | 4.8M ops/s | **43x** |
|
|
40
|
+
| large object (100 nested items) | 11.9K ops/s | 713K ops/s | **60x** |
|
|
41
|
+
| event log (combined) | 431K ops/s | 5.0M ops/s | **12x** |
|
|
42
42
|
|
|
43
43
|
Performance gains scale with schema complexity. The `discriminatedUnion` optimization uses an O(1) `switch` dispatch instead of Zod's sequential trial approach.
|
|
44
44
|
|
|
@@ -60,11 +60,13 @@ npm install zod@^4
|
|
|
60
60
|
|
|
61
61
|
## Quick Start
|
|
62
62
|
|
|
63
|
+
### 1. Define schemas with `compile()`
|
|
64
|
+
|
|
63
65
|
```typescript
|
|
66
|
+
// src/schemas.ts
|
|
64
67
|
import { z } from "zod";
|
|
65
|
-
import {
|
|
68
|
+
import { compile } from "zod-aot";
|
|
66
69
|
|
|
67
|
-
// 1. Define your Zod schema as usual
|
|
68
70
|
const UserSchema = z.object({
|
|
69
71
|
name: z.string().min(3),
|
|
70
72
|
age: z.number().int().positive(),
|
|
@@ -72,70 +74,115 @@ const UserSchema = z.object({
|
|
|
72
74
|
role: z.enum(["admin", "user"]),
|
|
73
75
|
});
|
|
74
76
|
|
|
75
|
-
//
|
|
76
|
-
const
|
|
77
|
+
// compile() falls back to Zod in dev, uses generated functions after build
|
|
78
|
+
export const validateUser = compile(UserSchema);
|
|
79
|
+
```
|
|
77
80
|
|
|
78
|
-
|
|
79
|
-
const { code, functionName } = generateValidator(ir, "validateUser");
|
|
81
|
+
### 2. Use the compiled validator
|
|
80
82
|
|
|
81
|
-
|
|
82
|
-
//
|
|
83
|
-
|
|
84
|
-
|
|
83
|
+
```typescript
|
|
84
|
+
// Same interface as Zod — works in both dev and production
|
|
85
|
+
const user = validateUser.parse(data); // throws on failure
|
|
86
|
+
const result = validateUser.safeParse(data); // { success, data/error }
|
|
87
|
+
const isUser = validateUser.is(data); // type guard (boolean)
|
|
85
88
|
```
|
|
86
89
|
|
|
87
|
-
###
|
|
90
|
+
### 3. Generate optimized code
|
|
88
91
|
|
|
89
|
-
|
|
92
|
+
Choose one of these approaches:
|
|
93
|
+
|
|
94
|
+
**Option A: Build plugin (Vite / webpack / esbuild / Rollup)**
|
|
90
95
|
|
|
91
96
|
```typescript
|
|
92
|
-
//
|
|
93
|
-
import
|
|
94
|
-
import { extractSchema, generateValidator } from "zod-aot";
|
|
97
|
+
// vite.config.ts
|
|
98
|
+
import zodAot from "zod-aot/vite";
|
|
95
99
|
|
|
96
|
-
|
|
97
|
-
|
|
100
|
+
export default defineConfig({
|
|
101
|
+
plugins: [zodAot()],
|
|
102
|
+
});
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Also available: `zod-aot/webpack`, `zod-aot/esbuild`, `zod-aot/rollup`
|
|
106
|
+
|
|
107
|
+
**Option B: CLI**
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
# Generate optimized validators
|
|
111
|
+
npx zod-aot generate src/schemas.ts -o src/schemas.compiled.ts
|
|
98
112
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
113
|
+
# Generate from a directory
|
|
114
|
+
npx zod-aot generate src/ -o src/compiled/
|
|
115
|
+
|
|
116
|
+
# Check if schemas are compilable (without generating)
|
|
117
|
+
npx zod-aot check src/schemas.ts
|
|
104
118
|
```
|
|
105
119
|
|
|
106
|
-
|
|
120
|
+
## Build Plugin (unplugin)
|
|
121
|
+
|
|
122
|
+
The build plugin automatically replaces `compile()` calls with optimized inline validators during the build step. No code changes needed — your source files stay the same.
|
|
107
123
|
|
|
108
124
|
```typescript
|
|
109
|
-
|
|
125
|
+
// vite.config.ts
|
|
126
|
+
import zodAot from "zod-aot/vite";
|
|
127
|
+
export default defineConfig({ plugins: [zodAot()] });
|
|
110
128
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
129
|
+
// webpack.config.js
|
|
130
|
+
const zodAot = require("zod-aot/webpack");
|
|
131
|
+
module.exports = { plugins: [zodAot()] };
|
|
114
132
|
```
|
|
115
133
|
|
|
116
|
-
###
|
|
134
|
+
### Options
|
|
117
135
|
|
|
118
|
-
|
|
136
|
+
```typescript
|
|
137
|
+
zodAot({
|
|
138
|
+
include: ["src/schemas"], // only process files matching these substrings
|
|
139
|
+
exclude: ["test", "mock"], // skip files matching these substrings
|
|
140
|
+
})
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
The plugin:
|
|
144
|
+
- Runs at build time (`enforce: "pre"`)
|
|
145
|
+
- Replaces `compile(Schema)` with optimized IIFE inline validators
|
|
146
|
+
- Adds `/* @__PURE__ */` annotations for tree-shaking
|
|
147
|
+
- Supports HMR in development
|
|
148
|
+
|
|
149
|
+
## Low-Level API
|
|
150
|
+
|
|
151
|
+
For custom build scripts or advanced use cases, you can use the extractor and code generator directly:
|
|
119
152
|
|
|
120
153
|
```typescript
|
|
121
154
|
import { z } from "zod";
|
|
122
|
-
import {
|
|
155
|
+
import { extractSchema, generateValidator } from "zod-aot";
|
|
123
156
|
|
|
124
157
|
const UserSchema = z.object({
|
|
125
158
|
name: z.string().min(3),
|
|
126
159
|
age: z.number().int().positive(),
|
|
127
160
|
});
|
|
128
161
|
|
|
129
|
-
//
|
|
130
|
-
const
|
|
162
|
+
// Extract schema into intermediate representation (IR)
|
|
163
|
+
const ir = extractSchema(UserSchema);
|
|
164
|
+
|
|
165
|
+
// Generate optimized JavaScript validation code
|
|
166
|
+
const { code, functionName } = generateValidator(ir, "validateUser");
|
|
167
|
+
|
|
168
|
+
// Execute the generated code
|
|
169
|
+
const safeParse = new Function(`${code}\nreturn ${functionName};`)();
|
|
170
|
+
const result = safeParse({ name: "Alice", age: 30 });
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### `createFallback(zodSchema)`
|
|
174
|
+
|
|
175
|
+
Wraps a Zod schema to provide the `CompiledSchema` interface, delegating to Zod at runtime. Useful for development or unsupported schema types:
|
|
131
176
|
|
|
132
|
-
|
|
177
|
+
```typescript
|
|
178
|
+
import { createFallback } from "zod-aot";
|
|
179
|
+
|
|
180
|
+
const validator = createFallback(UserSchema);
|
|
181
|
+
validator.parse(data); // throws on failure
|
|
133
182
|
validator.safeParse(data); // { success, data/error }
|
|
134
183
|
validator.is(data); // type guard (boolean)
|
|
135
184
|
```
|
|
136
185
|
|
|
137
|
-
This lets you write code against the `CompiledSchema` interface and swap in the generated code at build time without changing any call sites.
|
|
138
|
-
|
|
139
186
|
## How It Works
|
|
140
187
|
|
|
141
188
|
```
|
|
@@ -376,9 +423,9 @@ These schema types contain JavaScript closures that cannot be compiled to static
|
|
|
376
423
|
|
|
377
424
|
- [x] Tier 2 type support (9 types: any, unknown, readonly, date, tuple, record, default, intersection, discriminatedUnion)
|
|
378
425
|
- [x] `discriminatedUnion` → O(1) switch statement optimization
|
|
379
|
-
- [
|
|
426
|
+
- [x] CLI (`npx zod-aot generate` / `npx zod-aot check`)
|
|
380
427
|
- [ ] Partial fallback (objects with some transform properties)
|
|
381
|
-
- [
|
|
428
|
+
- [x] unplugin integration (Vite / webpack / esbuild / Rollup)
|
|
382
429
|
- [ ] Watch mode
|
|
383
430
|
|
|
384
431
|
### Phase 3: Ecosystem
|
|
@@ -424,10 +471,11 @@ zod-aot/
|
|
|
424
471
|
│ ├── extractor/ # Extractor unit tests
|
|
425
472
|
│ ├── codegen/ # CodeGen unit tests
|
|
426
473
|
│ └── runtime.test.ts # Fallback tests
|
|
427
|
-
├── benchmarks/ # vitest bench
|
|
428
|
-
├──
|
|
429
|
-
│ ├──
|
|
430
|
-
│ └──
|
|
474
|
+
├── benchmarks/ # vitest bench + standalone scripts
|
|
475
|
+
│ ├── standalone/
|
|
476
|
+
│ │ ├── zod-only.ts # Standalone Zod benchmark
|
|
477
|
+
│ │ └── zod-aot.ts # Standalone zod-aot benchmark
|
|
478
|
+
│ └── ...
|
|
431
479
|
└── .github/workflows/ # CI + release automation
|
|
432
480
|
```
|
|
433
481
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/check.ts"],"names":[],"mappings":"AASA,UAAU,YAAY;IACpB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AA2CD,wBAAsB,QAAQ,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAwDnE"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import process from "node:process";
|
|
4
|
+
import { extractSchema } from "../../extractor/index.js";
|
|
5
|
+
import { discoverSchemas } from "../discovery.js";
|
|
6
|
+
import { logger } from "../logger.js";
|
|
7
|
+
function hasFallback(ir) {
|
|
8
|
+
if (ir.type === "fallback") {
|
|
9
|
+
return ir.reason;
|
|
10
|
+
}
|
|
11
|
+
if (ir.type === "object") {
|
|
12
|
+
for (const [key, prop] of Object.entries(ir.properties)) {
|
|
13
|
+
const reason = hasFallback(prop);
|
|
14
|
+
if (reason)
|
|
15
|
+
return `${reason} at .${key}`;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
if (ir.type === "array") {
|
|
19
|
+
return hasFallback(ir.element);
|
|
20
|
+
}
|
|
21
|
+
if (ir.type === "optional" || ir.type === "nullable" || ir.type === "readonly") {
|
|
22
|
+
return hasFallback(ir.inner);
|
|
23
|
+
}
|
|
24
|
+
if (ir.type === "default") {
|
|
25
|
+
return hasFallback(ir.inner);
|
|
26
|
+
}
|
|
27
|
+
if (ir.type === "union" || ir.type === "discriminatedUnion") {
|
|
28
|
+
for (const opt of ir.options) {
|
|
29
|
+
const reason = hasFallback(opt);
|
|
30
|
+
if (reason)
|
|
31
|
+
return reason;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
if (ir.type === "tuple") {
|
|
35
|
+
for (const item of ir.items) {
|
|
36
|
+
const reason = hasFallback(item);
|
|
37
|
+
if (reason)
|
|
38
|
+
return reason;
|
|
39
|
+
}
|
|
40
|
+
if (ir.rest)
|
|
41
|
+
return hasFallback(ir.rest);
|
|
42
|
+
}
|
|
43
|
+
if (ir.type === "record") {
|
|
44
|
+
return hasFallback(ir.keyType) ?? hasFallback(ir.valueType);
|
|
45
|
+
}
|
|
46
|
+
if (ir.type === "intersection") {
|
|
47
|
+
return hasFallback(ir.left) ?? hasFallback(ir.right);
|
|
48
|
+
}
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
export async function runCheck(options) {
|
|
52
|
+
const files = [];
|
|
53
|
+
for (const input of options.inputs) {
|
|
54
|
+
const absPath = path.resolve(input);
|
|
55
|
+
const stat = await fs.promises.stat(absPath).catch(() => null);
|
|
56
|
+
if (!stat) {
|
|
57
|
+
logger.error(`File not found: ${input}`);
|
|
58
|
+
process.exit(1);
|
|
59
|
+
}
|
|
60
|
+
if (stat.isDirectory()) {
|
|
61
|
+
logger.error("check command expects file paths, not directories.");
|
|
62
|
+
process.exit(1);
|
|
63
|
+
}
|
|
64
|
+
files.push(absPath);
|
|
65
|
+
}
|
|
66
|
+
let hasCompilable = false;
|
|
67
|
+
for (const filePath of files) {
|
|
68
|
+
const relPath = path.relative(process.cwd(), filePath);
|
|
69
|
+
let schemas;
|
|
70
|
+
try {
|
|
71
|
+
schemas = await discoverSchemas(filePath);
|
|
72
|
+
}
|
|
73
|
+
catch (err) {
|
|
74
|
+
logger.error(`Failed to load ${relPath}: ${err instanceof Error ? err.message : String(err)}`);
|
|
75
|
+
process.exit(1);
|
|
76
|
+
}
|
|
77
|
+
if (schemas.length === 0) {
|
|
78
|
+
logger.warn(`${relPath}: no compile() calls found`);
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
for (const s of schemas) {
|
|
82
|
+
const ir = extractSchema(s.schema);
|
|
83
|
+
const fallbackReason = hasFallback(ir);
|
|
84
|
+
if (fallbackReason) {
|
|
85
|
+
logger.warn(`${s.exportName} — partial (fallback: ${fallbackReason})`);
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
logger.success(`${s.exportName} — compilable`);
|
|
89
|
+
hasCompilable = true;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
if (!hasCompilable) {
|
|
94
|
+
process.exit(1);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=check.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check.js","sourceRoot":"","sources":["../../../src/cli/commands/check.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/generate.ts"],"names":[],"mappings":"AAUA,UAAU,eAAe;IACvB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5B;AA0DD,wBAAsB,WAAW,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAuDzE"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import process from "node:process";
|
|
4
|
+
import { generateValidator } from "../../codegen/index.js";
|
|
5
|
+
import { extractSchema } from "../../extractor/index.js";
|
|
6
|
+
import { discoverSchemas } from "../discovery.js";
|
|
7
|
+
import { generateCompiledFileContent, resolveOutputPath, writeCompiledFile } from "../emitter.js";
|
|
8
|
+
import { logger } from "../logger.js";
|
|
9
|
+
/**
|
|
10
|
+
* Resolve input paths to a list of source files.
|
|
11
|
+
* If a path is a directory, find all .ts files (excluding .compiled.ts, .test.ts, node_modules).
|
|
12
|
+
*/
|
|
13
|
+
async function resolveInputFiles(inputs) {
|
|
14
|
+
const files = [];
|
|
15
|
+
for (const input of inputs) {
|
|
16
|
+
const absPath = path.resolve(input);
|
|
17
|
+
const stat = await fs.promises.stat(absPath).catch(() => null);
|
|
18
|
+
if (!stat) {
|
|
19
|
+
logger.error(`File not found: ${input}`);
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
if (stat.isDirectory()) {
|
|
23
|
+
const found = await findSchemaFiles(absPath);
|
|
24
|
+
files.push(...found);
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
files.push(absPath);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return files;
|
|
31
|
+
}
|
|
32
|
+
async function findSchemaFiles(dir) {
|
|
33
|
+
const results = [];
|
|
34
|
+
const entries = await fs.promises.readdir(dir, { withFileTypes: true });
|
|
35
|
+
for (const entry of entries) {
|
|
36
|
+
const fullPath = path.join(dir, entry.name);
|
|
37
|
+
if (entry.isDirectory()) {
|
|
38
|
+
if (entry.name === "node_modules" || entry.name === "dist" || entry.name.startsWith(".")) {
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
const nested = await findSchemaFiles(fullPath);
|
|
42
|
+
results.push(...nested);
|
|
43
|
+
}
|
|
44
|
+
else if (entry.isFile() &&
|
|
45
|
+
/\.(?:ts|mts|js|mjs)$/.test(entry.name) &&
|
|
46
|
+
!entry.name.endsWith(".compiled.ts") &&
|
|
47
|
+
!entry.name.endsWith(".compiled.js") &&
|
|
48
|
+
!entry.name.endsWith(".test.ts") &&
|
|
49
|
+
!entry.name.endsWith(".test.js") &&
|
|
50
|
+
!entry.name.endsWith(".d.ts")) {
|
|
51
|
+
results.push(fullPath);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return results;
|
|
55
|
+
}
|
|
56
|
+
export async function runGenerate(options) {
|
|
57
|
+
const files = await resolveInputFiles(options.inputs);
|
|
58
|
+
if (files.length === 0) {
|
|
59
|
+
logger.warn("No source files found.");
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
let totalSchemas = 0;
|
|
63
|
+
let totalFiles = 0;
|
|
64
|
+
for (const filePath of files) {
|
|
65
|
+
const relPath = path.relative(process.cwd(), filePath);
|
|
66
|
+
let schemas;
|
|
67
|
+
try {
|
|
68
|
+
schemas = await discoverSchemas(filePath);
|
|
69
|
+
}
|
|
70
|
+
catch (err) {
|
|
71
|
+
logger.error(`Failed to load ${relPath}: ${err instanceof Error ? err.message : String(err)}`);
|
|
72
|
+
process.exit(1);
|
|
73
|
+
}
|
|
74
|
+
if (schemas.length === 0) {
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
const codegenResults = schemas.map((s) => {
|
|
78
|
+
const ir = extractSchema(s.schema);
|
|
79
|
+
const result = generateValidator(ir, s.exportName);
|
|
80
|
+
return { exportName: s.exportName, codegenResult: result };
|
|
81
|
+
});
|
|
82
|
+
const outputPath = resolveOutputPath(filePath, options.output);
|
|
83
|
+
const outputRelPath = path.relative(process.cwd(), outputPath);
|
|
84
|
+
const sourceRelPath = path.relative(path.dirname(outputPath), filePath);
|
|
85
|
+
const content = generateCompiledFileContent(codegenResults, sourceRelPath);
|
|
86
|
+
await writeCompiledFile(outputPath, content);
|
|
87
|
+
const schemaNames = schemas.map((s) => s.exportName).join(", ");
|
|
88
|
+
logger.success(`${relPath} -> ${outputRelPath} (${schemaNames})`);
|
|
89
|
+
totalSchemas += schemas.length;
|
|
90
|
+
totalFiles++;
|
|
91
|
+
}
|
|
92
|
+
if (totalFiles === 0) {
|
|
93
|
+
logger.warn("No compile() calls found in any source file.");
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
logger.info(`Generated ${totalSchemas} schema${totalSchemas > 1 ? "s" : ""} from ${totalFiles} file${totalFiles > 1 ? "s" : ""}.`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=generate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate.js","sourceRoot":"","sources":["../../../src/cli/commands/generate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { LoadOptions } from "./loader.js";
|
|
2
|
+
export interface DiscoveredSchema {
|
|
3
|
+
exportName: string;
|
|
4
|
+
schema: unknown;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Discover all compile() calls in a source file by importing it and
|
|
8
|
+
* scanning exports for CompiledSchema objects.
|
|
9
|
+
*/
|
|
10
|
+
export declare function discoverSchemas(filePath: string, options?: LoadOptions): Promise<DiscoveredSchema[]>;
|
|
11
|
+
//# sourceMappingURL=discovery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../../src/cli/discovery.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAG/C,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,OAAO,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAW7B"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { isCompiledSchema } from "../compile.js";
|
|
2
|
+
import { loadSourceFile } from "./loader.js";
|
|
3
|
+
/**
|
|
4
|
+
* Discover all compile() calls in a source file by importing it and
|
|
5
|
+
* scanning exports for CompiledSchema objects.
|
|
6
|
+
*/
|
|
7
|
+
export async function discoverSchemas(filePath, options) {
|
|
8
|
+
const mod = await loadSourceFile(filePath, options);
|
|
9
|
+
const schemas = [];
|
|
10
|
+
for (const [exportName, value] of Object.entries(mod)) {
|
|
11
|
+
if (isCompiledSchema(value)) {
|
|
12
|
+
schemas.push({ exportName, schema: value.schema });
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
return schemas;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=discovery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discovery.js","sourceRoot":"","sources":["../../src/cli/discovery.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEjD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAO7C;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,QAAgB,EAChB,OAAqB;IAErB,MAAM,GAAG,GAAG,MAAM,cAAc,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACpD,MAAM,OAAO,GAAuB,EAAE,CAAC;IAEvC,KAAK,MAAM,CAAC,UAAU,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACtD,IAAI,gBAAgB,CAAC,KAAK,CAAC,EAAE,CAAC;YAC5B,OAAO,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;QACrD,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { CodeGenResult } from "../codegen/context.js";
|
|
2
|
+
interface EmitSchema {
|
|
3
|
+
exportName: string;
|
|
4
|
+
codegenResult: CodeGenResult;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Generate the content of a .compiled.ts file from multiple schemas.
|
|
8
|
+
*/
|
|
9
|
+
export declare function generateCompiledFileContent(schemas: EmitSchema[], sourceRelPath: string): string;
|
|
10
|
+
/**
|
|
11
|
+
* Resolve the output file path for a given input file.
|
|
12
|
+
*/
|
|
13
|
+
export declare function resolveOutputPath(inputPath: string, outputFlag: string | undefined): string;
|
|
14
|
+
/**
|
|
15
|
+
* Write the compiled file content to disk.
|
|
16
|
+
*/
|
|
17
|
+
export declare function writeCompiledFile(outputPath: string, content: string): Promise<void>;
|
|
18
|
+
export {};
|
|
19
|
+
//# sourceMappingURL=emitter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emitter.d.ts","sourceRoot":"","sources":["../../src/cli/emitter.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAG3D,UAAU,UAAU;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,aAAa,CAAC;CAC9B;AAED;;GAEG;AACH,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,UAAU,EAAE,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,CAkDhG;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAc3F;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAI1F"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { extractFunctionName } from "../codegen/context.js";
|
|
4
|
+
/**
|
|
5
|
+
* Generate the content of a .compiled.ts file from multiple schemas.
|
|
6
|
+
*/
|
|
7
|
+
export function generateCompiledFileContent(schemas, sourceRelPath) {
|
|
8
|
+
const lines = [];
|
|
9
|
+
// Header
|
|
10
|
+
lines.push("// AUTO-GENERATED by zod-aot — DO NOT EDIT");
|
|
11
|
+
lines.push(`// Source: ${sourceRelPath}`);
|
|
12
|
+
lines.push("");
|
|
13
|
+
// Merge preambles — each schema's `code` field contains `/* zod-aot */` + preamble declarations
|
|
14
|
+
const preambleSet = new Set();
|
|
15
|
+
for (const schema of schemas) {
|
|
16
|
+
for (const line of schema.codegenResult.code.split("\n")) {
|
|
17
|
+
if (line.trim() !== "" && line.trim() !== "/* zod-aot */") {
|
|
18
|
+
preambleSet.add(line);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
if (preambleSet.size > 0) {
|
|
23
|
+
lines.push("/* zod-aot:preamble */");
|
|
24
|
+
for (const line of preambleSet) {
|
|
25
|
+
lines.push(line);
|
|
26
|
+
}
|
|
27
|
+
lines.push("");
|
|
28
|
+
}
|
|
29
|
+
// Function definitions
|
|
30
|
+
for (const schema of schemas) {
|
|
31
|
+
lines.push(schema.codegenResult.functionName);
|
|
32
|
+
lines.push("");
|
|
33
|
+
}
|
|
34
|
+
// Export wrappers
|
|
35
|
+
for (const schema of schemas) {
|
|
36
|
+
const fnName = extractFunctionName(schema.codegenResult.functionName);
|
|
37
|
+
lines.push(`export const ${schema.exportName} = {`);
|
|
38
|
+
lines.push(" parse(input: unknown) {");
|
|
39
|
+
lines.push(` const r = ${fnName}(input);`);
|
|
40
|
+
lines.push(" if (r.success) return r.data;");
|
|
41
|
+
lines.push(' throw Object.assign(new Error("Validation failed"), r.error);');
|
|
42
|
+
lines.push(" },");
|
|
43
|
+
lines.push(` safeParse: ${fnName},`);
|
|
44
|
+
lines.push(" is(input: unknown): boolean {");
|
|
45
|
+
lines.push(` return ${fnName}(input).success;`);
|
|
46
|
+
lines.push(" },");
|
|
47
|
+
lines.push("};");
|
|
48
|
+
lines.push("");
|
|
49
|
+
}
|
|
50
|
+
return lines.join("\n");
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Resolve the output file path for a given input file.
|
|
54
|
+
*/
|
|
55
|
+
export function resolveOutputPath(inputPath, outputFlag) {
|
|
56
|
+
if (outputFlag) {
|
|
57
|
+
// If output flag ends with / or is a directory, put the compiled file inside it
|
|
58
|
+
if (outputFlag.endsWith("/") || outputFlag.endsWith(path.sep)) {
|
|
59
|
+
const baseName = path.basename(inputPath, path.extname(inputPath));
|
|
60
|
+
return path.join(outputFlag, `${baseName}.compiled.ts`);
|
|
61
|
+
}
|
|
62
|
+
return outputFlag;
|
|
63
|
+
}
|
|
64
|
+
// Default: replace .ts with .compiled.ts
|
|
65
|
+
const dir = path.dirname(inputPath);
|
|
66
|
+
const baseName = path.basename(inputPath, path.extname(inputPath));
|
|
67
|
+
return path.join(dir, `${baseName}.compiled.ts`);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Write the compiled file content to disk.
|
|
71
|
+
*/
|
|
72
|
+
export async function writeCompiledFile(outputPath, content) {
|
|
73
|
+
const dir = path.dirname(outputPath);
|
|
74
|
+
await fs.promises.mkdir(dir, { recursive: true });
|
|
75
|
+
await fs.promises.writeFile(outputPath, content, "utf-8");
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=emitter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emitter.js","sourceRoot":"","sources":["../../src/cli/emitter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":""}
|