zod-compiler 1.24.0 → 1.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -70
- package/dist/core/diagnostic.d.ts.map +1 -1
- package/dist/core/diagnostic.js +1 -0
- package/dist/core/diagnostic.js.map +1 -1
- package/dist/core/extract/extractors/readonly.d.ts +11 -4
- package/dist/core/extract/extractors/readonly.d.ts.map +1 -1
- package/dist/core/extract/extractors/readonly.js +61 -5
- package/dist/core/extract/extractors/readonly.js.map +1 -1
- package/dist/core/types.d.ts +1 -1
- package/dist/core/types.d.ts.map +1 -1
- package/dist/unplugin/hoist-compile.d.ts.map +1 -1
- package/dist/unplugin/hoist-compile.js +1 -1
- package/dist/unplugin/hoist-compile.js.map +1 -1
- package/dist/unplugin/hoist.d.ts.map +1 -1
- package/dist/unplugin/hoist.js +2 -1
- package/dist/unplugin/hoist.js.map +1 -1
- package/dist/unplugin/transform.d.ts.map +1 -1
- package/dist/unplugin/transform.js +1 -1
- package/dist/unplugin/transform.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -213,12 +213,11 @@ Validators share a runtime helper layer imported from one module, so each helper
|
|
|
213
213
|
bundle. Schemas in a file sharing a structurally identical sub-shape emit its error walk once —
|
|
214
214
|
**19-28% raw / 10-18% gzipped**, scaling with how much the file repeats.
|
|
215
215
|
|
|
216
|
-
Build plugins serve that module from
|
|
217
|
-
`__zod-compiler-runtime__` on webpack and rspack, which reject the `virtual:` scheme. A host
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
opt-in there.
|
|
216
|
+
Build plugins serve that module from a resolve hook (`virtual:zod-compiler/runtime`, or
|
|
217
|
+
`__zod-compiler-runtime__` on webpack and rspack, which reject the `virtual:` scheme). A loader host
|
|
218
|
+
has no hook, so [Turbopack](#nextjs-turbopack) imports the same code from the real subpath
|
|
219
|
+
`zod-compiler/runtime` instead — opt-in there, since it only pays off where the host bundles that
|
|
220
|
+
import rather than leaving it external.
|
|
222
221
|
|
|
223
222
|
**Transpile-only esbuild builds** (no `--bundle`) never fire the bundler's resolve hooks, so the
|
|
224
223
|
`virtual:` specifier would survive into `dist/` and fail at runtime. Set `codegenMode: "inline"` to emit
|
|
@@ -232,9 +231,9 @@ Set `output: "bag"` to also drop the retained Zod schema when you don't need `.s
|
|
|
232
231
|
|
|
233
232
|
### Next.js (Turbopack)
|
|
234
233
|
|
|
235
|
-
Turbopack — the default
|
|
236
|
-
plugins](https://nextjs.org/docs/app/api-reference/turbopack#webpack-plugins), so
|
|
237
|
-
|
|
234
|
+
Turbopack — the default since Next.js 16 — [runs webpack loaders but no webpack
|
|
235
|
+
plugins](https://nextjs.org/docs/app/api-reference/turbopack#webpack-plugins), so use the loader
|
|
236
|
+
entry point:
|
|
238
237
|
|
|
239
238
|
```typescript
|
|
240
239
|
// next.config.ts
|
|
@@ -259,70 +258,24 @@ const nextConfig: NextConfig = {
|
|
|
259
258
|
export default nextConfig;
|
|
260
259
|
```
|
|
261
260
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
`hoist.schemaNamePattern`
|
|
265
|
-
There is no `cache` option either: the loader keeps no disk cache of its own, because
|
|
266
|
-
Turbopack already caches loader results persistently, keyed on file content plus the dependencies
|
|
267
|
-
the loader declares. Nothing lands in `node_modules/.cache/zod-compiler`, so the CI cache step under
|
|
268
|
-
[Large projects and CI](#large-projects-and-ci) does not apply — cache `.next/cache` instead.
|
|
261
|
+
Automatic mode, unchanged sources, `next dev` and `next build`. Options go in the object form —
|
|
262
|
+
`loaders: [{ loader: "zod-compiler/turbopack", options: { verbose: true } }]` — and must be plain
|
|
263
|
+
JSON, so `hoist.schemaNamePattern` takes a string, not a RegExp.
|
|
269
264
|
|
|
270
|
-
|
|
271
|
-
them the loader is invoked on every `.ts` in the project. Keep the `content` pattern this loose:
|
|
272
|
-
narrowing it to `"zod"` silently skips `zod/v4`, `zod/mini` and the `zod-compiler` import behind
|
|
273
|
-
`schemas: "explicit"`, and skipped files just quietly stay uncompiled. Drop the `content` clause
|
|
274
|
-
entirely if you set a custom `hoist.schemaNamePattern`, which makes schema roots out of identifiers
|
|
275
|
-
(`UserModel`) in files that need never mention zod at all.
|
|
265
|
+
Three things worth knowing:
|
|
276
266
|
|
|
277
|
-
|
|
278
|
-
|
|
267
|
+
- **Keep the `content` pattern loose.** Narrowing it to `"zod"` skips `zod/v4`, `zod/mini` and the
|
|
268
|
+
`zod-compiler` import behind `schemas: "explicit"` — those files just quietly stay uncompiled.
|
|
269
|
+
- **`codegenMode: "lean"` is App-Router-only.** It shares one copy of the helpers across the bundle,
|
|
270
|
+
but Pages Router server code externalizes `node_modules` imports unless
|
|
271
|
+
[`bundlePagesRouterDependencies`](https://nextjs.org/docs/pages/api-reference/config/next-config-js/bundlePagesRouterDependencies)
|
|
272
|
+
is on, so a devDependency install throws `ERR_MODULE_NOT_FOUND` in production.
|
|
273
|
+
- **A `"use server"` file can only export async functions**, so keep schemas there inside a function —
|
|
274
|
+
[hoisting](#schema-hoisting) still compiles them. `"use client"` modules need nothing special.
|
|
279
275
|
|
|
280
|
-
|
|
281
|
-
`zod-compiler
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
```typescript
|
|
285
|
-
loaders: [{ loader: "zod-compiler/turbopack", options: { codegenMode: "lean" } }],
|
|
286
|
-
```
|
|
287
|
-
|
|
288
|
-
It is opt-in because it only holds where the host **bundles** that import. Next.js does for client
|
|
289
|
-
and App Router server code. Pages Router server code externalizes `node_modules` imports unless
|
|
290
|
-
[`bundlePagesRouterDependencies`](https://nextjs.org/docs/pages/api-reference/config/next-config-js/bundlePagesRouterDependencies)
|
|
291
|
-
is on — and `zod-compiler` is usually a devDependency, so a production install prunes it and the
|
|
292
|
-
route throws `ERR_MODULE_NOT_FOUND` on the first request, with nothing failing at build time. Use
|
|
293
|
-
lean for an App-Router-only app, or move `zod-compiler` to `dependencies`.
|
|
294
|
-
|
|
295
|
-
Expect a file reachable from both client and server components to be transformed more than once —
|
|
296
|
-
Turbopack applies loaders per output environment, and runs them in a worker pool, so the cache of
|
|
297
|
-
executed modules that makes discovery cheap is only shared within a worker. The first build of a
|
|
298
|
-
large schema set is the expensive one.
|
|
299
|
-
|
|
300
|
-
`next dev --webpack` / `next build --webpack` remain available, where `zod-compiler/webpack` applies
|
|
301
|
-
unchanged:
|
|
302
|
-
|
|
303
|
-
```typescript
|
|
304
|
-
// next.config.ts — webpack only
|
|
305
|
-
import type { NextConfig } from "next";
|
|
306
|
-
import zodCompiler from "zod-compiler/webpack";
|
|
307
|
-
|
|
308
|
-
const nextConfig: NextConfig = {
|
|
309
|
-
webpack: (config) => {
|
|
310
|
-
config.plugins?.push(zodCompiler({ verbose: true }));
|
|
311
|
-
return config;
|
|
312
|
-
},
|
|
313
|
-
};
|
|
314
|
-
|
|
315
|
-
export default nextConfig;
|
|
316
|
-
```
|
|
317
|
-
|
|
318
|
-
Schemas exported from a `"use client"` module compile like any other — the generated runtime is
|
|
319
|
-
emitted below the directive so it stays the first statement. A `"use server"` file is different, and
|
|
320
|
-
not because of zod-compiler: Next.js only allows async function exports there, so a schema in one
|
|
321
|
-
has to stay inside a function, where [hoisting](#schema-hoisting) still lifts and compiles it.
|
|
322
|
-
|
|
323
|
-
Note also the React Server Components rule that a server component may not import a _value_ from a
|
|
324
|
-
`"use client"` module — that yields a client reference rather than the schema, with or without
|
|
325
|
-
zod-compiler.
|
|
276
|
+
Turbopack caches loader results itself, so cache `.next/cache` in CI rather than
|
|
277
|
+
`node_modules/.cache/zod-compiler`. `next dev --webpack` / `next build --webpack` still work, with
|
|
278
|
+
`zod-compiler/webpack` in a `webpack()` config as usual.
|
|
326
279
|
|
|
327
280
|
### SWC
|
|
328
281
|
|
|
@@ -477,6 +430,7 @@ A schema delegates to Zod when it reaches JavaScript the generated code cannot r
|
|
|
477
430
|
| `ctx`-taking or `async` callbacks | Needs Zod's parse context / the async pipeline |
|
|
478
431
|
| `z.url()`, `z.jwt()` | Algorithmic formats (`new URL()`, signature parsing) |
|
|
479
432
|
| Overlapping or policy-sensitive object intersections | Zod's independent parse-and-merge semantics cannot be safely collapsed |
|
|
433
|
+
| `.readonly()` over a container | Zod freezes its rebuilt output; compiled containers are the caller's input |
|
|
480
434
|
| Dynamic error maps, unresolvable `z.lazy()` | Not knowable at build time |
|
|
481
435
|
|
|
482
436
|
Everything else compiles, including context-free `preprocess` callbacks and
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diagnostic.d.ts","names":[],"sources":["../../src/core/diagnostic.ts"],"mappings":";;KASY;UAEK;;EAEf;;EAEA;;EAEA,QAAQ;;EAER;;EAEA;;EAEA,UAAU;;UAGK;;EAEf,MAAM;;EAEN;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;IAAa;IAAgB;IAAc;;;;;;;
|
|
1
|
+
{"version":3,"file":"diagnostic.d.ts","names":[],"sources":["../../src/core/diagnostic.ts"],"mappings":";;KASY;UAEK;;EAEf;;EAEA;;EAEA,QAAQ;;EAER;;EAEA;;EAEA,UAAU;;UAGK;;EAEf,MAAM;;EAEN;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;IAAa;IAAgB;IAAc;;;;;;;iBA+L7B,eAAe,IAAI,WAAW"}
|
package/dist/core/diagnostic.js
CHANGED
|
@@ -21,6 +21,7 @@ const FALLBACK_HINTS = {
|
|
|
21
21
|
superRefine: "Replace .superRefine() with built-in checks if possible",
|
|
22
22
|
custom: "Replace z.custom() with a supported schema type",
|
|
23
23
|
lazy: "Ensure the lazy getter resolves to a static schema (recursion compiles automatically)",
|
|
24
|
+
readonly: "Zod freezes the container it rebuilt; compiled containers are the caller's own input, so this delegates rather than freeze it. .readonly() over a primitive compiles",
|
|
24
25
|
unsupported: "This schema type is not yet supported by zod-compiler",
|
|
25
26
|
coalesced: "Every property falls back to Zod, so the whole object is delegated once (faster than per-field delegation)"
|
|
26
27
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diagnostic.js","names":[],"sources":["../../src/core/diagnostic.ts"],"sourcesContent":["/**\n * Schema diagnostic utilities for the `check` command.\n * Walks SchemaIR in a single pass and collects per-node diagnostic info.\n */\n\nimport type { SchemaIR } from \"./types.js\";\n\n// ─── Types ──────────────────────────────────────────────────────────────────\n\nexport type NodeStatus = \"compiled\" | \"fallback\";\n\nexport interface DiagnosticNode {\n /** SchemaIR type (e.g. \"string\", \"object\", \"fallback\") */\n type: string;\n /** Dot-separated path from root (e.g. \".name\", \".addresses[]\") */\n path: string;\n /** Whether this node is compiled or falls back to Zod */\n status: NodeStatus;\n /** Fallback reason when status is \"fallback\" */\n reason?: string;\n /** Actionable hint for fixing the fallback */\n hint?: string;\n /** Child diagnostic nodes */\n children: DiagnosticNode[];\n}\n\nexport interface DiagnosticResult {\n /** Root diagnostic tree */\n root: DiagnosticNode;\n /** Total leaf node count */\n total: number;\n /** Number of compiled leaf nodes */\n compilable: number;\n /** Coverage percentage (0-100) */\n coveragePct: number;\n /** Whether the schema is eligible for Fast Path */\n fastPathEligible: boolean;\n /** Reason Fast Path is ineligible (when fastPathEligible is false) */\n fastPathBlocker?: string;\n /** Flat list of fallback entries for summary display */\n fallbacks: { reason: string; path: string; hint: string }[];\n}\n\n// ─── Fast Path Eligibility ──────────────────────────────────────────────────\n\n/** Schema types that block Fast Path eligibility. */\nconst FAST_PATH_BLOCKERS = new Set<string>([\"fallback\", \"effect\", \"stringBool\"]);\n\n/** Check if a single node blocks Fast Path (without recursing). */\nfunction detectFastPathBlocker(ir: SchemaIR): string | null {\n if (FAST_PATH_BLOCKERS.has(ir.type)) {\n return ir.type === \"fallback\" ? `fallback (${(ir as { reason: string }).reason})` : ir.type;\n }\n if (\"coerce\" in ir && ir.coerce) {\n return `coerce (${ir.type})`;\n }\n // Value-mutating string checks make the schema slow-path only: overwrite\n // effects (.trim()/.toLowerCase()) rewrite the value and url checks trim it,\n // while the fast path returns input unchanged.\n if (ir.type === \"string\") {\n for (const check of ir.checks) {\n if (check.kind === \"overwrite_effect\") return \"overwrite (.trim()/.toLowerCase())\";\n if (check.kind === \"string_format\" && check.format === \"url\") return \"url (trims value)\";\n }\n }\n return null;\n}\n\n// ─── Hint Generation ────────────────────────────────────────────────────────\n\nconst FALLBACK_HINTS: Record<string, string> = {\n transform: \"Extract transform into a separate post-processing step\",\n refine: \"Replace .refine() with built-in checks (e.g. .min(), .max(), .regex())\",\n superRefine: \"Replace .superRefine() with built-in checks if possible\",\n custom: \"Replace z.custom() with a supported schema type\",\n lazy: \"Ensure the lazy getter resolves to a static schema (recursion compiles automatically)\",\n unsupported: \"This schema type is not yet supported by zod-compiler\",\n coalesced:\n \"Every property falls back to Zod, so the whole object is delegated once (faster than per-field delegation)\",\n};\n\nfunction getHint(reason: string): string {\n return FALLBACK_HINTS[reason] ?? \"Check zod-compiler documentation for supported schemas\";\n}\n\n// ─── Child Iteration (with path computation) ───────────────────────────────\n\n/** Yields [childPath, childIR] pairs for a given SchemaIR node. */\nfunction* iterChildren(ir: SchemaIR, parentPath: string): Generator<[string, SchemaIR]> {\n switch (ir.type) {\n case \"object\":\n for (const [key, child] of Object.entries(ir.properties)) {\n yield [`${parentPath}.${key}`, child];\n }\n break;\n case \"array\":\n yield [`${parentPath}[]`, ir.element];\n break;\n case \"tuple\":\n for (const [i, item] of ir.items.entries()) {\n yield [`${parentPath}[${i}]`, item];\n }\n if (ir.rest) yield [`${parentPath}[...rest]`, ir.rest];\n break;\n case \"record\":\n yield [`${parentPath}[key]`, ir.keyType];\n yield [`${parentPath}[value]`, ir.valueType];\n break;\n case \"set\":\n yield [`${parentPath}[element]`, ir.valueType];\n break;\n case \"map\":\n yield [`${parentPath}[key]`, ir.keyType];\n yield [`${parentPath}[value]`, ir.valueType];\n break;\n case \"union\":\n case \"discriminatedUnion\":\n for (const [i, opt] of ir.options.entries()) {\n yield [`${parentPath}[${i}]`, opt];\n }\n break;\n case \"intersection\":\n yield [`${parentPath}[left]`, ir.left];\n yield [`${parentPath}[right]`, ir.right];\n break;\n case \"optional\":\n case \"nullable\":\n case \"readonly\":\n yield [parentPath, ir.inner];\n break;\n case \"default\":\n case \"catch\":\n yield [parentPath, ir.inner];\n break;\n case \"pipe\":\n yield [`${parentPath}[in]`, ir.in];\n yield [`${parentPath}[out]`, ir.out];\n break;\n case \"effect\":\n yield [`${parentPath}[inner]`, ir.inner];\n break;\n case \"recursionTarget\":\n // Transparent wrapper around a non-root recursive sub-schema: descend so\n // coverage and any inner fallbacks are reported at the same path.\n yield [parentPath, ir.inner];\n break;\n case \"zodDelegate\":\n // The success path is compiled; only issue materialization delegates.\n yield [parentPath, ir.inner];\n break;\n }\n}\n\n// ─── Single-Pass Diagnostic Walker ──────────────────────────────────────────\n\ninterface WalkResult {\n node: DiagnosticNode;\n total: number;\n compilable: number;\n fallbacks: { reason: string; path: string; hint: string }[];\n /** First Fast Path blocker found in this subtree, or null if eligible. */\n fastPathBlocker: string | null;\n}\n\nfunction walkIR(ir: SchemaIR, currentPath: string): WalkResult {\n // Fallback leaf\n if (ir.type === \"fallback\") {\n const hint = getHint(ir.reason);\n const nodePath = currentPath || \"(root)\";\n return {\n node: {\n type: ir.type,\n path: nodePath,\n status: \"fallback\",\n reason: ir.reason,\n hint,\n children: [],\n },\n total: 1,\n compilable: 0,\n fallbacks: [{ reason: ir.reason, path: nodePath, hint }],\n fastPathBlocker: `fallback (${ir.reason})`,\n };\n }\n\n // Check if this node itself blocks Fast Path\n let fastPathBlocker = detectFastPathBlocker(ir);\n\n // Recurse into children\n const children: DiagnosticNode[] = [];\n let total = 0;\n let compilable = 0;\n const fallbacks: { reason: string; path: string; hint: string }[] = [];\n\n for (const [childPath, child] of iterChildren(ir, currentPath)) {\n const r = walkIR(child, childPath);\n children.push(r.node);\n total += r.total;\n compilable += r.compilable;\n fallbacks.push(...r.fallbacks);\n if (fastPathBlocker === null && r.fastPathBlocker !== null) {\n fastPathBlocker = r.fastPathBlocker;\n }\n }\n\n // Leaf node (no children produced by iterChildren)\n if (children.length === 0) {\n total = 1;\n compilable = 1;\n }\n\n return {\n node: {\n type: ir.type,\n path: currentPath || \"(root)\",\n status: \"compiled\",\n children,\n },\n total,\n compilable,\n fallbacks,\n fastPathBlocker,\n };\n}\n\n/**\n * Diagnose a SchemaIR in a single pass.\n * Returns a diagnostic tree with coverage stats, Fast Path eligibility, and actionable hints.\n */\nexport function diagnoseSchema(ir: SchemaIR): DiagnosticResult {\n const { node: root, total, compilable, fallbacks, fastPathBlocker } = walkIR(ir, \"\");\n const coveragePct = total > 0 ? Math.round((compilable / total) * 100) : 100;\n\n const result: DiagnosticResult = {\n root,\n total,\n compilable,\n coveragePct,\n fastPathEligible: fastPathBlocker === null,\n fallbacks,\n };\n if (fastPathBlocker !== null) {\n result.fastPathBlocker = fastPathBlocker;\n }\n return result;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"diagnostic.js","names":[],"sources":["../../src/core/diagnostic.ts"],"sourcesContent":["/**\n * Schema diagnostic utilities for the `check` command.\n * Walks SchemaIR in a single pass and collects per-node diagnostic info.\n */\n\nimport type { SchemaIR } from \"./types.js\";\n\n// ─── Types ──────────────────────────────────────────────────────────────────\n\nexport type NodeStatus = \"compiled\" | \"fallback\";\n\nexport interface DiagnosticNode {\n /** SchemaIR type (e.g. \"string\", \"object\", \"fallback\") */\n type: string;\n /** Dot-separated path from root (e.g. \".name\", \".addresses[]\") */\n path: string;\n /** Whether this node is compiled or falls back to Zod */\n status: NodeStatus;\n /** Fallback reason when status is \"fallback\" */\n reason?: string;\n /** Actionable hint for fixing the fallback */\n hint?: string;\n /** Child diagnostic nodes */\n children: DiagnosticNode[];\n}\n\nexport interface DiagnosticResult {\n /** Root diagnostic tree */\n root: DiagnosticNode;\n /** Total leaf node count */\n total: number;\n /** Number of compiled leaf nodes */\n compilable: number;\n /** Coverage percentage (0-100) */\n coveragePct: number;\n /** Whether the schema is eligible for Fast Path */\n fastPathEligible: boolean;\n /** Reason Fast Path is ineligible (when fastPathEligible is false) */\n fastPathBlocker?: string;\n /** Flat list of fallback entries for summary display */\n fallbacks: { reason: string; path: string; hint: string }[];\n}\n\n// ─── Fast Path Eligibility ──────────────────────────────────────────────────\n\n/** Schema types that block Fast Path eligibility. */\nconst FAST_PATH_BLOCKERS = new Set<string>([\"fallback\", \"effect\", \"stringBool\"]);\n\n/** Check if a single node blocks Fast Path (without recursing). */\nfunction detectFastPathBlocker(ir: SchemaIR): string | null {\n if (FAST_PATH_BLOCKERS.has(ir.type)) {\n return ir.type === \"fallback\" ? `fallback (${(ir as { reason: string }).reason})` : ir.type;\n }\n if (\"coerce\" in ir && ir.coerce) {\n return `coerce (${ir.type})`;\n }\n // Value-mutating string checks make the schema slow-path only: overwrite\n // effects (.trim()/.toLowerCase()) rewrite the value and url checks trim it,\n // while the fast path returns input unchanged.\n if (ir.type === \"string\") {\n for (const check of ir.checks) {\n if (check.kind === \"overwrite_effect\") return \"overwrite (.trim()/.toLowerCase())\";\n if (check.kind === \"string_format\" && check.format === \"url\") return \"url (trims value)\";\n }\n }\n return null;\n}\n\n// ─── Hint Generation ────────────────────────────────────────────────────────\n\nconst FALLBACK_HINTS: Record<string, string> = {\n transform: \"Extract transform into a separate post-processing step\",\n refine: \"Replace .refine() with built-in checks (e.g. .min(), .max(), .regex())\",\n superRefine: \"Replace .superRefine() with built-in checks if possible\",\n custom: \"Replace z.custom() with a supported schema type\",\n lazy: \"Ensure the lazy getter resolves to a static schema (recursion compiles automatically)\",\n readonly:\n \"Zod freezes the container it rebuilt; compiled containers are the caller's own input, so this delegates rather than freeze it. .readonly() over a primitive compiles\",\n unsupported: \"This schema type is not yet supported by zod-compiler\",\n coalesced:\n \"Every property falls back to Zod, so the whole object is delegated once (faster than per-field delegation)\",\n};\n\nfunction getHint(reason: string): string {\n return FALLBACK_HINTS[reason] ?? \"Check zod-compiler documentation for supported schemas\";\n}\n\n// ─── Child Iteration (with path computation) ───────────────────────────────\n\n/** Yields [childPath, childIR] pairs for a given SchemaIR node. */\nfunction* iterChildren(ir: SchemaIR, parentPath: string): Generator<[string, SchemaIR]> {\n switch (ir.type) {\n case \"object\":\n for (const [key, child] of Object.entries(ir.properties)) {\n yield [`${parentPath}.${key}`, child];\n }\n break;\n case \"array\":\n yield [`${parentPath}[]`, ir.element];\n break;\n case \"tuple\":\n for (const [i, item] of ir.items.entries()) {\n yield [`${parentPath}[${i}]`, item];\n }\n if (ir.rest) yield [`${parentPath}[...rest]`, ir.rest];\n break;\n case \"record\":\n yield [`${parentPath}[key]`, ir.keyType];\n yield [`${parentPath}[value]`, ir.valueType];\n break;\n case \"set\":\n yield [`${parentPath}[element]`, ir.valueType];\n break;\n case \"map\":\n yield [`${parentPath}[key]`, ir.keyType];\n yield [`${parentPath}[value]`, ir.valueType];\n break;\n case \"union\":\n case \"discriminatedUnion\":\n for (const [i, opt] of ir.options.entries()) {\n yield [`${parentPath}[${i}]`, opt];\n }\n break;\n case \"intersection\":\n yield [`${parentPath}[left]`, ir.left];\n yield [`${parentPath}[right]`, ir.right];\n break;\n case \"optional\":\n case \"nullable\":\n case \"readonly\":\n yield [parentPath, ir.inner];\n break;\n case \"default\":\n case \"catch\":\n yield [parentPath, ir.inner];\n break;\n case \"pipe\":\n yield [`${parentPath}[in]`, ir.in];\n yield [`${parentPath}[out]`, ir.out];\n break;\n case \"effect\":\n yield [`${parentPath}[inner]`, ir.inner];\n break;\n case \"recursionTarget\":\n // Transparent wrapper around a non-root recursive sub-schema: descend so\n // coverage and any inner fallbacks are reported at the same path.\n yield [parentPath, ir.inner];\n break;\n case \"zodDelegate\":\n // The success path is compiled; only issue materialization delegates.\n yield [parentPath, ir.inner];\n break;\n }\n}\n\n// ─── Single-Pass Diagnostic Walker ──────────────────────────────────────────\n\ninterface WalkResult {\n node: DiagnosticNode;\n total: number;\n compilable: number;\n fallbacks: { reason: string; path: string; hint: string }[];\n /** First Fast Path blocker found in this subtree, or null if eligible. */\n fastPathBlocker: string | null;\n}\n\nfunction walkIR(ir: SchemaIR, currentPath: string): WalkResult {\n // Fallback leaf\n if (ir.type === \"fallback\") {\n const hint = getHint(ir.reason);\n const nodePath = currentPath || \"(root)\";\n return {\n node: {\n type: ir.type,\n path: nodePath,\n status: \"fallback\",\n reason: ir.reason,\n hint,\n children: [],\n },\n total: 1,\n compilable: 0,\n fallbacks: [{ reason: ir.reason, path: nodePath, hint }],\n fastPathBlocker: `fallback (${ir.reason})`,\n };\n }\n\n // Check if this node itself blocks Fast Path\n let fastPathBlocker = detectFastPathBlocker(ir);\n\n // Recurse into children\n const children: DiagnosticNode[] = [];\n let total = 0;\n let compilable = 0;\n const fallbacks: { reason: string; path: string; hint: string }[] = [];\n\n for (const [childPath, child] of iterChildren(ir, currentPath)) {\n const r = walkIR(child, childPath);\n children.push(r.node);\n total += r.total;\n compilable += r.compilable;\n fallbacks.push(...r.fallbacks);\n if (fastPathBlocker === null && r.fastPathBlocker !== null) {\n fastPathBlocker = r.fastPathBlocker;\n }\n }\n\n // Leaf node (no children produced by iterChildren)\n if (children.length === 0) {\n total = 1;\n compilable = 1;\n }\n\n return {\n node: {\n type: ir.type,\n path: currentPath || \"(root)\",\n status: \"compiled\",\n children,\n },\n total,\n compilable,\n fallbacks,\n fastPathBlocker,\n };\n}\n\n/**\n * Diagnose a SchemaIR in a single pass.\n * Returns a diagnostic tree with coverage stats, Fast Path eligibility, and actionable hints.\n */\nexport function diagnoseSchema(ir: SchemaIR): DiagnosticResult {\n const { node: root, total, compilable, fallbacks, fastPathBlocker } = walkIR(ir, \"\");\n const coveragePct = total > 0 ? Math.round((compilable / total) * 100) : 100;\n\n const result: DiagnosticResult = {\n root,\n total,\n compilable,\n coveragePct,\n fastPathEligible: fastPathBlocker === null,\n fallbacks,\n };\n if (fastPathBlocker !== null) {\n result.fastPathBlocker = fastPathBlocker;\n }\n return result;\n}\n"],"mappings":"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"}
|
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
import { Extractor } from "../types.js";
|
|
2
2
|
//#region src/core/extract/extractors/readonly.d.ts
|
|
3
3
|
/**
|
|
4
|
-
* z.readonly() freezes the parse OUTPUT in Zod.
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* z.readonly() freezes the parse OUTPUT in Zod.
|
|
5
|
+
*
|
|
6
|
+
* Over a primitive that freeze is unobservable, so the wrapper compiles away
|
|
7
|
+
* entirely and a single readonly field stops forcing its whole enclosing object
|
|
8
|
+
* onto the eager walk.
|
|
9
|
+
*
|
|
10
|
+
* Over a container it is very much observable, and compiled validators return
|
|
11
|
+
* the caller's input as-is for every container except a stripping object — so
|
|
12
|
+
* emitting Object.freeze would freeze the caller's own data, a side effect Zod
|
|
13
|
+
* avoids by freezing the object it rebuilt. Those keep delegating to Zod, which
|
|
14
|
+
* rebuilds and freezes its own output.
|
|
8
15
|
*/
|
|
9
16
|
declare const extractReadonly: Extractor;
|
|
10
17
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"readonly.d.ts","names":[],"sources":["../../../../src/core/extract/extractors/readonly.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"readonly.d.ts","names":[],"sources":["../../../../src/core/extract/extractors/readonly.ts"],"mappings":";;;;;;;;;;;;;;;cA0Ea,iBAAiB"}
|
|
@@ -1,11 +1,67 @@
|
|
|
1
1
|
//#region src/core/extract/extractors/readonly.ts
|
|
2
|
+
/** Does this node carry a check that replaces its value with an arbitrary one? */
|
|
3
|
+
function rewritesValue(ir) {
|
|
4
|
+
return ir.checks?.some((check) => check.kind === "overwrite_effect") === true;
|
|
5
|
+
}
|
|
2
6
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
+
* Does freezing this node's output provably do nothing?
|
|
8
|
+
*
|
|
9
|
+
* `Object.freeze` is a no-op on a primitive — `Object.isFrozen("a")` is already
|
|
10
|
+
* `true` — so a `.readonly()` whose inner always yields one is a pure
|
|
11
|
+
* type-level wrapper that can compile to its inner schema unchanged.
|
|
12
|
+
*
|
|
13
|
+
* Deliberately conservative. `any`/`unknown`/`custom`/`effect`/`pipe` can each
|
|
14
|
+
* yield an object at runtime, `default`/`catch` can substitute one, and `date`/
|
|
15
|
+
* `file` ARE objects, so none of them qualify — they keep the delegation below.
|
|
7
16
|
*/
|
|
8
|
-
|
|
17
|
+
function freezeIsNoop(ir) {
|
|
18
|
+
if (rewritesValue(ir)) return false;
|
|
19
|
+
switch (ir.type) {
|
|
20
|
+
case "string":
|
|
21
|
+
case "number":
|
|
22
|
+
case "boolean":
|
|
23
|
+
case "bigint":
|
|
24
|
+
case "symbol":
|
|
25
|
+
case "null":
|
|
26
|
+
case "undefined":
|
|
27
|
+
case "void":
|
|
28
|
+
case "nan":
|
|
29
|
+
case "never":
|
|
30
|
+
case "enum":
|
|
31
|
+
case "templateLiteral":
|
|
32
|
+
case "stringBool": return true;
|
|
33
|
+
case "literal": return ir.values.every((value) => value === null || typeof value !== "object" && typeof value !== "function");
|
|
34
|
+
case "optional":
|
|
35
|
+
case "nullable":
|
|
36
|
+
case "readonly": return freezeIsNoop(ir.inner);
|
|
37
|
+
case "union":
|
|
38
|
+
case "discriminatedUnion": return ir.options.every(freezeIsNoop);
|
|
39
|
+
default: return false;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* z.readonly() freezes the parse OUTPUT in Zod.
|
|
44
|
+
*
|
|
45
|
+
* Over a primitive that freeze is unobservable, so the wrapper compiles away
|
|
46
|
+
* entirely and a single readonly field stops forcing its whole enclosing object
|
|
47
|
+
* onto the eager walk.
|
|
48
|
+
*
|
|
49
|
+
* Over a container it is very much observable, and compiled validators return
|
|
50
|
+
* the caller's input as-is for every container except a stripping object — so
|
|
51
|
+
* emitting Object.freeze would freeze the caller's own data, a side effect Zod
|
|
52
|
+
* avoids by freezing the object it rebuilt. Those keep delegating to Zod, which
|
|
53
|
+
* rebuilds and freezes its own output.
|
|
54
|
+
*/
|
|
55
|
+
const extractReadonly = (def, ctx) => {
|
|
56
|
+
const refMark = ctx.refs?.length ?? 0;
|
|
57
|
+
const inner = ctx.visit(def.innerType, "._zod.def.innerType");
|
|
58
|
+
if (freezeIsNoop(inner)) return {
|
|
59
|
+
type: "readonly",
|
|
60
|
+
inner
|
|
61
|
+
};
|
|
62
|
+
if (ctx.refs) ctx.refs.length = refMark;
|
|
63
|
+
return ctx.fallback("readonly");
|
|
64
|
+
};
|
|
9
65
|
//#endregion
|
|
10
66
|
export { extractReadonly };
|
|
11
67
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"readonly.js","names":[],"sources":["../../../../src/core/extract/extractors/readonly.ts"],"sourcesContent":["import type { Extractor } from \"../types.js\";\n\n/**\n * z.readonly() freezes the parse OUTPUT in Zod
|
|
1
|
+
{"version":3,"file":"readonly.js","names":[],"sources":["../../../../src/core/extract/extractors/readonly.ts"],"sourcesContent":["import type { SchemaIR } from \"../../types.js\";\nimport type { Extractor } from \"../types.js\";\n\n/** Does this node carry a check that replaces its value with an arbitrary one? */\nfunction rewritesValue(ir: SchemaIR): boolean {\n const checks = (ir as { checks?: readonly { kind: string }[] }).checks;\n return checks?.some((check) => check.kind === \"overwrite_effect\") === true;\n}\n\n/**\n * Does freezing this node's output provably do nothing?\n *\n * `Object.freeze` is a no-op on a primitive — `Object.isFrozen(\"a\")` is already\n * `true` — so a `.readonly()` whose inner always yields one is a pure\n * type-level wrapper that can compile to its inner schema unchanged.\n *\n * Deliberately conservative. `any`/`unknown`/`custom`/`effect`/`pipe` can each\n * yield an object at runtime, `default`/`catch` can substitute one, and `date`/\n * `file` ARE objects, so none of them qualify — they keep the delegation below.\n */\nfunction freezeIsNoop(ir: SchemaIR): boolean {\n // `.overwrite(fn)` — and the built-ins that compile to it, `.trim()` /\n // `.toLowerCase()` — substitutes whatever its callback returns, so the IR tag\n // stops predicting the output type: `z.string().overwrite(v => ({ v }))` is a\n // `string` node that yields an object, which Zod's readonly then freezes.\n // Checked ahead of the switch so no allowlisted type can smuggle one in.\n if (rewritesValue(ir)) return false;\n switch (ir.type) {\n case \"string\":\n case \"number\":\n case \"boolean\":\n case \"bigint\":\n case \"symbol\":\n case \"null\":\n case \"undefined\":\n case \"void\":\n case \"nan\":\n // Yields no value at all, so there is nothing for a freeze to act on.\n case \"never\":\n case \"enum\":\n case \"templateLiteral\":\n case \"stringBool\":\n return true;\n // z.literal() compares by identity and accepts reference values, so a\n // literal qualifies only when every one of its values is a primitive.\n case \"literal\":\n return ir.values.every(\n (value) => value === null || (typeof value !== \"object\" && typeof value !== \"function\"),\n );\n case \"optional\":\n case \"nullable\":\n case \"readonly\":\n return freezeIsNoop(ir.inner);\n case \"union\":\n case \"discriminatedUnion\":\n return ir.options.every(freezeIsNoop);\n default:\n return false;\n }\n}\n\n/**\n * z.readonly() freezes the parse OUTPUT in Zod.\n *\n * Over a primitive that freeze is unobservable, so the wrapper compiles away\n * entirely and a single readonly field stops forcing its whole enclosing object\n * onto the eager walk.\n *\n * Over a container it is very much observable, and compiled validators return\n * the caller's input as-is for every container except a stripping object — so\n * emitting Object.freeze would freeze the caller's own data, a side effect Zod\n * avoids by freezing the object it rebuilt. Those keep delegating to Zod, which\n * rebuilds and freezes its own output.\n */\nexport const extractReadonly: Extractor = (def, ctx) => {\n const refMark = ctx.refs?.length ?? 0;\n const inner = ctx.visit(def.innerType, \"._zod.def.innerType\");\n if (freezeIsNoop(inner)) return { type: \"readonly\", inner };\n // The whole subtree is being discarded, so roll back any ref-table entries\n // its fallbacks registered — otherwise __rf[] retains schemas the emitted\n // code never reads (same rollback extractObject does when it coalesces).\n if (ctx.refs) ctx.refs.length = refMark;\n return ctx.fallback(\"readonly\");\n};\n"],"mappings":";;AAIA,SAAS,cAAc,IAAuB;CAE5C,OADgB,GAAgD,QACjD,MAAM,UAAU,MAAM,SAAS,kBAAkB,MAAM;AACxE;;;;;;;;;;;;AAaA,SAAS,aAAa,IAAuB;CAM3C,IAAI,cAAc,EAAE,GAAG,OAAO;CAC9B,QAAQ,GAAG,MAAX;EACE,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EAEL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK,cACH,OAAO;EAGT,KAAK,WACH,OAAO,GAAG,OAAO,OACd,UAAU,UAAU,QAAS,OAAO,UAAU,YAAY,OAAO,UAAU,UAC9E;EACF,KAAK;EACL,KAAK;EACL,KAAK,YACH,OAAO,aAAa,GAAG,KAAK;EAC9B,KAAK;EACL,KAAK,sBACH,OAAO,GAAG,QAAQ,MAAM,YAAY;EACtC,SACE,OAAO;CACX;AACF;;;;;;;;;;;;;;AAeA,MAAa,mBAA8B,KAAK,QAAQ;CACtD,MAAM,UAAU,IAAI,MAAM,UAAU;CACpC,MAAM,QAAQ,IAAI,MAAM,IAAI,WAAW,qBAAqB;CAC5D,IAAI,aAAa,KAAK,GAAG,OAAO;EAAE,MAAM;EAAY;CAAM;CAI1D,IAAI,IAAI,MAAM,IAAI,KAAK,SAAS;CAChC,OAAO,IAAI,SAAS,UAAU;AAChC"}
|
package/dist/core/types.d.ts
CHANGED
|
@@ -484,7 +484,7 @@ interface ZodDelegateIR {
|
|
|
484
484
|
}
|
|
485
485
|
interface FallbackIR {
|
|
486
486
|
type: "fallback";
|
|
487
|
-
reason: "transform" | "refine" | "superRefine" | "custom" | "lazy" | "unsupported" | "coalesced";
|
|
487
|
+
reason: "transform" | "refine" | "superRefine" | "custom" | "lazy" | "readonly" | "unsupported" | "coalesced";
|
|
488
488
|
/** Index into the __rf[] fallback schemas array. Present when partial fallback is used. */
|
|
489
489
|
refIndex?: number;
|
|
490
490
|
}
|
package/dist/core/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","names":[],"sources":["../../src/core/types.ts"],"mappings":";;;;;;UAQiB;;EAEf;;UAGe,uBAAuB;EACtC;EACA;;UAGe,uBAAuB;EACtC;EACA;;UAGe,0BAA0B;EACzC;EACA;;UAGe,yBAAyB;EACxC;EACA;EACA;;UAGe,sBAAsB;EACrC;EACA;EACA;;UAGe,wBAAwB;EACvC;EACA;;UAGe,0BAA0B;EACzC;EACA;;UAGe,0BAA0B;EACzC;EACA;EACA;;EAEA;;EAEA;EACA;;EAEA;EACA;;EAEA;;;;;;;;;;;;;;;;;;EAkBA;;UAGe,sBAAsB;EACrC;EACA;EACA;;UAGe,wBAAwB;EACvC;EACA;;UAGe,sBAAsB;EACrC;EACA;;KAGU,UACR,iBACA,iBACA,oBACA,mBACA,gBACA,kBACA,oBACA,oBACA,gBACA,kBACA;UAMa;EACf;;;;;;EAMA;;;;;;;;;EASA;;EAEA;;;;;;EAMA;;;;;;;;;EASA;;;;;;;;;;;;;UAce;EACf;;EAEA;;;;;;UAOe;EACf;;EAEA;;;KAIU,kBACR,UACA,sBACA,2BACA;UAIa,6BAA6B;EAC5C;EACA;EACA;EACA;;UAGe,0BAA0B;EACzC;EACA;EACA;EACA;;KAGU,cAAc,uBAAuB;UAIhC,+BAA+B;EAC9C;;EAEA;EACA;;UAGe,4BAA4B;EAC3C;;EAEA;EACA;;UAGe,8BAA8B;EAC7C;;EAEA;;KAGU,gBAAgB,yBAAyB,sBAAsB;UAI1D,qBAAqB;EACpC;EACA;;UAGe,qBAAqB;EACpC;EACA;;UAGe,wBAAwB;EACvC;EACA;;KAGU,aAAa,eAAe,eAAe;UAItC,sBAAsB;EACrC;EACA;;KAGU,cAAc,eAAe,eAAe;UAIvC;EACf;EACA,QAAQ;EACR;;UAGe;EACf;EACA,QAAQ;EACR;;UAGe;EACf;EACA;;UAGe;EACf;EACA,QAAQ;EACR;;UAGe;EACf;EACA,QAAQ;EACR;;UAGe;EACf;;UAGe;EACf;;UAGe;EACf;;UAGe;EACf;;UAGe;EACf;;UAGe;EACf;;UAGe;EACf;;UAGe;EACf;;;;;;;;;;;;;;KAeU;UAEK;EACf;EACA,QAAQ;;;;;;;EAOR;;UAGe;EACf;;EAEA;;UAKe;EACf;EACA,YAAY,eAAe;;;;;;;;;;EAU3B;;;;;;;;;;;;;EAaA;;EAEA,UAAU,sBAAsB;;;;;;;EAOhC,WAAW;;;;;;;EAOX;;UAGe;EACf;EACA,SAAS;EACT,QAAQ;;UAGO;EACf;EACA,OAAO;EACP,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;EA2BN;;UAGe;EACf;EACA,SAAS;EACT,WAAW;;UAGI;EACf;EACA,WAAW;EACX,SAAS;;UAGM;EACf;EACA,SAAS;EACT,WAAW;;UAGI;EACf;EACA,SAAS;;UAKM;EACf;EACA,SAAS;;UAGM;EACf;EACA;EACA,SAAS;;;;;;EAMT;IAAS;IAA8D;;;UAGxD;EACf;EACA,MAAM;EACN,OAAO;;UAKQ;EACf;EACA,OAAO;;UAGQ;EACf;EACA,OAAO;;UAGQ;EACf;EACA,OAAO;;UAGQ;EACf;EACA,OAAO;EACP;;;;;;;;;;;EAWA;;UAGe;EACf;EACA,IAAI;EACJ,KAAK;;UAKU;EACf;EACA;;;;;EAKA;;;;;;;EAOA;;EAEA,OAAO;;UAGQ;EACf;EACA;;EAEA;;EAEA;;EAEA,OAAO;;;;;;UASQ;EACf;;EAEA;;EAEA;;EAEA;;EAEA;;;;;;;UAQe;EACf;EACA,OAAO;;EAEP;;UAGe;EACf;EACA;;
|
|
1
|
+
{"version":3,"file":"types.d.ts","names":[],"sources":["../../src/core/types.ts"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hoist-compile.d.ts","names":[],"sources":["../../src/unplugin/hoist-compile.ts"],"mappings":";;;;;UA6CiB;;EAEf;;EAEA;;EAEA,MAAM;;;;;;
|
|
1
|
+
{"version":3,"file":"hoist-compile.d.ts","names":[],"sources":["../../src/unplugin/hoist-compile.ts"],"mappings":";;;;;UA6CiB;;EAEf;;EAEA;;EAEA,MAAM;;;;;;iBAmGc,sBACpB,kBAAkB,iBAClB,cACA,YACA,MAAM,cACL,QAAQ"}
|
|
@@ -58,7 +58,7 @@ async function compileOne(schema, importDetails, id, mode, moduleCache) {
|
|
|
58
58
|
}
|
|
59
59
|
}
|
|
60
60
|
function isZodSpecifier(specifier) {
|
|
61
|
-
return specifier === "zod" || specifier === "zod/v4" || specifier === "zod/mini" || specifier === "zod/v4/mini";
|
|
61
|
+
return specifier === "zod" || specifier === "zod/v4" || specifier === "zod/mini" || specifier === "zod/v4/mini" || specifier === "zod/v4-mini";
|
|
62
62
|
}
|
|
63
63
|
/**
|
|
64
64
|
* Compile every eligible hoisted schema. Failures are silent per schema —
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hoist-compile.js","names":[],"sources":["../../src/unplugin/hoist-compile.ts"],"sourcesContent":["/**\n * Build-time compilation of hoisted schemas.\n *\n * After hoistZodSchemasMeta() lifts `z.object({...})` constructions to\n * module-scope `_zh_*` declarations, this step evaluates each hoisted\n * expression with the project's real zod module, runs the regular\n * extract → codegen pipeline on the resulting schema object, and hands the\n * transform a compiled IIFE to splice in as the declaration initializer:\n *\n * const _zh_x = z.object({ id: z.number() });\n * ⇣\n * const _zh_x = /* @__PURE__ *\\/ (() => { ... return __zcMkv(...); })();\n *\n * Eligibility is STRICTER than hoist eligibility. Hoisting only moves an\n * expression; compiling it bakes build-time evaluation results into\n * generated checks, so the construction must be deterministic:\n *\n * - Every EAGER free identifier must be a zod-package binding. Anything\n * else (other imports: `getLimit()`, globals: `new Date()`,\n * `Math.random()`) could evaluate differently at build time vs module\n * load — those schemas stay plainly hoisted.\n * - DEFERRED references (inside refine/transform/default callbacks) are\n * unrestricted: callbacks reach generated code via fn.toString() or stay\n * on the runtime-constructed schema (`__rf` delegation), never via their\n * build-time closure values. If extraction itself needs a deferred value\n * it cannot have (z.lazy(() => ImportedChild)), evaluation throws and the\n * schema falls back to a plain hoist.\n *\n * Every failure path is graceful: the declaration keeps its original zod\n * expression and runtime behavior is unchanged.\n */\n\nimport type { CodegenMode } from \"../core/codegen/context.js\";\nimport { generateValidator } from \"../core/codegen/index.js\";\nimport { extractSchema, type RefEntry } from \"../core/extract/index.js\";\nimport type { CompiledSchemaInfo } from \"../core/pipeline.js\";\nimport { loadModule } from \"../loader.js\";\nimport {\n analyzeHoistedExpression,\n collectImportBindings,\n type HoistedSchema,\n type ImportDetail,\n} from \"./hoist.js\";\n\n/** A hoisted declaration whose initializer can be replaced with a compiled IIFE. */\nexport interface CompiledHoistedSchema {\n /** The `_zh_*` declaration name. */\n name: string;\n /** Original construction expression text (becomes the IIFE's schema expression). */\n text: string;\n /** Compiled validator for the schema. */\n info: CompiledSchemaInfo;\n}\n\n/** Duck-type check mirroring discovery's isZodSchema. */\nfunction isZodSchema(value: unknown): boolean {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"_zod\" in value &&\n typeof (value as { _zod: unknown })._zod === \"object\"\n );\n}\n\n/**\n * Evaluate a hoisted expression with its zod bindings and compile it.\n * Returns null when the schema is ineligible or anything fails.\n */\nasync function compileOne(\n schema: HoistedSchema,\n importDetails: Map<string, ImportDetail>,\n id: string,\n mode: CodegenMode,\n moduleCache: Map<string, Promise<Record<string, unknown>>>,\n): Promise<CompiledHoistedSchema | null> {\n const analysis = analyzeHoistedExpression(schema.text);\n if (analysis === null) return null;\n\n // Determinism gate: eager evaluation may only touch zod bindings.\n const free = new Set([...analysis.eagerFree, ...analysis.deferredFree]);\n const bindings: Array<{ name: string; detail: ImportDetail }> = [];\n for (const name of analysis.eagerFree) {\n const detail = importDetails.get(name);\n if (!detail || !isZodSpecifier(detail.specifier)) return null;\n }\n // Inject every free import binding we can resolve (eager ones are all zod\n // by the gate above; deferred ones are best-effort — extraction only\n // dereferences them for build-time-invoked callbacks like z.lazy getters).\n for (const name of free) {\n const detail = importDetails.get(name);\n if (detail && isZodSpecifier(detail.specifier)) {\n bindings.push({ name, detail });\n } else if (analysis.eagerFree.has(name)) {\n return null;\n }\n // deferred non-zod names stay unbound: the evaluated closure would throw\n // if invoked at build time, which the try/catch below converts to a skip.\n }\n\n try {\n const values = await Promise.all(\n bindings.map(async ({ detail }) => {\n let loading = moduleCache.get(detail.specifier);\n if (!loading) {\n loading = loadModule(detail.specifier, id);\n moduleCache.set(detail.specifier, loading);\n }\n const mod = await loading;\n return detail.imported === \"*\" ? mod : mod[detail.imported];\n }),\n );\n\n const evaluate = new Function(\n ...bindings.map((b) => b.name),\n `\"use strict\"; return (${schema.text});`,\n );\n const value: unknown = evaluate(...values);\n if (!isZodSchema(value)) return null;\n\n const refEntries: RefEntry[] = [];\n const ir = extractSchema(value, refEntries);\n // A root fallback compiles to a pure delegation wrapper — strictly worse\n // than leaving the plain hoisted construction in place.\n if (ir.type === \"fallback\") return null;\n\n const codegenResult = generateValidator(ir, schema.name, { mode });\n return {\n name: schema.name,\n text: schema.text,\n info: { exportName: schema.name, codegenResult, refEntries },\n };\n } catch {\n return null;\n }\n}\n\nfunction isZodSpecifier(specifier: string): boolean {\n return (\n specifier === \"zod\" ||\n specifier === \"zod/v4\" ||\n specifier === \"zod/mini\" ||\n specifier === \"zod/v4/mini\"\n );\n}\n\n/**\n * Compile every eligible hoisted schema. Failures are silent per schema —\n * the caller leaves ineligible declarations as plain hoists.\n */\nexport async function compileHoistedSchemas(\n schemas: readonly HoistedSchema[],\n code: string,\n id: string,\n mode: CodegenMode,\n): Promise<CompiledHoistedSchema[]> {\n const { details } = collectImportBindings(code);\n const moduleCache = new Map<string, Promise<Record<string, unknown>>>();\n const compiled: CompiledHoistedSchema[] = [];\n for (const schema of schemas) {\n const result = await compileOne(schema, details, id, mode, moduleCache);\n if (result !== null) compiled.push(result);\n }\n return compiled;\n}\n"],"mappings":";;;;;;AAuDA,SAAS,YAAY,OAAyB;CAC5C,OACE,OAAO,UAAU,YACjB,UAAU,QACV,UAAU,SACV,OAAQ,MAA4B,SAAS;AAEjD;;;;;AAMA,eAAe,WACb,QACA,eACA,IACA,MACA,aACuC;CACvC,MAAM,WAAW,yBAAyB,OAAO,IAAI;CACrD,IAAI,aAAa,MAAM,OAAO;CAG9B,MAAM,uBAAO,IAAI,IAAI,CAAC,GAAG,SAAS,WAAW,GAAG,SAAS,YAAY,CAAC;CACtE,MAAM,WAA0D,CAAC;CACjE,KAAK,MAAM,QAAQ,SAAS,WAAW;EACrC,MAAM,SAAS,cAAc,IAAI,IAAI;EACrC,IAAI,CAAC,UAAU,CAAC,eAAe,OAAO,SAAS,GAAG,OAAO;CAC3D;CAIA,KAAK,MAAM,QAAQ,MAAM;EACvB,MAAM,SAAS,cAAc,IAAI,IAAI;EACrC,IAAI,UAAU,eAAe,OAAO,SAAS,GAC3C,SAAS,KAAK;GAAE;GAAM;EAAO,CAAC;OACzB,IAAI,SAAS,UAAU,IAAI,IAAI,GACpC,OAAO;CAIX;CAEA,IAAI;EACF,MAAM,SAAS,MAAM,QAAQ,IAC3B,SAAS,IAAI,OAAO,EAAE,aAAa;GACjC,IAAI,UAAU,YAAY,IAAI,OAAO,SAAS;GAC9C,IAAI,CAAC,SAAS;IACZ,UAAU,WAAW,OAAO,WAAW,EAAE;IACzC,YAAY,IAAI,OAAO,WAAW,OAAO;GAC3C;GACA,MAAM,MAAM,MAAM;GAClB,OAAO,OAAO,aAAa,MAAM,MAAM,IAAI,OAAO;EACpD,CAAC,CACH;EAMA,MAAM,QAAiB,IAJF,SACnB,GAAG,SAAS,KAAK,MAAM,EAAE,IAAI,GAC7B,yBAAyB,OAAO,KAAK,GAET,CAAC,CAAC,GAAG,MAAM;EACzC,IAAI,CAAC,YAAY,KAAK,GAAG,OAAO;EAEhC,MAAM,aAAyB,CAAC;EAChC,MAAM,KAAK,cAAc,OAAO,UAAU;EAG1C,IAAI,GAAG,SAAS,YAAY,OAAO;EAEnC,MAAM,gBAAgB,kBAAkB,IAAI,OAAO,MAAM,EAAE,KAAK,CAAC;EACjE,OAAO;GACL,MAAM,OAAO;GACb,MAAM,OAAO;GACb,MAAM;IAAE,YAAY,OAAO;IAAM;IAAe;GAAW;EAC7D;CACF,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAS,eAAe,WAA4B;CAClD,OACE,cAAc,SACd,cAAc,YACd,cAAc,cACd,cAAc;AAElB;;;;;AAMA,eAAsB,sBACpB,SACA,MACA,IACA,MACkC;CAClC,MAAM,EAAE,YAAY,sBAAsB,IAAI;CAC9C,MAAM,8BAAc,IAAI,IAA8C;CACtE,MAAM,WAAoC,CAAC;CAC3C,KAAK,MAAM,UAAU,SAAS;EAC5B,MAAM,SAAS,MAAM,WAAW,QAAQ,SAAS,IAAI,MAAM,WAAW;EACtE,IAAI,WAAW,MAAM,SAAS,KAAK,MAAM;CAC3C;CACA,OAAO;AACT"}
|
|
1
|
+
{"version":3,"file":"hoist-compile.js","names":[],"sources":["../../src/unplugin/hoist-compile.ts"],"sourcesContent":["/**\n * Build-time compilation of hoisted schemas.\n *\n * After hoistZodSchemasMeta() lifts `z.object({...})` constructions to\n * module-scope `_zh_*` declarations, this step evaluates each hoisted\n * expression with the project's real zod module, runs the regular\n * extract → codegen pipeline on the resulting schema object, and hands the\n * transform a compiled IIFE to splice in as the declaration initializer:\n *\n * const _zh_x = z.object({ id: z.number() });\n * ⇣\n * const _zh_x = /* @__PURE__ *\\/ (() => { ... return __zcMkv(...); })();\n *\n * Eligibility is STRICTER than hoist eligibility. Hoisting only moves an\n * expression; compiling it bakes build-time evaluation results into\n * generated checks, so the construction must be deterministic:\n *\n * - Every EAGER free identifier must be a zod-package binding. Anything\n * else (other imports: `getLimit()`, globals: `new Date()`,\n * `Math.random()`) could evaluate differently at build time vs module\n * load — those schemas stay plainly hoisted.\n * - DEFERRED references (inside refine/transform/default callbacks) are\n * unrestricted: callbacks reach generated code via fn.toString() or stay\n * on the runtime-constructed schema (`__rf` delegation), never via their\n * build-time closure values. If extraction itself needs a deferred value\n * it cannot have (z.lazy(() => ImportedChild)), evaluation throws and the\n * schema falls back to a plain hoist.\n *\n * Every failure path is graceful: the declaration keeps its original zod\n * expression and runtime behavior is unchanged.\n */\n\nimport type { CodegenMode } from \"../core/codegen/context.js\";\nimport { generateValidator } from \"../core/codegen/index.js\";\nimport { extractSchema, type RefEntry } from \"../core/extract/index.js\";\nimport type { CompiledSchemaInfo } from \"../core/pipeline.js\";\nimport { loadModule } from \"../loader.js\";\nimport {\n analyzeHoistedExpression,\n collectImportBindings,\n type HoistedSchema,\n type ImportDetail,\n} from \"./hoist.js\";\n\n/** A hoisted declaration whose initializer can be replaced with a compiled IIFE. */\nexport interface CompiledHoistedSchema {\n /** The `_zh_*` declaration name. */\n name: string;\n /** Original construction expression text (becomes the IIFE's schema expression). */\n text: string;\n /** Compiled validator for the schema. */\n info: CompiledSchemaInfo;\n}\n\n/** Duck-type check mirroring discovery's isZodSchema. */\nfunction isZodSchema(value: unknown): boolean {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"_zod\" in value &&\n typeof (value as { _zod: unknown })._zod === \"object\"\n );\n}\n\n/**\n * Evaluate a hoisted expression with its zod bindings and compile it.\n * Returns null when the schema is ineligible or anything fails.\n */\nasync function compileOne(\n schema: HoistedSchema,\n importDetails: Map<string, ImportDetail>,\n id: string,\n mode: CodegenMode,\n moduleCache: Map<string, Promise<Record<string, unknown>>>,\n): Promise<CompiledHoistedSchema | null> {\n const analysis = analyzeHoistedExpression(schema.text);\n if (analysis === null) return null;\n\n // Determinism gate: eager evaluation may only touch zod bindings.\n const free = new Set([...analysis.eagerFree, ...analysis.deferredFree]);\n const bindings: Array<{ name: string; detail: ImportDetail }> = [];\n for (const name of analysis.eagerFree) {\n const detail = importDetails.get(name);\n if (!detail || !isZodSpecifier(detail.specifier)) return null;\n }\n // Inject every free import binding we can resolve (eager ones are all zod\n // by the gate above; deferred ones are best-effort — extraction only\n // dereferences them for build-time-invoked callbacks like z.lazy getters).\n for (const name of free) {\n const detail = importDetails.get(name);\n if (detail && isZodSpecifier(detail.specifier)) {\n bindings.push({ name, detail });\n } else if (analysis.eagerFree.has(name)) {\n return null;\n }\n // deferred non-zod names stay unbound: the evaluated closure would throw\n // if invoked at build time, which the try/catch below converts to a skip.\n }\n\n try {\n const values = await Promise.all(\n bindings.map(async ({ detail }) => {\n let loading = moduleCache.get(detail.specifier);\n if (!loading) {\n loading = loadModule(detail.specifier, id);\n moduleCache.set(detail.specifier, loading);\n }\n const mod = await loading;\n return detail.imported === \"*\" ? mod : mod[detail.imported];\n }),\n );\n\n const evaluate = new Function(\n ...bindings.map((b) => b.name),\n `\"use strict\"; return (${schema.text});`,\n );\n const value: unknown = evaluate(...values);\n if (!isZodSchema(value)) return null;\n\n const refEntries: RefEntry[] = [];\n const ir = extractSchema(value, refEntries);\n // A root fallback compiles to a pure delegation wrapper — strictly worse\n // than leaving the plain hoisted construction in place.\n if (ir.type === \"fallback\") return null;\n\n const codegenResult = generateValidator(ir, schema.name, { mode });\n return {\n name: schema.name,\n text: schema.text,\n info: { exportName: schema.name, codegenResult, refEntries },\n };\n } catch {\n return null;\n }\n}\n\nfunction isZodSpecifier(specifier: string): boolean {\n return (\n specifier === \"zod\" ||\n specifier === \"zod/v4\" ||\n specifier === \"zod/mini\" ||\n specifier === \"zod/v4/mini\" ||\n specifier === \"zod/v4-mini\"\n );\n}\n\n/**\n * Compile every eligible hoisted schema. Failures are silent per schema —\n * the caller leaves ineligible declarations as plain hoists.\n */\nexport async function compileHoistedSchemas(\n schemas: readonly HoistedSchema[],\n code: string,\n id: string,\n mode: CodegenMode,\n): Promise<CompiledHoistedSchema[]> {\n const { details } = collectImportBindings(code);\n const moduleCache = new Map<string, Promise<Record<string, unknown>>>();\n const compiled: CompiledHoistedSchema[] = [];\n for (const schema of schemas) {\n const result = await compileOne(schema, details, id, mode, moduleCache);\n if (result !== null) compiled.push(result);\n }\n return compiled;\n}\n"],"mappings":";;;;;;AAuDA,SAAS,YAAY,OAAyB;CAC5C,OACE,OAAO,UAAU,YACjB,UAAU,QACV,UAAU,SACV,OAAQ,MAA4B,SAAS;AAEjD;;;;;AAMA,eAAe,WACb,QACA,eACA,IACA,MACA,aACuC;CACvC,MAAM,WAAW,yBAAyB,OAAO,IAAI;CACrD,IAAI,aAAa,MAAM,OAAO;CAG9B,MAAM,uBAAO,IAAI,IAAI,CAAC,GAAG,SAAS,WAAW,GAAG,SAAS,YAAY,CAAC;CACtE,MAAM,WAA0D,CAAC;CACjE,KAAK,MAAM,QAAQ,SAAS,WAAW;EACrC,MAAM,SAAS,cAAc,IAAI,IAAI;EACrC,IAAI,CAAC,UAAU,CAAC,eAAe,OAAO,SAAS,GAAG,OAAO;CAC3D;CAIA,KAAK,MAAM,QAAQ,MAAM;EACvB,MAAM,SAAS,cAAc,IAAI,IAAI;EACrC,IAAI,UAAU,eAAe,OAAO,SAAS,GAC3C,SAAS,KAAK;GAAE;GAAM;EAAO,CAAC;OACzB,IAAI,SAAS,UAAU,IAAI,IAAI,GACpC,OAAO;CAIX;CAEA,IAAI;EACF,MAAM,SAAS,MAAM,QAAQ,IAC3B,SAAS,IAAI,OAAO,EAAE,aAAa;GACjC,IAAI,UAAU,YAAY,IAAI,OAAO,SAAS;GAC9C,IAAI,CAAC,SAAS;IACZ,UAAU,WAAW,OAAO,WAAW,EAAE;IACzC,YAAY,IAAI,OAAO,WAAW,OAAO;GAC3C;GACA,MAAM,MAAM,MAAM;GAClB,OAAO,OAAO,aAAa,MAAM,MAAM,IAAI,OAAO;EACpD,CAAC,CACH;EAMA,MAAM,QAAiB,IAJF,SACnB,GAAG,SAAS,KAAK,MAAM,EAAE,IAAI,GAC7B,yBAAyB,OAAO,KAAK,GAET,CAAC,CAAC,GAAG,MAAM;EACzC,IAAI,CAAC,YAAY,KAAK,GAAG,OAAO;EAEhC,MAAM,aAAyB,CAAC;EAChC,MAAM,KAAK,cAAc,OAAO,UAAU;EAG1C,IAAI,GAAG,SAAS,YAAY,OAAO;EAEnC,MAAM,gBAAgB,kBAAkB,IAAI,OAAO,MAAM,EAAE,KAAK,CAAC;EACjE,OAAO;GACL,MAAM,OAAO;GACb,MAAM,OAAO;GACb,MAAM;IAAE,YAAY,OAAO;IAAM;IAAe;GAAW;EAC7D;CACF,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAS,eAAe,WAA4B;CAClD,OACE,cAAc,SACd,cAAc,YACd,cAAc,cACd,cAAc,iBACd,cAAc;AAElB;;;;;AAMA,eAAsB,sBACpB,SACA,MACA,IACA,MACkC;CAClC,MAAM,EAAE,YAAY,sBAAsB,IAAI;CAC9C,MAAM,8BAAc,IAAI,IAA8C;CACtE,MAAM,WAAoC,CAAC;CAC3C,KAAK,MAAM,UAAU,SAAS;EAC5B,MAAM,SAAS,MAAM,WAAW,QAAQ,SAAS,IAAI,MAAM,WAAW;EACtE,IAAI,WAAW,MAAM,SAAS,KAAK,MAAM;CAC3C;CACA,OAAO;AACT"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hoist.d.ts","names":[],"sources":["../../src/unplugin/hoist.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cA+Da,qBAAmB;;;;;;cAOnB,aAAW;;
|
|
1
|
+
{"version":3,"file":"hoist.d.ts","names":[],"sources":["../../src/unplugin/hoist.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cA+Da,qBAAmB;;;;;;cAOnB,aAAW;;UAUP;;EAEf;;EAEA;;UAGQ;;EAER,KAAK;;EAEL,KAAK;;EAEL,SAAS,YAAY;;;;;;;iBAQP,sBAAsB,eAAe;UAw7BpC;;;;;;;EAOf,oBAAoB;;;;;;;;EAQpB;;;;;;;iBAQc,yBACd;EACG,WAAW;EAAa,cAAc;;;UAY1B;;EAEf;;EAEA;;UAGe;;EAEf;;EAEA,SAAS;;;;;;EAMT,OAAO;EACP,QAAQ;;;;;;iBAOM,gBAAgB,cAAc,UAAU;;;;;iBAQxC,oBAAoB,cAAc,UAAU,eAAe"}
|
package/dist/unplugin/hoist.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hoist.js","names":[],"sources":["../../src/unplugin/hoist.ts"],"sourcesContent":["import type { AnyNode, Expression, Options } from \"acorn\";\nimport { Parser } from \"acorn\";\nimport { applyEdits, type Edit, type Insertion, moduleHeadOffset } from \"./edits.js\";\n\n/**\n * Hoist Zod schema construction out of functions to module scope —\n * equivalent of babel-plugin-zod-hoist.\n *\n * Schemas built inside function bodies are re-constructed on every call:\n *\n * function getSchema() {\n * return z.object({ name: z.string() }); // rebuilt per call\n * }\n *\n * becomes\n *\n * const _zh_94b7f5c1 = z.object({ name: z.string() });\n * function getSchema() {\n * return _zh_94b7f5c1; // built once\n * }\n *\n * Safety rules (babel-plugin-zod-hoist's `canSafelyHoist`, hardened for\n * lexical analysis):\n * - A free identifier must be an import or a KNOWN_GLOBALS member, and must\n * never be bound anywhere in the file (function params, locals, catch\n * clauses, class names, module-level const/let/var — hoisting above those\n * would change meaning or hit the TDZ). The babel plugin additionally\n * allows arbitrary unbound identifiers because it has real scope\n * information; this port's binding collector is lexical, so an unknown\n * bare name is treated as a possibly-missed binding rather than a global\n * (a wrong guess crashes at module load with a ReferenceError).\n * `this`/`super` disqualify anywhere. Eager `await`/`yield` also\n * disqualify (stricter than the babel plugin, which never encounters\n * them: hoisting one would emit top-level await / orphaned yield).\n * - Eligible roots: any binding imported from zod, an imported identifier\n * matching /ZodSchema$/, or an imported identifier whose chain contains\n * an inline z.* reference (e.g. `Base.extend({ a: z.string() })`).\n * - Nesting (babel's `isNestedInZodCall`): the interior of a zod-rooted\n * chain never hoists separately — it goes with the outer schema or not at\n * all. Chains rooted elsewhere (`sql.type(...)`, `api.get(...)`) do NOT\n * suppress their arguments: when the outer chain is rejected, an inner\n * `z.object({...})` still hoists on its own.\n * - Declarations are inserted at the top of the module (after shebang and\n * directive prologue). Imports are initialized before module code runs,\n * so referencing them from above their textual position is safe.\n * - Names are content-hashed, so identical schemas dedupe to one binding.\n *\n * The source is TypeScript, which acorn cannot fully parse — candidates are\n * located with a string/comment/depth-aware scanner and extracted with\n * parseExpressionAt (the same technique as the autoDiscover rewrite).\n * Anything unparseable (TS generics, `as` casts) is skipped: a miss leaves\n * the schema unhoisted, never breaks the code.\n */\n\n/**\n * Imported identifiers matching this pattern are treated as schema roots.\n *\n * The default must keep implying a \"Zod\" substring: it is one of the three\n * triggers the transform hook's `code` filter (ZOD_MENTION in transform.ts)\n * is a superset of. A default that matched, say, `/Schema$/` would make\n * hoistable files without any \"zod\" mention invisible to bundlers with native\n * hook filters. (A *user-supplied* pattern is handled — it drops the filter.)\n */\nexport const SCHEMA_NAME_PATTERN = /ZodSchema$/;\n\n/**\n * Module specifiers whose bindings count as the zod namespace. Every entry\n * must contain \"zod\" for the same reason as SCHEMA_NAME_PATTERN above; both\n * are pinned by `describe(\"code filter soundness\")` in the transform tests.\n */\nexport const ZOD_MODULES = new Set([\"zod\", \"zod/v3\", \"zod/v4\", \"zod/mini\", \"zod/v4/mini\"]);\n\n/** How an imported local binding maps onto its source module. */\nexport interface ImportDetail {\n /** Module specifier (`\"zod\"`, `\"./shapes\"`). */\n specifier: string;\n /** Exported name the binding refers to; `\"*\"` for namespace imports, `\"default\"` for default imports. */\n imported: string;\n}\n\ninterface ImportBindings {\n /** Every runtime (non-type) imported binding name. */\n all: Set<string>;\n /** Bindings imported from a zod module (usually just `z`). */\n zod: Set<string>;\n /** Local binding name → source module/export, for build-time evaluation. */\n details: Map<string, ImportDetail>;\n}\n\n/**\n * Collect runtime import bindings with a regex over import statements.\n * Type-only imports and `type` specifiers are excluded — they cannot be\n * referenced at runtime, so excluding them keeps the capture rule sound.\n */\nexport function collectImportBindings(code: string): ImportBindings {\n const all = new Set<string>();\n const zod = new Set<string>();\n const details = new Map<string, ImportDetail>();\n const importPattern = /import\\s+(type\\s+)?([^'\";]+?)\\s+from\\s*[\"']([^\"']+)[\"']/g;\n\n for (const match of code.matchAll(importPattern)) {\n const [, typeOnly, clause, specifier] = match;\n if (typeOnly || clause === undefined || specifier === undefined) continue;\n const isZod = ZOD_MODULES.has(specifier);\n for (const { local, imported } of parseImportClause(clause)) {\n all.add(local);\n if (isZod) zod.add(local);\n details.set(local, { specifier, imported });\n }\n }\n return { all, zod, details };\n}\n\n/** Extract local binding names (with their source export) from an import clause. */\nfunction parseImportClause(clause: string): Array<{ local: string; imported: string }> {\n const names: Array<{ local: string; imported: string }> = [];\n const namedStart = clause.indexOf(\"{\");\n\n // Default import and/or namespace import before the named group\n const head = namedStart === -1 ? clause : clause.slice(0, namedStart);\n for (const part of head.split(\",\")) {\n const trimmed = part.trim();\n if (!trimmed) continue;\n const ns = trimmed.match(/^\\*\\s*as\\s+([A-Za-z_$][\\w$]*)$/);\n if (ns?.[1]) {\n names.push({ local: ns[1], imported: \"*\" });\n } else if (/^[A-Za-z_$][\\w$]*$/.test(trimmed)) {\n names.push({ local: trimmed, imported: \"default\" });\n }\n }\n\n if (namedStart !== -1) {\n const namedEnd = clause.indexOf(\"}\", namedStart);\n const inner = clause.slice(namedStart + 1, namedEnd === -1 ? undefined : namedEnd);\n for (const part of inner.split(\",\")) {\n const spec = part.trim();\n if (!spec || spec.startsWith(\"type \")) continue;\n // `a as b` binds b; plain `a` binds a\n const asMatch = spec.match(/^([A-Za-z_$][\\w$]*)\\s+as\\s+([A-Za-z_$][\\w$]*)$/);\n if (asMatch?.[1] && asMatch[2]) {\n names.push({ local: asMatch[2], imported: asMatch[1] });\n } else if (/^[A-Za-z_$][\\w$]*$/.test(spec)) {\n names.push({ local: spec, imported: spec });\n }\n }\n }\n return names;\n}\n\n/** Deterministic FNV-1a 32-bit hash, hex-encoded. */\nfunction fnv1a(text: string): string {\n let hash = 0x811c9dc5;\n for (let i = 0; i < text.length; i++) {\n hash ^= text.charCodeAt(i);\n hash = Math.imul(hash, 0x01000193);\n }\n return (hash >>> 0).toString(16).padStart(8, \"0\");\n}\n\ninterface Candidate {\n /** Offset of the root identifier. */\n index: number;\n /** Bracket/brace/paren depth at the offset (0 = top level). */\n depth: number;\n /** The root identifier text. */\n name: string;\n /**\n * The candidate directly follows `=>` — a concise arrow body. Even at\n * depth 0 (`const make = () => z.object(...)`) it re-evaluates per call.\n */\n afterArrow: boolean;\n}\n\n/**\n * Char-code identifier/whitespace classes for the scanner hot loops — a\n * regex `.test()` per character dominated scan time once the acorn parses\n * were gone. The ident classes are deliberately ASCII-only (`[A-Za-z_$]` /\n * `[\\w$]`, matching the scanner's historical regexes); the space check falls\n * back to `/\\s/` for the rare non-ASCII code points it matches (NBSP, BOM,\n * U+2028...).\n */\nfunction isIdentStartCode(c: number): boolean {\n return (c >= 97 && c <= 122) || (c >= 65 && c <= 90) || c === 95 || c === 36;\n}\nfunction isIdentPartCode(c: number): boolean {\n return (\n (c >= 97 && c <= 122) || (c >= 65 && c <= 90) || (c >= 48 && c <= 57) || c === 95 || c === 36\n );\n}\nfunction isSpaceCode(c: number): boolean {\n if (c === 32 || (c >= 9 && c <= 13)) return true;\n return c > 127 && /\\s/.test(String.fromCharCode(c));\n}\n\n/** After these tokens a `/` starts a regex literal, not division. */\nconst REGEX_PRECEDING_KEYWORDS = new Set([\n \"return\",\n \"typeof\",\n \"instanceof\",\n \"in\",\n \"of\",\n \"new\",\n \"delete\",\n \"void\",\n \"throw\",\n \"do\",\n \"else\",\n \"case\",\n \"yield\",\n \"await\",\n]);\n\n/** Is `/` after this token division (true) or a regex literal (false)? */\nfunction isDivisionContext(lastToken: string): boolean {\n if (lastToken === \")\" || lastToken === \"]\") return true;\n if (/^[\"'`]$/.test(lastToken)) return true;\n if (/^[\\w$]+$/.test(lastToken)) return !REGEX_PRECEDING_KEYWORDS.has(lastToken);\n return false;\n}\n\ninterface ScanResult {\n candidates: Candidate[];\n /**\n * Lazily builds the source with comments, string/template-string contents,\n * and regex literals masked to spaces (offsets preserved). Used for\n * binding-name collection so JSDoc examples and string contents never\n * count. Lazy because it is only needed when a candidate survives to\n * shadow-checking — schema modules (everything masked at depth 0) never\n * pay for it.\n */\n stripped: () => string;\n}\n\n/**\n * Scan the source for candidate root identifiers (`z`, `FooZodSchema`, ...)\n * followed by a `.`, tracking string/template/comment state and nesting\n * depth. Depth 0 candidates are top-level initializers — already evaluated\n * once — and are recorded only so their extents mask nested candidates.\n */\nfunction scanSource(code: string, roots: Set<string>): ScanResult {\n const candidates: Candidate[] = [];\n // Masked extents as flat [from, to) pairs, pushed in scan order (monotonic,\n // non-overlapping) — materialized into a stripped string only on demand.\n const maskRanges: number[] = [];\n const mask = (from: number, to: number): void => {\n maskRanges.push(from, to);\n };\n let depth = 0;\n // Template literals interleave string and expression states; the stack\n // records the brace depth at which each `${` opened so the matching `}`\n // resumes string state.\n const templateStack: number[] = [];\n let lastToken = \"\";\n let i = 0;\n\n while (i < code.length) {\n const ch = code[i] as string;\n const next = code[i + 1];\n\n // Comments\n if (ch === \"/\" && next === \"/\") {\n const nl = code.indexOf(\"\\n\", i);\n const end = nl === -1 ? code.length : nl + 1;\n mask(i, end);\n i = end;\n continue;\n }\n if (ch === \"/\" && next === \"*\") {\n const close = code.indexOf(\"*/\", i + 2);\n const end = close === -1 ? code.length : close + 2;\n mask(i, end);\n i = end;\n continue;\n }\n if (ch === \"/\") {\n if (!isDivisionContext(lastToken)) {\n const end = skipRegexLiteral(code, i);\n mask(i, end);\n i = end;\n lastToken = \")\"; // a regex literal is an operand\n continue;\n }\n lastToken = ch;\n i++;\n continue;\n }\n // Strings\n if (ch === '\"' || ch === \"'\") {\n const end = skipString(code, i, ch);\n mask(i, end);\n i = end;\n lastToken = ch;\n continue;\n }\n // Template literals\n if (ch === \"`\") {\n const end = skipTemplateChunk(code, i + 1, templateStack, depth);\n mask(i, end);\n i = end;\n lastToken = \"`\";\n continue;\n }\n if (\n templateStack.length > 0 &&\n ch === \"}\" &&\n depth === templateStack[templateStack.length - 1]\n ) {\n // End of a ${ } expression — back into template string state\n templateStack.pop();\n const end = skipTemplateChunk(code, i + 1, templateStack, depth);\n mask(i, end);\n i = end;\n lastToken = \"`\";\n continue;\n }\n\n if (ch === \"(\" || ch === \"[\" || ch === \"{\") {\n depth++;\n lastToken = ch;\n i++;\n continue;\n }\n if (ch === \")\" || ch === \"]\" || ch === \"}\") {\n depth--;\n lastToken = ch;\n i++;\n continue;\n }\n\n if (isIdentStartCode(code.charCodeAt(i)) && !isIdentPartCode(code.charCodeAt(i - 1))) {\n let j = i + 1;\n while (j < code.length && isIdentPartCode(code.charCodeAt(j))) j++;\n const word = code.slice(i, j);\n // Skip whitespace to check for the member access\n let k = j;\n while (k < code.length && isSpaceCode(code.charCodeAt(k))) k++;\n if (roots.has(word) && code[k] === \".\" && lastToken !== \".\") {\n candidates.push({ index: i, depth, name: word, afterArrow: lastToken === \"=>\" });\n }\n lastToken = word;\n i = j;\n continue;\n }\n\n if (!isSpaceCode(code.charCodeAt(i))) {\n lastToken = ch === \">\" && lastToken === \"=\" ? \"=>\" : ch;\n }\n i++;\n }\n\n const stripped = (): string => {\n if (maskRanges.length === 0) return code;\n let out = \"\";\n let prev = 0;\n for (let r = 0; r < maskRanges.length; r += 2) {\n const from = maskRanges[r] as number;\n const to = maskRanges[r + 1] as number;\n out += code.slice(prev, from) + code.slice(from, to).replace(/[^\\n]/g, \" \");\n prev = to;\n }\n return out + code.slice(prev);\n };\n return { candidates, stripped };\n}\n\nfunction skipString(code: string, start: number, quote: string): number {\n for (let i = start + 1; i < code.length; i++) {\n if (code[i] === \"\\\\\") {\n i++;\n } else if (code[i] === quote || code[i] === \"\\n\") {\n return i + 1;\n }\n }\n return code.length;\n}\n\n/**\n * Skip a template string chunk; returns the offset after the closing\n * `` ` `` or after a `${`, recording the current depth so the scanner can\n * recognize the matching `}` later.\n */\nfunction skipTemplateChunk(\n code: string,\n start: number,\n templateStack: number[],\n depth: number,\n): number {\n for (let i = start; i < code.length; i++) {\n if (code[i] === \"\\\\\") {\n i++;\n } else if (code[i] === \"`\") {\n return i + 1;\n } else if (code[i] === \"$\" && code[i + 1] === \"{\") {\n templateStack.push(depth);\n return i + 2;\n }\n }\n return code.length;\n}\n\nfunction skipRegexLiteral(code: string, start: number): number {\n let inClass = false;\n for (let i = start + 1; i < code.length; i++) {\n const ch = code[i];\n if (ch === \"\\\\\") {\n i++;\n } else if (ch === \"[\") {\n inClass = true;\n } else if (ch === \"]\") {\n inClass = false;\n } else if (ch === \"/\" && !inClass) {\n return i + 1;\n } else if (ch === \"\\n\") {\n // Not a regex after all (unterminated) — treat as division\n return start + 1;\n }\n }\n return code.length;\n}\n\n/**\n * Cheap chain-extent scan: from a root identifier, advance past the longest\n * member/call/tagged-template chain (`.x`, `?.x`, `!`, `(...)`, `[...]`,\n * `` `...` ``). Used to mask the interior of depth-0 chains WITHOUT an acorn\n * parse: schema modules are mostly top-level declarations, and parsing each\n * one only to discard it under the depth-0 rule dominated cold hoist cost in\n * a field report (hoist 37–46s vs discover 12–16s across ~7k transforms).\n * May overshoot an AST-exact end only across TS-only syntax (postfix `!`);\n * stops at anything else it does not recognize (`<` generics, operators) —\n * an undershoot leaves interior candidates to their own depth-0/eligibility\n * rules, an overshoot only widens the mask over an expression that already\n * evaluates once at module scope.\n */\nfunction findChainEnd(code: string, identStart: number): number {\n let i = identStart;\n while (i < code.length && isIdentPartCode(code.charCodeAt(i))) i++;\n\n const skipTrivia = (): void => {\n for (;;) {\n while (i < code.length && isSpaceCode(code.charCodeAt(i))) i++;\n if (code[i] === \"/\" && code[i + 1] === \"/\") {\n const nl = code.indexOf(\"\\n\", i);\n i = nl === -1 ? code.length : nl + 1;\n } else if (code[i] === \"/\" && code[i + 1] === \"*\") {\n const close = code.indexOf(\"*/\", i + 2);\n i = close === -1 ? code.length : close + 2;\n } else {\n return;\n }\n }\n };\n\n // Advance past one balanced construct starting at `(`, `[`, or a template\n // backtick — mirroring scanSource's string/template/regex/comment rules.\n const skipNested = (): void => {\n let depth = 0;\n const templateStack: number[] = [];\n let lastToken = \"\";\n while (i < code.length) {\n const ch = code[i] as string;\n const next = code[i + 1];\n if (ch === \"/\" && next === \"/\") {\n const nl = code.indexOf(\"\\n\", i);\n i = nl === -1 ? code.length : nl + 1;\n continue;\n }\n if (ch === \"/\" && next === \"*\") {\n const close = code.indexOf(\"*/\", i + 2);\n i = close === -1 ? code.length : close + 2;\n continue;\n }\n if (ch === \"/\") {\n if (!isDivisionContext(lastToken)) {\n i = skipRegexLiteral(code, i);\n lastToken = \")\";\n continue;\n }\n lastToken = ch;\n i++;\n continue;\n }\n if (ch === '\"' || ch === \"'\") {\n i = skipString(code, i, ch);\n lastToken = ch;\n continue;\n }\n if (ch === \"`\") {\n i = skipTemplateChunk(code, i + 1, templateStack, depth);\n lastToken = \"`\";\n if (depth === 0 && templateStack.length === 0) return;\n continue;\n }\n if (\n templateStack.length > 0 &&\n ch === \"}\" &&\n depth === templateStack[templateStack.length - 1]\n ) {\n templateStack.pop();\n i = skipTemplateChunk(code, i + 1, templateStack, depth);\n lastToken = \"`\";\n if (depth === 0 && templateStack.length === 0) return;\n continue;\n }\n if (ch === \"(\" || ch === \"[\" || ch === \"{\") {\n depth++;\n lastToken = ch;\n i++;\n continue;\n }\n if (ch === \")\" || ch === \"]\" || ch === \"}\") {\n depth--;\n lastToken = ch;\n i++;\n if (depth === 0 && templateStack.length === 0) return;\n continue;\n }\n if (isIdentStartCode(code.charCodeAt(i)) && !isIdentPartCode(code.charCodeAt(i - 1))) {\n let j = i + 1;\n while (j < code.length && isIdentPartCode(code.charCodeAt(j))) j++;\n lastToken = code.slice(i, j);\n i = j;\n continue;\n }\n if (!isSpaceCode(code.charCodeAt(i))) {\n lastToken = ch === \">\" && lastToken === \"=\" ? \"=>\" : ch;\n }\n i++;\n }\n };\n\n for (;;) {\n skipTrivia();\n const ch = code[i];\n if (ch === \".\" || (ch === \"?\" && code[i + 1] === \".\")) {\n i += ch === \".\" ? 1 : 2;\n skipTrivia();\n while (i < code.length && isIdentPartCode(code.charCodeAt(i))) i++;\n continue;\n }\n if (ch === \"!\") {\n i++;\n continue;\n }\n if (ch === \"(\" || ch === \"[\" || ch === \"`\") {\n skipNested();\n continue;\n }\n return i;\n }\n}\n\n/**\n * Parse a single assignment-level expression at `pos` — the same entry point\n * acorn's own parseExpressionAt uses, one precedence level down. At\n * expression level a trailing comma in an argument position\n * (`sql.type(z.object({...}),\\n)`) starts a sequence-expression parse that\n * throws on the surrounding `)`; assignment level treats the comma as\n * trailing garbage and stops cleanly. parseMaybeAssign is the entry point\n * the acorn plugin ecosystem overrides — stable across versions.\n */\nfunction parseAssignmentAt(code: string, pos: number): Expression {\n interface ParserInternals {\n nextToken(): void;\n parseMaybeAssign(): Expression;\n }\n const parser = new (Parser as unknown as new (\n options: Options,\n input: string,\n startPos?: number,\n ) => ParserInternals)({ ecmaVersion: \"latest\", sourceType: \"module\" }, code, pos);\n parser.nextToken();\n return parser.parseMaybeAssign();\n}\n\n/**\n * Narrow a parsed expression to the largest call chain starting at `start`.\n * The parse can overshoot into surrounding operators\n * (`z.string().min(1) || fallback` parses as a LogicalExpression) — descend\n * through same-start children until a CallExpression is found.\n */\nfunction narrowToCallChain(node: Expression, start: number): Expression | null {\n let current: AnyNode = node;\n while (current.start === start) {\n if (current.type === \"CallExpression\") return current as Expression;\n const child = sameStartChild(current, start);\n if (!child) return null;\n current = child;\n }\n return null;\n}\n\nfunction sameStartChild(node: AnyNode, start: number): AnyNode | null {\n const record = node as unknown as Record<string, unknown>;\n for (const key of [\"left\", \"object\", \"callee\", \"test\", \"tag\", \"expression\", \"expressions\"]) {\n const value = record[key];\n const child = Array.isArray(value) ? value[0] : value;\n if (\n typeof child === \"object\" &&\n child !== null &&\n (child as AnyNode).start === start &&\n typeof (child as AnyNode).type === \"string\"\n ) {\n return child as AnyNode;\n }\n }\n return null;\n}\n\n/**\n * Walk a member/call chain down to its base identifier, collecting the\n * non-computed method names along the spine. Computed members\n * (`base[name]()`) are unanalyzable — the chain is rejected.\n */\nfunction describeChain(node: Expression): { root: string; methods: string[] } | null {\n const methods: string[] = [];\n let current: AnyNode = node;\n while (true) {\n if (current.type === \"CallExpression\") {\n current = current.callee;\n } else if (current.type === \"MemberExpression\") {\n if (current.computed || current.property.type !== \"Identifier\") return null;\n methods.push(current.property.name);\n current = current.object;\n } else if (current.type === \"Identifier\") {\n return { root: current.name, methods };\n } else {\n return null;\n }\n }\n}\n\n/**\n * Combinators eligible on non-z chain bases (babel-plugin-zod-hoist's\n * SCHEMA_COMBINATOR_METHODS, verbatim) — `Base.extend({...})`,\n * `Base.pick({...})`, `UserZodSchema.optional()`, ...\n */\nconst COMBINATOR_METHODS = new Set([\n \"and\",\n \"array\",\n \"brand\",\n \"catchall\",\n \"deepPartial\",\n \"describe\",\n \"extend\",\n \"merge\",\n \"nullable\",\n \"nullish\",\n \"omit\",\n \"optional\",\n \"or\",\n \"partial\",\n \"passthrough\",\n \"pick\",\n \"readonly\",\n \"refine\",\n \"required\",\n \"strict\",\n \"strip\",\n \"superRefine\",\n \"transform\",\n]);\n\n/**\n * Methods that evaluate data rather than construct schemas. Hoisting one\n * would move the evaluation (and any throw) to module load.\n */\nconst PARSE_METHODS = new Set([\n \"parse\",\n \"safeParse\",\n \"parseAsync\",\n \"safeParseAsync\",\n \"decode\",\n \"encode\",\n \"decodeAsync\",\n \"encodeAsync\",\n]);\n\n/**\n * Standard globals a hoisted expression may reference (eager or deferred —\n * babel-parity behaviors like hoisting `z.date().default(new Date())` rely\n * on Date/Math being recognized).\n *\n * The babel plugin allows ANY unbound identifier because it has real scope\n * information; this port's binding collector is a lexical approximation, so\n * an unknown bare name must be assumed to be a binding the collector missed\n * — hoisting it would crash at module load with\n * `ReferenceError: <name> is not defined`. A fixed allowlist converts that\n * failure mode into a missed optimization.\n */\nconst KNOWN_GLOBALS = new Set([\n \"globalThis\",\n \"NaN\",\n \"Infinity\",\n \"Math\",\n \"Number\",\n \"String\",\n \"Boolean\",\n \"Array\",\n \"Object\",\n \"JSON\",\n \"Date\",\n \"RegExp\",\n \"BigInt\",\n \"Symbol\",\n \"Map\",\n \"Set\",\n \"WeakMap\",\n \"WeakSet\",\n \"Promise\",\n \"Proxy\",\n \"Reflect\",\n \"Intl\",\n \"Error\",\n \"TypeError\",\n \"RangeError\",\n \"SyntaxError\",\n \"EvalError\",\n \"URIError\",\n \"AggregateError\",\n \"ArrayBuffer\",\n \"Uint8Array\",\n \"parseInt\",\n \"parseFloat\",\n \"isNaN\",\n \"isFinite\",\n \"encodeURI\",\n \"decodeURI\",\n \"encodeURIComponent\",\n \"decodeURIComponent\",\n \"structuredClone\",\n \"URL\",\n \"URLSearchParams\",\n \"TextEncoder\",\n \"TextDecoder\",\n \"atob\",\n \"btoa\",\n \"crypto\",\n \"console\",\n \"process\",\n \"Buffer\",\n]);\n\ninterface CaptureAnalysis {\n /** Free identifiers referenced in eager (immediately evaluated) positions. */\n eagerFree: Set<string>;\n /** Free identifiers referenced only inside nested function bodies. */\n deferredFree: Set<string>;\n /** Disqualifying constructs (`this`/`super` anywhere; `await`/`yield` in eager positions). */\n impure: boolean;\n}\n\n/**\n * Scope-aware free-variable analysis of an expression. Nested function\n * params and local declarations are bound names, not captures — so\n * `z.string().refine((v) => v.length > 0)` has no free variables beyond `z`.\n * References inside nested function bodies are tracked separately: they\n * evaluate per call even after hoisting, so safe globals are allowed there.\n */\nfunction analyzeCaptures(expr: Expression): CaptureAnalysis {\n const eagerFree = new Set<string>();\n const deferredFree = new Set<string>();\n let impure = false;\n\n function patternNames(node: AnyNode, into: Set<string>): void {\n switch (node.type) {\n case \"Identifier\":\n into.add(node.name);\n return;\n case \"ObjectPattern\":\n for (const prop of node.properties) {\n if (prop.type === \"Property\") patternNames(prop.value, into);\n else patternNames(prop.argument, into);\n }\n return;\n case \"ArrayPattern\":\n for (const el of node.elements) {\n if (el) patternNames(el, into);\n }\n return;\n case \"AssignmentPattern\":\n patternNames(node.left, into);\n return;\n case \"RestElement\":\n patternNames(node.argument, into);\n return;\n default:\n return;\n }\n }\n\n function collectFunctionScope(body: AnyNode, into: Set<string>): void {\n // Flatten block scoping into the function scope — over-approximating\n // bound names can only suppress a hoist's free set, and the failure\n // mode is a loud ReferenceError, never silent misvalidation.\n const stack: AnyNode[] = [body];\n while (stack.length > 0) {\n const node = stack.pop();\n if (!node || typeof node !== \"object\") continue;\n if (node.type === \"VariableDeclaration\") {\n for (const decl of node.declarations) patternNames(decl.id, into);\n } else if (node.type === \"FunctionDeclaration\" || node.type === \"ClassDeclaration\") {\n if (node.id) into.add(node.id.name);\n continue; // do not descend into nested declarations' bodies here\n } else if (node.type === \"FunctionExpression\" || node.type === \"ArrowFunctionExpression\") {\n continue; // nested functions get their own scope in visit()\n }\n for (const value of Object.values(node as unknown as Record<string, unknown>)) {\n if (Array.isArray(value)) {\n for (const item of value) {\n if (typeof item === \"object\" && item !== null && \"type\" in item) {\n stack.push(item as AnyNode);\n }\n }\n } else if (typeof value === \"object\" && value !== null && \"type\" in value) {\n stack.push(value as AnyNode);\n }\n }\n }\n }\n\n function visit(node: AnyNode, scopes: Set<string>[], deferred: boolean): void {\n switch (node.type) {\n case \"Identifier\": {\n const name = node.name;\n if (name !== \"undefined\" && !scopes.some((s) => s.has(name))) {\n (deferred ? deferredFree : eagerFree).add(name);\n }\n return;\n }\n case \"ThisExpression\":\n case \"Super\":\n // Arrows bind `this` lexically — hoisting changes it even when the\n // reference sits inside a callback. Always disqualifying.\n impure = true;\n return;\n case \"AwaitExpression\":\n case \"YieldExpression\":\n // Eager occurrences cannot be moved to module scope: hoisting would\n // emit top-level await (broken in CJS output) or an orphaned yield.\n // (Stricter than the babel plugin, whose suite never exercises\n // these.) Deferred occurrences run per call — fine to move.\n if (!deferred) {\n impure = true;\n return;\n }\n break;\n case \"MemberExpression\":\n visit(node.object, scopes, deferred);\n if (node.computed) visit(node.property, scopes, deferred);\n return;\n case \"Property\":\n if (node.computed) visit(node.key, scopes, deferred);\n visit(node.value, scopes, deferred);\n return;\n case \"FunctionExpression\":\n case \"ArrowFunctionExpression\": {\n const scope = new Set<string>();\n for (const param of node.params) patternNames(param, scope);\n if (node.type === \"FunctionExpression\" && node.id) scope.add(node.id.name);\n collectFunctionScope(node.body, scope);\n visit(node.body, [...scopes, scope], true);\n return;\n }\n default:\n break;\n }\n for (const value of Object.values(node as unknown as Record<string, unknown>)) {\n if (Array.isArray(value)) {\n for (const item of value) {\n if (typeof item === \"object\" && item !== null && \"type\" in item) {\n visit(item as AnyNode, scopes, deferred);\n }\n }\n } else if (typeof value === \"object\" && value !== null && \"type\" in value) {\n visit(value as AnyNode, scopes, deferred);\n }\n }\n }\n\n visit(expr, [], false);\n return { eagerFree, deferredFree, impure };\n}\n\n/** Keywords that precede `( ... ) {` without binding anything. */\nconst NON_BINDING_KEYWORDS =\n \"if|for|while|switch|return|typeof|await|yield|new|do|else|case|in|of|delete|void\";\n\n/**\n * Conservative shadow detection: collect every identifier appearing in a\n * binding-like position — function/method/arrow parameter lists, catch\n * clauses, class names, const/let/var declarator patterns. The scanner has\n * no scope information, so an import referenced from a hoisted expression\n * must resolve to that import everywhere; a name that is ever re-bound\n * cannot be trusted and disqualifies hoists referencing it.\n *\n * Collection is depth-aware and multiline (balanced delimiter scanning, not\n * line-bounded regexes): multiline destructuring declarations and parameter\n * defaults containing calls are real production patterns whose bindings a\n * line-based collector misses — and a missed binding here used to mean a\n * hoist referencing it crashed at module load (`ReferenceError`).\n * Over-collection (type names, destructuring default values, for-of\n * iterables) is deliberate and safe: it can only suppress a hoist.\n */\nfunction collectBoundNames(code: string): Set<string> {\n const bound = new Set<string>();\n\n // Per top-level-comma piece, keep only the binding side: names before any\n // top-level `:` (type annotation) or `=` (default/initializer). Inside\n // destructuring patterns the `:`/`=` sit at depth > 0, so the whole\n // pattern is collected (renames and default values over-collect — safe).\n const addBindingSegment = (segment: string): void => {\n let depth = 0;\n let pieceStart = 0;\n let cut = -1;\n const flush = (end: number): void => {\n const prefix = segment.slice(pieceStart, cut === -1 ? end : cut);\n for (const id of prefix.matchAll(/[A-Za-z_$][\\w$]*/g)) {\n bound.add(id[0]);\n }\n cut = -1;\n };\n for (let i = 0; i < segment.length; i++) {\n const ch = segment[i];\n if (ch === \"(\" || ch === \"[\" || ch === \"{\") {\n depth++;\n } else if (ch === \")\" || ch === \"]\" || ch === \"}\") {\n depth--;\n } else if (depth === 0 && ch === \",\") {\n flush(i);\n pieceStart = i + 1;\n } else if (depth === 0 && cut === -1 && (ch === \":\" || ch === \"=\")) {\n cut = i;\n }\n }\n flush(segment.length);\n };\n\n /** Balanced `( ... )` span starting at `open` (must point at `(`). */\n const parenSpan = (open: number): { inner: string; end: number } | null => {\n let depth = 0;\n for (let i = open; i < code.length; i++) {\n const ch = code[i];\n if (ch === \"(\") depth++;\n else if (ch === \")\") {\n depth--;\n if (depth === 0) return { inner: code.slice(open + 1, i), end: i };\n }\n }\n return null;\n };\n\n // function f(a, b) / function (a = call()) — balanced + multiline\n for (const m of code.matchAll(/\\bfunction\\b/g)) {\n let i = m.index + m[0].length;\n while (i < code.length && code[i] !== \"(\" && code[i] !== \"{\" && code[i] !== \";\") i++;\n if (code[i] !== \"(\") continue;\n const span = parenSpan(i);\n if (span) addBindingSegment(span.inner);\n }\n // (a, b) => / (a = call()): Ret => — balanced params located from the arrow\n for (const m of code.matchAll(/=>/g)) {\n let i = m.index - 1;\n while (i >= 0 && /\\s/.test(code[i] as string)) i--;\n if (i < 0) continue;\n let closeAt = -1;\n if (code[i] === \")\") {\n closeAt = i;\n } else {\n // Possible return-type annotation between `)` and `=>`:\n // `(a): Promise<T> =>`. Find the nearest `)` whose gap to the arrow\n // looks like a type annotation; give up otherwise (over-approximation\n // elsewhere keeps this safe).\n const before = code.slice(0, m.index);\n const lastClose = before.lastIndexOf(\")\");\n if (lastClose !== -1 && /^\\s*:[^(){};]*$/.test(before.slice(lastClose + 1))) {\n closeAt = lastClose;\n }\n }\n if (closeAt === -1) continue;\n // walk back to the matching `(`\n let depth = 0;\n for (let j = closeAt; j >= 0; j--) {\n const ch = code[j];\n if (ch === \")\") depth++;\n else if (ch === \"(\") {\n depth--;\n if (depth === 0) {\n addBindingSegment(code.slice(j + 1, closeAt));\n break;\n }\n }\n }\n }\n // bare arrow param: a =>\n for (const m of code.matchAll(/([A-Za-z_$][\\w$]*)\\s*=>/g)) {\n bound.add(m[1] ?? \"\");\n }\n // method(a, b) { / method(a = call()): Ret { — excluding control flow.\n // The balanced span must be directly followed by `{` (after an optional\n // return type), which call expressions essentially never are.\n const methodAnchor = new RegExp(\n String.raw`(?<![.\\w$])(?!(?:${NON_BINDING_KEYWORDS})\\b)[A-Za-z_$][\\w$]*\\s*\\(`,\n \"g\",\n );\n for (const m of code.matchAll(methodAnchor)) {\n const span = parenSpan(m.index + m[0].length - 1);\n if (!span) continue;\n const after = code.slice(span.end + 1);\n if (/^\\s*(?::[^{};()]*)?\\{/.test(after)) addBindingSegment(span.inner);\n }\n // catch (e)\n for (const m of code.matchAll(/\\bcatch\\s*\\(/g)) {\n const span = parenSpan(m.index + m[0].length - 1);\n if (span) addBindingSegment(span.inner);\n }\n // class names are TDZ bindings (function declarations hoist, classes don't)\n for (const m of code.matchAll(/\\bclass\\s+([A-Za-z_$][\\w$]*)/g)) {\n bound.add(m[1] ?? \"\");\n }\n // const/let/var declarator patterns — balanced + multiline. The span runs\n // to the first top-level `;` (or an unbalanced closer: for-headers), so\n // `const {\\n inputSchema,\\n} = getSchemas();` collects inputSchema.\n for (const m of code.matchAll(/\\b(?:const|let|var)\\b/g)) {\n const start = m.index + m[0].length;\n let depth = 0;\n let end = code.length;\n for (let i = start; i < code.length; i++) {\n const ch = code[i];\n if (ch === \"(\" || ch === \"[\" || ch === \"{\") {\n depth++;\n } else if (ch === \")\" || ch === \"]\" || ch === \"}\") {\n depth--;\n if (depth < 0) {\n end = i;\n break;\n }\n } else if (depth === 0 && ch === \";\") {\n end = i;\n break;\n }\n }\n addBindingSegment(code.slice(start, end));\n }\n return bound;\n}\n\nexport interface HoistOptions {\n /**\n * Imported identifiers matching this pattern are treated as schema chain\n * roots even without an inline z.* reference. A string is compiled as a\n * RegExp source; null disables name-based matching.\n * @default /ZodSchema$/\n */\n schemaNamePattern?: RegExp | string | null | undefined;\n /**\n * Fired when the file has hoist-relevant roots and the full source scan\n * actually runs — i.e., real parse-level work happened (as opposed to the\n * microsecond import-collection bail). The disk cache uses this to decide\n * that even a null transform result is worth persisting: re-deriving\n * \"nothing to hoist\" costs a full scan per zod-importing file per run.\n */\n onScan?: (() => void) | undefined;\n}\n\n/**\n * Free-variable analysis of a hoisted expression's source text, for the\n * build-time compile step. Returns null when the text does not parse (it\n * always should — it was extracted by this module).\n */\nexport function analyzeHoistedExpression(\n text: string,\n): { eagerFree: Set<string>; deferredFree: Set<string> } | null {\n try {\n const parsed = parseAssignmentAt(text, 0);\n const { eagerFree, deferredFree, impure } = analyzeCaptures(parsed);\n if (impure) return null;\n return { eagerFree, deferredFree };\n } catch {\n return null;\n }\n}\n\n/** A schema construction hoisted to module scope. */\nexport interface HoistedSchema {\n /** Module-scope binding name (`_zh_<hash>`). */\n name: string;\n /** Source text of the hoisted construction expression. */\n text: string;\n}\n\nexport interface HoistResult {\n /** The rewritten source. */\n code: string;\n /** One entry per hoisted declaration, in declaration order. */\n schemas: HoistedSchema[];\n /**\n * The splices (input coordinates) that produced `code`, for sourcemap\n * generation: expression → `_zh_*` replacements plus the declaration-block\n * insertion. `code === applyEdits(input, edits, insert)` by construction.\n */\n edits: Edit[];\n insert: Insertion;\n}\n\n/**\n * Hoist eligible Zod schema expressions to module scope.\n * Returns the rewritten source, or null when nothing was hoisted.\n */\nexport function hoistZodSchemas(code: string, options?: HoistOptions): string | null {\n return hoistZodSchemasMeta(code, options)?.code ?? null;\n}\n\n/**\n * hoistZodSchemas + metadata about each hoisted declaration, so the\n * transform can compile the hoisted schemas into optimized validators.\n */\nexport function hoistZodSchemasMeta(code: string, options?: HoistOptions): HoistResult | null {\n // Idempotency: a file carrying hoisted declarations IS this pass's output.\n // Plain hoists are naturally inert on re-runs (depth-0 masking), but a\n // compiled hoisted decl embeds its original z.* expression inside the IIFE\n // (depth > 0) — re-hoisting it would emit a duplicate _zh_ declaration.\n if (/\\bconst _zh_[0-9a-f]{8} = /.test(code)) return null;\n\n const imports = collectImportBindings(code);\n if (imports.all.size === 0) return null;\n\n const rawPattern = options?.schemaNamePattern;\n const namePattern =\n rawPattern === null\n ? null\n : rawPattern === undefined\n ? SCHEMA_NAME_PATTERN\n : typeof rawPattern === \"string\"\n ? new RegExp(rawPattern)\n : rawPattern;\n\n const roots = new Set<string>(imports.zod);\n if (namePattern) {\n for (const name of imports.all) {\n if (namePattern.test(name)) roots.add(name);\n }\n }\n // Imported roots that only qualify via an inline z.* reference in the\n // chain are validated per-expression below; scan them as candidates too.\n if (imports.zod.size > 0) {\n for (const name of imports.all) roots.add(name);\n }\n if (roots.size === 0) return null;\n\n options?.onScan?.();\n const { candidates, stripped } = scanSource(code, roots);\n if (candidates.length === 0) return null;\n\n let boundNames: Set<string> | undefined;\n function isShadowed(name: string): boolean {\n boundNames ??= collectBoundNames(stripped());\n return boundNames.has(name);\n }\n\n interface Hoist {\n start: number;\n end: number;\n name: string;\n }\n const hoists: Hoist[] = [];\n const declByText = new Map<string, string>();\n let consumedUntil = 0;\n\n for (const candidate of candidates) {\n if (candidate.index < consumedUntil) continue;\n\n // Masking (babel-plugin-zod-hoist nesting semantics):\n // - Depth-0 chains are top-level statements/initializers — already\n // evaluated once per module load, nothing to gain — and their interior\n // must not hoist separately either. Exception: concise arrow bodies\n // (`const make = () => z.object(...)`) re-run per call.\n // Their extent comes from the cheap scanner (findChainEnd), NOT acorn:\n // schema modules are mostly top-level declarations, and an acorn parse\n // per declaration only to discard it dominated cold hoist cost.\n // - Zod-rooted chains mask their interior REGARDLESS of eligibility (an\n // inner z.string() of `z.object({ a: z.string(), b: local })` belongs\n // to the outer schema — babel's isNestedInZodCall).\n // - Chains rooted elsewhere (`sql.type(...)`, `api.get(...)`,\n // `Base.extend(...)`) mask their interior only when actually hoisted:\n // a rejected outer chain leaves its arguments free, so the inner\n // `z.object({...})` of `sql.type(z.object({...}))` hoists on its own.\n if (candidate.depth === 0 && !candidate.afterArrow) {\n consumedUntil = findChainEnd(code, candidate.index);\n continue;\n }\n\n let parsed: Expression;\n try {\n parsed = parseAssignmentAt(code, candidate.index);\n } catch {\n continue;\n }\n let chain = narrowToCallChain(parsed, candidate.index);\n if (!chain) continue;\n\n const rootIsZod = imports.zod.has(candidate.name);\n\n if (rootIsZod) consumedUntil = chain.end;\n\n // Peel trailing parse calls: for `z.object({...}).safeParse(input)`,\n // hoist the construction and leave `.safeParse(input)` — with its\n // local-variable arguments — at the call site.\n let described = describeChain(chain);\n while (\n chain !== null &&\n described !== null &&\n described.methods.length > 0 &&\n PARSE_METHODS.has(described.methods[0] as string)\n ) {\n const callee: AnyNode | null = chain.type === \"CallExpression\" ? chain.callee : null;\n const inner: AnyNode | null =\n callee !== null && callee.type === \"MemberExpression\" ? callee.object : null;\n chain = inner !== null && inner.type === \"CallExpression\" ? (inner as Expression) : null;\n described = chain === null ? null : describeChain(chain);\n }\n if (chain === null || described === null) continue;\n // Tighten the zod-rooted mask to the peeled construction extent: the\n // arguments of a peeled `.parse(...)` are not part of the schema, so\n // candidates inside them stay free (babel traverses execution-method\n // arguments normally).\n if (rootIsZod) consumedUntil = chain.end;\n if (described.root !== candidate.name) continue;\n if (described.methods.some((m) => PARSE_METHODS.has(m))) continue;\n\n const rootMatchesPattern = namePattern?.test(candidate.name) === true;\n // Non-z bases must look like schema derivation: the chain must START\n // with a combinator (`Base.extend({...}).optional()` qualifies via\n // extend), so an arbitrary imported object with a z-mentioning argument\n // (`api.get(z.string())`) is never hoisted. describeChain records\n // methods outermost-first — the deepest method is last.\n const deepestMethod = described.methods[described.methods.length - 1];\n if (!rootIsZod && (deepestMethod === undefined || !COMBINATOR_METHODS.has(deepestMethod))) {\n continue;\n }\n\n const { eagerFree, deferredFree, impure } = analyzeCaptures(chain);\n if (impure) continue;\n // Capture rule (babel-plugin-zod-hoist's canSafelyHoist, hardened): a\n // free name is safe only when it is an import or a recognized standard\n // global, and is never re-bound anywhere in the file (no scope info, so\n // a name bound in ANY function cannot be trusted to mean the import —\n // over-rejection only costs a missed hoist). The babel plugin also\n // allows arbitrary unbound identifiers, but it has real scope analysis;\n // here an unknown bare name is more likely a binding the lexical\n // collector missed than a genuine global, and hoisting it would crash\n // at module load (`ReferenceError: <name> is not defined`).\n let eligible = true;\n for (const name of eagerFree) {\n if ((!imports.all.has(name) && !KNOWN_GLOBALS.has(name)) || isShadowed(name)) {\n eligible = false;\n break;\n }\n }\n if (eligible) {\n for (const name of deferredFree) {\n if ((!imports.all.has(name) && !KNOWN_GLOBALS.has(name)) || isShadowed(name)) {\n eligible = false;\n break;\n }\n }\n }\n if (!eligible) continue;\n\n // Non-zod, non-pattern roots qualify only when the chain itself\n // references a zod binding (`Base.extend({ a: z.string() })`).\n if (!rootIsZod && !rootMatchesPattern) {\n let referencesZod = false;\n for (const name of eagerFree) {\n if (imports.zod.has(name)) {\n referencesZod = true;\n break;\n }\n }\n for (const name of deferredFree) {\n if (imports.zod.has(name)) {\n referencesZod = true;\n break;\n }\n }\n if (!referencesZod) continue;\n }\n\n const text = code.slice(candidate.index, chain.end);\n let declName = declByText.get(text);\n if (!declName) {\n declName = `_zh_${fnv1a(text)}`;\n declByText.set(text, declName);\n }\n hoists.push({ start: candidate.index, end: chain.end, name: declName });\n // Non-zod-rooted chains mask their interior only on success — the inner\n // parts are consumed by this hoist's replacement.\n consumedUntil = Math.max(consumedUntil, chain.end);\n }\n\n if (hoists.length === 0) return null;\n\n const decls = [...declByText.entries()]\n .map(([text, name]) => `const ${name} = ${text};`)\n .join(\"\\n\");\n // The insertion offset is identical in input and output coordinates: the\n // directive prologue precedes every statement, and all hoist replacements\n // sit inside statements.\n const edits: Edit[] = hoists.map((h) => ({ start: h.start, end: h.end, text: h.name }));\n const insert: Insertion = { offset: moduleHeadOffset(code), text: `${decls}\\n` };\n return {\n code: applyEdits(code, edits, insert),\n schemas: [...declByText.entries()].map(([text, name]) => ({ name, text })),\n edits,\n insert,\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"hoist.js","names":[],"sources":["../../src/unplugin/hoist.ts"],"sourcesContent":["import type { AnyNode, Expression, Options } from \"acorn\";\nimport { Parser } from \"acorn\";\nimport { applyEdits, type Edit, type Insertion, moduleHeadOffset } from \"./edits.js\";\n\n/**\n * Hoist Zod schema construction out of functions to module scope —\n * equivalent of babel-plugin-zod-hoist.\n *\n * Schemas built inside function bodies are re-constructed on every call:\n *\n * function getSchema() {\n * return z.object({ name: z.string() }); // rebuilt per call\n * }\n *\n * becomes\n *\n * const _zh_94b7f5c1 = z.object({ name: z.string() });\n * function getSchema() {\n * return _zh_94b7f5c1; // built once\n * }\n *\n * Safety rules (babel-plugin-zod-hoist's `canSafelyHoist`, hardened for\n * lexical analysis):\n * - A free identifier must be an import or a KNOWN_GLOBALS member, and must\n * never be bound anywhere in the file (function params, locals, catch\n * clauses, class names, module-level const/let/var — hoisting above those\n * would change meaning or hit the TDZ). The babel plugin additionally\n * allows arbitrary unbound identifiers because it has real scope\n * information; this port's binding collector is lexical, so an unknown\n * bare name is treated as a possibly-missed binding rather than a global\n * (a wrong guess crashes at module load with a ReferenceError).\n * `this`/`super` disqualify anywhere. Eager `await`/`yield` also\n * disqualify (stricter than the babel plugin, which never encounters\n * them: hoisting one would emit top-level await / orphaned yield).\n * - Eligible roots: any binding imported from zod, an imported identifier\n * matching /ZodSchema$/, or an imported identifier whose chain contains\n * an inline z.* reference (e.g. `Base.extend({ a: z.string() })`).\n * - Nesting (babel's `isNestedInZodCall`): the interior of a zod-rooted\n * chain never hoists separately — it goes with the outer schema or not at\n * all. Chains rooted elsewhere (`sql.type(...)`, `api.get(...)`) do NOT\n * suppress their arguments: when the outer chain is rejected, an inner\n * `z.object({...})` still hoists on its own.\n * - Declarations are inserted at the top of the module (after shebang and\n * directive prologue). Imports are initialized before module code runs,\n * so referencing them from above their textual position is safe.\n * - Names are content-hashed, so identical schemas dedupe to one binding.\n *\n * The source is TypeScript, which acorn cannot fully parse — candidates are\n * located with a string/comment/depth-aware scanner and extracted with\n * parseExpressionAt (the same technique as the autoDiscover rewrite).\n * Anything unparseable (TS generics, `as` casts) is skipped: a miss leaves\n * the schema unhoisted, never breaks the code.\n */\n\n/**\n * Imported identifiers matching this pattern are treated as schema roots.\n *\n * The default must keep implying a \"Zod\" substring: it is one of the three\n * triggers the transform hook's `code` filter (ZOD_MENTION in transform.ts)\n * is a superset of. A default that matched, say, `/Schema$/` would make\n * hoistable files without any \"zod\" mention invisible to bundlers with native\n * hook filters. (A *user-supplied* pattern is handled — it drops the filter.)\n */\nexport const SCHEMA_NAME_PATTERN = /ZodSchema$/;\n\n/**\n * Module specifiers whose bindings count as the zod namespace. Every entry\n * must contain \"zod\" for the same reason as SCHEMA_NAME_PATTERN above; both\n * are pinned by `describe(\"code filter soundness\")` in the transform tests.\n */\nexport const ZOD_MODULES = new Set([\n \"zod\",\n \"zod/v3\",\n \"zod/v4\",\n \"zod/mini\",\n \"zod/v4/mini\",\n \"zod/v4-mini\",\n]);\n\n/** How an imported local binding maps onto its source module. */\nexport interface ImportDetail {\n /** Module specifier (`\"zod\"`, `\"./shapes\"`). */\n specifier: string;\n /** Exported name the binding refers to; `\"*\"` for namespace imports, `\"default\"` for default imports. */\n imported: string;\n}\n\ninterface ImportBindings {\n /** Every runtime (non-type) imported binding name. */\n all: Set<string>;\n /** Bindings imported from a zod module (usually just `z`). */\n zod: Set<string>;\n /** Local binding name → source module/export, for build-time evaluation. */\n details: Map<string, ImportDetail>;\n}\n\n/**\n * Collect runtime import bindings with a regex over import statements.\n * Type-only imports and `type` specifiers are excluded — they cannot be\n * referenced at runtime, so excluding them keeps the capture rule sound.\n */\nexport function collectImportBindings(code: string): ImportBindings {\n const all = new Set<string>();\n const zod = new Set<string>();\n const details = new Map<string, ImportDetail>();\n const importPattern = /import\\s+(type\\s+)?([^'\";]+?)\\s+from\\s*[\"']([^\"']+)[\"']/g;\n\n for (const match of code.matchAll(importPattern)) {\n const [, typeOnly, clause, specifier] = match;\n if (typeOnly || clause === undefined || specifier === undefined) continue;\n const isZod = ZOD_MODULES.has(specifier);\n for (const { local, imported } of parseImportClause(clause)) {\n all.add(local);\n if (isZod) zod.add(local);\n details.set(local, { specifier, imported });\n }\n }\n return { all, zod, details };\n}\n\n/** Extract local binding names (with their source export) from an import clause. */\nfunction parseImportClause(clause: string): Array<{ local: string; imported: string }> {\n const names: Array<{ local: string; imported: string }> = [];\n const namedStart = clause.indexOf(\"{\");\n\n // Default import and/or namespace import before the named group\n const head = namedStart === -1 ? clause : clause.slice(0, namedStart);\n for (const part of head.split(\",\")) {\n const trimmed = part.trim();\n if (!trimmed) continue;\n const ns = trimmed.match(/^\\*\\s*as\\s+([A-Za-z_$][\\w$]*)$/);\n if (ns?.[1]) {\n names.push({ local: ns[1], imported: \"*\" });\n } else if (/^[A-Za-z_$][\\w$]*$/.test(trimmed)) {\n names.push({ local: trimmed, imported: \"default\" });\n }\n }\n\n if (namedStart !== -1) {\n const namedEnd = clause.indexOf(\"}\", namedStart);\n const inner = clause.slice(namedStart + 1, namedEnd === -1 ? undefined : namedEnd);\n for (const part of inner.split(\",\")) {\n const spec = part.trim();\n if (!spec || spec.startsWith(\"type \")) continue;\n // `a as b` binds b; plain `a` binds a\n const asMatch = spec.match(/^([A-Za-z_$][\\w$]*)\\s+as\\s+([A-Za-z_$][\\w$]*)$/);\n if (asMatch?.[1] && asMatch[2]) {\n names.push({ local: asMatch[2], imported: asMatch[1] });\n } else if (/^[A-Za-z_$][\\w$]*$/.test(spec)) {\n names.push({ local: spec, imported: spec });\n }\n }\n }\n return names;\n}\n\n/** Deterministic FNV-1a 32-bit hash, hex-encoded. */\nfunction fnv1a(text: string): string {\n let hash = 0x811c9dc5;\n for (let i = 0; i < text.length; i++) {\n hash ^= text.charCodeAt(i);\n hash = Math.imul(hash, 0x01000193);\n }\n return (hash >>> 0).toString(16).padStart(8, \"0\");\n}\n\ninterface Candidate {\n /** Offset of the root identifier. */\n index: number;\n /** Bracket/brace/paren depth at the offset (0 = top level). */\n depth: number;\n /** The root identifier text. */\n name: string;\n /**\n * The candidate directly follows `=>` — a concise arrow body. Even at\n * depth 0 (`const make = () => z.object(...)`) it re-evaluates per call.\n */\n afterArrow: boolean;\n}\n\n/**\n * Char-code identifier/whitespace classes for the scanner hot loops — a\n * regex `.test()` per character dominated scan time once the acorn parses\n * were gone. The ident classes are deliberately ASCII-only (`[A-Za-z_$]` /\n * `[\\w$]`, matching the scanner's historical regexes); the space check falls\n * back to `/\\s/` for the rare non-ASCII code points it matches (NBSP, BOM,\n * U+2028...).\n */\nfunction isIdentStartCode(c: number): boolean {\n return (c >= 97 && c <= 122) || (c >= 65 && c <= 90) || c === 95 || c === 36;\n}\nfunction isIdentPartCode(c: number): boolean {\n return (\n (c >= 97 && c <= 122) || (c >= 65 && c <= 90) || (c >= 48 && c <= 57) || c === 95 || c === 36\n );\n}\nfunction isSpaceCode(c: number): boolean {\n if (c === 32 || (c >= 9 && c <= 13)) return true;\n return c > 127 && /\\s/.test(String.fromCharCode(c));\n}\n\n/** After these tokens a `/` starts a regex literal, not division. */\nconst REGEX_PRECEDING_KEYWORDS = new Set([\n \"return\",\n \"typeof\",\n \"instanceof\",\n \"in\",\n \"of\",\n \"new\",\n \"delete\",\n \"void\",\n \"throw\",\n \"do\",\n \"else\",\n \"case\",\n \"yield\",\n \"await\",\n]);\n\n/** Is `/` after this token division (true) or a regex literal (false)? */\nfunction isDivisionContext(lastToken: string): boolean {\n if (lastToken === \")\" || lastToken === \"]\") return true;\n if (/^[\"'`]$/.test(lastToken)) return true;\n if (/^[\\w$]+$/.test(lastToken)) return !REGEX_PRECEDING_KEYWORDS.has(lastToken);\n return false;\n}\n\ninterface ScanResult {\n candidates: Candidate[];\n /**\n * Lazily builds the source with comments, string/template-string contents,\n * and regex literals masked to spaces (offsets preserved). Used for\n * binding-name collection so JSDoc examples and string contents never\n * count. Lazy because it is only needed when a candidate survives to\n * shadow-checking — schema modules (everything masked at depth 0) never\n * pay for it.\n */\n stripped: () => string;\n}\n\n/**\n * Scan the source for candidate root identifiers (`z`, `FooZodSchema`, ...)\n * followed by a `.`, tracking string/template/comment state and nesting\n * depth. Depth 0 candidates are top-level initializers — already evaluated\n * once — and are recorded only so their extents mask nested candidates.\n */\nfunction scanSource(code: string, roots: Set<string>): ScanResult {\n const candidates: Candidate[] = [];\n // Masked extents as flat [from, to) pairs, pushed in scan order (monotonic,\n // non-overlapping) — materialized into a stripped string only on demand.\n const maskRanges: number[] = [];\n const mask = (from: number, to: number): void => {\n maskRanges.push(from, to);\n };\n let depth = 0;\n // Template literals interleave string and expression states; the stack\n // records the brace depth at which each `${` opened so the matching `}`\n // resumes string state.\n const templateStack: number[] = [];\n let lastToken = \"\";\n let i = 0;\n\n while (i < code.length) {\n const ch = code[i] as string;\n const next = code[i + 1];\n\n // Comments\n if (ch === \"/\" && next === \"/\") {\n const nl = code.indexOf(\"\\n\", i);\n const end = nl === -1 ? code.length : nl + 1;\n mask(i, end);\n i = end;\n continue;\n }\n if (ch === \"/\" && next === \"*\") {\n const close = code.indexOf(\"*/\", i + 2);\n const end = close === -1 ? code.length : close + 2;\n mask(i, end);\n i = end;\n continue;\n }\n if (ch === \"/\") {\n if (!isDivisionContext(lastToken)) {\n const end = skipRegexLiteral(code, i);\n mask(i, end);\n i = end;\n lastToken = \")\"; // a regex literal is an operand\n continue;\n }\n lastToken = ch;\n i++;\n continue;\n }\n // Strings\n if (ch === '\"' || ch === \"'\") {\n const end = skipString(code, i, ch);\n mask(i, end);\n i = end;\n lastToken = ch;\n continue;\n }\n // Template literals\n if (ch === \"`\") {\n const end = skipTemplateChunk(code, i + 1, templateStack, depth);\n mask(i, end);\n i = end;\n lastToken = \"`\";\n continue;\n }\n if (\n templateStack.length > 0 &&\n ch === \"}\" &&\n depth === templateStack[templateStack.length - 1]\n ) {\n // End of a ${ } expression — back into template string state\n templateStack.pop();\n const end = skipTemplateChunk(code, i + 1, templateStack, depth);\n mask(i, end);\n i = end;\n lastToken = \"`\";\n continue;\n }\n\n if (ch === \"(\" || ch === \"[\" || ch === \"{\") {\n depth++;\n lastToken = ch;\n i++;\n continue;\n }\n if (ch === \")\" || ch === \"]\" || ch === \"}\") {\n depth--;\n lastToken = ch;\n i++;\n continue;\n }\n\n if (isIdentStartCode(code.charCodeAt(i)) && !isIdentPartCode(code.charCodeAt(i - 1))) {\n let j = i + 1;\n while (j < code.length && isIdentPartCode(code.charCodeAt(j))) j++;\n const word = code.slice(i, j);\n // Skip whitespace to check for the member access\n let k = j;\n while (k < code.length && isSpaceCode(code.charCodeAt(k))) k++;\n if (roots.has(word) && code[k] === \".\" && lastToken !== \".\") {\n candidates.push({ index: i, depth, name: word, afterArrow: lastToken === \"=>\" });\n }\n lastToken = word;\n i = j;\n continue;\n }\n\n if (!isSpaceCode(code.charCodeAt(i))) {\n lastToken = ch === \">\" && lastToken === \"=\" ? \"=>\" : ch;\n }\n i++;\n }\n\n const stripped = (): string => {\n if (maskRanges.length === 0) return code;\n let out = \"\";\n let prev = 0;\n for (let r = 0; r < maskRanges.length; r += 2) {\n const from = maskRanges[r] as number;\n const to = maskRanges[r + 1] as number;\n out += code.slice(prev, from) + code.slice(from, to).replace(/[^\\n]/g, \" \");\n prev = to;\n }\n return out + code.slice(prev);\n };\n return { candidates, stripped };\n}\n\nfunction skipString(code: string, start: number, quote: string): number {\n for (let i = start + 1; i < code.length; i++) {\n if (code[i] === \"\\\\\") {\n i++;\n } else if (code[i] === quote || code[i] === \"\\n\") {\n return i + 1;\n }\n }\n return code.length;\n}\n\n/**\n * Skip a template string chunk; returns the offset after the closing\n * `` ` `` or after a `${`, recording the current depth so the scanner can\n * recognize the matching `}` later.\n */\nfunction skipTemplateChunk(\n code: string,\n start: number,\n templateStack: number[],\n depth: number,\n): number {\n for (let i = start; i < code.length; i++) {\n if (code[i] === \"\\\\\") {\n i++;\n } else if (code[i] === \"`\") {\n return i + 1;\n } else if (code[i] === \"$\" && code[i + 1] === \"{\") {\n templateStack.push(depth);\n return i + 2;\n }\n }\n return code.length;\n}\n\nfunction skipRegexLiteral(code: string, start: number): number {\n let inClass = false;\n for (let i = start + 1; i < code.length; i++) {\n const ch = code[i];\n if (ch === \"\\\\\") {\n i++;\n } else if (ch === \"[\") {\n inClass = true;\n } else if (ch === \"]\") {\n inClass = false;\n } else if (ch === \"/\" && !inClass) {\n return i + 1;\n } else if (ch === \"\\n\") {\n // Not a regex after all (unterminated) — treat as division\n return start + 1;\n }\n }\n return code.length;\n}\n\n/**\n * Cheap chain-extent scan: from a root identifier, advance past the longest\n * member/call/tagged-template chain (`.x`, `?.x`, `!`, `(...)`, `[...]`,\n * `` `...` ``). Used to mask the interior of depth-0 chains WITHOUT an acorn\n * parse: schema modules are mostly top-level declarations, and parsing each\n * one only to discard it under the depth-0 rule dominated cold hoist cost in\n * a field report (hoist 37–46s vs discover 12–16s across ~7k transforms).\n * May overshoot an AST-exact end only across TS-only syntax (postfix `!`);\n * stops at anything else it does not recognize (`<` generics, operators) —\n * an undershoot leaves interior candidates to their own depth-0/eligibility\n * rules, an overshoot only widens the mask over an expression that already\n * evaluates once at module scope.\n */\nfunction findChainEnd(code: string, identStart: number): number {\n let i = identStart;\n while (i < code.length && isIdentPartCode(code.charCodeAt(i))) i++;\n\n const skipTrivia = (): void => {\n for (;;) {\n while (i < code.length && isSpaceCode(code.charCodeAt(i))) i++;\n if (code[i] === \"/\" && code[i + 1] === \"/\") {\n const nl = code.indexOf(\"\\n\", i);\n i = nl === -1 ? code.length : nl + 1;\n } else if (code[i] === \"/\" && code[i + 1] === \"*\") {\n const close = code.indexOf(\"*/\", i + 2);\n i = close === -1 ? code.length : close + 2;\n } else {\n return;\n }\n }\n };\n\n // Advance past one balanced construct starting at `(`, `[`, or a template\n // backtick — mirroring scanSource's string/template/regex/comment rules.\n const skipNested = (): void => {\n let depth = 0;\n const templateStack: number[] = [];\n let lastToken = \"\";\n while (i < code.length) {\n const ch = code[i] as string;\n const next = code[i + 1];\n if (ch === \"/\" && next === \"/\") {\n const nl = code.indexOf(\"\\n\", i);\n i = nl === -1 ? code.length : nl + 1;\n continue;\n }\n if (ch === \"/\" && next === \"*\") {\n const close = code.indexOf(\"*/\", i + 2);\n i = close === -1 ? code.length : close + 2;\n continue;\n }\n if (ch === \"/\") {\n if (!isDivisionContext(lastToken)) {\n i = skipRegexLiteral(code, i);\n lastToken = \")\";\n continue;\n }\n lastToken = ch;\n i++;\n continue;\n }\n if (ch === '\"' || ch === \"'\") {\n i = skipString(code, i, ch);\n lastToken = ch;\n continue;\n }\n if (ch === \"`\") {\n i = skipTemplateChunk(code, i + 1, templateStack, depth);\n lastToken = \"`\";\n if (depth === 0 && templateStack.length === 0) return;\n continue;\n }\n if (\n templateStack.length > 0 &&\n ch === \"}\" &&\n depth === templateStack[templateStack.length - 1]\n ) {\n templateStack.pop();\n i = skipTemplateChunk(code, i + 1, templateStack, depth);\n lastToken = \"`\";\n if (depth === 0 && templateStack.length === 0) return;\n continue;\n }\n if (ch === \"(\" || ch === \"[\" || ch === \"{\") {\n depth++;\n lastToken = ch;\n i++;\n continue;\n }\n if (ch === \")\" || ch === \"]\" || ch === \"}\") {\n depth--;\n lastToken = ch;\n i++;\n if (depth === 0 && templateStack.length === 0) return;\n continue;\n }\n if (isIdentStartCode(code.charCodeAt(i)) && !isIdentPartCode(code.charCodeAt(i - 1))) {\n let j = i + 1;\n while (j < code.length && isIdentPartCode(code.charCodeAt(j))) j++;\n lastToken = code.slice(i, j);\n i = j;\n continue;\n }\n if (!isSpaceCode(code.charCodeAt(i))) {\n lastToken = ch === \">\" && lastToken === \"=\" ? \"=>\" : ch;\n }\n i++;\n }\n };\n\n for (;;) {\n skipTrivia();\n const ch = code[i];\n if (ch === \".\" || (ch === \"?\" && code[i + 1] === \".\")) {\n i += ch === \".\" ? 1 : 2;\n skipTrivia();\n while (i < code.length && isIdentPartCode(code.charCodeAt(i))) i++;\n continue;\n }\n if (ch === \"!\") {\n i++;\n continue;\n }\n if (ch === \"(\" || ch === \"[\" || ch === \"`\") {\n skipNested();\n continue;\n }\n return i;\n }\n}\n\n/**\n * Parse a single assignment-level expression at `pos` — the same entry point\n * acorn's own parseExpressionAt uses, one precedence level down. At\n * expression level a trailing comma in an argument position\n * (`sql.type(z.object({...}),\\n)`) starts a sequence-expression parse that\n * throws on the surrounding `)`; assignment level treats the comma as\n * trailing garbage and stops cleanly. parseMaybeAssign is the entry point\n * the acorn plugin ecosystem overrides — stable across versions.\n */\nfunction parseAssignmentAt(code: string, pos: number): Expression {\n interface ParserInternals {\n nextToken(): void;\n parseMaybeAssign(): Expression;\n }\n const parser = new (Parser as unknown as new (\n options: Options,\n input: string,\n startPos?: number,\n ) => ParserInternals)({ ecmaVersion: \"latest\", sourceType: \"module\" }, code, pos);\n parser.nextToken();\n return parser.parseMaybeAssign();\n}\n\n/**\n * Narrow a parsed expression to the largest call chain starting at `start`.\n * The parse can overshoot into surrounding operators\n * (`z.string().min(1) || fallback` parses as a LogicalExpression) — descend\n * through same-start children until a CallExpression is found.\n */\nfunction narrowToCallChain(node: Expression, start: number): Expression | null {\n let current: AnyNode = node;\n while (current.start === start) {\n if (current.type === \"CallExpression\") return current as Expression;\n const child = sameStartChild(current, start);\n if (!child) return null;\n current = child;\n }\n return null;\n}\n\nfunction sameStartChild(node: AnyNode, start: number): AnyNode | null {\n const record = node as unknown as Record<string, unknown>;\n for (const key of [\"left\", \"object\", \"callee\", \"test\", \"tag\", \"expression\", \"expressions\"]) {\n const value = record[key];\n const child = Array.isArray(value) ? value[0] : value;\n if (\n typeof child === \"object\" &&\n child !== null &&\n (child as AnyNode).start === start &&\n typeof (child as AnyNode).type === \"string\"\n ) {\n return child as AnyNode;\n }\n }\n return null;\n}\n\n/**\n * Walk a member/call chain down to its base identifier, collecting the\n * non-computed method names along the spine. Computed members\n * (`base[name]()`) are unanalyzable — the chain is rejected.\n */\nfunction describeChain(node: Expression): { root: string; methods: string[] } | null {\n const methods: string[] = [];\n let current: AnyNode = node;\n while (true) {\n if (current.type === \"CallExpression\") {\n current = current.callee;\n } else if (current.type === \"MemberExpression\") {\n if (current.computed || current.property.type !== \"Identifier\") return null;\n methods.push(current.property.name);\n current = current.object;\n } else if (current.type === \"Identifier\") {\n return { root: current.name, methods };\n } else {\n return null;\n }\n }\n}\n\n/**\n * Combinators eligible on non-z chain bases (babel-plugin-zod-hoist's\n * SCHEMA_COMBINATOR_METHODS, verbatim) — `Base.extend({...})`,\n * `Base.pick({...})`, `UserZodSchema.optional()`, ...\n */\nconst COMBINATOR_METHODS = new Set([\n \"and\",\n \"array\",\n \"brand\",\n \"catchall\",\n \"deepPartial\",\n \"describe\",\n \"extend\",\n \"merge\",\n \"nullable\",\n \"nullish\",\n \"omit\",\n \"optional\",\n \"or\",\n \"partial\",\n \"passthrough\",\n \"pick\",\n \"readonly\",\n \"refine\",\n \"required\",\n \"strict\",\n \"strip\",\n \"superRefine\",\n \"transform\",\n]);\n\n/**\n * Methods that evaluate data rather than construct schemas. Hoisting one\n * would move the evaluation (and any throw) to module load.\n */\nconst PARSE_METHODS = new Set([\n \"parse\",\n \"safeParse\",\n \"parseAsync\",\n \"safeParseAsync\",\n \"decode\",\n \"encode\",\n \"decodeAsync\",\n \"encodeAsync\",\n]);\n\n/**\n * Standard globals a hoisted expression may reference (eager or deferred —\n * babel-parity behaviors like hoisting `z.date().default(new Date())` rely\n * on Date/Math being recognized).\n *\n * The babel plugin allows ANY unbound identifier because it has real scope\n * information; this port's binding collector is a lexical approximation, so\n * an unknown bare name must be assumed to be a binding the collector missed\n * — hoisting it would crash at module load with\n * `ReferenceError: <name> is not defined`. A fixed allowlist converts that\n * failure mode into a missed optimization.\n */\nconst KNOWN_GLOBALS = new Set([\n \"globalThis\",\n \"NaN\",\n \"Infinity\",\n \"Math\",\n \"Number\",\n \"String\",\n \"Boolean\",\n \"Array\",\n \"Object\",\n \"JSON\",\n \"Date\",\n \"RegExp\",\n \"BigInt\",\n \"Symbol\",\n \"Map\",\n \"Set\",\n \"WeakMap\",\n \"WeakSet\",\n \"Promise\",\n \"Proxy\",\n \"Reflect\",\n \"Intl\",\n \"Error\",\n \"TypeError\",\n \"RangeError\",\n \"SyntaxError\",\n \"EvalError\",\n \"URIError\",\n \"AggregateError\",\n \"ArrayBuffer\",\n \"Uint8Array\",\n \"parseInt\",\n \"parseFloat\",\n \"isNaN\",\n \"isFinite\",\n \"encodeURI\",\n \"decodeURI\",\n \"encodeURIComponent\",\n \"decodeURIComponent\",\n \"structuredClone\",\n \"URL\",\n \"URLSearchParams\",\n \"TextEncoder\",\n \"TextDecoder\",\n \"atob\",\n \"btoa\",\n \"crypto\",\n \"console\",\n \"process\",\n \"Buffer\",\n]);\n\ninterface CaptureAnalysis {\n /** Free identifiers referenced in eager (immediately evaluated) positions. */\n eagerFree: Set<string>;\n /** Free identifiers referenced only inside nested function bodies. */\n deferredFree: Set<string>;\n /** Disqualifying constructs (`this`/`super` anywhere; `await`/`yield` in eager positions). */\n impure: boolean;\n}\n\n/**\n * Scope-aware free-variable analysis of an expression. Nested function\n * params and local declarations are bound names, not captures — so\n * `z.string().refine((v) => v.length > 0)` has no free variables beyond `z`.\n * References inside nested function bodies are tracked separately: they\n * evaluate per call even after hoisting, so safe globals are allowed there.\n */\nfunction analyzeCaptures(expr: Expression): CaptureAnalysis {\n const eagerFree = new Set<string>();\n const deferredFree = new Set<string>();\n let impure = false;\n\n function patternNames(node: AnyNode, into: Set<string>): void {\n switch (node.type) {\n case \"Identifier\":\n into.add(node.name);\n return;\n case \"ObjectPattern\":\n for (const prop of node.properties) {\n if (prop.type === \"Property\") patternNames(prop.value, into);\n else patternNames(prop.argument, into);\n }\n return;\n case \"ArrayPattern\":\n for (const el of node.elements) {\n if (el) patternNames(el, into);\n }\n return;\n case \"AssignmentPattern\":\n patternNames(node.left, into);\n return;\n case \"RestElement\":\n patternNames(node.argument, into);\n return;\n default:\n return;\n }\n }\n\n function collectFunctionScope(body: AnyNode, into: Set<string>): void {\n // Flatten block scoping into the function scope — over-approximating\n // bound names can only suppress a hoist's free set, and the failure\n // mode is a loud ReferenceError, never silent misvalidation.\n const stack: AnyNode[] = [body];\n while (stack.length > 0) {\n const node = stack.pop();\n if (!node || typeof node !== \"object\") continue;\n if (node.type === \"VariableDeclaration\") {\n for (const decl of node.declarations) patternNames(decl.id, into);\n } else if (node.type === \"FunctionDeclaration\" || node.type === \"ClassDeclaration\") {\n if (node.id) into.add(node.id.name);\n continue; // do not descend into nested declarations' bodies here\n } else if (node.type === \"FunctionExpression\" || node.type === \"ArrowFunctionExpression\") {\n continue; // nested functions get their own scope in visit()\n }\n for (const value of Object.values(node as unknown as Record<string, unknown>)) {\n if (Array.isArray(value)) {\n for (const item of value) {\n if (typeof item === \"object\" && item !== null && \"type\" in item) {\n stack.push(item as AnyNode);\n }\n }\n } else if (typeof value === \"object\" && value !== null && \"type\" in value) {\n stack.push(value as AnyNode);\n }\n }\n }\n }\n\n function visit(node: AnyNode, scopes: Set<string>[], deferred: boolean): void {\n switch (node.type) {\n case \"Identifier\": {\n const name = node.name;\n if (name !== \"undefined\" && !scopes.some((s) => s.has(name))) {\n (deferred ? deferredFree : eagerFree).add(name);\n }\n return;\n }\n case \"ThisExpression\":\n case \"Super\":\n // Arrows bind `this` lexically — hoisting changes it even when the\n // reference sits inside a callback. Always disqualifying.\n impure = true;\n return;\n case \"AwaitExpression\":\n case \"YieldExpression\":\n // Eager occurrences cannot be moved to module scope: hoisting would\n // emit top-level await (broken in CJS output) or an orphaned yield.\n // (Stricter than the babel plugin, whose suite never exercises\n // these.) Deferred occurrences run per call — fine to move.\n if (!deferred) {\n impure = true;\n return;\n }\n break;\n case \"MemberExpression\":\n visit(node.object, scopes, deferred);\n if (node.computed) visit(node.property, scopes, deferred);\n return;\n case \"Property\":\n if (node.computed) visit(node.key, scopes, deferred);\n visit(node.value, scopes, deferred);\n return;\n case \"FunctionExpression\":\n case \"ArrowFunctionExpression\": {\n const scope = new Set<string>();\n for (const param of node.params) patternNames(param, scope);\n if (node.type === \"FunctionExpression\" && node.id) scope.add(node.id.name);\n collectFunctionScope(node.body, scope);\n visit(node.body, [...scopes, scope], true);\n return;\n }\n default:\n break;\n }\n for (const value of Object.values(node as unknown as Record<string, unknown>)) {\n if (Array.isArray(value)) {\n for (const item of value) {\n if (typeof item === \"object\" && item !== null && \"type\" in item) {\n visit(item as AnyNode, scopes, deferred);\n }\n }\n } else if (typeof value === \"object\" && value !== null && \"type\" in value) {\n visit(value as AnyNode, scopes, deferred);\n }\n }\n }\n\n visit(expr, [], false);\n return { eagerFree, deferredFree, impure };\n}\n\n/** Keywords that precede `( ... ) {` without binding anything. */\nconst NON_BINDING_KEYWORDS =\n \"if|for|while|switch|return|typeof|await|yield|new|do|else|case|in|of|delete|void\";\n\n/**\n * Conservative shadow detection: collect every identifier appearing in a\n * binding-like position — function/method/arrow parameter lists, catch\n * clauses, class names, const/let/var declarator patterns. The scanner has\n * no scope information, so an import referenced from a hoisted expression\n * must resolve to that import everywhere; a name that is ever re-bound\n * cannot be trusted and disqualifies hoists referencing it.\n *\n * Collection is depth-aware and multiline (balanced delimiter scanning, not\n * line-bounded regexes): multiline destructuring declarations and parameter\n * defaults containing calls are real production patterns whose bindings a\n * line-based collector misses — and a missed binding here used to mean a\n * hoist referencing it crashed at module load (`ReferenceError`).\n * Over-collection (type names, destructuring default values, for-of\n * iterables) is deliberate and safe: it can only suppress a hoist.\n */\nfunction collectBoundNames(code: string): Set<string> {\n const bound = new Set<string>();\n\n // Per top-level-comma piece, keep only the binding side: names before any\n // top-level `:` (type annotation) or `=` (default/initializer). Inside\n // destructuring patterns the `:`/`=` sit at depth > 0, so the whole\n // pattern is collected (renames and default values over-collect — safe).\n const addBindingSegment = (segment: string): void => {\n let depth = 0;\n let pieceStart = 0;\n let cut = -1;\n const flush = (end: number): void => {\n const prefix = segment.slice(pieceStart, cut === -1 ? end : cut);\n for (const id of prefix.matchAll(/[A-Za-z_$][\\w$]*/g)) {\n bound.add(id[0]);\n }\n cut = -1;\n };\n for (let i = 0; i < segment.length; i++) {\n const ch = segment[i];\n if (ch === \"(\" || ch === \"[\" || ch === \"{\") {\n depth++;\n } else if (ch === \")\" || ch === \"]\" || ch === \"}\") {\n depth--;\n } else if (depth === 0 && ch === \",\") {\n flush(i);\n pieceStart = i + 1;\n } else if (depth === 0 && cut === -1 && (ch === \":\" || ch === \"=\")) {\n cut = i;\n }\n }\n flush(segment.length);\n };\n\n /** Balanced `( ... )` span starting at `open` (must point at `(`). */\n const parenSpan = (open: number): { inner: string; end: number } | null => {\n let depth = 0;\n for (let i = open; i < code.length; i++) {\n const ch = code[i];\n if (ch === \"(\") depth++;\n else if (ch === \")\") {\n depth--;\n if (depth === 0) return { inner: code.slice(open + 1, i), end: i };\n }\n }\n return null;\n };\n\n // function f(a, b) / function (a = call()) — balanced + multiline\n for (const m of code.matchAll(/\\bfunction\\b/g)) {\n let i = m.index + m[0].length;\n while (i < code.length && code[i] !== \"(\" && code[i] !== \"{\" && code[i] !== \";\") i++;\n if (code[i] !== \"(\") continue;\n const span = parenSpan(i);\n if (span) addBindingSegment(span.inner);\n }\n // (a, b) => / (a = call()): Ret => — balanced params located from the arrow\n for (const m of code.matchAll(/=>/g)) {\n let i = m.index - 1;\n while (i >= 0 && /\\s/.test(code[i] as string)) i--;\n if (i < 0) continue;\n let closeAt = -1;\n if (code[i] === \")\") {\n closeAt = i;\n } else {\n // Possible return-type annotation between `)` and `=>`:\n // `(a): Promise<T> =>`. Find the nearest `)` whose gap to the arrow\n // looks like a type annotation; give up otherwise (over-approximation\n // elsewhere keeps this safe).\n const before = code.slice(0, m.index);\n const lastClose = before.lastIndexOf(\")\");\n if (lastClose !== -1 && /^\\s*:[^(){};]*$/.test(before.slice(lastClose + 1))) {\n closeAt = lastClose;\n }\n }\n if (closeAt === -1) continue;\n // walk back to the matching `(`\n let depth = 0;\n for (let j = closeAt; j >= 0; j--) {\n const ch = code[j];\n if (ch === \")\") depth++;\n else if (ch === \"(\") {\n depth--;\n if (depth === 0) {\n addBindingSegment(code.slice(j + 1, closeAt));\n break;\n }\n }\n }\n }\n // bare arrow param: a =>\n for (const m of code.matchAll(/([A-Za-z_$][\\w$]*)\\s*=>/g)) {\n bound.add(m[1] ?? \"\");\n }\n // method(a, b) { / method(a = call()): Ret { — excluding control flow.\n // The balanced span must be directly followed by `{` (after an optional\n // return type), which call expressions essentially never are.\n const methodAnchor = new RegExp(\n String.raw`(?<![.\\w$])(?!(?:${NON_BINDING_KEYWORDS})\\b)[A-Za-z_$][\\w$]*\\s*\\(`,\n \"g\",\n );\n for (const m of code.matchAll(methodAnchor)) {\n const span = parenSpan(m.index + m[0].length - 1);\n if (!span) continue;\n const after = code.slice(span.end + 1);\n if (/^\\s*(?::[^{};()]*)?\\{/.test(after)) addBindingSegment(span.inner);\n }\n // catch (e)\n for (const m of code.matchAll(/\\bcatch\\s*\\(/g)) {\n const span = parenSpan(m.index + m[0].length - 1);\n if (span) addBindingSegment(span.inner);\n }\n // class names are TDZ bindings (function declarations hoist, classes don't)\n for (const m of code.matchAll(/\\bclass\\s+([A-Za-z_$][\\w$]*)/g)) {\n bound.add(m[1] ?? \"\");\n }\n // const/let/var declarator patterns — balanced + multiline. The span runs\n // to the first top-level `;` (or an unbalanced closer: for-headers), so\n // `const {\\n inputSchema,\\n} = getSchemas();` collects inputSchema.\n for (const m of code.matchAll(/\\b(?:const|let|var)\\b/g)) {\n const start = m.index + m[0].length;\n let depth = 0;\n let end = code.length;\n for (let i = start; i < code.length; i++) {\n const ch = code[i];\n if (ch === \"(\" || ch === \"[\" || ch === \"{\") {\n depth++;\n } else if (ch === \")\" || ch === \"]\" || ch === \"}\") {\n depth--;\n if (depth < 0) {\n end = i;\n break;\n }\n } else if (depth === 0 && ch === \";\") {\n end = i;\n break;\n }\n }\n addBindingSegment(code.slice(start, end));\n }\n return bound;\n}\n\nexport interface HoistOptions {\n /**\n * Imported identifiers matching this pattern are treated as schema chain\n * roots even without an inline z.* reference. A string is compiled as a\n * RegExp source; null disables name-based matching.\n * @default /ZodSchema$/\n */\n schemaNamePattern?: RegExp | string | null | undefined;\n /**\n * Fired when the file has hoist-relevant roots and the full source scan\n * actually runs — i.e., real parse-level work happened (as opposed to the\n * microsecond import-collection bail). The disk cache uses this to decide\n * that even a null transform result is worth persisting: re-deriving\n * \"nothing to hoist\" costs a full scan per zod-importing file per run.\n */\n onScan?: (() => void) | undefined;\n}\n\n/**\n * Free-variable analysis of a hoisted expression's source text, for the\n * build-time compile step. Returns null when the text does not parse (it\n * always should — it was extracted by this module).\n */\nexport function analyzeHoistedExpression(\n text: string,\n): { eagerFree: Set<string>; deferredFree: Set<string> } | null {\n try {\n const parsed = parseAssignmentAt(text, 0);\n const { eagerFree, deferredFree, impure } = analyzeCaptures(parsed);\n if (impure) return null;\n return { eagerFree, deferredFree };\n } catch {\n return null;\n }\n}\n\n/** A schema construction hoisted to module scope. */\nexport interface HoistedSchema {\n /** Module-scope binding name (`_zh_<hash>`). */\n name: string;\n /** Source text of the hoisted construction expression. */\n text: string;\n}\n\nexport interface HoistResult {\n /** The rewritten source. */\n code: string;\n /** One entry per hoisted declaration, in declaration order. */\n schemas: HoistedSchema[];\n /**\n * The splices (input coordinates) that produced `code`, for sourcemap\n * generation: expression → `_zh_*` replacements plus the declaration-block\n * insertion. `code === applyEdits(input, edits, insert)` by construction.\n */\n edits: Edit[];\n insert: Insertion;\n}\n\n/**\n * Hoist eligible Zod schema expressions to module scope.\n * Returns the rewritten source, or null when nothing was hoisted.\n */\nexport function hoistZodSchemas(code: string, options?: HoistOptions): string | null {\n return hoistZodSchemasMeta(code, options)?.code ?? null;\n}\n\n/**\n * hoistZodSchemas + metadata about each hoisted declaration, so the\n * transform can compile the hoisted schemas into optimized validators.\n */\nexport function hoistZodSchemasMeta(code: string, options?: HoistOptions): HoistResult | null {\n // Idempotency: a file carrying hoisted declarations IS this pass's output.\n // Plain hoists are naturally inert on re-runs (depth-0 masking), but a\n // compiled hoisted decl embeds its original z.* expression inside the IIFE\n // (depth > 0) — re-hoisting it would emit a duplicate _zh_ declaration.\n if (/\\bconst _zh_[0-9a-f]{8} = /.test(code)) return null;\n\n const imports = collectImportBindings(code);\n if (imports.all.size === 0) return null;\n\n const rawPattern = options?.schemaNamePattern;\n const namePattern =\n rawPattern === null\n ? null\n : rawPattern === undefined\n ? SCHEMA_NAME_PATTERN\n : typeof rawPattern === \"string\"\n ? new RegExp(rawPattern)\n : rawPattern;\n\n const roots = new Set<string>(imports.zod);\n if (namePattern) {\n for (const name of imports.all) {\n if (namePattern.test(name)) roots.add(name);\n }\n }\n // Imported roots that only qualify via an inline z.* reference in the\n // chain are validated per-expression below; scan them as candidates too.\n if (imports.zod.size > 0) {\n for (const name of imports.all) roots.add(name);\n }\n if (roots.size === 0) return null;\n\n options?.onScan?.();\n const { candidates, stripped } = scanSource(code, roots);\n if (candidates.length === 0) return null;\n\n let boundNames: Set<string> | undefined;\n function isShadowed(name: string): boolean {\n boundNames ??= collectBoundNames(stripped());\n return boundNames.has(name);\n }\n\n interface Hoist {\n start: number;\n end: number;\n name: string;\n }\n const hoists: Hoist[] = [];\n const declByText = new Map<string, string>();\n let consumedUntil = 0;\n\n for (const candidate of candidates) {\n if (candidate.index < consumedUntil) continue;\n\n // Masking (babel-plugin-zod-hoist nesting semantics):\n // - Depth-0 chains are top-level statements/initializers — already\n // evaluated once per module load, nothing to gain — and their interior\n // must not hoist separately either. Exception: concise arrow bodies\n // (`const make = () => z.object(...)`) re-run per call.\n // Their extent comes from the cheap scanner (findChainEnd), NOT acorn:\n // schema modules are mostly top-level declarations, and an acorn parse\n // per declaration only to discard it dominated cold hoist cost.\n // - Zod-rooted chains mask their interior REGARDLESS of eligibility (an\n // inner z.string() of `z.object({ a: z.string(), b: local })` belongs\n // to the outer schema — babel's isNestedInZodCall).\n // - Chains rooted elsewhere (`sql.type(...)`, `api.get(...)`,\n // `Base.extend(...)`) mask their interior only when actually hoisted:\n // a rejected outer chain leaves its arguments free, so the inner\n // `z.object({...})` of `sql.type(z.object({...}))` hoists on its own.\n if (candidate.depth === 0 && !candidate.afterArrow) {\n consumedUntil = findChainEnd(code, candidate.index);\n continue;\n }\n\n let parsed: Expression;\n try {\n parsed = parseAssignmentAt(code, candidate.index);\n } catch {\n continue;\n }\n let chain = narrowToCallChain(parsed, candidate.index);\n if (!chain) continue;\n\n const rootIsZod = imports.zod.has(candidate.name);\n\n if (rootIsZod) consumedUntil = chain.end;\n\n // Peel trailing parse calls: for `z.object({...}).safeParse(input)`,\n // hoist the construction and leave `.safeParse(input)` — with its\n // local-variable arguments — at the call site.\n let described = describeChain(chain);\n while (\n chain !== null &&\n described !== null &&\n described.methods.length > 0 &&\n PARSE_METHODS.has(described.methods[0] as string)\n ) {\n const callee: AnyNode | null = chain.type === \"CallExpression\" ? chain.callee : null;\n const inner: AnyNode | null =\n callee !== null && callee.type === \"MemberExpression\" ? callee.object : null;\n chain = inner !== null && inner.type === \"CallExpression\" ? (inner as Expression) : null;\n described = chain === null ? null : describeChain(chain);\n }\n if (chain === null || described === null) continue;\n // Tighten the zod-rooted mask to the peeled construction extent: the\n // arguments of a peeled `.parse(...)` are not part of the schema, so\n // candidates inside them stay free (babel traverses execution-method\n // arguments normally).\n if (rootIsZod) consumedUntil = chain.end;\n if (described.root !== candidate.name) continue;\n if (described.methods.some((m) => PARSE_METHODS.has(m))) continue;\n\n const rootMatchesPattern = namePattern?.test(candidate.name) === true;\n // Non-z bases must look like schema derivation: the chain must START\n // with a combinator (`Base.extend({...}).optional()` qualifies via\n // extend), so an arbitrary imported object with a z-mentioning argument\n // (`api.get(z.string())`) is never hoisted. describeChain records\n // methods outermost-first — the deepest method is last.\n const deepestMethod = described.methods[described.methods.length - 1];\n if (!rootIsZod && (deepestMethod === undefined || !COMBINATOR_METHODS.has(deepestMethod))) {\n continue;\n }\n\n const { eagerFree, deferredFree, impure } = analyzeCaptures(chain);\n if (impure) continue;\n // Capture rule (babel-plugin-zod-hoist's canSafelyHoist, hardened): a\n // free name is safe only when it is an import or a recognized standard\n // global, and is never re-bound anywhere in the file (no scope info, so\n // a name bound in ANY function cannot be trusted to mean the import —\n // over-rejection only costs a missed hoist). The babel plugin also\n // allows arbitrary unbound identifiers, but it has real scope analysis;\n // here an unknown bare name is more likely a binding the lexical\n // collector missed than a genuine global, and hoisting it would crash\n // at module load (`ReferenceError: <name> is not defined`).\n let eligible = true;\n for (const name of eagerFree) {\n if ((!imports.all.has(name) && !KNOWN_GLOBALS.has(name)) || isShadowed(name)) {\n eligible = false;\n break;\n }\n }\n if (eligible) {\n for (const name of deferredFree) {\n if ((!imports.all.has(name) && !KNOWN_GLOBALS.has(name)) || isShadowed(name)) {\n eligible = false;\n break;\n }\n }\n }\n if (!eligible) continue;\n\n // Non-zod, non-pattern roots qualify only when the chain itself\n // references a zod binding (`Base.extend({ a: z.string() })`).\n if (!rootIsZod && !rootMatchesPattern) {\n let referencesZod = false;\n for (const name of eagerFree) {\n if (imports.zod.has(name)) {\n referencesZod = true;\n break;\n }\n }\n for (const name of deferredFree) {\n if (imports.zod.has(name)) {\n referencesZod = true;\n break;\n }\n }\n if (!referencesZod) continue;\n }\n\n const text = code.slice(candidate.index, chain.end);\n let declName = declByText.get(text);\n if (!declName) {\n declName = `_zh_${fnv1a(text)}`;\n declByText.set(text, declName);\n }\n hoists.push({ start: candidate.index, end: chain.end, name: declName });\n // Non-zod-rooted chains mask their interior only on success — the inner\n // parts are consumed by this hoist's replacement.\n consumedUntil = Math.max(consumedUntil, chain.end);\n }\n\n if (hoists.length === 0) return null;\n\n const decls = [...declByText.entries()]\n .map(([text, name]) => `const ${name} = ${text};`)\n .join(\"\\n\");\n // The insertion offset is identical in input and output coordinates: the\n // directive prologue precedes every statement, and all hoist replacements\n // sit inside statements.\n const edits: Edit[] = hoists.map((h) => ({ start: h.start, end: h.end, text: h.name }));\n const insert: Insertion = { offset: moduleHeadOffset(code), text: `${decls}\\n` };\n return {\n code: applyEdits(code, edits, insert),\n schemas: [...declByText.entries()].map(([text, name]) => ({ name, text })),\n edits,\n insert,\n };\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transform.d.ts","names":[],"sources":["../../src/unplugin/transform.ts"],"mappings":";;;;UA6BiB;EACf;EACA;EACA;EACA;EACA;EACA;;;;;;;;;;cAsHW,wBAAsB;;;;
|
|
1
|
+
{"version":3,"file":"transform.d.ts","names":[],"sources":["../../src/unplugin/transform.ts"],"mappings":";;;;UA6BiB;EACf;EACA;EACA;EACA;EACA;EACA;;;;;;;;;;cAsHW,wBAAsB;;;;iBAgDnB,gBAAgB,YAAY,UAAU;;;;;;;;;;;;;cA6BzC;EAAuB,SAAS;EAAU,SAAS;;;;;;;;iBAgChD,oBAAoB,UAAU,2BAA2B;iBAOzD,IAAI;UAUH;EACf;EACA,KAAK;;;;;;;iBAQe,cACpB,cACA,YACA,SAAS,mBACR;;;;;;iBAUmB,qBACpB,cACA,YACA,SAAS,mBACR,QAAQ;;;;iBAqXK,cACd,cACA,SAAS,sBACT;EAAY;;;;;;iBAiDE,kBAAkB,cAAc;;;;;iBAgBhC,0BACd,cACA,SAAS,sBACT;EAAY;;;;;;iBAuCE,oBAAoB"}
|
|
@@ -102,7 +102,7 @@ var StagedTransform = class {
|
|
|
102
102
|
* contain "zod" silently strips those files from every bundler with native
|
|
103
103
|
* hook filters. `describe("code filter soundness")` fails if it drifts.
|
|
104
104
|
*/
|
|
105
|
-
const HAS_RUNTIME_ZOD_IMPORT = /import\s+(?!type\s)[^;]*from\s+["']zod(?:\/v\d+)?["']/;
|
|
105
|
+
const HAS_RUNTIME_ZOD_IMPORT = /import\s+(?!type\s)[^;]*from\s+["']zod(?:\/v\d+)?(?:[/-]mini)?["']/;
|
|
106
106
|
/**
|
|
107
107
|
* Opt-in phase timing (ZOD_COMPILER_TIMING=1): accumulates per-phase wall time
|
|
108
108
|
* across all transform calls and prints a summary on process exit. Used to
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transform.js","names":[],"sources":["../../src/unplugin/transform.ts"],"sourcesContent":["import remapping from \"@jridgewell/remapping\";\nimport { parseExpressionAt } from \"acorn\";\nimport MagicString from \"magic-string\";\nimport picomatch from \"picomatch\";\nimport type { CodegenMode } from \"../core/codegen/context.js\";\nimport { SHARED_BLOCK_MARKER } from \"../core/codegen/dedupe.js\";\nimport {\n FAIL_CLASS_DECL,\n FAILZ_CLASS_DECL,\n FIN_DECL,\n FIN_DEFERRED_DECL,\n FINZ_DECL,\n generateIIFE,\n MK_VALIDATOR_DECL,\n ZOD_CONFIG_IMPORT,\n ZOD_MSG_DECLARATION,\n} from \"../core/iife.js\";\nimport { aggregateUsedHelpers, type CompiledSchemaInfo, compileSchemas } from \"../core/pipeline.js\";\nimport type { DiscoveredSchema } from \"../core/types.js\";\nimport { discoverSchemas } from \"../discovery.js\";\nimport { ProcessExitDuringLoadError } from \"../loader.js\";\nimport { mayExportSchemas } from \"../static-filter.js\";\nimport { applyEdits, type Edit, type Insertion, moduleHeadOffset } from \"./edits.js\";\nimport { hoistZodSchemasMeta } from \"./hoist.js\";\nimport { compileHoistedSchemas } from \"./hoist-compile.js\";\nimport type { TransformOptions, ZodCompilerPluginOptions } from \"./types.js\";\nimport { VIRTUAL_RUNTIME_ID } from \"./virtual.js\";\n\n/** JSON shape of the composed sourcemap returned alongside transformed code. */\nexport interface TransformSourceMap {\n version: number;\n sources: (string | null)[];\n sourcesContent?: (string | null)[];\n names: string[];\n mappings: string;\n file?: string | null;\n}\n\n/**\n * The transform pipeline as a chain of edit batches. Each batch is applied\n * to the CURRENT text through a MagicString (one stage map per batch); the\n * final original→output map is the remapping-composed chain. Deriving the\n * output string and the map from the same edit list makes divergence\n * impossible.\n */\nclass StagedTransform {\n current: string;\n private readonly source: string;\n private readonly maps: unknown[] = [];\n\n constructor(original: string, source: string) {\n this.current = original;\n this.source = source;\n }\n\n apply(edits: readonly Edit[], insert?: Insertion): void {\n this.stage(edits, (s) => {\n if (insert === undefined) return false;\n s.appendLeft(insert.offset, insert.text);\n return true;\n });\n }\n\n /**\n * Apply `edits`, then prepend `deferred`'s text to the module head — both\n * inside ONE stage.\n *\n * The head injection (runtime import + shared dedup block) has to be decided\n * from the REWRITTEN source, because `computeRuntimePrefix` probes it for\n * already-present markers. Staging it separately made a whole second\n * `generateMap` over the full generated output — for what is only a prepend at\n * the module head — and then forced `remapping` to compose the two. Together\n * those were the dominant cost of a transform: on a 320-schema project they ran\n * to 64% of total wall time, more than discovery and codegen combined. Deferring\n * the insertion into the same MagicString buys byte-identical output and an\n * equivalent map for one generation and no composition — 1.6x (small schemas)\n * to 3.4x (large ones) on the transform, scaling with how much code a file\n * emits, since that is what both costs are proportional to.\n *\n * `deferred` returns TEXT, not an `Insertion`: `appendLeft` resolves offsets\n * against the PRE-edit text while `deferred` is shown the POST-edit text, so a\n * callback-supplied offset would be in the wrong coordinate system. Deriving it\n * here from `this.current` keeps the two in step by construction.\n */\n applyThen(edits: readonly Edit[], deferred?: (rewritten: string) => string | undefined): void {\n this.stage(edits, (s, rewritten) => {\n // `?.()` short-circuits its arguments, so a stage with no deferred step\n // never materializes the rewritten text.\n const head = deferred?.(rewritten());\n if (head === undefined) return false;\n s.appendLeft(moduleHeadOffset(this.current), head);\n return true;\n });\n }\n\n /**\n * One stage: apply `edits` to a fresh MagicString, let `inject` add at most\n * one insertion, then commit the text and its map. `inject` reports whether\n * it inserted, so a no-op stage can be skipped entirely.\n *\n * `rewritten` is a thunk, not a string: materializing it costs a full\n * `toString()` over generated-code-sized input, and the injectors that do not\n * read it (every `apply()` call) must not pay for it.\n */\n private stage(\n edits: readonly Edit[],\n inject: (s: MagicString, rewritten: () => string) => boolean,\n ): void {\n const s = new MagicString(this.current);\n for (const e of edits) {\n if (e.start === e.end) {\n s.appendLeft(e.start, e.text);\n } else {\n s.overwrite(e.start, e.end, e.text);\n }\n }\n // `toString()` is the only way to show the deferred step what the rewrite\n // produced; it measured well under 1% of a transform.\n const inserted = inject(s, () => (edits.length === 0 ? this.current : s.toString()));\n if (edits.length === 0 && !inserted) return;\n this.current = s.toString();\n // `hires: \"boundary\"` is load-bearing, not a tuning knob: without it every\n // mapping collapses to column 0, so a stack frame or debugger breakpoint in\n // untouched user code below a compiled schema lands at the start of its line\n // instead of the right column (tests/unplugin/sourcemap.test.ts pins it). It\n // is also the most expensive thing here, which is why the stage COUNT is\n // what to economize on.\n this.maps.push(s.generateMap({ source: this.source, hires: \"boundary\", includeContent: true }));\n }\n\n /** Composed original→current map, or null when nothing was applied. */\n map(): TransformSourceMap | null {\n if (this.maps.length === 0) return null;\n // A single stage needs no composition: `remapping` over a one-map chain\n // reproduces that map, and it is expensive on generated-code-sized input.\n const [only] = this.maps;\n if (this.maps.length === 1) return only as TransformSourceMap;\n const chain = [...this.maps].reverse();\n return remapping(\n chain as Parameters<typeof remapping>[0],\n () => null,\n ) as unknown as TransformSourceMap;\n }\n}\n\n/**\n * Matches a runtime (non-type-only) import from \"zod\".\n *\n * One of the three triggers ZOD_MENTION (the transform hook's `code` filter)\n * must remain a superset of — widening this to a specifier that does not\n * contain \"zod\" silently strips those files from every bundler with native\n * hook filters. `describe(\"code filter soundness\")` fails if it drifts.\n */\nexport const HAS_RUNTIME_ZOD_IMPORT = /import\\s+(?!type\\s)[^;]*from\\s+[\"']zod(?:\\/v\\d+)?[\"']/;\n\n/**\n * Opt-in phase timing (ZOD_COMPILER_TIMING=1): accumulates per-phase wall time\n * across all transform calls and prints a summary on process exit. Used to\n * attribute plugin overhead in real builds/test runs.\n */\nconst TIMING = process.env[\"ZOD_COMPILER_TIMING\"] === \"1\";\n\n/** A single file's discovery exceeding this is worth an actionable warning. */\nconst SLOW_DISCOVERY_WARN_MS = 5_000;\nconst phaseTotals = new Map<string, { ms: number; calls: number }>();\nlet timingHookInstalled = false;\n\n/** Dedupes the process.exit-during-discovery warning to one per process. */\nlet warnedProcessExit = false;\n\nfunction timePhase<T>(phase: string, fn: () => T): T {\n if (!TIMING) return fn();\n const t0 = performance.now();\n const done = (): void => {\n const dt = performance.now() - t0;\n const agg = phaseTotals.get(phase) ?? { ms: 0, calls: 0 };\n agg.ms += dt;\n agg.calls++;\n phaseTotals.set(phase, agg);\n };\n if (!timingHookInstalled) {\n timingHookInstalled = true;\n process.on(\"exit\", () => {\n const rows = [...phaseTotals.entries()].sort((a, b) => b[1].ms - a[1].ms);\n for (const [name, { ms, calls }] of rows) {\n log(`timing ${name}: ${ms.toFixed(1)}ms over ${calls} call(s)`);\n }\n });\n }\n const r = fn();\n if (r instanceof Promise) {\n return r.finally(done) as T;\n }\n done();\n return r;\n}\n\n/**\n * Check if a file should be transformed by the plugin.\n */\nexport function shouldTransform(id: string, options?: ZodCompilerPluginOptions): boolean {\n if (!/\\.[cm]?[jt]sx?$/.test(id)) return false;\n if (id.includes(\"node_modules\")) return false;\n if (id.endsWith(\".d.ts\")) return false;\n if (id.endsWith(\".compiled.ts\") || id.endsWith(\".compiled.js\")) return false;\n\n if (options?.exclude?.some((pattern) => picomatch.isMatch(id, pattern, { contains: true })))\n return false;\n if (\n options?.include &&\n !options.include.some((pattern) => picomatch.isMatch(id, pattern, { contains: true }))\n )\n return false;\n\n return true;\n}\n\n/**\n * `id` half of the transform hook filter: the option-independent checks of\n * shouldTransform(), restated as patterns the bundler can evaluate itself.\n * Rolldown, Vite and Rollup 4.40+ apply hook filters natively, so a rejected\n * module never crosses into JS; unplugin applies the same patterns in JS for\n * the rest (webpack/rspack skip installing the transform loader entirely).\n *\n * The `include`/`exclude` options stay out of the filter on purpose: they are\n * matched with picomatch's `contains: true` semantics, which the native glob\n * support (patterns resolved against cwd, matched whole) would silently\n * narrow — shouldTransform() keeps applying them inside the handler.\n */\nexport const TRANSFORM_ID_FILTER: { exclude: RegExp[]; include: RegExp[] } = {\n exclude: [/node_modules/, /\\.d\\.ts$/, /\\.compiled\\.[jt]s$/],\n include: [/\\.[cm]?[jt]sx?$/],\n};\n\n/**\n * Every transform path that can change a file needs the substring \"zod\" (or\n * \"Zod\") somewhere in the source. There are exactly three triggers, and each\n * one is pinned by `describe(\"code filter soundness\")` in the transform tests:\n *\n * 1. auto-discovery — HAS_RUNTIME_ZOD_IMPORT (above), which only matches\n * specifiers spelled \"zod…\";\n * 2. `schemas: \"explicit\"` — an import from \"zod-compiler\" (the package name);\n * 3. hoisting — a root imported from ZOD_MODULES or an identifier matching\n * SCHEMA_NAME_PATTERN (both in hoist.ts; a *custom* pattern drops this\n * filter entirely, see transformCodeFilter).\n *\n * Adding a fourth trigger that can fire without a \"zod\" mention MUST widen\n * this pattern, or those files are silently skipped on every bundler with\n * native hook filters — no error, schemas just quietly stay uncompiled.\n *\n * Spelled as a character class rather than an `i` flag: native filters\n * recompile these patterns outside JS, where flag support is narrower.\n */\nconst ZOD_MENTION = /[Zz]od/;\n\n/**\n * `code` half of the transform hook filter, or undefined when no sound filter\n * exists. A custom `hoist.schemaNamePattern` promotes arbitrary imported\n * identifiers to schema roots (`UserModel`), so nothing in such a file is\n * guaranteed to mention zod — those setups keep the unfiltered behavior.\n */\nexport function transformCodeFilter(options?: ZodCompilerPluginOptions): RegExp | undefined {\n const namePattern = typeof options?.hoist === \"object\" ? options.hoist.schemaNamePattern : null;\n // `null` disables name matching and `undefined` keeps the default\n // /ZodSchema$/ — both leave a \"zod\" mention as the only way in.\n return namePattern === null || namePattern === undefined ? ZOD_MENTION : undefined;\n}\n\nexport function log(msg: string): void {\n // oxlint-disable-next-line no-console -- build output\n console.log(`[zod-compiler] ${msg}`);\n}\n\nfunction warn(msg: string): void {\n // oxlint-disable-next-line no-console -- build output\n console.warn(`[zod-compiler] ${msg}`);\n}\n\nexport interface TransformOutput {\n code: string;\n map: TransformSourceMap | null;\n}\n\n/**\n * Transform source code by replacing compile() calls with optimized validators.\n * Returns the transformed code or null if no transformation was needed.\n * Compatibility wrapper over transformCodeWithMap() — discards the map.\n */\nexport async function transformCode(\n code: string,\n id: string,\n options: TransformOptions,\n): Promise<string | null> {\n const result = await transformCodeWithMap(code, id, options);\n return result === null ? null : result.code;\n}\n\n/**\n * transformCode + a composed sourcemap (original → output). Stack traces in\n * transformed files shift by prepended declarations and expanded IIFEs\n * without it — a vitest assertion can be reported dozens of lines off.\n */\nexport async function transformCodeWithMap(\n code: string,\n id: string,\n options: TransformOptions,\n): Promise<TransformOutput | null> {\n const verbose = options.verbose === true;\n const autoDiscover = options.autoDiscover === true;\n const mode = options.mode;\n const staged = new StagedTransform(code, id);\n\n // Hoist Zod schema construction out of function bodies to module scope\n // (babel-plugin-zod-hoist equivalent). Mode-independent: inline schemas\n // live exactly in the files that export none. hoistZodSchemasMeta() bails\n // in microseconds when no eligible imports exist.\n let hoistedSchemas: ReturnType<typeof hoistZodSchemasMeta> = null;\n if (options.hoist !== false && code.includes(\"import\")) {\n hoistedSchemas = timePhase(\"hoist\", () =>\n hoistZodSchemasMeta(code, {\n ...(typeof options.hoist === \"object\" ? options.hoist : undefined),\n onScan: options.onSubstantialWork,\n }),\n );\n if (hoistedSchemas !== null) {\n staged.apply(hoistedSchemas.edits, hoistedSchemas.insert);\n if (verbose) {\n log(`Hoisted inline Zod schemas in ${id}`);\n }\n }\n }\n\n // Compile the hoisted schemas (autoDiscover only — compiling anonymous\n // schemas is auto-discovery of unexported module-scope schemas). Each\n // hoisted `const _zh_x = z.object({...});` whose construction is\n // deterministic (eager refs are zod bindings only) is evaluated at build\n // time and its initializer replaced with the compiled validator IIFE;\n // anything ineligible stays a plain hoist.\n const hoistHelpers = new Set<string>();\n let hoistCompiledCount = 0;\n if (autoDiscover && hoistedSchemas !== null && hoistedSchemas.schemas.length > 0) {\n const hoistCompiled = await timePhase(\"hoist-compile\", () =>\n compileHoistedSchemas(hoistedSchemas.schemas, code, id, mode),\n );\n const spliceEdits: Edit[] = [];\n for (const h of hoistCompiled) {\n const decl = `const ${h.name} = ${h.text};`;\n const at = staged.current.indexOf(decl);\n if (at === -1) continue;\n const iife = generateIIFE(h.text, h.info, { zodCompat: options.zodCompat });\n spliceEdits.push({ start: at, end: at + decl.length, text: `const ${h.name} = ${iife};` });\n hoistCompiledCount++;\n for (const helper of h.info.codegenResult.usedHelpers) {\n hoistHelpers.add(helper);\n }\n if (verbose) {\n log(` ✓ ${h.name} (hoisted schema compiled)`);\n }\n }\n staged.apply(spliceEdits);\n if (hoistCompiledCount > 0) {\n hoistHelpers.add(\"__zcMkv\");\n hoistHelpers.add(\"__zcFin\");\n }\n }\n\n // When only hoisting (± hoisted-schema compilation) changed the file, that\n // is still a transform result — with runtime helpers injected if any\n // hoisted schema compiled.\n const finishHoistOnly = (): TransformOutput | null => {\n if (staged.current === code) return null;\n if (hoistCompiledCount > 0) {\n options.onBuildStats?.({\n files: 1,\n schemas: hoistedSchemas?.schemas.length ?? 0,\n optimized: hoistCompiledCount,\n failed: 0,\n });\n const prefix = computeRuntimePrefix(staged.current, hoistHelpers, mode, options.runtimeId);\n if (prefix !== null) {\n staged.applyThen([], () => prefix);\n }\n }\n return { code: staged.current, map: staged.map() };\n };\n\n // Quick bail-out check. Both gates are also encoded in the transform hook's\n // `code` filter (ZOD_MENTION) so bundlers can skip the hook call entirely —\n // relaxing either one here without widening that pattern makes the bundler\n // drop those files before this code ever runs.\n if (autoDiscover) {\n // autoDiscover: any file with a runtime Zod import is a candidate.\n // Skip `import type` — these files have no runtime schemas.\n if (!HAS_RUNTIME_ZOD_IMPORT.test(staged.current)) return finishHoistOnly();\n } else {\n // Legacy mode: require compile() from zod-compiler. The word-boundary\n // check matters: the package name itself contains the substring\n // \"compile\", so a plain includes(\"compile\") would match every import of\n // \"zod-compiler\" — \\bcompile\\b does not match inside \"zod-compiler\"\n // (no boundary between \"e\" and \"r\") but matches compile( / { compile }.\n if (!staged.current.includes(\"zod-compiler\") || !/\\bcompile\\b/.test(staged.current))\n return finishHoistOnly();\n }\n\n // Static pre-filter: skip files whose exports provably cannot be schemas\n // (functions, components, constants, type-only modules) without executing\n // them. Conservative — anything ambiguous stays a candidate. The filter\n // transpiles + parses the file, so its outcome is worth persisting even\n // when the eventual result is null.\n options.onSubstantialWork?.();\n if (!(await timePhase(\"static-filter\", () => mayExportSchemas(staged.current, id))))\n return finishHoistOnly();\n\n // Discover schemas by executing the file. Module executions are cached in\n // the shared loader; watch/HMR changes invalidate via invalidateModuleCache().\n options.onDiscovery?.();\n let schemas: DiscoveredSchema[];\n const discoverStart = performance.now();\n try {\n schemas = await timePhase(\"discover\", () => discoverSchemas(id, { autoDiscover }));\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n // A module in the import graph called process.exit() during discovery —\n // typically an env-validation guard in a CI build where secrets are\n // intentionally absent. The loader converts that exit into a catchable\n // error so the build survives; the affected files just fall back to\n // runtime Zod. Handle it in both modes (never crash on a build-time exit)\n // and surface the cooperative remedy once.\n if (e instanceof ProcessExitDuringLoadError) {\n // The result reflects missing secrets, not file content — never persist\n // it to the content-hashed disk cache (a later secret-ful build would be\n // served this stale \"nothing compiled\" entry).\n options.onUncacheableResult?.();\n if (!warnedProcessExit) {\n warnedProcessExit = true;\n warn(\n `${id} (or a module it imports) called process.exit during build-time schema ` +\n `discovery — those files fall back to runtime Zod instead of crashing the build. ` +\n `This is usually an env-validation guard; wrap it in ` +\n `\\`if (!process.env.ZOD_COMPILER) { ... }\\` to keep these schemas compiled, or set ` +\n `schemas:\"explicit\" / use include to scope discovery.`,\n );\n }\n return finishHoistOnly();\n }\n // In autoDiscover mode, files that can't be loaded (JSX components,\n // unresolved path aliases, etc.) are expected — warn and skip.\n if (autoDiscover) {\n if (verbose) {\n warn(`Skipping ${id}: ${msg}`);\n }\n return finishHoistOnly();\n }\n throw new Error(`[zod-compiler] Failed to load schemas from ${id}: ${msg}`);\n }\n const discoverMs = performance.now() - discoverStart;\n if (discoverMs >= SLOW_DISCOVERY_WARN_MS) {\n // Discovery executes the file's whole first-party import graph inside\n // the bundler's single-threaded process — on saturated CI hosts a large\n // graph can stall the event loop long enough to trip test timeouts.\n // Surface the cost with the two effective remedies.\n warn(\n `Discovery of ${id} took ${(discoverMs / 1000).toFixed(1)}s executing its import graph ` +\n `in the bundler process. Persist node_modules/.cache/zod-compiler across CI runs to pay ` +\n `this once, or narrow autoDiscover/include for test runs (see README \"Large projects ` +\n `and CI\"). ZOD_COMPILER_TIMING=1 prints a per-phase breakdown.`,\n );\n }\n if (schemas.length === 0) return finishHoistOnly();\n\n // Lean mode (every bundler in VIRTUAL_MODULE_FRAMEWORKS — Vite/Rollup/webpack/rspack/etc.)\n // imports shared helpers from a runtime module for cross-file dedup: virtual:zod-compiler/runtime\n // on virtual-friendly bundlers, the __zod-compiler-runtime__ bare specifier on webpack/rspack.\n // Inline mode (CLI emitter, and any bundler not in VIRTUAL_MODULE_FRAMEWORKS) emits self-contained\n // file-level helpers.\n let failedCount = 0;\n const { schemas: compiled, shared } = timePhase(\"compile\", () =>\n compileSchemas(schemas, {\n mode,\n compact: options.compact,\n onError(exportName, error) {\n failedCount++;\n warn(\n `Failed to compile \"${exportName}\" in ${id}: ${error.message}. Keeping original${autoDiscover ? \"\" : \" compile()\"} call.`,\n );\n },\n }),\n );\n\n if (verbose) {\n if (autoDiscover) {\n log(\n `Auto-discovering: ${id} (${schemas.length} Zod export${schemas.length > 1 ? \"s\" : \"\"} found)`,\n );\n }\n for (const s of compiled) {\n const rfCount = s.refEntries.length;\n const rfSuffix = rfCount > 0 ? ` (${rfCount} ref${rfCount > 1 ? \"s\" : \"\"})` : \"\";\n log(` ✓ ${s.exportName}${rfSuffix}`);\n }\n if (failedCount > 0) {\n log(` ✗ ${failedCount} schema(s) failed`);\n }\n }\n\n if (compiled.length === 0) return finishHoistOnly();\n\n // Report build stats only when at least one schema was compiled\n // (hoisted-schema compiles count alongside export schemas).\n options.onBuildStats?.({\n files: 1,\n schemas: schemas.length + (hoistedSchemas?.schemas.length ?? 0),\n optimized: compiled.length + hoistCompiledCount,\n failed: failedCount,\n });\n\n // __zcMkv and __zcFin are always needed (they wrap every IIFE). Helpers used\n // by compiled hoisted schemas ride along in the same injection.\n const usedHelpers = aggregateUsedHelpers(compiled);\n usedHelpers.add(\"__zcMkv\");\n usedHelpers.add(\"__zcFin\");\n for (const helper of hoistHelpers) {\n usedHelpers.add(helper);\n }\n // Shared dedup validators ride the same runtime import.\n for (const helper of shared.usedHelpers) {\n usedHelpers.add(helper);\n }\n\n // Two-pass rewrite: separate compile() schemas from autoDiscover schemas.\n // Both passes collect edits against the same pristine stage input — their\n // target regions are disjoint (compile() assignments vs plain exported\n // declarations of OTHER names), so one batched application is equivalent\n // to the historical sequential rewrites.\n let rewriteEdits: readonly Edit[];\n if (autoDiscover) {\n // Detect compile() schemas by checking source code patterns\n const compileExportNames = new Set<string>();\n for (const s of compiled) {\n const pattern = new RegExp(`\\\\b${s.exportName}\\\\s*=\\\\s*compile[\\\\s<(]`);\n if (pattern.test(staged.current)) {\n compileExportNames.add(s.exportName);\n }\n }\n const compileSchemaInfos = compiled.filter((s) => compileExportNames.has(s.exportName));\n const autoDiscoverSchemaInfos = compiled.filter((s) => !compileExportNames.has(s.exportName));\n\n const edits: Edit[] = [];\n // Pass 1: compile() schemas (includes compile-import removal — only when\n // compile() schemas were actually rewritten, mirroring the historical\n // conditional rewriteSource call)\n if (compileSchemaInfos.length > 0) {\n edits.push(\n ...collectCompileRewriteEdits(staged.current, compileSchemaInfos, {\n zodCompat: options.zodCompat,\n }),\n );\n }\n // Pass 2: plain exported schemas\n if (autoDiscoverSchemaInfos.length > 0) {\n edits.push(\n ...collectAutoDiscoverEdits(staged.current, autoDiscoverSchemaInfos, {\n zodCompat: options.zodCompat,\n }),\n );\n }\n rewriteEdits = edits;\n } else {\n rewriteEdits = collectCompileRewriteEdits(staged.current, compiled, {\n zodCompat: options.zodCompat,\n });\n }\n\n // Head = runtime helpers/import, then the file-level shared dedup block, then\n // the rewritten source. The shared `__zcSw_N` functions live at module scope\n // so every IIFE closes over them; they must follow the runtime import (lean)\n // and the helper decls (inline) that they reference. Guard against\n // double-injection on watch/HMR re-runs the same way computeRuntimePrefix\n // does — a second copy would redeclare every `__zcSw_N`.\n //\n // Deferred into the rewrite's own stage rather than staged after it: both\n // decisions read the REWRITTEN text, and giving a bare prepend its own stage\n // doubled the sourcemap work and added a composition pass (see applyThen).\n staged.applyThen(rewriteEdits, (rewritten) => {\n const prefix = computeRuntimePrefix(rewritten, usedHelpers, mode, options.runtimeId);\n const needsShared = shared.code !== \"\" && !rewritten.includes(SHARED_BLOCK_MARKER);\n const head = (prefix ?? \"\") + (needsShared ? `${shared.code}\\n` : \"\");\n return head === \"\" ? undefined : head;\n });\n return { code: staged.current, map: staged.map() };\n}\n\n/**\n * Prepend the runtime helpers required by the rewritten source.\n *\n * Lean mode emits a single `import { ... } from \"<runtimeId>\";` line —\n * bundlers whose resolveId hook intercepts the specifier dedup helpers across\n * every transformed file into one shared virtual module.\n *\n * Inline mode prepends file-level `function __zcMkv` / `function __zcFin`\n * declarations directly so the file is self-contained.\n *\n * Idempotent: if the file already contains the relevant marker (re-run during\n * watch/HMR), we skip re-injection.\n */\n/** The runtime-helper text to prepend, or null when nothing is needed. */\nfunction computeRuntimePrefix(\n code: string,\n usedHelpers: Set<string>,\n mode: CodegenMode,\n runtimeId: string = VIRTUAL_RUNTIME_ID,\n): string | null {\n if (mode === \"lean\") {\n if (usedHelpers.size === 0) return null;\n // Match the import STATEMENT, not the bare id. `zod-compiler/runtime` is a\n // plain package specifier and a substring of `virtual:zod-compiler/runtime`,\n // so a file merely mentioning either — a comment, a docs snippet — would\n // suppress the import while codegen still emits calls to the helpers.\n if (code.includes(`from \"${runtimeId}\"`)) return null;\n const names = [...usedHelpers].sort().join(\", \");\n return `import { ${names} } from \"${runtimeId}\";\\n`;\n }\n // Inline mode (CLI emitter, and any bundler not in VIRTUAL_MODULE_FRAMEWORKS):\n // ship file-level helper declarations instead of a virtual import.\n // Codegen emits per-IIFE issue literals + per-IIFE `__re_*` decls,\n // so we only need __zcMkv / __zcFin (plus __zcMsg via the zod config import).\n if (!code.includes(\"__zcMkv\")) return null;\n const prefix: string[] = [];\n if (!code.includes(\"__zodCompilerConfig\")) {\n prefix.push(ZOD_CONFIG_IMPORT, ZOD_MSG_DECLARATION);\n }\n if (!code.includes(\"function __zcMkv(\")) {\n prefix.push(MK_VALIDATOR_DECL);\n }\n // __zcFin and __zcFinD both construct __ZcFail; declare it once before either,\n // guarding against a header already shipped earlier in the same module.\n const needsFin = !code.includes(\"function __zcFin(\");\n const needsFinD = code.includes(\"__zcFinD(\") && !code.includes(\"function __zcFinD(\");\n if ((needsFin || needsFinD) && !code.includes(\"function __ZcFail(\")) {\n prefix.push(FAIL_CLASS_DECL);\n }\n if (needsFin) {\n prefix.push(FIN_DECL);\n }\n if (needsFinD) {\n prefix.push(FIN_DEFERRED_DECL);\n }\n // Compact mode (output: \"compact\") delegates cold errors to zod via __zcFinZ,\n // which constructs its own __ZcFailZ (distinct from __ZcFail).\n const needsFinZ = code.includes(\"__zcFinZ(\") && !code.includes(\"function __zcFinZ(\");\n if (needsFinZ && !code.includes(\"function __ZcFailZ(\")) {\n prefix.push(FAILZ_CLASS_DECL);\n }\n if (needsFinZ) {\n prefix.push(FINZ_DECL);\n }\n return prefix.length > 0 ? `${prefix.join(\"\\n\")}\\n` : null;\n}\n\n/**\n * Find the matching closing parenthesis for a compile() call,\n * handling nested parentheses like compile(z.object({...})).\n * Returns the index of the closing ')' or -1 if not found.\n */\nfunction findMatchingParen(code: string, openIndex: number): number {\n let depth = 1;\n for (let i = openIndex + 1; i < code.length; i++) {\n if (code[i] === \"(\") depth++;\n else if (code[i] === \")\") {\n depth--;\n if (depth === 0) return i;\n }\n }\n return -1;\n}\n\n/**\n * Rewrite source code by replacing compile() calls with IIFE-wrapped optimized validators.\n */\nexport function rewriteSource(\n code: string,\n schemas: CompiledSchemaInfo[],\n options?: { zodCompat?: boolean | undefined },\n): string {\n return applyEdits(code, collectCompileRewriteEdits(code, schemas, options));\n}\n\n/**\n * Edits for rewriteSource (compile() call replacements + compile-import\n * removal), collected against pristine `code`. Each schema's declaration is\n * a distinct region and the import statement is distinct from all of them,\n * so the batch is non-overlapping and order-independent.\n */\nfunction collectCompileRewriteEdits(\n code: string,\n schemas: CompiledSchemaInfo[],\n options?: { zodCompat?: boolean | undefined },\n): Edit[] {\n const edits: Edit[] = [];\n for (const schema of schemas) {\n // Match: <exportName> = compile<...>( with word boundary to prevent substring matches\n const prefixPattern = new RegExp(\n `(\\\\b${schema.exportName}\\\\s*=\\\\s*)compile\\\\s*(?:<[^>]*(?:<[^>]*>[^>]*)?>)?\\\\s*\\\\(`,\n );\n const match = prefixPattern.exec(code);\n if (!match) continue;\n\n // Find the matching closing paren (handles nested parens)\n const openParenIndex = match.index + match[0].length - 1;\n const closeParenIndex = findMatchingParen(code, openParenIndex);\n if (closeParenIndex === -1) continue;\n\n const schemaArgName = code\n .slice(openParenIndex + 1, closeParenIndex)\n .trim()\n .replace(/,\\s*$/, \"\");\n const prefix = match[1] ?? \"\";\n edits.push({\n start: match.index,\n end: closeParenIndex + 1,\n text: prefix + generateIIFE(schemaArgName, schema, options),\n });\n }\n edits.push(...collectRemoveCompileImportEdits(code));\n return edits;\n}\n\n/**\n * Find the end position of a JavaScript expression starting at `start` using acorn.\n * Returns the end offset, or -1 if the expression cannot be parsed.\n */\nexport function findExpressionEnd(code: string, start: number): number {\n try {\n const node = parseExpressionAt(code, start, {\n ecmaVersion: \"latest\",\n sourceType: \"module\",\n });\n return node.end;\n } catch {\n return -1;\n }\n}\n\n/**\n * Rewrite source code by replacing plain Zod schema exports with IIFE-wrapped optimized validators.\n * Used by autoDiscover mode (no compile() wrappers needed).\n */\nexport function rewriteSourceAutoDiscover(\n code: string,\n schemas: CompiledSchemaInfo[],\n options?: { zodCompat?: boolean | undefined },\n): string {\n return applyEdits(code, collectAutoDiscoverEdits(code, schemas, options));\n}\n\n/** Edits for rewriteSourceAutoDiscover, collected against pristine `code`. */\nfunction collectAutoDiscoverEdits(\n code: string,\n schemas: CompiledSchemaInfo[],\n options?: { zodCompat?: boolean | undefined },\n): Edit[] {\n const edits: Edit[] = [];\n for (const schema of schemas) {\n const escapedName = schema.exportName.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n // Match: export? (const|let|var) ExportName[: TypeAnnotation] = <expr>\n const assignPattern = new RegExp(\n `((?:export\\\\s+)?(?:const|let|var)\\\\s+${escapedName}(?:\\\\s*:[^=]*)?\\\\s*=\\\\s*)`,\n );\n const match = assignPattern.exec(code);\n if (!match) continue;\n\n const rhsStart = match.index + match[0].length;\n const rhsEnd = findExpressionEnd(code, rhsStart);\n if (rhsEnd === -1) continue;\n\n const originalExpr = code.slice(rhsStart, rhsEnd).trim();\n edits.push({\n start: rhsStart,\n end: rhsEnd,\n text: generateIIFE(originalExpr, schema, options),\n });\n }\n return edits;\n}\n\n/**\n * Remove the `compile` binding from `import { compile, ... } from \"zod-compiler\"` statements.\n * If `compile` is the only import, the entire import line is removed.\n */\nexport function removeCompileImport(code: string): string {\n return applyEdits(code, collectRemoveCompileImportEdits(code));\n}\n\n/** Edits stripping the `compile` binding from zod-compiler import statements. */\nfunction collectRemoveCompileImportEdits(code: string): Edit[] {\n // Match: import { ... } from \"zod-compiler\" or 'zod-compiler'\n const importPattern = /import\\s*\\{([^}]*)\\}\\s*from\\s*[\"']zod-compiler[\"'];?/g;\n const edits: Edit[] = [];\n for (const match of code.matchAll(importPattern)) {\n const imports = match[1] ?? \"\";\n const names = imports\n .split(\",\")\n .map((n) => n.trim())\n .filter(Boolean);\n const remaining = names.filter((n) => n !== \"compile\");\n const text =\n remaining.length === 0 ? \"\" : `import { ${remaining.join(\", \")} } from \"zod-compiler\";`;\n if (text !== match[0]) {\n edits.push({ start: match.index, end: match.index + match[0].length, text });\n }\n }\n return edits;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"transform.js","names":[],"sources":["../../src/unplugin/transform.ts"],"sourcesContent":["import remapping from \"@jridgewell/remapping\";\nimport { parseExpressionAt } from \"acorn\";\nimport MagicString from \"magic-string\";\nimport picomatch from \"picomatch\";\nimport type { CodegenMode } from \"../core/codegen/context.js\";\nimport { SHARED_BLOCK_MARKER } from \"../core/codegen/dedupe.js\";\nimport {\n FAIL_CLASS_DECL,\n FAILZ_CLASS_DECL,\n FIN_DECL,\n FIN_DEFERRED_DECL,\n FINZ_DECL,\n generateIIFE,\n MK_VALIDATOR_DECL,\n ZOD_CONFIG_IMPORT,\n ZOD_MSG_DECLARATION,\n} from \"../core/iife.js\";\nimport { aggregateUsedHelpers, type CompiledSchemaInfo, compileSchemas } from \"../core/pipeline.js\";\nimport type { DiscoveredSchema } from \"../core/types.js\";\nimport { discoverSchemas } from \"../discovery.js\";\nimport { ProcessExitDuringLoadError } from \"../loader.js\";\nimport { mayExportSchemas } from \"../static-filter.js\";\nimport { applyEdits, type Edit, type Insertion, moduleHeadOffset } from \"./edits.js\";\nimport { hoistZodSchemasMeta } from \"./hoist.js\";\nimport { compileHoistedSchemas } from \"./hoist-compile.js\";\nimport type { TransformOptions, ZodCompilerPluginOptions } from \"./types.js\";\nimport { VIRTUAL_RUNTIME_ID } from \"./virtual.js\";\n\n/** JSON shape of the composed sourcemap returned alongside transformed code. */\nexport interface TransformSourceMap {\n version: number;\n sources: (string | null)[];\n sourcesContent?: (string | null)[];\n names: string[];\n mappings: string;\n file?: string | null;\n}\n\n/**\n * The transform pipeline as a chain of edit batches. Each batch is applied\n * to the CURRENT text through a MagicString (one stage map per batch); the\n * final original→output map is the remapping-composed chain. Deriving the\n * output string and the map from the same edit list makes divergence\n * impossible.\n */\nclass StagedTransform {\n current: string;\n private readonly source: string;\n private readonly maps: unknown[] = [];\n\n constructor(original: string, source: string) {\n this.current = original;\n this.source = source;\n }\n\n apply(edits: readonly Edit[], insert?: Insertion): void {\n this.stage(edits, (s) => {\n if (insert === undefined) return false;\n s.appendLeft(insert.offset, insert.text);\n return true;\n });\n }\n\n /**\n * Apply `edits`, then prepend `deferred`'s text to the module head — both\n * inside ONE stage.\n *\n * The head injection (runtime import + shared dedup block) has to be decided\n * from the REWRITTEN source, because `computeRuntimePrefix` probes it for\n * already-present markers. Staging it separately made a whole second\n * `generateMap` over the full generated output — for what is only a prepend at\n * the module head — and then forced `remapping` to compose the two. Together\n * those were the dominant cost of a transform: on a 320-schema project they ran\n * to 64% of total wall time, more than discovery and codegen combined. Deferring\n * the insertion into the same MagicString buys byte-identical output and an\n * equivalent map for one generation and no composition — 1.6x (small schemas)\n * to 3.4x (large ones) on the transform, scaling with how much code a file\n * emits, since that is what both costs are proportional to.\n *\n * `deferred` returns TEXT, not an `Insertion`: `appendLeft` resolves offsets\n * against the PRE-edit text while `deferred` is shown the POST-edit text, so a\n * callback-supplied offset would be in the wrong coordinate system. Deriving it\n * here from `this.current` keeps the two in step by construction.\n */\n applyThen(edits: readonly Edit[], deferred?: (rewritten: string) => string | undefined): void {\n this.stage(edits, (s, rewritten) => {\n // `?.()` short-circuits its arguments, so a stage with no deferred step\n // never materializes the rewritten text.\n const head = deferred?.(rewritten());\n if (head === undefined) return false;\n s.appendLeft(moduleHeadOffset(this.current), head);\n return true;\n });\n }\n\n /**\n * One stage: apply `edits` to a fresh MagicString, let `inject` add at most\n * one insertion, then commit the text and its map. `inject` reports whether\n * it inserted, so a no-op stage can be skipped entirely.\n *\n * `rewritten` is a thunk, not a string: materializing it costs a full\n * `toString()` over generated-code-sized input, and the injectors that do not\n * read it (every `apply()` call) must not pay for it.\n */\n private stage(\n edits: readonly Edit[],\n inject: (s: MagicString, rewritten: () => string) => boolean,\n ): void {\n const s = new MagicString(this.current);\n for (const e of edits) {\n if (e.start === e.end) {\n s.appendLeft(e.start, e.text);\n } else {\n s.overwrite(e.start, e.end, e.text);\n }\n }\n // `toString()` is the only way to show the deferred step what the rewrite\n // produced; it measured well under 1% of a transform.\n const inserted = inject(s, () => (edits.length === 0 ? this.current : s.toString()));\n if (edits.length === 0 && !inserted) return;\n this.current = s.toString();\n // `hires: \"boundary\"` is load-bearing, not a tuning knob: without it every\n // mapping collapses to column 0, so a stack frame or debugger breakpoint in\n // untouched user code below a compiled schema lands at the start of its line\n // instead of the right column (tests/unplugin/sourcemap.test.ts pins it). It\n // is also the most expensive thing here, which is why the stage COUNT is\n // what to economize on.\n this.maps.push(s.generateMap({ source: this.source, hires: \"boundary\", includeContent: true }));\n }\n\n /** Composed original→current map, or null when nothing was applied. */\n map(): TransformSourceMap | null {\n if (this.maps.length === 0) return null;\n // A single stage needs no composition: `remapping` over a one-map chain\n // reproduces that map, and it is expensive on generated-code-sized input.\n const [only] = this.maps;\n if (this.maps.length === 1) return only as TransformSourceMap;\n const chain = [...this.maps].reverse();\n return remapping(\n chain as Parameters<typeof remapping>[0],\n () => null,\n ) as unknown as TransformSourceMap;\n }\n}\n\n/**\n * Matches a runtime (non-type-only) import from \"zod\".\n *\n * One of the three triggers ZOD_MENTION (the transform hook's `code` filter)\n * must remain a superset of — widening this to a specifier that does not\n * contain \"zod\" silently strips those files from every bundler with native\n * hook filters. `describe(\"code filter soundness\")` fails if it drifts.\n */\nexport const HAS_RUNTIME_ZOD_IMPORT =\n /import\\s+(?!type\\s)[^;]*from\\s+[\"']zod(?:\\/v\\d+)?(?:[/-]mini)?[\"']/;\n\n/**\n * Opt-in phase timing (ZOD_COMPILER_TIMING=1): accumulates per-phase wall time\n * across all transform calls and prints a summary on process exit. Used to\n * attribute plugin overhead in real builds/test runs.\n */\nconst TIMING = process.env[\"ZOD_COMPILER_TIMING\"] === \"1\";\n\n/** A single file's discovery exceeding this is worth an actionable warning. */\nconst SLOW_DISCOVERY_WARN_MS = 5_000;\nconst phaseTotals = new Map<string, { ms: number; calls: number }>();\nlet timingHookInstalled = false;\n\n/** Dedupes the process.exit-during-discovery warning to one per process. */\nlet warnedProcessExit = false;\n\nfunction timePhase<T>(phase: string, fn: () => T): T {\n if (!TIMING) return fn();\n const t0 = performance.now();\n const done = (): void => {\n const dt = performance.now() - t0;\n const agg = phaseTotals.get(phase) ?? { ms: 0, calls: 0 };\n agg.ms += dt;\n agg.calls++;\n phaseTotals.set(phase, agg);\n };\n if (!timingHookInstalled) {\n timingHookInstalled = true;\n process.on(\"exit\", () => {\n const rows = [...phaseTotals.entries()].sort((a, b) => b[1].ms - a[1].ms);\n for (const [name, { ms, calls }] of rows) {\n log(`timing ${name}: ${ms.toFixed(1)}ms over ${calls} call(s)`);\n }\n });\n }\n const r = fn();\n if (r instanceof Promise) {\n return r.finally(done) as T;\n }\n done();\n return r;\n}\n\n/**\n * Check if a file should be transformed by the plugin.\n */\nexport function shouldTransform(id: string, options?: ZodCompilerPluginOptions): boolean {\n if (!/\\.[cm]?[jt]sx?$/.test(id)) return false;\n if (id.includes(\"node_modules\")) return false;\n if (id.endsWith(\".d.ts\")) return false;\n if (id.endsWith(\".compiled.ts\") || id.endsWith(\".compiled.js\")) return false;\n\n if (options?.exclude?.some((pattern) => picomatch.isMatch(id, pattern, { contains: true })))\n return false;\n if (\n options?.include &&\n !options.include.some((pattern) => picomatch.isMatch(id, pattern, { contains: true }))\n )\n return false;\n\n return true;\n}\n\n/**\n * `id` half of the transform hook filter: the option-independent checks of\n * shouldTransform(), restated as patterns the bundler can evaluate itself.\n * Rolldown, Vite and Rollup 4.40+ apply hook filters natively, so a rejected\n * module never crosses into JS; unplugin applies the same patterns in JS for\n * the rest (webpack/rspack skip installing the transform loader entirely).\n *\n * The `include`/`exclude` options stay out of the filter on purpose: they are\n * matched with picomatch's `contains: true` semantics, which the native glob\n * support (patterns resolved against cwd, matched whole) would silently\n * narrow — shouldTransform() keeps applying them inside the handler.\n */\nexport const TRANSFORM_ID_FILTER: { exclude: RegExp[]; include: RegExp[] } = {\n exclude: [/node_modules/, /\\.d\\.ts$/, /\\.compiled\\.[jt]s$/],\n include: [/\\.[cm]?[jt]sx?$/],\n};\n\n/**\n * Every transform path that can change a file needs the substring \"zod\" (or\n * \"Zod\") somewhere in the source. There are exactly three triggers, and each\n * one is pinned by `describe(\"code filter soundness\")` in the transform tests:\n *\n * 1. auto-discovery — HAS_RUNTIME_ZOD_IMPORT (above), which only matches\n * specifiers spelled \"zod…\";\n * 2. `schemas: \"explicit\"` — an import from \"zod-compiler\" (the package name);\n * 3. hoisting — a root imported from ZOD_MODULES or an identifier matching\n * SCHEMA_NAME_PATTERN (both in hoist.ts; a *custom* pattern drops this\n * filter entirely, see transformCodeFilter).\n *\n * Adding a fourth trigger that can fire without a \"zod\" mention MUST widen\n * this pattern, or those files are silently skipped on every bundler with\n * native hook filters — no error, schemas just quietly stay uncompiled.\n *\n * Spelled as a character class rather than an `i` flag: native filters\n * recompile these patterns outside JS, where flag support is narrower.\n */\nconst ZOD_MENTION = /[Zz]od/;\n\n/**\n * `code` half of the transform hook filter, or undefined when no sound filter\n * exists. A custom `hoist.schemaNamePattern` promotes arbitrary imported\n * identifiers to schema roots (`UserModel`), so nothing in such a file is\n * guaranteed to mention zod — those setups keep the unfiltered behavior.\n */\nexport function transformCodeFilter(options?: ZodCompilerPluginOptions): RegExp | undefined {\n const namePattern = typeof options?.hoist === \"object\" ? options.hoist.schemaNamePattern : null;\n // `null` disables name matching and `undefined` keeps the default\n // /ZodSchema$/ — both leave a \"zod\" mention as the only way in.\n return namePattern === null || namePattern === undefined ? ZOD_MENTION : undefined;\n}\n\nexport function log(msg: string): void {\n // oxlint-disable-next-line no-console -- build output\n console.log(`[zod-compiler] ${msg}`);\n}\n\nfunction warn(msg: string): void {\n // oxlint-disable-next-line no-console -- build output\n console.warn(`[zod-compiler] ${msg}`);\n}\n\nexport interface TransformOutput {\n code: string;\n map: TransformSourceMap | null;\n}\n\n/**\n * Transform source code by replacing compile() calls with optimized validators.\n * Returns the transformed code or null if no transformation was needed.\n * Compatibility wrapper over transformCodeWithMap() — discards the map.\n */\nexport async function transformCode(\n code: string,\n id: string,\n options: TransformOptions,\n): Promise<string | null> {\n const result = await transformCodeWithMap(code, id, options);\n return result === null ? null : result.code;\n}\n\n/**\n * transformCode + a composed sourcemap (original → output). Stack traces in\n * transformed files shift by prepended declarations and expanded IIFEs\n * without it — a vitest assertion can be reported dozens of lines off.\n */\nexport async function transformCodeWithMap(\n code: string,\n id: string,\n options: TransformOptions,\n): Promise<TransformOutput | null> {\n const verbose = options.verbose === true;\n const autoDiscover = options.autoDiscover === true;\n const mode = options.mode;\n const staged = new StagedTransform(code, id);\n\n // Hoist Zod schema construction out of function bodies to module scope\n // (babel-plugin-zod-hoist equivalent). Mode-independent: inline schemas\n // live exactly in the files that export none. hoistZodSchemasMeta() bails\n // in microseconds when no eligible imports exist.\n let hoistedSchemas: ReturnType<typeof hoistZodSchemasMeta> = null;\n if (options.hoist !== false && code.includes(\"import\")) {\n hoistedSchemas = timePhase(\"hoist\", () =>\n hoistZodSchemasMeta(code, {\n ...(typeof options.hoist === \"object\" ? options.hoist : undefined),\n onScan: options.onSubstantialWork,\n }),\n );\n if (hoistedSchemas !== null) {\n staged.apply(hoistedSchemas.edits, hoistedSchemas.insert);\n if (verbose) {\n log(`Hoisted inline Zod schemas in ${id}`);\n }\n }\n }\n\n // Compile the hoisted schemas (autoDiscover only — compiling anonymous\n // schemas is auto-discovery of unexported module-scope schemas). Each\n // hoisted `const _zh_x = z.object({...});` whose construction is\n // deterministic (eager refs are zod bindings only) is evaluated at build\n // time and its initializer replaced with the compiled validator IIFE;\n // anything ineligible stays a plain hoist.\n const hoistHelpers = new Set<string>();\n let hoistCompiledCount = 0;\n if (autoDiscover && hoistedSchemas !== null && hoistedSchemas.schemas.length > 0) {\n const hoistCompiled = await timePhase(\"hoist-compile\", () =>\n compileHoistedSchemas(hoistedSchemas.schemas, code, id, mode),\n );\n const spliceEdits: Edit[] = [];\n for (const h of hoistCompiled) {\n const decl = `const ${h.name} = ${h.text};`;\n const at = staged.current.indexOf(decl);\n if (at === -1) continue;\n const iife = generateIIFE(h.text, h.info, { zodCompat: options.zodCompat });\n spliceEdits.push({ start: at, end: at + decl.length, text: `const ${h.name} = ${iife};` });\n hoistCompiledCount++;\n for (const helper of h.info.codegenResult.usedHelpers) {\n hoistHelpers.add(helper);\n }\n if (verbose) {\n log(` ✓ ${h.name} (hoisted schema compiled)`);\n }\n }\n staged.apply(spliceEdits);\n if (hoistCompiledCount > 0) {\n hoistHelpers.add(\"__zcMkv\");\n hoistHelpers.add(\"__zcFin\");\n }\n }\n\n // When only hoisting (± hoisted-schema compilation) changed the file, that\n // is still a transform result — with runtime helpers injected if any\n // hoisted schema compiled.\n const finishHoistOnly = (): TransformOutput | null => {\n if (staged.current === code) return null;\n if (hoistCompiledCount > 0) {\n options.onBuildStats?.({\n files: 1,\n schemas: hoistedSchemas?.schemas.length ?? 0,\n optimized: hoistCompiledCount,\n failed: 0,\n });\n const prefix = computeRuntimePrefix(staged.current, hoistHelpers, mode, options.runtimeId);\n if (prefix !== null) {\n staged.applyThen([], () => prefix);\n }\n }\n return { code: staged.current, map: staged.map() };\n };\n\n // Quick bail-out check. Both gates are also encoded in the transform hook's\n // `code` filter (ZOD_MENTION) so bundlers can skip the hook call entirely —\n // relaxing either one here without widening that pattern makes the bundler\n // drop those files before this code ever runs.\n if (autoDiscover) {\n // autoDiscover: any file with a runtime Zod import is a candidate.\n // Skip `import type` — these files have no runtime schemas.\n if (!HAS_RUNTIME_ZOD_IMPORT.test(staged.current)) return finishHoistOnly();\n } else {\n // Legacy mode: require compile() from zod-compiler. The word-boundary\n // check matters: the package name itself contains the substring\n // \"compile\", so a plain includes(\"compile\") would match every import of\n // \"zod-compiler\" — \\bcompile\\b does not match inside \"zod-compiler\"\n // (no boundary between \"e\" and \"r\") but matches compile( / { compile }.\n if (!staged.current.includes(\"zod-compiler\") || !/\\bcompile\\b/.test(staged.current))\n return finishHoistOnly();\n }\n\n // Static pre-filter: skip files whose exports provably cannot be schemas\n // (functions, components, constants, type-only modules) without executing\n // them. Conservative — anything ambiguous stays a candidate. The filter\n // transpiles + parses the file, so its outcome is worth persisting even\n // when the eventual result is null.\n options.onSubstantialWork?.();\n if (!(await timePhase(\"static-filter\", () => mayExportSchemas(staged.current, id))))\n return finishHoistOnly();\n\n // Discover schemas by executing the file. Module executions are cached in\n // the shared loader; watch/HMR changes invalidate via invalidateModuleCache().\n options.onDiscovery?.();\n let schemas: DiscoveredSchema[];\n const discoverStart = performance.now();\n try {\n schemas = await timePhase(\"discover\", () => discoverSchemas(id, { autoDiscover }));\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n // A module in the import graph called process.exit() during discovery —\n // typically an env-validation guard in a CI build where secrets are\n // intentionally absent. The loader converts that exit into a catchable\n // error so the build survives; the affected files just fall back to\n // runtime Zod. Handle it in both modes (never crash on a build-time exit)\n // and surface the cooperative remedy once.\n if (e instanceof ProcessExitDuringLoadError) {\n // The result reflects missing secrets, not file content — never persist\n // it to the content-hashed disk cache (a later secret-ful build would be\n // served this stale \"nothing compiled\" entry).\n options.onUncacheableResult?.();\n if (!warnedProcessExit) {\n warnedProcessExit = true;\n warn(\n `${id} (or a module it imports) called process.exit during build-time schema ` +\n `discovery — those files fall back to runtime Zod instead of crashing the build. ` +\n `This is usually an env-validation guard; wrap it in ` +\n `\\`if (!process.env.ZOD_COMPILER) { ... }\\` to keep these schemas compiled, or set ` +\n `schemas:\"explicit\" / use include to scope discovery.`,\n );\n }\n return finishHoistOnly();\n }\n // In autoDiscover mode, files that can't be loaded (JSX components,\n // unresolved path aliases, etc.) are expected — warn and skip.\n if (autoDiscover) {\n if (verbose) {\n warn(`Skipping ${id}: ${msg}`);\n }\n return finishHoistOnly();\n }\n throw new Error(`[zod-compiler] Failed to load schemas from ${id}: ${msg}`);\n }\n const discoverMs = performance.now() - discoverStart;\n if (discoverMs >= SLOW_DISCOVERY_WARN_MS) {\n // Discovery executes the file's whole first-party import graph inside\n // the bundler's single-threaded process — on saturated CI hosts a large\n // graph can stall the event loop long enough to trip test timeouts.\n // Surface the cost with the two effective remedies.\n warn(\n `Discovery of ${id} took ${(discoverMs / 1000).toFixed(1)}s executing its import graph ` +\n `in the bundler process. Persist node_modules/.cache/zod-compiler across CI runs to pay ` +\n `this once, or narrow autoDiscover/include for test runs (see README \"Large projects ` +\n `and CI\"). ZOD_COMPILER_TIMING=1 prints a per-phase breakdown.`,\n );\n }\n if (schemas.length === 0) return finishHoistOnly();\n\n // Lean mode (every bundler in VIRTUAL_MODULE_FRAMEWORKS — Vite/Rollup/webpack/rspack/etc.)\n // imports shared helpers from a runtime module for cross-file dedup: virtual:zod-compiler/runtime\n // on virtual-friendly bundlers, the __zod-compiler-runtime__ bare specifier on webpack/rspack.\n // Inline mode (CLI emitter, and any bundler not in VIRTUAL_MODULE_FRAMEWORKS) emits self-contained\n // file-level helpers.\n let failedCount = 0;\n const { schemas: compiled, shared } = timePhase(\"compile\", () =>\n compileSchemas(schemas, {\n mode,\n compact: options.compact,\n onError(exportName, error) {\n failedCount++;\n warn(\n `Failed to compile \"${exportName}\" in ${id}: ${error.message}. Keeping original${autoDiscover ? \"\" : \" compile()\"} call.`,\n );\n },\n }),\n );\n\n if (verbose) {\n if (autoDiscover) {\n log(\n `Auto-discovering: ${id} (${schemas.length} Zod export${schemas.length > 1 ? \"s\" : \"\"} found)`,\n );\n }\n for (const s of compiled) {\n const rfCount = s.refEntries.length;\n const rfSuffix = rfCount > 0 ? ` (${rfCount} ref${rfCount > 1 ? \"s\" : \"\"})` : \"\";\n log(` ✓ ${s.exportName}${rfSuffix}`);\n }\n if (failedCount > 0) {\n log(` ✗ ${failedCount} schema(s) failed`);\n }\n }\n\n if (compiled.length === 0) return finishHoistOnly();\n\n // Report build stats only when at least one schema was compiled\n // (hoisted-schema compiles count alongside export schemas).\n options.onBuildStats?.({\n files: 1,\n schemas: schemas.length + (hoistedSchemas?.schemas.length ?? 0),\n optimized: compiled.length + hoistCompiledCount,\n failed: failedCount,\n });\n\n // __zcMkv and __zcFin are always needed (they wrap every IIFE). Helpers used\n // by compiled hoisted schemas ride along in the same injection.\n const usedHelpers = aggregateUsedHelpers(compiled);\n usedHelpers.add(\"__zcMkv\");\n usedHelpers.add(\"__zcFin\");\n for (const helper of hoistHelpers) {\n usedHelpers.add(helper);\n }\n // Shared dedup validators ride the same runtime import.\n for (const helper of shared.usedHelpers) {\n usedHelpers.add(helper);\n }\n\n // Two-pass rewrite: separate compile() schemas from autoDiscover schemas.\n // Both passes collect edits against the same pristine stage input — their\n // target regions are disjoint (compile() assignments vs plain exported\n // declarations of OTHER names), so one batched application is equivalent\n // to the historical sequential rewrites.\n let rewriteEdits: readonly Edit[];\n if (autoDiscover) {\n // Detect compile() schemas by checking source code patterns\n const compileExportNames = new Set<string>();\n for (const s of compiled) {\n const pattern = new RegExp(`\\\\b${s.exportName}\\\\s*=\\\\s*compile[\\\\s<(]`);\n if (pattern.test(staged.current)) {\n compileExportNames.add(s.exportName);\n }\n }\n const compileSchemaInfos = compiled.filter((s) => compileExportNames.has(s.exportName));\n const autoDiscoverSchemaInfos = compiled.filter((s) => !compileExportNames.has(s.exportName));\n\n const edits: Edit[] = [];\n // Pass 1: compile() schemas (includes compile-import removal — only when\n // compile() schemas were actually rewritten, mirroring the historical\n // conditional rewriteSource call)\n if (compileSchemaInfos.length > 0) {\n edits.push(\n ...collectCompileRewriteEdits(staged.current, compileSchemaInfos, {\n zodCompat: options.zodCompat,\n }),\n );\n }\n // Pass 2: plain exported schemas\n if (autoDiscoverSchemaInfos.length > 0) {\n edits.push(\n ...collectAutoDiscoverEdits(staged.current, autoDiscoverSchemaInfos, {\n zodCompat: options.zodCompat,\n }),\n );\n }\n rewriteEdits = edits;\n } else {\n rewriteEdits = collectCompileRewriteEdits(staged.current, compiled, {\n zodCompat: options.zodCompat,\n });\n }\n\n // Head = runtime helpers/import, then the file-level shared dedup block, then\n // the rewritten source. The shared `__zcSw_N` functions live at module scope\n // so every IIFE closes over them; they must follow the runtime import (lean)\n // and the helper decls (inline) that they reference. Guard against\n // double-injection on watch/HMR re-runs the same way computeRuntimePrefix\n // does — a second copy would redeclare every `__zcSw_N`.\n //\n // Deferred into the rewrite's own stage rather than staged after it: both\n // decisions read the REWRITTEN text, and giving a bare prepend its own stage\n // doubled the sourcemap work and added a composition pass (see applyThen).\n staged.applyThen(rewriteEdits, (rewritten) => {\n const prefix = computeRuntimePrefix(rewritten, usedHelpers, mode, options.runtimeId);\n const needsShared = shared.code !== \"\" && !rewritten.includes(SHARED_BLOCK_MARKER);\n const head = (prefix ?? \"\") + (needsShared ? `${shared.code}\\n` : \"\");\n return head === \"\" ? undefined : head;\n });\n return { code: staged.current, map: staged.map() };\n}\n\n/**\n * Prepend the runtime helpers required by the rewritten source.\n *\n * Lean mode emits a single `import { ... } from \"<runtimeId>\";` line —\n * bundlers whose resolveId hook intercepts the specifier dedup helpers across\n * every transformed file into one shared virtual module.\n *\n * Inline mode prepends file-level `function __zcMkv` / `function __zcFin`\n * declarations directly so the file is self-contained.\n *\n * Idempotent: if the file already contains the relevant marker (re-run during\n * watch/HMR), we skip re-injection.\n */\n/** The runtime-helper text to prepend, or null when nothing is needed. */\nfunction computeRuntimePrefix(\n code: string,\n usedHelpers: Set<string>,\n mode: CodegenMode,\n runtimeId: string = VIRTUAL_RUNTIME_ID,\n): string | null {\n if (mode === \"lean\") {\n if (usedHelpers.size === 0) return null;\n // Match the import STATEMENT, not the bare id. `zod-compiler/runtime` is a\n // plain package specifier and a substring of `virtual:zod-compiler/runtime`,\n // so a file merely mentioning either — a comment, a docs snippet — would\n // suppress the import while codegen still emits calls to the helpers.\n if (code.includes(`from \"${runtimeId}\"`)) return null;\n const names = [...usedHelpers].sort().join(\", \");\n return `import { ${names} } from \"${runtimeId}\";\\n`;\n }\n // Inline mode (CLI emitter, and any bundler not in VIRTUAL_MODULE_FRAMEWORKS):\n // ship file-level helper declarations instead of a virtual import.\n // Codegen emits per-IIFE issue literals + per-IIFE `__re_*` decls,\n // so we only need __zcMkv / __zcFin (plus __zcMsg via the zod config import).\n if (!code.includes(\"__zcMkv\")) return null;\n const prefix: string[] = [];\n if (!code.includes(\"__zodCompilerConfig\")) {\n prefix.push(ZOD_CONFIG_IMPORT, ZOD_MSG_DECLARATION);\n }\n if (!code.includes(\"function __zcMkv(\")) {\n prefix.push(MK_VALIDATOR_DECL);\n }\n // __zcFin and __zcFinD both construct __ZcFail; declare it once before either,\n // guarding against a header already shipped earlier in the same module.\n const needsFin = !code.includes(\"function __zcFin(\");\n const needsFinD = code.includes(\"__zcFinD(\") && !code.includes(\"function __zcFinD(\");\n if ((needsFin || needsFinD) && !code.includes(\"function __ZcFail(\")) {\n prefix.push(FAIL_CLASS_DECL);\n }\n if (needsFin) {\n prefix.push(FIN_DECL);\n }\n if (needsFinD) {\n prefix.push(FIN_DEFERRED_DECL);\n }\n // Compact mode (output: \"compact\") delegates cold errors to zod via __zcFinZ,\n // which constructs its own __ZcFailZ (distinct from __ZcFail).\n const needsFinZ = code.includes(\"__zcFinZ(\") && !code.includes(\"function __zcFinZ(\");\n if (needsFinZ && !code.includes(\"function __ZcFailZ(\")) {\n prefix.push(FAILZ_CLASS_DECL);\n }\n if (needsFinZ) {\n prefix.push(FINZ_DECL);\n }\n return prefix.length > 0 ? `${prefix.join(\"\\n\")}\\n` : null;\n}\n\n/**\n * Find the matching closing parenthesis for a compile() call,\n * handling nested parentheses like compile(z.object({...})).\n * Returns the index of the closing ')' or -1 if not found.\n */\nfunction findMatchingParen(code: string, openIndex: number): number {\n let depth = 1;\n for (let i = openIndex + 1; i < code.length; i++) {\n if (code[i] === \"(\") depth++;\n else if (code[i] === \")\") {\n depth--;\n if (depth === 0) return i;\n }\n }\n return -1;\n}\n\n/**\n * Rewrite source code by replacing compile() calls with IIFE-wrapped optimized validators.\n */\nexport function rewriteSource(\n code: string,\n schemas: CompiledSchemaInfo[],\n options?: { zodCompat?: boolean | undefined },\n): string {\n return applyEdits(code, collectCompileRewriteEdits(code, schemas, options));\n}\n\n/**\n * Edits for rewriteSource (compile() call replacements + compile-import\n * removal), collected against pristine `code`. Each schema's declaration is\n * a distinct region and the import statement is distinct from all of them,\n * so the batch is non-overlapping and order-independent.\n */\nfunction collectCompileRewriteEdits(\n code: string,\n schemas: CompiledSchemaInfo[],\n options?: { zodCompat?: boolean | undefined },\n): Edit[] {\n const edits: Edit[] = [];\n for (const schema of schemas) {\n // Match: <exportName> = compile<...>( with word boundary to prevent substring matches\n const prefixPattern = new RegExp(\n `(\\\\b${schema.exportName}\\\\s*=\\\\s*)compile\\\\s*(?:<[^>]*(?:<[^>]*>[^>]*)?>)?\\\\s*\\\\(`,\n );\n const match = prefixPattern.exec(code);\n if (!match) continue;\n\n // Find the matching closing paren (handles nested parens)\n const openParenIndex = match.index + match[0].length - 1;\n const closeParenIndex = findMatchingParen(code, openParenIndex);\n if (closeParenIndex === -1) continue;\n\n const schemaArgName = code\n .slice(openParenIndex + 1, closeParenIndex)\n .trim()\n .replace(/,\\s*$/, \"\");\n const prefix = match[1] ?? \"\";\n edits.push({\n start: match.index,\n end: closeParenIndex + 1,\n text: prefix + generateIIFE(schemaArgName, schema, options),\n });\n }\n edits.push(...collectRemoveCompileImportEdits(code));\n return edits;\n}\n\n/**\n * Find the end position of a JavaScript expression starting at `start` using acorn.\n * Returns the end offset, or -1 if the expression cannot be parsed.\n */\nexport function findExpressionEnd(code: string, start: number): number {\n try {\n const node = parseExpressionAt(code, start, {\n ecmaVersion: \"latest\",\n sourceType: \"module\",\n });\n return node.end;\n } catch {\n return -1;\n }\n}\n\n/**\n * Rewrite source code by replacing plain Zod schema exports with IIFE-wrapped optimized validators.\n * Used by autoDiscover mode (no compile() wrappers needed).\n */\nexport function rewriteSourceAutoDiscover(\n code: string,\n schemas: CompiledSchemaInfo[],\n options?: { zodCompat?: boolean | undefined },\n): string {\n return applyEdits(code, collectAutoDiscoverEdits(code, schemas, options));\n}\n\n/** Edits for rewriteSourceAutoDiscover, collected against pristine `code`. */\nfunction collectAutoDiscoverEdits(\n code: string,\n schemas: CompiledSchemaInfo[],\n options?: { zodCompat?: boolean | undefined },\n): Edit[] {\n const edits: Edit[] = [];\n for (const schema of schemas) {\n const escapedName = schema.exportName.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n // Match: export? (const|let|var) ExportName[: TypeAnnotation] = <expr>\n const assignPattern = new RegExp(\n `((?:export\\\\s+)?(?:const|let|var)\\\\s+${escapedName}(?:\\\\s*:[^=]*)?\\\\s*=\\\\s*)`,\n );\n const match = assignPattern.exec(code);\n if (!match) continue;\n\n const rhsStart = match.index + match[0].length;\n const rhsEnd = findExpressionEnd(code, rhsStart);\n if (rhsEnd === -1) continue;\n\n const originalExpr = code.slice(rhsStart, rhsEnd).trim();\n edits.push({\n start: rhsStart,\n end: rhsEnd,\n text: generateIIFE(originalExpr, schema, options),\n });\n }\n return edits;\n}\n\n/**\n * Remove the `compile` binding from `import { compile, ... } from \"zod-compiler\"` statements.\n * If `compile` is the only import, the entire import line is removed.\n */\nexport function removeCompileImport(code: string): string {\n return applyEdits(code, collectRemoveCompileImportEdits(code));\n}\n\n/** Edits stripping the `compile` binding from zod-compiler import statements. */\nfunction collectRemoveCompileImportEdits(code: string): Edit[] {\n // Match: import { ... } from \"zod-compiler\" or 'zod-compiler'\n const importPattern = /import\\s*\\{([^}]*)\\}\\s*from\\s*[\"']zod-compiler[\"'];?/g;\n const edits: Edit[] = [];\n for (const match of code.matchAll(importPattern)) {\n const imports = match[1] ?? \"\";\n const names = imports\n .split(\",\")\n .map((n) => n.trim())\n .filter(Boolean);\n const remaining = names.filter((n) => n !== \"compile\");\n const text =\n remaining.length === 0 ? \"\" : `import { ${remaining.join(\", \")} } from \"zod-compiler\";`;\n if (text !== match[0]) {\n edits.push({ start: match.index, end: match.index + match[0].length, text });\n }\n }\n return edits;\n}\n"],"mappings":"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"}
|