zod-compiler 1.22.4 → 1.22.6
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 +75 -89
- package/dist/core/iife.d.ts +39 -3
- package/dist/core/iife.d.ts.map +1 -1
- package/dist/core/iife.js +46 -3
- package/dist/core/iife.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
**Compile Zod schemas into zero-overhead validation functions at build time.**
|
|
4
4
|
|
|
5
|
-
Keep your existing Zod schemas. Get **2-
|
|
5
|
+
Keep your existing Zod schemas. Get **2-43x faster** validation. No code changes required.
|
|
6
6
|
|
|
7
7
|
- [What Gets Compiled](#what-gets-compiled)
|
|
8
8
|
- [Schema Hoisting](#schema-hoisting)
|
|
@@ -13,11 +13,11 @@ Keep your existing Zod schemas. Get **2-45x faster** validation. No code changes
|
|
|
13
13
|
|
|
14
14
|
## Usage
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
Three ways to use zod-compiler — pick one:
|
|
17
17
|
|
|
18
18
|
### 1. Automatic Mode (Default)
|
|
19
19
|
|
|
20
|
-
The plugin
|
|
20
|
+
The plugin detects and compiles every exported Zod schema at build time. No wrappers, no imports from `zod-compiler` in your source.
|
|
21
21
|
|
|
22
22
|
**vite.config.ts:**
|
|
23
23
|
|
|
@@ -42,11 +42,11 @@ export const CreateUserSchema = z.object({
|
|
|
42
42
|
});
|
|
43
43
|
```
|
|
44
44
|
|
|
45
|
-
Use them as usual.
|
|
46
|
-
|
|
45
|
+
Use them as usual. Methods are installed on the original schema object, so `.shape`, `._zod`, Standard
|
|
46
|
+
Schema, `instanceof` and `z.toJSONSchema()` keep working.
|
|
47
47
|
|
|
48
|
-
Compiled schemas also expose **`.is(input): input is T`** —
|
|
49
|
-
|
|
48
|
+
Compiled schemas also expose **`.is(input): input is T`** — a zero-allocation drop-in for
|
|
49
|
+
`safeParse(x).success`.
|
|
50
50
|
|
|
51
51
|
### 2. compile() (Explicit)
|
|
52
52
|
|
|
@@ -69,7 +69,7 @@ validateUser.parse(data);
|
|
|
69
69
|
validateUser.safeParse(data);
|
|
70
70
|
```
|
|
71
71
|
|
|
72
|
-
`compile()` and auto mode coexist
|
|
72
|
+
`compile()` and auto mode coexist. Pair with `schemas: "explicit"` to make `compile()` the _only_ path — no automatic detection, no build-time execution of plain schema files.
|
|
73
73
|
|
|
74
74
|
### 3. CLI (No Bundler)
|
|
75
75
|
|
|
@@ -148,8 +148,7 @@ export default defineConfig({
|
|
|
148
148
|
|
|
149
149
|
### Bun
|
|
150
150
|
|
|
151
|
-
|
|
152
|
-
Requires **Bun ≥ 1.2.22**.
|
|
151
|
+
Applies wherever your code passes through a build step. Requires **Bun ≥ 1.2.22**.
|
|
153
152
|
|
|
154
153
|
```typescript
|
|
155
154
|
import zodCompiler from "zod-compiler/bun";
|
|
@@ -179,16 +178,14 @@ Only expressions built from imported bindings and literals move; anything touchi
|
|
|
179
178
|
`new Date()` stays put. Combinator chains on imported schemas qualify via `schemaNamePattern`
|
|
180
179
|
(default `/ZodSchema$/`).
|
|
181
180
|
|
|
182
|
-
In auto mode hoisted schemas also **compile
|
|
183
|
-
|
|
184
|
-
~14 ns per call.
|
|
181
|
+
In auto mode hoisted schemas also **compile**, rescuing the schema that never leaves a function (a
|
|
182
|
+
slonik query, a tRPC input) and so is invisible to export scanning: ~16,700 ns → ~14 ns per call.
|
|
185
183
|
|
|
186
184
|
### Bundle Size & Cross-File Dedup
|
|
187
185
|
|
|
188
186
|
Validators share a runtime helper layer imported from one module, so each helper appears once per
|
|
189
|
-
bundle. Schemas in a file sharing a structurally identical sub-shape emit its error walk once
|
|
190
|
-
|
|
191
|
-
shape, **28% / 18%** for four exports reusing two.
|
|
187
|
+
bundle. Schemas in a file sharing a structurally identical sub-shape emit its error walk once —
|
|
188
|
+
**19-28% raw / 10-18% gzipped**, scaling with how much the file repeats.
|
|
192
189
|
|
|
193
190
|
**Transpile-only esbuild builds** (no `--bundle`) never fire the bundler's resolve hooks, so the
|
|
194
191
|
`virtual:` specifier would survive into `dist/` and fail at runtime. Set `codegenMode: "inline"` to emit
|
|
@@ -202,8 +199,8 @@ Set `output: "bag"` to also drop the retained Zod schema when you don't need `.s
|
|
|
202
199
|
|
|
203
200
|
### SWC
|
|
204
201
|
|
|
205
|
-
|
|
206
|
-
|
|
202
|
+
A programmatic `@swc/core` bridge wrapping `transform()`, not a `.swcrc` plugin. Install
|
|
203
|
+
`@swc/core`, then:
|
|
207
204
|
|
|
208
205
|
```typescript
|
|
209
206
|
import { transform } from "zod-compiler/swc";
|
|
@@ -220,13 +217,9 @@ Defaults `codegenMode` to `"inline"` (SWC has no virtual-module hook); pass
|
|
|
220
217
|
|
|
221
218
|
### Compact Output (`output: "compact"`)
|
|
222
219
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
On 50 distinct schemas, output drops **~73% raw / ~71% gzipped**. The hot path is unchanged, errors are
|
|
228
|
-
Zod's own, and `safeParse(x).success` / `.is(x)` never invoke Zod — only reading `.error` does. Mutation
|
|
229
|
-
schemas keep the compiled path. Mutually exclusive with `output: "bag"`.
|
|
220
|
+
Compiles the fast path and delegates the cold error path to the retained Zod schema, dropping
|
|
221
|
+
**~73% raw / ~71% gzipped** on 50 distinct schemas. The hot path is unchanged and errors are Zod's own;
|
|
222
|
+
only reading `.error` invokes Zod. Mutually exclusive with `output: "bag"`.
|
|
230
223
|
|
|
231
224
|
### Auto Mode: Side Effects Warning
|
|
232
225
|
|
|
@@ -245,16 +238,6 @@ if (!process.env.ZOD_COMPILER) {
|
|
|
245
238
|
|
|
246
239
|
With `@t3-oss/env-*`, pass `skipValidation: !!process.env.ZOD_COMPILER`.
|
|
247
240
|
|
|
248
|
-
### schemas: "auto" vs "explicit"
|
|
249
|
-
|
|
250
|
-
| | `"auto"` (default) | `"explicit"` + compile() |
|
|
251
|
-
| ---------------------------- | ---------------------------------------------------------- | ------------------------------------------- |
|
|
252
|
-
| Source code changes | None | Wrap each schema |
|
|
253
|
-
| `zod-compiler` import needed | No | Yes |
|
|
254
|
-
| What gets compiled | All exported Zod schemas | Only wrapped schemas |
|
|
255
|
-
| Build-time file execution | Zod-importing files that may export schemas (pre-filtered) | Files with `import ... from "zod-compiler"` |
|
|
256
|
-
| Best for | New projects, framework integration | Gradual adoption, selective optimization |
|
|
257
|
-
|
|
258
241
|
### Large projects and CI
|
|
259
242
|
|
|
260
243
|
Discovery executes each schema file inside the bundler's process, so the **first cold run** is the
|
|
@@ -267,14 +250,13 @@ expensive one — later runs hit the persistent cache.
|
|
|
267
250
|
key: zod-compiler-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
|
|
268
251
|
```
|
|
269
252
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
mention `zod` cost nothing.
|
|
253
|
+
Scope discovery with `include`; set `ZOD_COMPILER_TIMING=1` for a per-phase breakdown. Files that
|
|
254
|
+
never mention `zod` cost nothing.
|
|
273
255
|
|
|
274
256
|
## Framework Examples
|
|
275
257
|
|
|
276
|
-
Nothing framework-specific is needed
|
|
277
|
-
|
|
258
|
+
Nothing framework-specific is needed — exported schemas are compiled in place, so anything accepting
|
|
259
|
+
a Zod schema picks up the compiled version:
|
|
278
260
|
|
|
279
261
|
```typescript
|
|
280
262
|
// tRPC — no .input(compile(...)) needed
|
|
@@ -287,12 +269,15 @@ app.post("/users", zValidator("json", UserSchema), (c) => c.json(c.req.valid("js
|
|
|
287
269
|
useForm({ resolver: zodResolver(SignupSchema) });
|
|
288
270
|
```
|
|
289
271
|
|
|
290
|
-
The same applies to any [Standard Schema](https://standardschema.dev) consumer — `~standard`
|
|
291
|
-
|
|
272
|
+
The same applies to any [Standard Schema](https://standardschema.dev) consumer — `~standard.validate`
|
|
273
|
+
routes through the compiled validator.
|
|
274
|
+
|
|
275
|
+
Compiled methods live on the schema object, so Zod's functional API (`z.safeParse(Schema, x)`) and a
|
|
276
|
+
compiled schema composed into an uncompiled parent stay on plain Zod.
|
|
292
277
|
|
|
293
278
|
## Schema Diagnostics
|
|
294
279
|
|
|
295
|
-
|
|
280
|
+
Check coverage and Fast Path eligibility before compiling:
|
|
296
281
|
|
|
297
282
|
```bash
|
|
298
283
|
npx zod-compiler check src/schemas.ts
|
|
@@ -341,7 +326,7 @@ npx zod-compiler check src/schemas.ts --json --fail-under 80
|
|
|
341
326
|
|
|
342
327
|
## What Gets Compiled
|
|
343
328
|
|
|
344
|
-
### Fully Compiled (2-
|
|
329
|
+
### Fully Compiled (2-43x faster)
|
|
345
330
|
|
|
346
331
|
Every Zod type except the fallbacks below — all primitives, `object` / `strictObject` / `looseObject`,
|
|
347
332
|
`array`, `tuple`, `record`, `set`, `map`, `union`, `discriminatedUnion`, `intersection`, `pipe`,
|
|
@@ -372,16 +357,18 @@ see what compiled.
|
|
|
372
357
|
### Behavioral Differences from Zod
|
|
373
358
|
|
|
374
359
|
Compiled validators match Zod on verdicts, output data and error messages, including issue ordering.
|
|
375
|
-
|
|
360
|
+
Three things differ by design:
|
|
361
|
+
|
|
362
|
+
| Behavior | Zod | zod-compiler |
|
|
363
|
+
| ------------------------- | ----------------------------------------------- | ------------------------------------------------------- |
|
|
364
|
+
| Record key iteration | All own keys (`Reflect.ownKeys`) | Own enumerable **string** keys only |
|
|
365
|
+
| Container output identity | A fresh array / set / map / object | The input container, by reference (array holes survive) |
|
|
366
|
+
| Per-call parse params | `safeParse(x, { error, reportInput })` honoured | Ignored; global `z.config()` maps still apply |
|
|
376
367
|
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
| Record key iteration | All own keys (`Reflect.ownKeys`) | Own enumerable **string** keys only |
|
|
380
|
-
| Container output identity | A fresh array / set / map / object | The input container, by reference (array holes survive) |
|
|
368
|
+
Schema-level `error` and `z.config()` maps are unaffected; for a per-call map use
|
|
369
|
+
`z.safeParse(Schema, x, params)`.
|
|
381
370
|
|
|
382
|
-
|
|
383
|
-
rebuilds it. `z.object()` is the exception — it strips unknown keys exactly as Zod does, so its output
|
|
384
|
-
is always a fresh object.
|
|
371
|
+
`z.object()` strips unknown keys exactly as Zod does, so its output is always a fresh object.
|
|
385
372
|
|
|
386
373
|
## Benchmark
|
|
387
374
|
|
|
@@ -389,42 +376,42 @@ is always a fresh object.
|
|
|
389
376
|
|
|
390
377
|
| Scenario | Zod v3 | Zod v4 | **zod-compiler** | Typia | AJV | vs Zod v4 |
|
|
391
378
|
| ----------------------------------------------- | ------ | ------ | ---------------- | ----- | ----- | --------- |
|
|
392
|
-
| simple string | 12.
|
|
393
|
-
| string (min/max) | 12.
|
|
394
|
-
| number (int+positive) |
|
|
395
|
-
| enum | 11.
|
|
396
|
-
| bigint (min/max) |
|
|
397
|
-
| tuple [string, int, bool] | 5.
|
|
398
|
-
| record\<string, number\> | 3.2M | 2.
|
|
399
|
-
| set\<string\> (5 items) | 3.
|
|
400
|
-
| set\<string\> (20 items) | 1.3M |
|
|
401
|
-
| map\<string, number\> (5 entries) | 2.
|
|
402
|
-
| map\<string, number\> (20 entries) |
|
|
403
|
-
| pipe (non-transform) | 8.
|
|
404
|
-
| discriminatedUnion (3 variants) | 3.
|
|
405
|
-
| discriminatedUnion (8 variants, rotating) | 2.7M | 3.
|
|
406
|
-
| plain union of 8 tagged objects (auto-discrim.) |
|
|
407
|
-
| strict object (DB row) | 1.8M | 3.1M | **
|
|
408
|
-
| medium object (valid) | 1.
|
|
409
|
-
| medium object (extra keys stripped) | 1.8M | 2.
|
|
410
|
-
| medium object (invalid) |
|
|
411
|
-
| large object (10 items) |
|
|
412
|
-
| large object (100 items) | 13K | 18K | **
|
|
413
|
-
| recursive tree (7 nodes) |
|
|
414
|
-
| recursive tree (121 nodes) | 32K |
|
|
415
|
-
| nested recursion (7 nodes) |
|
|
416
|
-
| nested recursion (121 nodes) |
|
|
417
|
-
| deeply nested object (243 leaves) | 11K | 20K | **
|
|
418
|
-
| event log (combined) |
|
|
419
|
-
| object with transform (zero-capture) | 1.
|
|
420
|
-
| array 10 × transform (zero-capture) |
|
|
421
|
-
| array 50 × transform (zero-capture) | 25K |
|
|
422
|
-
| object with captured transform | 1.
|
|
423
|
-
| object with captured refine (cross-field) | 1.6M | 2.
|
|
424
|
-
| object with superRefine (cross-field) | 1.
|
|
379
|
+
| simple string | 12.6M | 14.3M | **16.5M** | 17.8M | 17.6M | 1.2x |
|
|
380
|
+
| string (min/max) | 12.5M | 7.5M | **15.9M** | 17.0M | 15.2M | 2.1x |
|
|
381
|
+
| number (int+positive) | 12.3M | 7.8M | **16.6M** | 16.8M | 17.3M | 2.1x |
|
|
382
|
+
| enum | 11.7M | 12.1M | **16.2M** | 17.7M | 17.3M | 1.3x |
|
|
383
|
+
| bigint (min/max) | 12.0M | 7.7M | **15.9M** | — | — | 2.1x |
|
|
384
|
+
| tuple [string, int, bool] | 5.8M | 6.5M | **15.7M** | 17.1M | 16.3M | 2.4x |
|
|
385
|
+
| record\<string, number\> | 3.2M | 2.8M | **15.2M** | 12.1M | 15.2M | 5.5x |
|
|
386
|
+
| set\<string\> (5 items) | 3.7M | 2.3M | **14.7M** | — | — | 6.4x |
|
|
387
|
+
| set\<string\> (20 items) | 1.3M | 683K | **12.0M** | — | — | **18x** |
|
|
388
|
+
| map\<string, number\> (5 entries) | 2.1M | 1.4M | **13.1M** | — | — | 9.6x |
|
|
389
|
+
| map\<string, number\> (20 entries) | 635K | 362K | **8.3M** | — | — | **23x** |
|
|
390
|
+
| pipe (non-transform) | 8.6M | 5.6M | **15.9M** | — | — | 2.8x |
|
|
391
|
+
| discriminatedUnion (3 variants) | 3.3M | 4.0M | **15.8M** | 15.5M | 7.7M | 4.0x |
|
|
392
|
+
| discriminatedUnion (8 variants, rotating) | 2.7M | 3.4M | **9.2M** | — | — | 2.7x |
|
|
393
|
+
| plain union of 8 tagged objects (auto-discrim.) | 363K | 632K | **9.1M** | — | — | **14x** |
|
|
394
|
+
| strict object (DB row) | 1.8M | 3.1M | **10.9M** | — | — | 3.5x |
|
|
395
|
+
| medium object (valid) | 1.9M | 2.4M | **9.7M** | 11.2M | 7.7M | 4.1x |
|
|
396
|
+
| medium object (extra keys stripped) | 1.8M | 2.3M | **9.4M** | — | — | 4.2x |
|
|
397
|
+
| medium object (invalid) | 504K | 80K | **14.7M** | 2.9M | 7.7M | **184x** |
|
|
398
|
+
| large object (10 items) | 122K | 166K | **5.3M** | 5.9M | 1.2M | **32x** |
|
|
399
|
+
| large object (100 items) | 13K | 18K | **781K** | 1.3M | 125K | **43x** |
|
|
400
|
+
| recursive tree (7 nodes) | 569K | 2.1M | **8.2M** | 11.6M | 4.8M | 3.9x |
|
|
401
|
+
| recursive tree (121 nodes) | 32K | 135K | **800K** | 1.9M | 372K | 5.9x |
|
|
402
|
+
| nested recursion (7 nodes) | 391K | 1.0M | **7.9M** | 11.1M | 3.1M | 7.8x |
|
|
403
|
+
| nested recursion (121 nodes) | 24K | 62K | **818K** | 1.6M | 218K | **13x** |
|
|
404
|
+
| deeply nested object (243 leaves) | 11K | 20K | **828K** | 1.1M | 117K | **42x** |
|
|
405
|
+
| event log (combined) | 368K | 609K | **8.2M** | — | — | **13x** |
|
|
406
|
+
| object with transform (zero-capture) | 1.2M | 1.9M | **6.5M** | — | — | 3.4x |
|
|
407
|
+
| array 10 × transform (zero-capture) | 121K | 214K | **4.2M** | — | — | **20x** |
|
|
408
|
+
| array 50 × transform (zero-capture) | 25K | 44K | **1.0M** | — | — | **24x** |
|
|
409
|
+
| object with captured transform | 1.4M | 6.3M | **15.1M** | — | — | 2.4x |
|
|
410
|
+
| object with captured refine (cross-field) | 1.6M | 2.4M | **15.3M** | — | — | 6.3x |
|
|
411
|
+
| object with superRefine (cross-field) | 1.6M | 2.3M | **11.6M** | — | — | 5.0x |
|
|
425
412
|
|
|
426
413
|
_ops/s, higher is better. `vitest bench` on an Apple M4 Max (zod 4.3.6, zod v3 3.23.8, typia 12, ajv 8),
|
|
427
|
-
best of
|
|
414
|
+
best of three runs. The harness costs ~55 ns per iteration, so the fastest rows sit at that floor and gaps
|
|
428
415
|
between the AOT columns there are noise, not real._
|
|
429
416
|
|
|
430
417
|
Nested objects, arrays and recursive types gain the most. Rejection is fast because a failed
|
|
@@ -439,9 +426,8 @@ pnpm benchmark # run locally
|
|
|
439
426
|
An eligible schema compiles to a **fast path** — one `&&` chain validating the whole input with zero
|
|
440
427
|
allocations, reused by `.is()` and `parse()` — plus a **slow path** that collects errors, run only on
|
|
441
428
|
failure and deferred until `.error` is read. A `z.object()` strips, so it instead compiles to a single
|
|
442
|
-
pass that validates and rebuilds together, bailing on the first failure
|
|
443
|
-
idioms
|
|
444
|
-
so one of them in a schema no longer costs it the whole single-pass parse.
|
|
429
|
+
pass that validates and rebuilds together, bailing on the first failure — including the reshaping
|
|
430
|
+
idioms (array size checks, `.refine()`, `.default()`, `.trim()`, `.transform()`).
|
|
445
431
|
|
|
446
432
|
Regexes are pre-compiled with bounded repeats unrolled, checks run cheapest-first, discriminated unions
|
|
447
433
|
dispatch through a jump table (plain tagged unions are auto-discriminated into it), and oversized check
|
package/dist/core/iife.d.ts
CHANGED
|
@@ -11,8 +11,26 @@ import type { CompiledSchemaInfo } from "./pipeline.js";
|
|
|
11
11
|
* parse raises (see ZC_SR_DECL).
|
|
12
12
|
*/
|
|
13
13
|
export declare const ZOD_CONFIG_IMPORT = "import { config as __zodCompilerConfig, core as __zcCore, ZodRealError as __zcZodError } from \"zod\";";
|
|
14
|
-
/**
|
|
15
|
-
|
|
14
|
+
/**
|
|
15
|
+
* File-level `__zcMsg` declaration (must appear once after ZOD_CONFIG_IMPORT):
|
|
16
|
+
* the message an issue gets when nothing was baked into it at build time.
|
|
17
|
+
*
|
|
18
|
+
* Resolves zod's tail of `finalizeIssue` — `config.customError` then
|
|
19
|
+
* `config.localeError` then "Invalid input" — and does it PER CALL, because the
|
|
20
|
+
* config is mutable: `z.config({ localeError })` in an entry point runs after
|
|
21
|
+
* the schema modules it imports, so a value snapshotted at module init misses
|
|
22
|
+
* it. Reading a captured `localeError` alone also dropped `customError`
|
|
23
|
+
* outright, silently ignoring the global map most i18n setups install.
|
|
24
|
+
*
|
|
25
|
+
* The head of zod's chain — the schema's own `error` option — is baked into the
|
|
26
|
+
* issue at build time and short-circuits this. The one link that cannot be
|
|
27
|
+
* reproduced is a per-CALL `ctx.error`, which would have to travel through
|
|
28
|
+
* `safeParse`; that entry point sits at V8's inlining budget, where even an
|
|
29
|
+
* unused extra parameter measured ~12% on every parse.
|
|
30
|
+
*
|
|
31
|
+
* Only ever called while building an error, never on a successful parse.
|
|
32
|
+
*/
|
|
33
|
+
export declare const ZOD_MSG_DECLARATION: string;
|
|
16
34
|
/**
|
|
17
35
|
* Shared failure-result for __zcFin / __zcFinD. Inline mode (CLI emitter)
|
|
18
36
|
* declares it once per compiled file; lean mode (all unplugin bundlers) declares
|
|
@@ -127,8 +145,26 @@ export declare const FINZ_DECL = "function __zcFinZ(z,i){return new __ZcFailZ(z,
|
|
|
127
145
|
* partial fc can pass-through valid input but its `false` does not imply
|
|
128
146
|
* rejection (a default/catch may still succeed), so it would be unsound as a
|
|
129
147
|
* standalone guard.
|
|
148
|
+
*
|
|
149
|
+
* `~standard` is REPLACED, not merely preserved. Zod builds it lazily as
|
|
150
|
+
* `validate: (v) => safeParse(inst, v)` — the core FUNCTION, which goes straight
|
|
151
|
+
* to `inst._zod.run`. It never reads the schema's own `safeParse` property, so
|
|
152
|
+
* installing the compiled one leaves this route entirely uncompiled: measured
|
|
153
|
+
* 271.7 ns against the compiled 26.6 ns on the same schema, i.e. Standard Schema
|
|
154
|
+
* consumers (tRPC, Hono, TanStack) were getting plain Zod.
|
|
155
|
+
*
|
|
156
|
+
* Zod's own validate is captured first and kept as the throw path: it catches a
|
|
157
|
+
* synchronous throw and retries through `safeParseAsync`, which is how an async
|
|
158
|
+
* refinement resolves and how a throwing check surfaces as a rejected promise
|
|
159
|
+
* rather than a synchronous throw. The compiled validator cannot reproduce that
|
|
160
|
+
* (async schemas delegate to Zod anyway), so deferring to the original is both
|
|
161
|
+
* simpler and exact.
|
|
162
|
+
*
|
|
163
|
+
* Installed with defineProperty rather than assignment: Zod's lazy setter
|
|
164
|
+
* redefines the slot as non-writable, so a second `__zcMkv` on the same schema
|
|
165
|
+
* object — two exports aliasing one schema — would throw under ESM strict mode.
|
|
130
166
|
*/
|
|
131
|
-
export declare const MK_VALIDATOR_DECL
|
|
167
|
+
export declare const MK_VALIDATOR_DECL: string;
|
|
132
168
|
/**
|
|
133
169
|
* Generate a `/* @__PURE__ * /` IIFE wrapping a compiled validator.
|
|
134
170
|
*
|
package/dist/core/iife.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"iife.d.ts","sourceRoot":"","sources":["../../src/core/iife.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAExD;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,2GAC0E,CAAC;AAEzG
|
|
1
|
+
{"version":3,"file":"iife.d.ts","sourceRoot":"","sources":["../../src/core/iife.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAExD;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,2GAC0E,CAAC;AAEzG;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,mBAAmB,QAKH,CAAC;AAE9B;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,eAAe,QAMe,CAAC;AAE5C;yEACyE;AACzE,eAAO,MAAM,QAAQ,sGACgF,CAAC;AAEtG;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,iBAAiB,+DAA+D,CAAC;AAE9F;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,gBAAgB,QAG4B,CAAC;AAE1D,qGAAqG;AACrG,eAAO,MAAM,SAAS,uDAAuD,CAAC;AAE9E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsDG;AACH,eAAO,MAAM,iBAAiB,QAIhB,CAAC;AAUf;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAC1B,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,kBAAkB,EAC1B,OAAO,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;CAAE,GAC5C,MAAM,CAuBR"}
|
package/dist/core/iife.js
CHANGED
|
@@ -10,8 +10,30 @@
|
|
|
10
10
|
* parse raises (see ZC_SR_DECL).
|
|
11
11
|
*/
|
|
12
12
|
export const ZOD_CONFIG_IMPORT = 'import { config as __zodCompilerConfig, core as __zcCore, ZodRealError as __zcZodError } from "zod";';
|
|
13
|
-
/**
|
|
14
|
-
|
|
13
|
+
/**
|
|
14
|
+
* File-level `__zcMsg` declaration (must appear once after ZOD_CONFIG_IMPORT):
|
|
15
|
+
* the message an issue gets when nothing was baked into it at build time.
|
|
16
|
+
*
|
|
17
|
+
* Resolves zod's tail of `finalizeIssue` — `config.customError` then
|
|
18
|
+
* `config.localeError` then "Invalid input" — and does it PER CALL, because the
|
|
19
|
+
* config is mutable: `z.config({ localeError })` in an entry point runs after
|
|
20
|
+
* the schema modules it imports, so a value snapshotted at module init misses
|
|
21
|
+
* it. Reading a captured `localeError` alone also dropped `customError`
|
|
22
|
+
* outright, silently ignoring the global map most i18n setups install.
|
|
23
|
+
*
|
|
24
|
+
* The head of zod's chain — the schema's own `error` option — is baked into the
|
|
25
|
+
* issue at build time and short-circuits this. The one link that cannot be
|
|
26
|
+
* reproduced is a per-CALL `ctx.error`, which would have to travel through
|
|
27
|
+
* `safeParse`; that entry point sits at V8's inlining budget, where even an
|
|
28
|
+
* unused extra parameter measured ~12% on every parse.
|
|
29
|
+
*
|
|
30
|
+
* Only ever called while building an error, never on a successful parse.
|
|
31
|
+
*/
|
|
32
|
+
export const ZOD_MSG_DECLARATION = 'function __zcUw(m){return typeof m==="string"?m:(m===undefined||m===null?undefined:m.message);}' +
|
|
33
|
+
"var __zcMsg=function(iss){var c=__zodCompilerConfig(),m;" +
|
|
34
|
+
"if(c.customError){m=__zcUw(c.customError(iss));if(m!==undefined&&m!==null)return m;}" +
|
|
35
|
+
"if(c.localeError){m=__zcUw(c.localeError(iss));if(m!==undefined&&m!==null)return m;}" +
|
|
36
|
+
'return "Invalid input";};';
|
|
15
37
|
/**
|
|
16
38
|
* Shared failure-result for __zcFin / __zcFinD. Inline mode (CLI emitter)
|
|
17
39
|
* declares it once per compiled file; lean mode (all unplugin bundlers) declares
|
|
@@ -133,8 +155,29 @@ export const FINZ_DECL = "function __zcFinZ(z,i){return new __ZcFailZ(z,i);}";
|
|
|
133
155
|
* partial fc can pass-through valid input but its `false` does not imply
|
|
134
156
|
* rejection (a default/catch may still succeed), so it would be unsound as a
|
|
135
157
|
* standalone guard.
|
|
158
|
+
*
|
|
159
|
+
* `~standard` is REPLACED, not merely preserved. Zod builds it lazily as
|
|
160
|
+
* `validate: (v) => safeParse(inst, v)` — the core FUNCTION, which goes straight
|
|
161
|
+
* to `inst._zod.run`. It never reads the schema's own `safeParse` property, so
|
|
162
|
+
* installing the compiled one leaves this route entirely uncompiled: measured
|
|
163
|
+
* 271.7 ns against the compiled 26.6 ns on the same schema, i.e. Standard Schema
|
|
164
|
+
* consumers (tRPC, Hono, TanStack) were getting plain Zod.
|
|
165
|
+
*
|
|
166
|
+
* Zod's own validate is captured first and kept as the throw path: it catches a
|
|
167
|
+
* synchronous throw and retries through `safeParseAsync`, which is how an async
|
|
168
|
+
* refinement resolves and how a throwing check surfaces as a rejected promise
|
|
169
|
+
* rather than a synchronous throw. The compiled validator cannot reproduce that
|
|
170
|
+
* (async schemas delegate to Zod anyway), so deferring to the original is both
|
|
171
|
+
* simpler and exact.
|
|
172
|
+
*
|
|
173
|
+
* Installed with defineProperty rather than assignment: Zod's lazy setter
|
|
174
|
+
* redefines the slot as non-writable, so a second `__zcMkv` on the same schema
|
|
175
|
+
* object — two exports aliasing one schema — would throw under ESM strict mode.
|
|
136
176
|
*/
|
|
137
|
-
export const MK_VALIDATOR_DECL = "function __zcMkv(fn,schema,fc,is){var w=schema||{};w.parse=fc?function(input){if(fc(input))return input;var r=fn(input);if(r.success)return r.data;throw r.error;}:function(input){var r=fn(input);if(r.success)return r.data;throw r.error;};w.safeParse=fn;w.safeParseAsync=function(input){return Promise.resolve(fn(input));};w.parseAsync=fc?function(input){if(fc(input))return Promise.resolve(input);var r=fn(input);if(r.success)return Promise.resolve(r.data);return Promise.reject(r.error);}:function(input){var r=fn(input);if(r.success)return Promise.resolve(r.data);return Promise.reject(r.error);};w.is=is||function(input){return fn(input).success;};
|
|
177
|
+
export const MK_VALIDATOR_DECL = "function __zcMkv(fn,schema,fc,is){var w=schema||{};w.parse=fc?function(input){if(fc(input))return input;var r=fn(input);if(r.success)return r.data;throw r.error;}:function(input){var r=fn(input);if(r.success)return r.data;throw r.error;};w.safeParse=fn;w.safeParseAsync=function(input){return Promise.resolve(fn(input));};w.parseAsync=fc?function(input){if(fc(input))return Promise.resolve(input);var r=fn(input);if(r.success)return Promise.resolve(r.data);return Promise.reject(r.error);}:function(input){var r=fn(input);if(r.success)return Promise.resolve(r.data);return Promise.reject(r.error);};w.is=is||function(input){return fn(input).success;};" +
|
|
178
|
+
'var s=w["~standard"],zv=s&&s.validate;' +
|
|
179
|
+
'Object.defineProperty(w,"~standard",{configurable:true,value:{version:1,vendor:(s&&s.vendor)||"zod",validate:function(input){var r;try{if(fc&&fc(input))return{value:input};r=fn(input);}catch(e){if(zv)return zv(input);throw e;}return r.success?{value:r.data}:{issues:r.error.issues};}}});' +
|
|
180
|
+
"return w;}";
|
|
138
181
|
function extractFunctionName(functionDef) {
|
|
139
182
|
const match = /^function\s+(\w+)\s*\(/.exec(functionDef);
|
|
140
183
|
if (!match?.[1]) {
|
package/dist/core/iife.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"iife.js","sourceRoot":"","sources":["../../src/core/iife.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAC5B,sGAAsG,CAAC;AAEzG
|
|
1
|
+
{"version":3,"file":"iife.js","sourceRoot":"","sources":["../../src/core/iife.ts"],"names":[],"mappings":"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"}
|