zod-compiler 1.28.0 → 2.0.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 +176 -148
- package/dist/core/codegen/build-path.d.ts +12 -1
- package/dist/core/codegen/build-path.d.ts.map +1 -1
- package/dist/core/codegen/build-path.js +102 -21
- package/dist/core/codegen/build-path.js.map +1 -1
- package/dist/core/codegen/context.d.ts +31 -16
- package/dist/core/codegen/context.d.ts.map +1 -1
- package/dist/core/codegen/context.js +43 -18
- package/dist/core/codegen/context.js.map +1 -1
- package/dist/core/codegen/emit-issue.d.ts +17 -20
- package/dist/core/codegen/emit-issue.d.ts.map +1 -1
- package/dist/core/codegen/emit-issue.js +13 -13
- package/dist/core/codegen/emit-issue.js.map +1 -1
- package/dist/core/codegen/index.d.ts.map +1 -1
- package/dist/core/codegen/index.js +9 -7
- package/dist/core/codegen/index.js.map +1 -1
- package/dist/core/codegen/issue-decls.d.ts +83 -7
- package/dist/core/codegen/issue-decls.d.ts.map +1 -1
- package/dist/core/codegen/issue-decls.js +93 -10
- package/dist/core/codegen/issue-decls.js.map +1 -1
- package/dist/core/codegen/schemas/array.js +1 -1
- package/dist/core/codegen/schemas/array.js.map +1 -1
- package/dist/core/codegen/schemas/bigint.d.ts.map +1 -1
- package/dist/core/codegen/schemas/bigint.js +15 -4
- package/dist/core/codegen/schemas/bigint.js.map +1 -1
- package/dist/core/codegen/schemas/catch.d.ts.map +1 -1
- package/dist/core/codegen/schemas/catch.js +3 -2
- package/dist/core/codegen/schemas/catch.js.map +1 -1
- package/dist/core/codegen/schemas/discriminated-union.d.ts +6 -2
- package/dist/core/codegen/schemas/discriminated-union.d.ts.map +1 -1
- package/dist/core/codegen/schemas/discriminated-union.js +16 -56
- package/dist/core/codegen/schemas/discriminated-union.js.map +1 -1
- package/dist/core/codegen/schemas/effect.d.ts.map +1 -1
- package/dist/core/codegen/schemas/effect.js +4 -2
- package/dist/core/codegen/schemas/effect.js.map +1 -1
- package/dist/core/codegen/schemas/file.js +2 -8
- package/dist/core/codegen/schemas/file.js.map +1 -1
- package/dist/core/codegen/schemas/number.js +4 -3
- package/dist/core/codegen/schemas/number.js.map +1 -1
- package/dist/core/codegen/schemas/object.d.ts +11 -1
- package/dist/core/codegen/schemas/object.d.ts.map +1 -1
- package/dist/core/codegen/schemas/object.js +58 -14
- package/dist/core/codegen/schemas/object.js.map +1 -1
- package/dist/core/codegen/schemas/readonly.d.ts.map +1 -1
- package/dist/core/codegen/schemas/readonly.js.map +1 -1
- package/dist/core/codegen/schemas/record.d.ts.map +1 -1
- package/dist/core/codegen/schemas/record.js +8 -3
- package/dist/core/codegen/schemas/record.js.map +1 -1
- package/dist/core/codegen/schemas/sizeable.d.ts +49 -3
- package/dist/core/codegen/schemas/sizeable.d.ts.map +1 -1
- package/dist/core/codegen/schemas/sizeable.js +101 -8
- package/dist/core/codegen/schemas/sizeable.js.map +1 -1
- package/dist/core/codegen/schemas/string-bool.d.ts +12 -1
- package/dist/core/codegen/schemas/string-bool.d.ts.map +1 -1
- package/dist/core/codegen/schemas/string-bool.js +19 -4
- package/dist/core/codegen/schemas/string-bool.js.map +1 -1
- package/dist/core/codegen/schemas/string.d.ts.map +1 -1
- package/dist/core/codegen/schemas/string.js +60 -26
- package/dist/core/codegen/schemas/string.js.map +1 -1
- package/dist/core/codegen/schemas/tuple.d.ts +14 -11
- package/dist/core/codegen/schemas/tuple.d.ts.map +1 -1
- package/dist/core/codegen/schemas/tuple.js +99 -49
- package/dist/core/codegen/schemas/tuple.js.map +1 -1
- package/dist/core/codegen/well-known-regex.d.ts +26 -1
- package/dist/core/codegen/well-known-regex.d.ts.map +1 -1
- package/dist/core/codegen/well-known-regex.js +31 -4
- package/dist/core/codegen/well-known-regex.js.map +1 -1
- package/dist/core/extract/checks.d.ts.map +1 -1
- package/dist/core/extract/checks.js +1 -0
- package/dist/core/extract/checks.js.map +1 -1
- package/dist/core/extract/extractors/intersection.js +21 -6
- package/dist/core/extract/extractors/intersection.js.map +1 -1
- package/dist/core/extract/extractors/object.d.ts.map +1 -1
- package/dist/core/extract/extractors/object.js +25 -9
- package/dist/core/extract/extractors/object.js.map +1 -1
- package/dist/core/extract/extractors/optional.d.ts.map +1 -1
- package/dist/core/extract/extractors/optional.js +1 -28
- package/dist/core/extract/extractors/optional.js.map +1 -1
- package/dist/core/extract/extractors/record.js +9 -3
- package/dist/core/extract/extractors/record.js.map +1 -1
- package/dist/core/extract/extractors/tuple.d.ts.map +1 -1
- package/dist/core/extract/extractors/tuple.js +16 -20
- package/dist/core/extract/extractors/tuple.js.map +1 -1
- package/dist/core/extract/types.d.ts +16 -8
- package/dist/core/extract/types.d.ts.map +1 -1
- package/dist/core/iife.d.ts +2 -1
- package/dist/core/iife.d.ts.map +1 -1
- package/dist/core/iife.js +2 -1
- package/dist/core/iife.js.map +1 -1
- package/dist/core/types.d.ts +70 -21
- package/dist/core/types.d.ts.map +1 -1
- package/dist/jit.d.ts.map +1 -1
- package/dist/jit.js +47 -12
- package/dist/jit.js.map +1 -1
- package/dist/runtime.d.ts +4 -1
- package/dist/runtime.js +14 -11
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -2,19 +2,43 @@
|
|
|
2
2
|
|
|
3
3
|
**Compile Zod schemas into zero-overhead validation functions at build time.**
|
|
4
4
|
|
|
5
|
-
Keep your existing Zod schemas. Get **
|
|
5
|
+
Keep your existing Zod schemas. Get **up to 42x faster** validation, and up to **47x** on rejected
|
|
6
6
|
input. No code changes required.
|
|
7
7
|
|
|
8
|
+
Requires **Zod ≥ 4.5**. Compiled output reproduces 4.5's semantics exactly, down to code-point string
|
|
9
|
+
lengths, symbol-keyed shapes and tuple issue order, so it does not match earlier 4.x releases. Stay on
|
|
10
|
+
zod-compiler 1.x for Zod 4.0–4.4.
|
|
11
|
+
|
|
8
12
|
- [What Gets Compiled](#what-gets-compiled)
|
|
9
13
|
- [Schema Hoisting](#schema-hoisting)
|
|
14
|
+
- [z.compile vs zod-compiler](#zcompile-vs-zod-compiler)
|
|
10
15
|
- [Benchmark](#benchmark)
|
|
11
16
|
|
|
12
17
|
> [!NOTE]
|
|
13
18
|
> zod-compiler has been tested to work in large projects with tens of thousands of Zod schemas.
|
|
14
19
|
|
|
20
|
+
## z.compile vs zod-compiler
|
|
21
|
+
|
|
22
|
+
Both generate optimized JavaScript. Zod's [`z.compile()`](https://zod.dev/compile) does it at runtime
|
|
23
|
+
with `new Function()` (JIT); zod-compiler's plugins and CLI do it at build time (AOT), so production
|
|
24
|
+
loads pre-generated validators.
|
|
25
|
+
|
|
26
|
+
| | zod-compiler (build plugins / CLI) | Zod `z.compile()` |
|
|
27
|
+
| -------------------------------------- | -------------------------------------------- | --------------------------------------------- |
|
|
28
|
+
| Compilation | Build time (true AOT) | Runtime (`z.compile()` or the first parse) |
|
|
29
|
+
| Reported validation speedup | Up to 42x; up to 47x on rejected input | ~9x in Zod's headline example |
|
|
30
|
+
| Uses `new Function()` at runtime\* | No | Yes |
|
|
31
|
+
| Cold start | Fast; the validator is already generated | Pays for code generation at startup/first use |
|
|
32
|
+
| Strict CSP without `'unsafe-eval'` | Supported | Compilation is unavailable |
|
|
33
|
+
| Compiler shipped in the runtime bundle | No; only validators and runtime helpers ship | Yes; about 7 KB gzipped according to Zod |
|
|
34
|
+
|
|
35
|
+
\*zod-compiler's optional [`jit()`](#4-runtime-compilation-no-build-step) and
|
|
36
|
+
[Node.js register hook](#5-nodejs-register-hook) use `new Function()` and have the same runtime
|
|
37
|
+
code-generation and CSP trade-offs as Zod's `z.compile()`.
|
|
38
|
+
|
|
15
39
|
## Usage
|
|
16
40
|
|
|
17
|
-
Five ways to use zod-compiler
|
|
41
|
+
Five ways to use zod-compiler. Pick one:
|
|
18
42
|
|
|
19
43
|
### 1. Automatic Mode (Default)
|
|
20
44
|
|
|
@@ -46,7 +70,7 @@ export const CreateUserSchema = z.object({
|
|
|
46
70
|
Use them as usual. Methods are installed on the original schema object, so `.shape`, `._zod`, Standard
|
|
47
71
|
Schema, `instanceof` and `z.toJSONSchema()` keep working.
|
|
48
72
|
|
|
49
|
-
Compiled schemas also expose **`.is(input): input is T
|
|
73
|
+
Compiled schemas also expose **`.is(input): input is T`**, a zero-allocation drop-in for
|
|
50
74
|
`safeParse(x).success`.
|
|
51
75
|
|
|
52
76
|
### 2. compile() (Explicit)
|
|
@@ -70,7 +94,8 @@ validateUser.parse(data);
|
|
|
70
94
|
validateUser.safeParse(data);
|
|
71
95
|
```
|
|
72
96
|
|
|
73
|
-
`compile()` and auto mode coexist. Pair with `schemas: "explicit"` to make `compile()` the _only_ path
|
|
97
|
+
`compile()` and auto mode coexist. Pair with `schemas: "explicit"` to make `compile()` the _only_ path:
|
|
98
|
+
no automatic detection, no build-time execution of plain schema files.
|
|
74
99
|
|
|
75
100
|
### 3. CLI (No Bundler)
|
|
76
101
|
|
|
@@ -95,7 +120,7 @@ npx zod-compiler generate src/ --emit compact
|
|
|
95
120
|
|
|
96
121
|
### 4. Runtime Compilation (No Build Step)
|
|
97
122
|
|
|
98
|
-
`jit()` runs the same pipeline in-process
|
|
123
|
+
`jit()` runs the same pipeline in-process for `tsx`, `ts-node`, Jest, and anywhere else no plugin fires:
|
|
99
124
|
|
|
100
125
|
```typescript
|
|
101
126
|
import { jit } from "zod-compiler/jit";
|
|
@@ -104,12 +129,12 @@ export const UserSchema = jit(z.object({ name: z.string().min(1), email: z.email
|
|
|
104
129
|
```
|
|
105
130
|
|
|
106
131
|
Same validators a build emits, installed on the schema object, so Zod interop is unchanged.
|
|
107
|
-
Compilation is lazy
|
|
108
|
-
`jitAll(namespace)` takes a whole module.
|
|
132
|
+
Compilation is lazy, costing 0.1-0.3 ms on a schema's first parse. `{ eager: true }` compiles up front
|
|
133
|
+
and `jitAll(namespace)` takes a whole module.
|
|
109
134
|
|
|
110
135
|
The cost is the import: ~570 KB of codegen and `acorn`, **~10 ms of module load**. That suits a
|
|
111
|
-
long-lived process, not a CLI, a cold serverless handler or a browser
|
|
112
|
-
|
|
136
|
+
long-lived process, not a CLI, a cold serverless handler or a browser. Use the build plugin there, and
|
|
137
|
+
have libraries ship plain Zod so the app can decide.
|
|
113
138
|
|
|
114
139
|
Needs `new Function`, as Zod's own object fast-path does. `z.config({ jitless: true })` and a CSP
|
|
115
140
|
that blocks eval both leave a working plain-Zod schema.
|
|
@@ -130,11 +155,11 @@ also chains with TypeScript runners:
|
|
|
130
155
|
node --import zod-compiler/register --import tsx src/server.ts
|
|
131
156
|
```
|
|
132
157
|
|
|
133
|
-
This is runtime JIT instrumentation, not the AOT source rewriting
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
158
|
+
This is runtime JIT instrumentation, not the AOT source rewriting the build plugins perform. The hook
|
|
159
|
+
registers the live Zod objects behind exported schema bindings and generates validators in-process on
|
|
160
|
+
first use. It does not execute modules twice, and adds no cache beyond Node's own module cache. Use a
|
|
161
|
+
build plugin or the CLI when validator code must exist before Node starts, or when `new Function` is
|
|
162
|
+
unavailable at runtime.
|
|
138
163
|
|
|
139
164
|
Optional settings come from `zod-compiler.json` in the working directory:
|
|
140
165
|
|
|
@@ -150,9 +175,9 @@ Optional settings come from `zod-compiler.json` in the working directory:
|
|
|
150
175
|
}
|
|
151
176
|
```
|
|
152
177
|
|
|
153
|
-
`output: "compact"`
|
|
154
|
-
|
|
155
|
-
|
|
178
|
+
`output: "compact"` keeps the Zod schema and the compiled fast path, delegating cold error production
|
|
179
|
+
to Zod. Full `"schema"` output stays the default. `"bag"` is unavailable here: a load hook cannot safely
|
|
180
|
+
replace already-linked ESM export bindings.
|
|
156
181
|
|
|
157
182
|
## Build Plugin
|
|
158
183
|
|
|
@@ -172,8 +197,8 @@ load hook cannot replace already-linked ESM export bindings safely.
|
|
|
172
197
|
| Bun | `import zodCompiler from "zod-compiler/bun"` |
|
|
173
198
|
| Farm | `import zodCompiler from "zod-compiler/farm"` |
|
|
174
199
|
|
|
175
|
-
Turbopack takes a loader rather than a plugin
|
|
176
|
-
|
|
200
|
+
Turbopack takes a loader rather than a plugin; see [Next.js (Turbopack)](#nextjs-turbopack). Metro has
|
|
201
|
+
neither; see [React Native / Expo](#react-native--expo).
|
|
177
202
|
|
|
178
203
|
### Options
|
|
179
204
|
|
|
@@ -182,13 +207,13 @@ has neither — see [React Native / Expo](#react-native--expo).
|
|
|
182
207
|
| `schemas` | `"auto" \| "explicit"` | `"auto"` | `"auto"` compiles every exported schema (and hoisted in-function ones); `"explicit"` only `compile()` calls |
|
|
183
208
|
| `include` | `string[]` | — | Only process files matching these path globs |
|
|
184
209
|
| `exclude` | `string[]` | — | Skip files matching these path globs |
|
|
185
|
-
| `output` | `"schema" \| "bag" \| "compact"` | `"schema"` | What a compiled export evaluates to
|
|
210
|
+
| `output` | `"schema" \| "bag" \| "compact"` | `"schema"` | What a compiled export evaluates to; see [Compact Output](#compact-output-output-compact) |
|
|
186
211
|
| `verbose` | `boolean` | `false` | Log per-schema compilation status |
|
|
187
|
-
| `hoist` | `boolean` | `true` | Move schemas built inside functions to module scope
|
|
212
|
+
| `hoist` | `boolean` | `true` | Move schemas built inside functions to module scope; see [Schema Hoisting](#schema-hoisting) |
|
|
188
213
|
| `apply` | `"build" \| "serve" \| "all"` | builds + Vitest | **Vite only**: when the plugin runs |
|
|
189
|
-
| `codegenMode` | `"lean" \| "inline"` | auto | `"inline"` emits helpers per file; needed for transpile-only esbuild
|
|
214
|
+
| `codegenMode` | `"lean" \| "inline"` | auto | `"inline"` emits helpers per file; needed for transpile-only esbuild (see [SWC](#swc)) |
|
|
190
215
|
| `cache` | `boolean \| string` | `true` | Persistent transform cache in `node_modules/.cache/zod-compiler` |
|
|
191
|
-
| `parallel` | `boolean \| number` | `false` | Run transforms on worker threads
|
|
216
|
+
| `parallel` | `boolean \| number` | `false` | Run transforms on worker threads; see [Parallel Transforms](#parallel-transforms) |
|
|
192
217
|
|
|
193
218
|
```typescript
|
|
194
219
|
zodCompiler({
|
|
@@ -208,10 +233,9 @@ export default defineConfig({
|
|
|
208
233
|
});
|
|
209
234
|
```
|
|
210
235
|
|
|
211
|
-
> **Note:** Vitest is detected automatically (via the `VITEST` env var), so
|
|
212
|
-
>
|
|
213
|
-
>
|
|
214
|
-
> the plain Zod fallback instead.
|
|
236
|
+
> **Note:** Vitest is detected automatically (via the `VITEST` env var), so tests exercise the same
|
|
237
|
+
> validators that ship to production, performance included. Pass `apply: "build"` to have tests use the
|
|
238
|
+
> plain Zod fallback instead.
|
|
215
239
|
|
|
216
240
|
### Bun
|
|
217
241
|
|
|
@@ -223,7 +247,7 @@ import zodCompiler from "zod-compiler/bun";
|
|
|
223
247
|
await Bun.build({ entrypoints: ["./src/index.tsx"], outdir: "./dist", plugins: [zodCompiler()] });
|
|
224
248
|
```
|
|
225
249
|
|
|
226
|
-
|
|
250
|
+
No build plugin fires for code run straight from source (`bun run src/server.ts`). Use
|
|
227
251
|
[`jit()`](#4-runtime-compilation-no-build-step) to compile in-process, or the
|
|
228
252
|
[CLI](#3-cli-no-bundler) to compile ahead of time.
|
|
229
253
|
|
|
@@ -243,22 +267,22 @@ function getSchema() {
|
|
|
243
267
|
```
|
|
244
268
|
|
|
245
269
|
Only expressions built from imported bindings and literals move; anything touching locals, `this` or
|
|
246
|
-
`new Date()` stays put. Combinator chains on imported schemas qualify via `schemaNamePattern`
|
|
247
|
-
|
|
270
|
+
`new Date()` stays put. Combinator chains on imported schemas qualify via `schemaNamePattern` (default
|
|
271
|
+
`/ZodSchema$/`).
|
|
248
272
|
|
|
249
|
-
In auto mode hoisted schemas also **compile**, rescuing
|
|
250
|
-
|
|
273
|
+
In auto mode hoisted schemas also **compile**, rescuing schemas that never leave a function (a slonik
|
|
274
|
+
query, a tRPC input) and are therefore invisible to export scanning: ~16,700 ns → ~14 ns per call.
|
|
251
275
|
|
|
252
276
|
### Bundle Size & Cross-File Dedup
|
|
253
277
|
|
|
254
278
|
Validators share a runtime helper layer imported from one module, so each helper appears once per
|
|
255
|
-
bundle. Schemas in a file
|
|
256
|
-
**19-28% raw / 10-18% gzipped
|
|
279
|
+
bundle. Schemas in a file that share a structurally identical sub-shape emit its error walk once, worth
|
|
280
|
+
**19-28% raw / 10-18% gzipped** and scaling with how much the file repeats.
|
|
257
281
|
|
|
258
282
|
Build plugins serve that module from a resolve hook (`virtual:zod-compiler/runtime`, or
|
|
259
283
|
`__zod-compiler-runtime__` on webpack and rspack, which reject the `virtual:` scheme). A loader host
|
|
260
284
|
has no hook, so [Turbopack](#nextjs-turbopack) imports the same code from the real subpath
|
|
261
|
-
`zod-compiler/runtime` instead
|
|
285
|
+
`zod-compiler/runtime` instead. It is opt-in there, since it only pays off where the host bundles that
|
|
262
286
|
import rather than leaving it external.
|
|
263
287
|
|
|
264
288
|
**Transpile-only esbuild builds** (no `--bundle`) never fire the bundler's resolve hooks, so the
|
|
@@ -273,7 +297,7 @@ Set `output: "bag"` to also drop the retained Zod schema when you don't need `.s
|
|
|
273
297
|
|
|
274
298
|
### Next.js (Turbopack)
|
|
275
299
|
|
|
276
|
-
Turbopack
|
|
300
|
+
Turbopack, the default since Next.js 16, [runs webpack loaders but no webpack
|
|
277
301
|
plugins](https://nextjs.org/docs/app/api-reference/turbopack#webpack-plugins), so use the loader
|
|
278
302
|
entry point:
|
|
279
303
|
|
|
@@ -300,20 +324,20 @@ const nextConfig: NextConfig = {
|
|
|
300
324
|
export default nextConfig;
|
|
301
325
|
```
|
|
302
326
|
|
|
303
|
-
Automatic mode, unchanged sources, `next dev` and `next build`. Options go in the object form
|
|
304
|
-
`loaders: [{ loader: "zod-compiler/turbopack", options: { verbose: true } }]
|
|
305
|
-
|
|
327
|
+
Automatic mode, unchanged sources, `next dev` and `next build`. Options go in the object form,
|
|
328
|
+
`loaders: [{ loader: "zod-compiler/turbopack", options: { verbose: true } }]`, and must be plain JSON,
|
|
329
|
+
so `hoist.schemaNamePattern` takes a string, not a RegExp.
|
|
306
330
|
|
|
307
331
|
Three things worth knowing:
|
|
308
332
|
|
|
309
333
|
- **Keep the `content` pattern loose.** Narrowing it to `"zod"` skips `zod/v4`, `zod/mini` and the
|
|
310
|
-
`zod-compiler` import behind `schemas: "explicit"
|
|
334
|
+
`zod-compiler` import behind `schemas: "explicit"`, leaving those files quietly uncompiled.
|
|
311
335
|
- **`codegenMode: "lean"` is App-Router-only.** It shares one copy of the helpers across the bundle,
|
|
312
336
|
but Pages Router server code externalizes `node_modules` imports unless
|
|
313
337
|
[`bundlePagesRouterDependencies`](https://nextjs.org/docs/pages/api-reference/config/next-config-js/bundlePagesRouterDependencies)
|
|
314
338
|
is on, so a devDependency install throws `ERR_MODULE_NOT_FOUND` in production.
|
|
315
|
-
- **A `"use server"` file can only export async functions**, so keep schemas there inside a function
|
|
316
|
-
[
|
|
339
|
+
- **A `"use server"` file can only export async functions**, so keep schemas there inside a function.
|
|
340
|
+
[Hoisting](#schema-hoisting) still compiles them. `"use client"` modules need nothing special.
|
|
317
341
|
|
|
318
342
|
Turbopack caches loader results itself, so cache `.next/cache` in CI rather than
|
|
319
343
|
`node_modules/.cache/zod-compiler`. `next dev --webpack` / `next build --webpack` still work, with
|
|
@@ -339,25 +363,25 @@ Defaults `codegenMode` to `"inline"` (SWC has no virtual-module hook); pass
|
|
|
339
363
|
|
|
340
364
|
### React Native / Expo
|
|
341
365
|
|
|
342
|
-
There is no Metro plugin
|
|
366
|
+
There is no Metro plugin, since unplugin has no Metro adapter. Use the [CLI](#3-cli-no-bundler); Metro
|
|
343
367
|
bundles what it emits as ordinary source:
|
|
344
368
|
|
|
345
369
|
```bash
|
|
346
370
|
npx zod-compiler generate src/schemas/ -o src/schemas/compiled/ --watch
|
|
347
371
|
```
|
|
348
372
|
|
|
349
|
-
|
|
350
|
-
unavailable on device and [`jit()`](#4-runtime-compilation-no-build-step) cannot run there at all.
|
|
373
|
+
The step pays for itself: **Hermes ships no JIT and no `new Function`**, so Zod's own object fast path
|
|
374
|
+
is unavailable on device and [`jit()`](#4-runtime-compilation-no-build-step) cannot run there at all.
|
|
351
375
|
|
|
352
|
-
Keep schema modules free of `react-native` and `expo-*` imports, transitively
|
|
353
|
-
|
|
354
|
-
|
|
376
|
+
Keep schema modules free of `react-native` and `expo-*` imports, transitively. Discovery executes each
|
|
377
|
+
file and its import graph in Node (in both modes), and one that throws falls back to runtime Zod
|
|
378
|
+
silently.
|
|
355
379
|
|
|
356
380
|
### Compact Output (`output: "compact"`)
|
|
357
381
|
|
|
358
382
|
Compiles the fast path and delegates the cold error path to the retained Zod schema, dropping
|
|
359
|
-
**~73% raw / ~71% gzipped**
|
|
360
|
-
only reading `.error` invokes Zod. Mutually exclusive with `output: "bag"`.
|
|
383
|
+
**~73% raw / ~71% gzipped** across 50 distinct schemas. The hot path is unchanged and errors are Zod's
|
|
384
|
+
own; only reading `.error` invokes Zod. Mutually exclusive with `output: "bag"`.
|
|
361
385
|
|
|
362
386
|
```typescript
|
|
363
387
|
zodCompiler({ output: "compact" });
|
|
@@ -365,18 +389,16 @@ zodCompiler({ output: "compact" });
|
|
|
365
389
|
|
|
366
390
|
### Workers and Serverless Startup
|
|
367
391
|
|
|
368
|
-
Workers
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
Automatic discovery remains the default. If an application has a clear schema boundary, narrow
|
|
374
|
-
`include` or use `schemas: "explicit"` to avoid compiling intermediate exports.
|
|
392
|
+
Workers construct every imported schema at module init, even when an isolate validates only a few.
|
|
393
|
+
Compiling all of them buys validation speed at the cost of bundle size and startup work. Compact output
|
|
394
|
+
trims the generated error path but still retains the Zod schema, and does not make eager construction
|
|
395
|
+
lazy.
|
|
375
396
|
|
|
376
|
-
|
|
377
|
-
|
|
397
|
+
If your app has a clear schema boundary, narrow `include` or use `schemas: "explicit"` to skip
|
|
398
|
+
intermediate exports. Use `output: "bag"` only where consumers need no Zod APIs (`.shape`, `.extend()`,
|
|
399
|
+
`.meta()`, `z.toJSONSchema()`); it can drop the retained schema entirely.
|
|
378
400
|
|
|
379
|
-
Measure startup separately from validation throughput
|
|
401
|
+
Measure startup separately from validation throughput, on the target deployment and bundle.
|
|
380
402
|
|
|
381
403
|
### Auto Mode: Side Effects Warning
|
|
382
404
|
|
|
@@ -384,8 +406,8 @@ Auto mode executes files to inspect their exports, so a file with schema-shaped
|
|
|
384
406
|
effects runs them at build time. Limit the scan with `include`.
|
|
385
407
|
|
|
386
408
|
For the common `env.ts` that validates `process.env` and exits, zod-compiler sets
|
|
387
|
-
`process.env.ZOD_COMPILER` during discovery and intercepts `process.exit`, so the build never crashes
|
|
388
|
-
|
|
409
|
+
`process.env.ZOD_COMPILER` during discovery and intercepts `process.exit`, so the build never crashes.
|
|
410
|
+
Those files fall back to runtime Zod. To keep them compiled, guard on it:
|
|
389
411
|
|
|
390
412
|
```typescript
|
|
391
413
|
if (!process.env.ZOD_COMPILER) {
|
|
@@ -396,12 +418,12 @@ if (!process.env.ZOD_COMPILER) {
|
|
|
396
418
|
With `@t3-oss/env-*`, pass `skipValidation: !!process.env.ZOD_COMPILER`.
|
|
397
419
|
|
|
398
420
|
A schema whose SHAPE branches on an env var is baked at build time, and the cache key does not include
|
|
399
|
-
the environment
|
|
421
|
+
the environment. Give each environment its own `cache` directory if you share one across them.
|
|
400
422
|
|
|
401
423
|
### Large projects and CI
|
|
402
424
|
|
|
403
425
|
Discovery executes each schema file inside the bundler's process, so the **first cold run** is the
|
|
404
|
-
expensive one
|
|
426
|
+
expensive one. Later runs hit the persistent cache.
|
|
405
427
|
|
|
406
428
|
```yaml
|
|
407
429
|
- uses: actions/cache@v4
|
|
@@ -415,10 +437,10 @@ never mention `zod` cost nothing.
|
|
|
415
437
|
|
|
416
438
|
### Parallel Transforms
|
|
417
439
|
|
|
418
|
-
Discovery runs one file at a time on the bundler's own thread
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
440
|
+
Discovery runs one file at a time on the bundler's own thread, serializing executions so concurrent
|
|
441
|
+
transforms cannot double-execute a shared dependency. `parallel` moves whole transforms onto worker
|
|
442
|
+
threads instead, each with its own loader and module cache, which is what makes running them at the
|
|
443
|
+
same time sound.
|
|
422
444
|
|
|
423
445
|
```typescript
|
|
424
446
|
zodCompiler({ parallel: true }); // one worker per core, less one, capped at 4
|
|
@@ -427,34 +449,34 @@ zodCompiler({ parallel: 2 }); // or pick the count yourself
|
|
|
427
449
|
|
|
428
450
|
**Whether it pays depends on your import graph, not your core count.** A module shared by many
|
|
429
451
|
schema files is executed once in-process and once _per worker_ here. Files with independent graphs
|
|
430
|
-
win; files chained through each other can lose. Both rows below are 120 files of 8 schemas each
|
|
431
|
-
12 performance cores
|
|
452
|
+
win; files chained through each other can lose. Both rows below are 120 files of 8 schemas each on
|
|
453
|
+
12 performance cores, differing only in whether the files import one another:
|
|
432
454
|
|
|
433
455
|
| Transform (120 files) | in-process | n=2 | n=4 | n=8 | n=12 |
|
|
434
456
|
| --------------------- | ---------: | -------: | -------: | -------: | -------: |
|
|
435
457
|
| independent graphs | 3,633 ms | 2,263 ms | 1,508 ms | 1,786 ms | 2,119 ms |
|
|
436
458
|
| 120-deep import chain | 945 ms | 977 ms | 1,045 ms | 1,796 ms | 3,332 ms |
|
|
437
459
|
|
|
438
|
-
So measure before adopting it
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
460
|
+
So measure before adopting it. `ZOD_COMPILER_TIMING=1` prints the per-phase breakdown, and `discover`
|
|
461
|
+
is the line workers move. Throughput peaks around four workers and declines past it: every extra worker
|
|
462
|
+
re-executes more graph, holds another copy in memory, and adds to the generated source that the single
|
|
463
|
+
receiving thread has to deserialize.
|
|
442
464
|
|
|
443
|
-
Emitted code, sourcemaps and cache entries are identical either way
|
|
444
|
-
cache key, so
|
|
445
|
-
|
|
446
|
-
|
|
465
|
+
Emitted code, sourcemaps and cache entries are identical either way. `parallel` is not part of the
|
|
466
|
+
cache key, so parallel and serial builds share one cache. Disk caching and dependency crawling stay on
|
|
467
|
+
the bundler thread, and a worker that cannot start or dies mid-build has its file retried in-process
|
|
468
|
+
rather than failing the build.
|
|
447
469
|
|
|
448
|
-
A **warm cache still beats parallelism
|
|
449
|
-
|
|
470
|
+
A **warm cache still beats parallelism** and costs no memory. Reach for `parallel` on the cold runs the
|
|
471
|
+
cache cannot help with.
|
|
450
472
|
|
|
451
473
|
## Framework Examples
|
|
452
474
|
|
|
453
|
-
Nothing framework-specific is needed
|
|
454
|
-
|
|
475
|
+
Nothing framework-specific is needed. Exported schemas are compiled in place, so anything accepting a
|
|
476
|
+
Zod schema picks up the compiled version:
|
|
455
477
|
|
|
456
478
|
```typescript
|
|
457
|
-
// tRPC
|
|
479
|
+
// tRPC: no .input(compile(...)) needed
|
|
458
480
|
t.procedure.input(CreateUserSchema).mutation(({ input }) => createUser(input));
|
|
459
481
|
|
|
460
482
|
// Hono
|
|
@@ -464,7 +486,7 @@ app.post("/users", zValidator("json", UserSchema), (c) => c.json(c.req.valid("js
|
|
|
464
486
|
useForm({ resolver: zodResolver(SignupSchema) });
|
|
465
487
|
```
|
|
466
488
|
|
|
467
|
-
The same applies to any [Standard Schema](https://standardschema.dev) consumer
|
|
489
|
+
The same applies to any [Standard Schema](https://standardschema.dev) consumer: `~standard.validate`
|
|
468
490
|
routes through the compiled validator.
|
|
469
491
|
|
|
470
492
|
Compiled methods live on the schema object, so Zod's functional API (`z.safeParse(Schema, x)`) and a
|
|
@@ -521,9 +543,9 @@ npx zod-compiler check src/schemas.ts --json --fail-under 80
|
|
|
521
543
|
|
|
522
544
|
## What Gets Compiled
|
|
523
545
|
|
|
524
|
-
### Fully Compiled (
|
|
546
|
+
### Fully Compiled (up to 42x faster)
|
|
525
547
|
|
|
526
|
-
Every Zod type except the fallbacks below
|
|
548
|
+
Every Zod type except the fallbacks below: all primitives, `object` / `strictObject` / `looseObject`,
|
|
527
549
|
`array`, `tuple`, `record`, `set`, `map`, `union`, `discriminatedUnion`, `intersection`, `pipe`,
|
|
528
550
|
the `optional` / `nullable` / `readonly` / `default` / `catch` / `coerce` wrappers, `templateLiteral`,
|
|
529
551
|
recursive `lazy` (self, mutual and nested), `custom` / `instanceof`, and
|
|
@@ -546,7 +568,7 @@ A schema delegates to Zod when it reaches JavaScript the generated code cannot r
|
|
|
546
568
|
| Dynamic error maps, unresolvable `z.lazy()` | Not knowable at build time |
|
|
547
569
|
|
|
548
570
|
Everything else compiles, including context-free `preprocess` callbacks and
|
|
549
|
-
`transform`/`refine`/`superRefine` whether or not the callback captures
|
|
571
|
+
`transform`/`refine`/`superRefine` whether or not the callback captures. A zero-capture one is inlined,
|
|
550
572
|
a capturing one called by reference. Delegation is per-sub-schema: one uncompilable field goes to Zod,
|
|
551
573
|
not the whole object. Run `zod-compiler check` to see what compiled.
|
|
552
574
|
|
|
@@ -557,7 +579,7 @@ Three things differ by design:
|
|
|
557
579
|
|
|
558
580
|
| Behavior | Zod | zod-compiler |
|
|
559
581
|
| ------------------------- | ----------------------------------------------- | ------------------------------------------------------- |
|
|
560
|
-
| Record key iteration |
|
|
582
|
+
| Record key iteration | Own enumerable keys, symbols included | Own enumerable **string** keys only |
|
|
561
583
|
| Container output identity | A fresh array / set / map / object | The input container, by reference (array holes survive) |
|
|
562
584
|
| Per-call parse params | `safeParse(x, { error, reportInput })` honoured | Ignored; global `z.config()` maps still apply |
|
|
563
585
|
|
|
@@ -572,59 +594,61 @@ Schema-level `error` and `z.config()` maps are unaffected; for a per-call map us
|
|
|
572
594
|
|
|
573
595
|
| Scenario | Zod v3 | Zod v4 | **zod-compiler** | Typia | AJV | vs Zod v4 |
|
|
574
596
|
| ----------------------------------------------- | ------ | ------ | ---------------- | ----- | ----- | --------- |
|
|
575
|
-
| simple string | 12.
|
|
576
|
-
| string (min/max) |
|
|
577
|
-
| number (int+positive) | 12.
|
|
578
|
-
| enum | 11.
|
|
579
|
-
| bigint (min/max) |
|
|
580
|
-
| tuple [string, int, bool] | 5.
|
|
581
|
-
| record\<string, number\> | 3.
|
|
582
|
-
| set\<string\> (5 items) | 3.
|
|
583
|
-
| set\<string\> (20 items) | 1.3M |
|
|
584
|
-
| map\<string, number\> (5 entries) | 2.
|
|
585
|
-
| map\<string, number\> (20 entries) |
|
|
586
|
-
| pipe (non-transform) | 8.
|
|
587
|
-
| discriminatedUnion (3 variants) | 3.3M |
|
|
588
|
-
| discriminatedUnion (8 variants, rotating) | 2.
|
|
589
|
-
| plain union of 8 tagged objects (auto-discrim.) |
|
|
590
|
-
| strict object (DB row) | 1.
|
|
591
|
-
| medium object (valid) | 1.9M | 2.4M | **9.
|
|
592
|
-
| medium object (extra keys stripped) | 1.8M | 2.
|
|
593
|
-
| medium object (invalid) |
|
|
594
|
-
| large object (10 items) |
|
|
595
|
-
| large object (100 items) | 13K | 18K | **
|
|
596
|
-
| readonly field (wrapper compiles away) | 3.
|
|
597
|
-
| readonly root object (rebuild + freeze) | 2.
|
|
598
|
-
| readonly array (delegates to Zod) | 3.
|
|
599
|
-
| recursive tree (7 nodes) |
|
|
600
|
-
| recursive tree (121 nodes) |
|
|
601
|
-
| nested recursion (7 nodes) |
|
|
602
|
-
| nested recursion (121 nodes) |
|
|
603
|
-
| deeply nested object (243 leaves) | 11K |
|
|
604
|
-
| event log (combined) |
|
|
605
|
-
| object with transform (zero-capture) | 1.
|
|
606
|
-
| array 10 × transform (zero-capture) |
|
|
607
|
-
| array 50 × transform (zero-capture) | 25K |
|
|
608
|
-
| object with captured transform | 1.
|
|
609
|
-
| object with captured refine (cross-field) | 1.
|
|
610
|
-
| object with superRefine (cross-field) | 1.
|
|
611
|
-
| coerced query object (valid) | 1.
|
|
612
|
-
| coerced query object (invalid) | 1.
|
|
613
|
-
| preprocessed query object (valid) |
|
|
614
|
-
| preprocessed query object (invalid) |
|
|
615
|
-
| stringbool config object (valid) | — |
|
|
616
|
-
| stringbool config object (invalid) | — |
|
|
617
|
-
| custom/instanceof request (valid) |
|
|
618
|
-
| custom/instanceof request (invalid) |
|
|
619
|
-
| disjoint object intersection (valid) | 1.4M | 1.
|
|
620
|
-
| disjoint object intersection (invalid) |
|
|
621
|
-
|
|
622
|
-
_ops/s, higher is better. `vp test bench` on an Apple M4 Max (zod 4.
|
|
623
|
-
best of three runs. The harness costs ~
|
|
597
|
+
| simple string | 12.7M | 15.8M | **16.6M** | 17.4M | 17.4M | 1.0x |
|
|
598
|
+
| string (min/max) | 11.9M | 7.4M | **17.5M** | 17.3M | 15.6M | 2.4x |
|
|
599
|
+
| number (int+positive) | 12.0M | 9.6M | **16.9M** | 16.9M | 16.9M | 1.8x |
|
|
600
|
+
| enum | 11.2M | 15.4M | **17.4M** | 16.9M | 17.0M | 1.1x |
|
|
601
|
+
| bigint (min/max) | 11.8M | 8.3M | **17.0M** | — | — | 2.1x |
|
|
602
|
+
| tuple [string, int, bool] | 5.7M | 7.6M | **17.9M** | 16.8M | 16.0M | 2.4x |
|
|
603
|
+
| record\<string, number\> | 3.1M | 2.5M | **12.6M** | 12.0M | 15.3M | 5.0x |
|
|
604
|
+
| set\<string\> (5 items) | 3.6M | 2.2M | **16.0M** | — | — | 7.2x |
|
|
605
|
+
| set\<string\> (20 items) | 1.3M | 661K | **12.4M** | — | — | **19x** |
|
|
606
|
+
| map\<string, number\> (5 entries) | 2.0M | 1.3M | **13.6M** | — | — | **11x** |
|
|
607
|
+
| map\<string, number\> (20 entries) | 618K | 338K | **8.7M** | — | — | **26x** |
|
|
608
|
+
| pipe (non-transform) | 8.9M | 4.7M | **17.3M** | — | — | 3.7x |
|
|
609
|
+
| discriminatedUnion (3 variants) | 3.3M | 5.2M | **16.2M** | 15.9M | 7.5M | 3.1x |
|
|
610
|
+
| discriminatedUnion (8 variants, rotating) | 2.6M | 4.4M | **9.5M** | — | — | 2.2x |
|
|
611
|
+
| plain union of 8 tagged objects (auto-discrim.) | 348K | 1.3M | **10.2M** | — | — | 8.1x |
|
|
612
|
+
| strict object (DB row) | 1.7M | 3.0M | **11.1M** | — | — | 3.6x |
|
|
613
|
+
| medium object (valid) | 1.9M | 2.4M | **9.9M** | 10.8M | 7.5M | 4.2x |
|
|
614
|
+
| medium object (extra keys stripped) | 1.8M | 2.1M | **9.8M** | — | — | 4.7x |
|
|
615
|
+
| medium object (invalid) | 511K | 359K | **15.7M** | 2.9M | 7.5M | **44x** |
|
|
616
|
+
| large object (10 items) | 117K | 175K | **5.3M** | 5.7M | 1.2M | **30x** |
|
|
617
|
+
| large object (100 items) | 13K | 18K | **779K** | 1.3M | 127K | **42x** |
|
|
618
|
+
| readonly field (wrapper compiles away) | 3.0M | 6.6M | **15.7M** | — | — | 2.4x |
|
|
619
|
+
| readonly root object (rebuild + freeze) | 2.8M | 5.4M | **12.8M** | — | — | 2.4x |
|
|
620
|
+
| readonly array (delegates to Zod) | 3.8M | 4.2M | **4.1M** | — | — | 1.0x |
|
|
621
|
+
| recursive tree (7 nodes) | 564K | 994K | **7.9M** | 12.1M | 4.7M | 7.9x |
|
|
622
|
+
| recursive tree (121 nodes) | 31K | 55K | **783K** | 1.9M | 361K | **14x** |
|
|
623
|
+
| nested recursion (7 nodes) | 383K | 667K | **7.9M** | 11.2M | 2.9M | **12x** |
|
|
624
|
+
| nested recursion (121 nodes) | 23K | 41K | **817K** | 1.6M | 206K | **20x** |
|
|
625
|
+
| deeply nested object (243 leaves) | 11K | 27K | **803K** | 1.0M | 122K | **30x** |
|
|
626
|
+
| event log (combined) | 371K | 782K | **7.5M** | — | — | 9.6x |
|
|
627
|
+
| object with transform (zero-capture) | 1.1M | 2.0M | **7.2M** | — | — | 3.7x |
|
|
628
|
+
| array 10 × transform (zero-capture) | 122K | 203K | **4.2M** | — | — | **21x** |
|
|
629
|
+
| array 50 × transform (zero-capture) | 25K | 42K | **1.0M** | — | — | **25x** |
|
|
630
|
+
| object with captured transform | 1.2M | 8.2M | **16.2M** | — | — | 2.0x |
|
|
631
|
+
| object with captured refine (cross-field) | 1.4M | 2.2M | **11.2M** | — | — | 5.0x |
|
|
632
|
+
| object with superRefine (cross-field) | 1.4M | 2.2M | **9.3M** | — | — | 4.3x |
|
|
633
|
+
| coerced query object (valid) | 1.8M | 2.9M | **5.4M** | — | — | 1.9x |
|
|
634
|
+
| coerced query object (invalid) | 1.0M | 828K | **10.3M** | — | — | **12x** |
|
|
635
|
+
| preprocessed query object (valid) | 401K | 1.7M | **5.2M** | — | — | 3.0x |
|
|
636
|
+
| preprocessed query object (invalid) | 378K | 755K | **12.7M** | — | — | **17x** |
|
|
637
|
+
| stringbool config object (valid) | — | 2.8M | **6.3M** | — | — | 2.2x |
|
|
638
|
+
| stringbool config object (invalid) | — | 670K | **13.8M** | — | — | **21x** |
|
|
639
|
+
| custom/instanceof request (valid) | 965K | 3.1M | **10.4M** | — | — | 3.3x |
|
|
640
|
+
| custom/instanceof request (invalid) | 784K | 930K | **10.2M** | — | — | **11x** |
|
|
641
|
+
| disjoint object intersection (valid) | 1.4M | 1.6M | **9.8M** | — | — | 6.0x |
|
|
642
|
+
| disjoint object intersection (invalid) | 493K | 327K | **15.4M** | — | — | **47x** |
|
|
643
|
+
|
|
644
|
+
_ops/s, higher is better. `vp test bench` on an Apple M4 Max (zod 4.5.2, zod v3 3.23.8, typia 12, ajv 8),
|
|
645
|
+
best of three runs. The harness costs ~60 ns per iteration, so the fastest rows sit at that floor and gaps
|
|
624
646
|
between the AOT columns there are noise, not real._
|
|
625
647
|
|
|
626
648
|
Nested objects, arrays and recursive types gain the most. Rejection is fast because a failed
|
|
627
|
-
`safeParse` defers building the error until `.error` is read.
|
|
649
|
+
`safeParse` defers building the error until `.error` is read. Zod 4.5 stopped capturing a stack trace on
|
|
650
|
+
that path too, so its own rejected-input rows are several times faster than 4.3's and the gap there is
|
|
651
|
+
narrower than it was.
|
|
628
652
|
|
|
629
653
|
```bash
|
|
630
654
|
vp run benchmark # run locally
|
|
@@ -632,23 +656,27 @@ vp run benchmark # run locally
|
|
|
632
656
|
|
|
633
657
|
### Performance Architecture
|
|
634
658
|
|
|
635
|
-
An eligible schema compiles to a **fast path
|
|
636
|
-
allocations
|
|
637
|
-
failure and deferred until `.error` is read. A `z.object()` strips, so it instead compiles to a
|
|
638
|
-
pass that validates and rebuilds together
|
|
639
|
-
idioms (array size checks, `.refine()`, `.default()`, `.trim()`, `.transform()`).
|
|
659
|
+
An eligible schema compiles to a **fast path**, one `&&` chain validating the whole input with zero
|
|
660
|
+
allocations and reused by `.is()` and `parse()`, plus a **slow path** that collects errors, runs only on
|
|
661
|
+
failure, and is deferred until `.error` is read. A `z.object()` strips, so it instead compiles to a
|
|
662
|
+
single pass that validates and rebuilds together and bails on the first failure, covering the reshaping
|
|
663
|
+
idioms too (array size checks, `.refine()`, `.default()`, `.trim()`, `.transform()`).
|
|
640
664
|
|
|
641
665
|
Regexes are pre-compiled with bounded repeats unrolled, checks run cheapest-first, discriminated unions
|
|
642
|
-
dispatch through a
|
|
643
|
-
functions are split to stay within V8's
|
|
666
|
+
dispatch through a `switch` on the tag (plain tagged unions are auto-discriminated into it, on the
|
|
667
|
+
stripping pass as well as the fast check), and oversized check functions are split to stay within V8's
|
|
668
|
+
optimizer budget. `z.email()` runs as a single linear scan instead of a backtracking regex, a record's
|
|
669
|
+
plain-object guard exits on one comparison for an ordinary object, and a case-insensitive `stringbool`
|
|
670
|
+
looks its input up verbatim before paying for `toLowerCase()`. Stripping objects, native coercions,
|
|
644
671
|
`stringbool`, defaults, string rewrites, context-free preprocessors and synchronous transforms validate
|
|
645
672
|
and build their output in one pass. An intersection of two objects with disjoint keys compiles to that
|
|
646
673
|
same single pass over the merged shape, and `z.custom()` / `z.instanceof()` compile to a direct predicate
|
|
647
674
|
call.
|
|
648
675
|
|
|
649
|
-
Where success is cheaper to compile than failure, only the verdict and output are compiled
|
|
650
|
-
and `custom` keep the original Zod schema to construct issues, so a rejection still
|
|
651
|
-
Zod would
|
|
676
|
+
Where success is cheaper to compile than failure, only the verdict and output are compiled.
|
|
677
|
+
Intersections and `custom` keep the original Zod schema to construct issues, so a rejection still
|
|
678
|
+
reports exactly what Zod would, an intersection's one-issue-per-side shape included, without slowing the
|
|
679
|
+
hot path.
|
|
652
680
|
|
|
653
681
|
## Development
|
|
654
682
|
|
|
@@ -33,6 +33,17 @@ declare function rebuildsOutput(ir: SchemaIR): boolean;
|
|
|
33
33
|
* size-gated `__fo_` split) to fix a shortcut that only the root takes.
|
|
34
34
|
*/
|
|
35
35
|
declare function fastResultIsInput(ir: SchemaIR): boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Does anything STRICTLY BELOW `ir` hand back a container needing a `__proto__`
|
|
38
|
+
* scrub?
|
|
39
|
+
*
|
|
40
|
+
* The root's by-reference shortcut can filter the value it returns
|
|
41
|
+
* (`data: __zcPs(input)`), but that only reaches the OUTER container — a nested
|
|
42
|
+
* one is never touched, because the shortcut does not walk. So a schema with a
|
|
43
|
+
* scrub-needing descendant keeps the eager slow walk, which scrubs at every
|
|
44
|
+
* level. Only the root's own scrub is shortcut-compatible.
|
|
45
|
+
*/
|
|
46
|
+
declare function nestedNeedsProtoScrub(ir: SchemaIR): boolean;
|
|
36
47
|
/**
|
|
37
48
|
* Host the whole schema as `function NAME(input){…}` returning the built value
|
|
38
49
|
* or the FAIL sentinel. Returns the function name, or null when the schema is
|
|
@@ -40,5 +51,5 @@ declare function fastResultIsInput(ir: SchemaIR): boolean;
|
|
|
40
51
|
*/
|
|
41
52
|
declare function generateBuild(ir: SchemaIR, ctx: CodeGenContext): string | null;
|
|
42
53
|
//#endregion
|
|
43
|
-
export { fastResultIsInput, generateBuild, rebuildsOutput };
|
|
54
|
+
export { fastResultIsInput, generateBuild, nestedNeedsProtoScrub, rebuildsOutput };
|
|
44
55
|
//# sourceMappingURL=build-path.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-path.d.ts","names":[],"sources":["../../../src/core/codegen/build-path.ts"],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"build-path.d.ts","names":[],"sources":["../../../src/core/codegen/build-path.ts"],"mappings":";;;;iBAyLgB,eAAe,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAiCnB,kBAAkB,IAAI;;;;;;;;;;;iBAmFtB,sBAAsB,IAAI;;;;;;iBAmD1B,cAAc,IAAI,UAAU,KAAK"}
|