zod-compiler 2.0.2 → 2.0.4

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.
Files changed (61) hide show
  1. package/README.md +8 -6
  2. package/dist/cli/commands/check.d.ts.map +1 -1
  3. package/dist/cli/commands/check.js +5 -0
  4. package/dist/cli/commands/check.js.map +1 -1
  5. package/dist/core/codegen/build-path.js +18 -6
  6. package/dist/core/codegen/build-path.js.map +1 -1
  7. package/dist/core/codegen/context.d.ts +12 -1
  8. package/dist/core/codegen/context.d.ts.map +1 -1
  9. package/dist/core/codegen/context.js +15 -1
  10. package/dist/core/codegen/context.js.map +1 -1
  11. package/dist/core/codegen/index.js +1 -0
  12. package/dist/core/codegen/index.js.map +1 -1
  13. package/dist/core/codegen/issue-decls.d.ts +67 -5
  14. package/dist/core/codegen/issue-decls.d.ts.map +1 -1
  15. package/dist/core/codegen/issue-decls.js +72 -7
  16. package/dist/core/codegen/issue-decls.js.map +1 -1
  17. package/dist/core/codegen/schemas/array.d.ts.map +1 -1
  18. package/dist/core/codegen/schemas/array.js +3 -3
  19. package/dist/core/codegen/schemas/array.js.map +1 -1
  20. package/dist/core/codegen/schemas/effect.d.ts +13 -1
  21. package/dist/core/codegen/schemas/effect.d.ts.map +1 -1
  22. package/dist/core/codegen/schemas/effect.js +26 -3
  23. package/dist/core/codegen/schemas/effect.js.map +1 -1
  24. package/dist/core/codegen/schemas/fallback.d.ts +17 -1
  25. package/dist/core/codegen/schemas/fallback.d.ts.map +1 -1
  26. package/dist/core/codegen/schemas/fallback.js +31 -15
  27. package/dist/core/codegen/schemas/fallback.js.map +1 -1
  28. package/dist/core/codegen/schemas/number.d.ts.map +1 -1
  29. package/dist/core/codegen/schemas/number.js +35 -35
  30. package/dist/core/codegen/schemas/number.js.map +1 -1
  31. package/dist/core/codegen/schemas/object.d.ts.map +1 -1
  32. package/dist/core/codegen/schemas/object.js +64 -29
  33. package/dist/core/codegen/schemas/object.js.map +1 -1
  34. package/dist/core/codegen/schemas/recursive-ref.d.ts.map +1 -1
  35. package/dist/core/codegen/schemas/recursive-ref.js +1 -0
  36. package/dist/core/codegen/schemas/recursive-ref.js.map +1 -1
  37. package/dist/core/codegen/schemas/string.d.ts.map +1 -1
  38. package/dist/core/codegen/schemas/string.js +3 -3
  39. package/dist/core/codegen/schemas/string.js.map +1 -1
  40. package/dist/core/codegen/schemas/template-literal.d.ts.map +1 -1
  41. package/dist/core/codegen/schemas/template-literal.js +1 -1
  42. package/dist/core/codegen/schemas/template-literal.js.map +1 -1
  43. package/dist/core/extract/index.d.ts.map +1 -1
  44. package/dist/core/extract/index.js +2 -0
  45. package/dist/core/extract/index.js.map +1 -1
  46. package/dist/core/extract/zod-version.d.ts +78 -0
  47. package/dist/core/extract/zod-version.d.ts.map +1 -0
  48. package/dist/core/extract/zod-version.js +109 -0
  49. package/dist/core/extract/zod-version.js.map +1 -0
  50. package/dist/jit.d.ts.map +1 -1
  51. package/dist/jit.js +9 -1
  52. package/dist/jit.js.map +1 -1
  53. package/dist/runtime.d.ts +3 -0
  54. package/dist/runtime.js +4 -1
  55. package/dist/unplugin/hoist-compile.d.ts.map +1 -1
  56. package/dist/unplugin/hoist-compile.js +3 -1
  57. package/dist/unplugin/hoist-compile.js.map +1 -1
  58. package/dist/unplugin/transform.d.ts.map +1 -1
  59. package/dist/unplugin/transform.js +5 -0
  60. package/dist/unplugin/transform.js.map +1 -1
  61. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"string.js","names":[],"sources":["../../../../src/core/codegen/schemas/string.ts"],"sourcesContent":["import type { CheckIR, CheckStringFormat, StringIR } from \"../../types.js\";\nimport type { CodeGenContext, FastGen, SlowGen } from \"../context.js\";\nimport {\n checkPriority,\n emitEffectCallable,\n emitEffectFn,\n emitRegex,\n emitRegexSourceString,\n emitRuntimeHelper,\n escapeString,\n} from \"../context.js\";\nimport { emit } from \"../emit.js\";\nimport { invalidFormat, invalidType, tooBig, tooSmall } from \"../emit-issue.js\";\nimport { ZC_EMAIL_DECL } from \"../issue-decls.js\";\nimport {\n EMAIL_REGEX_SOURCE,\n fastTestSource,\n isDefaultEmailPattern,\n UUID_REGEX_SOURCE,\n} from \"../well-known-regex.js\";\nimport { refineCheck, superRefineCheck, superRefineFastTest } from \"./effect.js\";\nimport { stringLengthTests, whenGatedSizeChecks } from \"./sizeable.js\";\n\n/** `re.lastIndex=0;` reset statement for stateful (g/y-flagged) regexes. */\nfunction lastIndexReset(regexVar: string, flags: string | undefined): string {\n return flags && /[gy]/.test(flags) ? `${regexVar}.lastIndex=0;` : \"\";\n}\n\n/**\n * `regexes.httpProtocol.source`. `parseURLObject` compares a url check's\n * protocol SOURCE against it — not the schema constructor — so any check whose\n * protocol is spelled this way gets the guard, `z.httpUrl()` or not.\n */\nconst HTTP_PROTOCOL_SOURCE = \"^https?$\";\n\n/**\n * Generate the url check, mirroring $ZodURL semantics:\n * trim → (for an http(s)-protocol check without normalize) require `://` →\n * new URL(trimmed) → optional hostname/protocol regex tests → write back\n * url.href (normalize) or the trimmed input with its tabs and newlines deleted.\n *\n * The `://` guard is `parseURLObject`'s: without it the URL parser accepts\n * `http:example.com`, and its rejection is a distinct issue (`note: \"Invalid\n * URL format\"`, no `pattern`) pushed BEFORE the parser runs. The deletion of\n * `\\t`, `\\n` and `\\r` (`stripTabAndNewline`) matches what the parser itself\n * drops before it reads the host, so the returned value names the host that was\n * validated.\n *\n * $ZodURL is another constructor that OVERRIDES the `??=`-installed default\n * check, so none of the issues below carries `origin` — and the two that do\n * carry a `pattern` use `regex.source`, not the default check's\n * `regex.toString()` (no delimiters, no flags). Both are reproduced verbatim.\n */\nfunction slowUrlCheck(check: CheckStringFormat, g: SlowGen): string {\n const trimmedVar = g.temp(\"ut\");\n const urlVar = g.temp(\"u\");\n let inner = \"\";\n if (check.hostname) {\n const re = g.regex(\"host\", check.hostname, check.hostnameFlags);\n inner += emit`\n ${lastIndexReset(re, check.hostnameFlags)}\n if(!${re}.test(${urlVar}.hostname)){\n ${invalidFormat(g, \"url\", {\n extra: `note:\"Invalid hostname\",pattern:${escapeString(check.hostname)}`,\n message: check.message,\n })}\n }`;\n }\n if (check.protocol) {\n const re = g.regex(\"proto\", check.protocol, check.protocolFlags);\n const protoExpr = `(${urlVar}.protocol.endsWith(\":\")?${urlVar}.protocol.slice(0,-1):${urlVar}.protocol)`;\n inner += emit`\n ${lastIndexReset(re, check.protocolFlags)}\n if(!${re}.test(${protoExpr})){\n ${invalidFormat(g, \"url\", {\n extra: `note:\"Invalid protocol\",pattern:${escapeString(check.protocol)}`,\n message: check.message,\n })}\n }`;\n }\n // Zod writes the value back even when hostname/protocol issues were pushed.\n const stripped = check.normalize\n ? `${urlVar}.href`\n : `${trimmedVar}.replace(${g.regex(\"tnl\", \"[\\\\t\\\\n\\\\r]\", \"g\")},\"\")`;\n inner += `${g.output}=${stripped};`;\n let parse = emit`\n var ${urlVar}=null;\n try{${urlVar}=new URL(${trimmedVar});}catch(_){}\n if(${urlVar}===null){\n ${invalidFormat(g, \"url\", { message: check.message })}\n }else{\n ${inner}\n }`;\n if (!check.normalize && check.protocol === HTTP_PROTOCOL_SOURCE) {\n const re = g.regex(\"httpUrl\", \"^https?:\\\\/\\\\/\", \"i\");\n parse = emit`\n if(!${re}.test(${trimmedVar})){\n ${invalidFormat(g, \"url\", { extra: `note:\"Invalid URL format\"`, message: check.message })}\n }else{\n ${parse}\n }`;\n }\n return emit`\n var ${trimmedVar}=${g.input}.trim();\n ${parse}`;\n}\n\nexport function slowString(ir: StringIR, g: SlowGen): string {\n let code = \"\";\n if (ir.coerce) {\n code += emit`try{${g.output}=String(${g.input});}catch(_){}`;\n }\n code += emit`\n if(typeof ${g.input}!==\"string\"){\n ${invalidType(g, \"string\")}\n ${whenGatedSizeChecks(ir.checks, g, \"length\")}\n }`;\n\n if (ir.checks.length > 0) {\n code += `else{`;\n // Insertion order mirrors zod's issue order for multi-failure inputs;\n // the slow path collects all issues with no short-circuit.\n for (const check of ir.checks) {\n switch (check.kind) {\n // Length is measured in code points where the unit count leaves the\n // verdict in doubt — see stringLengthTests.\n case \"min_length\":\n code += emit`\n if(${stringLengthTests.minFails(g.input, check.minimum, g.ctx)}){\n ${tooSmall(g, check.minimum, \"string\", true, { message: check.message })}\n }`;\n break;\n case \"max_length\":\n code += emit`\n if(${stringLengthTests.maxFails(g.input, check.maximum, g.ctx)}){\n ${tooBig(g, check.maximum, \"string\", true, { message: check.message })}\n }`;\n break;\n case \"length_equals\": {\n const length = g.temp(\"cl\");\n code += emit`\n var ${length}=${stringLengthTests.measure(g.input, check.length, g.ctx)};\n if(${length}<${check.length}){\n ${tooSmall(g, check.length, \"string\", true, { exact: true, message: check.message })}\n }else if(${length}>${check.length}){\n ${tooBig(g, check.length, \"string\", true, { exact: true, message: check.message })}\n }`;\n break;\n }\n // includes/starts_with/ends_with each carry `origin:\"string\"` but NO\n // `pattern`: $ZodCheckIncludes/StartsWith/EndsWith bypass\n // $ZodCheckStringFormat entirely (they init from $ZodCheck and assign\n // `inst._zod.check` directly), and the pattern they build is registered\n // in the bag for JSON Schema only, never put on the issue.\n case \"includes\":\n code += emit`\n if(!${g.input}.includes(${escapeString(check.includes)}${check.position !== undefined ? `,${check.position}` : \"\"})){\n ${invalidFormat(g, \"includes\", { origin: \"string\", extra: `includes:${escapeString(check.includes)}`, message: check.message })}\n }`;\n break;\n case \"starts_with\":\n code += emit`\n if(!${g.input}.startsWith(${escapeString(check.prefix)})){\n ${invalidFormat(g, \"starts_with\", { origin: \"string\", extra: `prefix:${escapeString(check.prefix)}`, message: check.message })}\n }`;\n break;\n case \"ends_with\":\n code += emit`\n if(!${g.input}.endsWith(${escapeString(check.suffix)})){\n ${invalidFormat(g, \"ends_with\", { origin: \"string\", extra: `suffix:${escapeString(check.suffix)}`, message: check.message })}\n }`;\n break;\n case \"refine_effect\":\n code += refineCheck(check, g.input, g);\n break;\n case \"super_refine_effect\":\n code += superRefineCheck(check, g.input, g);\n break;\n case \"overwrite_effect\":\n // $ZodCheckOverwrite: value = tx(value). Later checks read the\n // rewritten value because input aliases the output location.\n code += emit`${g.output}=${emitEffectFn(g.ctx, check.source)}(${g.input});`;\n break;\n case \"string_format\": {\n let prefix: string;\n let pattern: string;\n // Only the BUILT-IN z.url() gets the URL-parser check, and extraction\n // never gives that one a pattern. A `pattern` on a \"url\"-named check\n // therefore marks a custom format that merely borrowed the name\n // (`z.stringFormat(\"url\", /re/)`); it validates through its own regex,\n // so fall through and compile that instead of the URL parser.\n if (check.format === \"url\" && !check.pattern) {\n code += slowUrlCheck(check, g);\n continue;\n }\n if (check.format === \"email\") {\n pattern = check.pattern ?? EMAIL_REGEX_SOURCE;\n prefix = \"email\";\n } else if (check.format === \"regex\" && check.pattern) {\n pattern = check.pattern;\n prefix = \"str\";\n } else if (check.format === \"uuid\") {\n pattern = check.pattern ?? UUID_REGEX_SOURCE;\n prefix = \"uuid\";\n } else {\n if (check.pattern) {\n pattern = check.pattern;\n prefix = \"str\";\n } else {\n // Extraction guarantees a pattern for non-special formats;\n // defensive skip kept for hand-built IR.\n continue;\n }\n }\n // Zod's default email pattern is tested by the `__zcEmail` scanner, so\n // no RegExp is declared for it at all (see ZC_EMAIL_DECL); the issue\n // below still names the pattern, through the shared source string.\n const scanner = isDefaultEmailPattern(pattern, check.patternFlags)\n ? emitRuntimeHelper(g.ctx, \"__zcEmail\", ZC_EMAIL_DECL)\n : null;\n const regexVar = scanner === null ? g.regex(prefix, pattern, check.patternFlags) : null;\n // Zod's invalid_format shape depends on WHICH check instance ran.\n // `$ZodCheckStringFormat.init` installs the default pattern check with\n // `??=`, and that default pushes `origin:\"string\"` + `pattern`. A\n // constructor that OVERRIDES `inst._zod.check` pushes its own issue\n // instead — `$ZodCustomStringFormat` (z.stringFormat/z.hex/z.hostname/\n // z.hash) pushes a bare `{code, format, input}` because it validates\n // through `def.fn` and never reads `def.pattern`. We test the pattern\n // either way, so the issue shape is driven off the extracted flag.\n let extra: string | undefined;\n if (!check.bareIssue) {\n // When emitRegex swapped in a faster equivalent pattern (or the\n // scanner stands in for the RegExp), the runtime regex's toString()\n // would leak the rewrite into the issue. Reference the shared\n // original-pattern string instead (pattern came from RegExp.source,\n // so it matches zod's `.toString()` byte-for-byte).\n const rewritten = !check.patternFlags && fastTestSource(pattern) !== null;\n const patternExpr =\n rewritten || regexVar === null\n ? emitRegexSourceString(g.ctx, pattern)\n : `${regexVar}.toString()`;\n extra = `pattern:${patternExpr}`;\n }\n const test =\n regexVar === null ? `${scanner}(${g.input})` : `${regexVar}.test(${g.input})`;\n code += emit`\n ${regexVar === null ? \"\" : lastIndexReset(regexVar, check.patternFlags)}\n if(!${test}){\n ${invalidFormat(g, { expr: escapeString(check.format) }, { origin: check.bareIssue ? undefined : \"string\", extra, message: check.message })}\n }`;\n break;\n }\n }\n }\n code += `}`;\n }\n\n return `${code}\\n`;\n}\n\n/**\n * Boolean expression testing ONE compiled string check against `x`, or null when\n * the check is not expressible as a pure predicate (`z.url()`, which trims and\n * normalizes, and an unknown format with no pattern).\n *\n * Shared by the fast path — which sorts the checks cheapest-first and joins them\n * with `&&` — and by the build path, which emits them one statement at a time in\n * DECLARATION order so an interleaved `.trim()` rewrite is visible to the checks\n * that follow it (see buildString).\n */\nexport function fastStringCheck(check: CheckIR, x: string, ctx: CodeGenContext): string | null {\n switch (check.kind) {\n case \"min_length\":\n return stringLengthTests.min(x, check.minimum, ctx);\n case \"max_length\":\n return stringLengthTests.max(x, check.maximum, ctx);\n case \"length_equals\":\n return stringLengthTests.equals(x, check.length, ctx);\n case \"includes\":\n return check.position !== undefined\n ? `${x}.includes(${escapeString(check.includes)},${check.position})`\n : `${x}.includes(${escapeString(check.includes)})`;\n case \"starts_with\":\n return `${x}.startsWith(${escapeString(check.prefix)})`;\n case \"ends_with\":\n return `${x}.endsWith(${escapeString(check.suffix)})`;\n case \"string_format\": {\n // URL validation mutates (trims) and uses try/catch — not a predicate.\n // A patterned \"url\" check is a custom format that borrowed the name (see\n // buildString), and its regex IS a predicate.\n if (check.format === \"url\" && !check.pattern) return null;\n let pattern: string;\n let prefix: string;\n if (check.format === \"email\") {\n prefix = \"email\";\n pattern = check.pattern ?? EMAIL_REGEX_SOURCE;\n } else if (check.format === \"uuid\") {\n prefix = \"uuid\";\n pattern = check.pattern ?? UUID_REGEX_SOURCE;\n } else if (check.pattern) {\n prefix = \"re\";\n pattern = check.pattern;\n } else {\n // Unknown format without pattern — can't generate a check\n return null;\n }\n // Zod's default email pattern runs as a linear scan instead of a RegExp\n // (see ZC_EMAIL_DECL) — a plain call, so it needs no parens either.\n if (isDefaultEmailPattern(pattern, check.patternFlags)) {\n return `${emitRuntimeHelper(ctx, \"__zcEmail\", ZC_EMAIL_DECL)}(${x})`;\n }\n const v = emitRegex(ctx, prefix, pattern, check.patternFlags);\n // Stateful (g/y) regexes need lastIndex reset; comma expression keeps\n // this usable inside the boolean chain.\n return check.patternFlags && /[gy]/.test(check.patternFlags)\n ? `((${v}.lastIndex=0),${v}.test(${x}))`\n : `${v}.test(${x})`;\n }\n default:\n // A check kind this generator does not model (number/bigint/date/set\n // shapes never reach here from a string node).\n return null;\n }\n}\n\nexport function fastString(ir: StringIR, g: FastGen): string | null {\n if (ir.coerce) return null;\n // Overwrite effects rewrite the value — the fast path returns input\n // unchanged, so any mutation makes it ineligible.\n if (ir.checks.some((c) => c.kind === \"overwrite_effect\")) return null;\n\n const x = g.input;\n const parts: string[] = [`typeof ${x}===\"string\"`];\n const checks = ir.checks.filter(\n (c): c is CheckIR => c.kind !== \"refine_effect\" && c.kind !== \"overwrite_effect\",\n );\n\n for (const check of checks.sort(checkPriority)) {\n const expr = fastStringCheck(check, x, g.ctx);\n if (expr === null) return null;\n parts.push(expr);\n }\n\n // Refine effect checks (appended last — run after cheap checks short-circuit)\n for (const check of ir.checks) {\n if (check.kind === \"refine_effect\") {\n parts.push(`${emitEffectCallable(g.ctx, check)}(${x})`);\n } else if (check.kind === \"super_refine_effect\") {\n parts.push(superRefineFastTest(check, x, g));\n }\n }\n\n return parts.join(\"&&\");\n}\n"],"mappings":";;;;;;;;;AAwBA,SAAS,eAAe,UAAkB,OAAmC;CAC3E,OAAO,SAAS,OAAO,KAAK,KAAK,IAAI,GAAG,SAAS,iBAAiB;AACpE;;;;;;AAOA,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;AAoB7B,SAAS,aAAa,OAA0B,GAAoB;CAClE,MAAM,aAAa,EAAE,KAAK,IAAI;CAC9B,MAAM,SAAS,EAAE,KAAK,GAAG;CACzB,IAAI,QAAQ;CACZ,IAAI,MAAM,UAAU;EAClB,MAAM,KAAK,EAAE,MAAM,QAAQ,MAAM,UAAU,MAAM,aAAa;EAC9D,SAAS,IAAI;QACT,eAAe,IAAI,MAAM,aAAa,EAAE;YACpC,GAAG,QAAQ,OAAO;UACpB,cAAc,GAAG,OAAO;GACxB,OAAO,mCAAmC,aAAa,MAAM,QAAQ;GACrE,SAAS,MAAM;EACjB,CAAC,EAAE;;CAET;CACA,IAAI,MAAM,UAAU;EAClB,MAAM,KAAK,EAAE,MAAM,SAAS,MAAM,UAAU,MAAM,aAAa;EAC/D,MAAM,YAAY,IAAI,OAAO,0BAA0B,OAAO,wBAAwB,OAAO;EAC7F,SAAS,IAAI;QACT,eAAe,IAAI,MAAM,aAAa,EAAE;YACpC,GAAG,QAAQ,UAAU;UACvB,cAAc,GAAG,OAAO;GACxB,OAAO,mCAAmC,aAAa,MAAM,QAAQ;GACrE,SAAS,MAAM;EACjB,CAAC,EAAE;;CAET;CAEA,MAAM,WAAW,MAAM,YACnB,GAAG,OAAO,SACV,GAAG,WAAW,WAAW,EAAE,MAAM,OAAO,eAAe,GAAG,EAAE;CAChE,SAAS,GAAG,EAAE,OAAO,GAAG,SAAS;CACjC,IAAI,QAAQ,IAAI;UACR,OAAO;UACP,OAAO,WAAW,WAAW;SAC9B,OAAO;QACR,cAAc,GAAG,OAAO,EAAE,SAAS,MAAM,QAAQ,CAAC,EAAE;;QAEpD,MAAM;;CAEZ,IAAI,CAAC,MAAM,aAAa,MAAM,aAAa,sBAEzC,QAAQ,IAAI;YADD,EAAE,MAAM,WAAW,kBAAkB,GAEvC,EAAE,QAAQ,WAAW;UACxB,cAAc,GAAG,OAAO;EAAE,OAAO;EAA6B,SAAS,MAAM;CAAQ,CAAC,EAAE;;UAExF,MAAM;;CAGd,OAAO,IAAI;UACH,WAAW,GAAG,EAAE,MAAM;MAC1B;AACN;AAEA,SAAgB,WAAW,IAAc,GAAoB;CAC3D,IAAI,OAAO;CACX,IAAI,GAAG,QACL,QAAQ,IAAI,OAAO,EAAE,OAAO,UAAU,EAAE,MAAM;CAEhD,QAAQ,IAAI;gBACE,EAAE,MAAM;QAChB,YAAY,GAAG,QAAQ,EAAE;QACzB,oBAAoB,GAAG,QAAQ,GAAG,QAAQ,EAAE;;CAGlD,IAAI,GAAG,OAAO,SAAS,GAAG;EACxB,QAAQ;EAGR,KAAK,MAAM,SAAS,GAAG,QACrB,QAAQ,MAAM,MAAd;GAGE,KAAK;IACH,QAAQ,IAAI;iBACL,kBAAkB,SAAS,EAAE,OAAO,MAAM,SAAS,EAAE,GAAG,EAAE;gBAC3D,SAAS,GAAG,MAAM,SAAS,UAAU,MAAM,EAAE,SAAS,MAAM,QAAQ,CAAC,EAAE;;IAE7E;GACF,KAAK;IACH,QAAQ,IAAI;iBACL,kBAAkB,SAAS,EAAE,OAAO,MAAM,SAAS,EAAE,GAAG,EAAE;gBAC3D,OAAO,GAAG,MAAM,SAAS,UAAU,MAAM,EAAE,SAAS,MAAM,QAAQ,CAAC,EAAE;;IAE3E;GACF,KAAK,iBAAiB;IACpB,MAAM,SAAS,EAAE,KAAK,IAAI;IAC1B,QAAQ,IAAI;kBACJ,OAAO,GAAG,kBAAkB,QAAQ,EAAE,OAAO,MAAM,QAAQ,EAAE,GAAG,EAAE;iBACnE,OAAO,GAAG,MAAM,OAAO;gBACxB,SAAS,GAAG,MAAM,QAAQ,UAAU,MAAM;KAAE,OAAO;KAAM,SAAS,MAAM;IAAQ,CAAC,EAAE;uBAC5E,OAAO,GAAG,MAAM,OAAO;gBAC9B,OAAO,GAAG,MAAM,QAAQ,UAAU,MAAM;KAAE,OAAO;KAAM,SAAS,MAAM;IAAQ,CAAC,EAAE;;IAEvF;GACF;GAMA,KAAK;IACH,QAAQ,IAAI;kBACJ,EAAE,MAAM,YAAY,aAAa,MAAM,QAAQ,IAAI,MAAM,aAAa,KAAA,IAAY,IAAI,MAAM,aAAa,GAAG;gBAC9G,cAAc,GAAG,YAAY;KAAE,QAAQ;KAAU,OAAO,YAAY,aAAa,MAAM,QAAQ;KAAK,SAAS,MAAM;IAAQ,CAAC,EAAE;;IAEpI;GACF,KAAK;IACH,QAAQ,IAAI;kBACJ,EAAE,MAAM,cAAc,aAAa,MAAM,MAAM,EAAE;gBACnD,cAAc,GAAG,eAAe;KAAE,QAAQ;KAAU,OAAO,UAAU,aAAa,MAAM,MAAM;KAAK,SAAS,MAAM;IAAQ,CAAC,EAAE;;IAEnI;GACF,KAAK;IACH,QAAQ,IAAI;kBACJ,EAAE,MAAM,YAAY,aAAa,MAAM,MAAM,EAAE;gBACjD,cAAc,GAAG,aAAa;KAAE,QAAQ;KAAU,OAAO,UAAU,aAAa,MAAM,MAAM;KAAK,SAAS,MAAM;IAAQ,CAAC,EAAE;;IAEjI;GACF,KAAK;IACH,QAAQ,YAAY,OAAO,EAAE,OAAO,CAAC;IACrC;GACF,KAAK;IACH,QAAQ,iBAAiB,OAAO,EAAE,OAAO,CAAC;IAC1C;GACF,KAAK;IAGH,QAAQ,IAAI,GAAG,EAAE,OAAO,GAAG,aAAa,EAAE,KAAK,MAAM,MAAM,EAAE,GAAG,EAAE,MAAM;IACxE;GACF,KAAK,iBAAiB;IACpB,IAAI;IACJ,IAAI;IAMJ,IAAI,MAAM,WAAW,SAAS,CAAC,MAAM,SAAS;KAC5C,QAAQ,aAAa,OAAO,CAAC;KAC7B;IACF;IACA,IAAI,MAAM,WAAW,SAAS;KAC5B,UAAU,MAAM,WAAW;KAC3B,SAAS;IACX,OAAO,IAAI,MAAM,WAAW,WAAW,MAAM,SAAS;KACpD,UAAU,MAAM;KAChB,SAAS;IACX,OAAO,IAAI,MAAM,WAAW,QAAQ;KAClC,UAAU,MAAM,WAAA;KAChB,SAAS;IACX,OACE,IAAI,MAAM,SAAS;KACjB,UAAU,MAAM;KAChB,SAAS;IACX,OAGE;IAMJ,MAAM,UAAU,sBAAsB,SAAS,MAAM,YAAY,IAC7D,kBAAkB,EAAE,KAAK,aAAa,aAAa,IACnD;IACJ,MAAM,WAAW,YAAY,OAAO,EAAE,MAAM,QAAQ,SAAS,MAAM,YAAY,IAAI;IASnF,IAAI;IACJ,IAAI,CAAC,MAAM,WAWT,QAAQ,WALU,CAAC,MAAM,gBAAgB,eAAe,OAAO,MAAM,QAEtD,aAAa,OACtB,sBAAsB,EAAE,KAAK,OAAO,IACpC,GAAG,SAAS;IAGpB,MAAM,OACJ,aAAa,OAAO,GAAG,QAAQ,GAAG,EAAE,MAAM,KAAK,GAAG,SAAS,QAAQ,EAAE,MAAM;IAC7E,QAAQ,IAAI;cACR,aAAa,OAAO,KAAK,eAAe,UAAU,MAAM,YAAY,EAAE;kBAClE,KAAK;gBACP,cAAc,GAAG,EAAE,MAAM,aAAa,MAAM,MAAM,EAAE,GAAG;KAAE,QAAQ,MAAM,YAAY,KAAA,IAAY;KAAU;KAAO,SAAS,MAAM;IAAQ,CAAC,EAAE;;IAEhJ;GACF;EACF;EAEF,QAAQ;CACV;CAEA,OAAO,GAAG,KAAK;AACjB;;;;;;;;;;;AAYA,SAAgB,gBAAgB,OAAgB,GAAW,KAAoC;CAC7F,QAAQ,MAAM,MAAd;EACE,KAAK,cACH,OAAO,kBAAkB,IAAI,GAAG,MAAM,SAAS,GAAG;EACpD,KAAK,cACH,OAAO,kBAAkB,IAAI,GAAG,MAAM,SAAS,GAAG;EACpD,KAAK,iBACH,OAAO,kBAAkB,OAAO,GAAG,MAAM,QAAQ,GAAG;EACtD,KAAK,YACH,OAAO,MAAM,aAAa,KAAA,IACtB,GAAG,EAAE,YAAY,aAAa,MAAM,QAAQ,EAAE,GAAG,MAAM,SAAS,KAChE,GAAG,EAAE,YAAY,aAAa,MAAM,QAAQ,EAAE;EACpD,KAAK,eACH,OAAO,GAAG,EAAE,cAAc,aAAa,MAAM,MAAM,EAAE;EACvD,KAAK,aACH,OAAO,GAAG,EAAE,YAAY,aAAa,MAAM,MAAM,EAAE;EACrD,KAAK,iBAAiB;GAIpB,IAAI,MAAM,WAAW,SAAS,CAAC,MAAM,SAAS,OAAO;GACrD,IAAI;GACJ,IAAI;GACJ,IAAI,MAAM,WAAW,SAAS;IAC5B,SAAS;IACT,UAAU,MAAM,WAAW;GAC7B,OAAO,IAAI,MAAM,WAAW,QAAQ;IAClC,SAAS;IACT,UAAU,MAAM,WAAA;GAClB,OAAO,IAAI,MAAM,SAAS;IACxB,SAAS;IACT,UAAU,MAAM;GAClB,OAEE,OAAO;GAIT,IAAI,sBAAsB,SAAS,MAAM,YAAY,GACnD,OAAO,GAAG,kBAAkB,KAAK,aAAa,aAAa,EAAE,GAAG,EAAE;GAEpE,MAAM,IAAI,UAAU,KAAK,QAAQ,SAAS,MAAM,YAAY;GAG5D,OAAO,MAAM,gBAAgB,OAAO,KAAK,MAAM,YAAY,IACvD,KAAK,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MACnC,GAAG,EAAE,QAAQ,EAAE;EACrB;EACA,SAGE,OAAO;CACX;AACF;AAEA,SAAgB,WAAW,IAAc,GAA2B;CAClE,IAAI,GAAG,QAAQ,OAAO;CAGtB,IAAI,GAAG,OAAO,MAAM,MAAM,EAAE,SAAS,kBAAkB,GAAG,OAAO;CAEjE,MAAM,IAAI,EAAE;CACZ,MAAM,QAAkB,CAAC,UAAU,EAAE,YAAY;CACjD,MAAM,SAAS,GAAG,OAAO,QACtB,MAAoB,EAAE,SAAS,mBAAmB,EAAE,SAAS,kBAChE;CAEA,KAAK,MAAM,SAAS,OAAO,KAAK,aAAa,GAAG;EAC9C,MAAM,OAAO,gBAAgB,OAAO,GAAG,EAAE,GAAG;EAC5C,IAAI,SAAS,MAAM,OAAO;EAC1B,MAAM,KAAK,IAAI;CACjB;CAGA,KAAK,MAAM,SAAS,GAAG,QACrB,IAAI,MAAM,SAAS,iBACjB,MAAM,KAAK,GAAG,mBAAmB,EAAE,KAAK,KAAK,EAAE,GAAG,EAAE,EAAE;MACjD,IAAI,MAAM,SAAS,uBACxB,MAAM,KAAK,oBAAoB,OAAO,GAAG,CAAC,CAAC;CAI/C,OAAO,MAAM,KAAK,IAAI;AACxB"}
1
+ {"version":3,"file":"string.js","names":[],"sources":["../../../../src/core/codegen/schemas/string.ts"],"sourcesContent":["import type { CheckIR, CheckStringFormat, StringIR } from \"../../types.js\";\nimport type { CodeGenContext, FastGen, SlowGen } from \"../context.js\";\nimport {\n checkPriority,\n emitEffectFn,\n emitRegex,\n emitRegexSourceString,\n emitRuntimeHelper,\n escapeString,\n} from \"../context.js\";\nimport { emit } from \"../emit.js\";\nimport { invalidFormat, invalidType, tooBig, tooSmall } from \"../emit-issue.js\";\nimport { ZC_EMAIL_DECL } from \"../issue-decls.js\";\nimport {\n EMAIL_REGEX_SOURCE,\n fastTestSource,\n isDefaultEmailPattern,\n UUID_REGEX_SOURCE,\n} from \"../well-known-regex.js\";\nimport { fastRefineTest, refineCheck, superRefineCheck, superRefineFastTest } from \"./effect.js\";\nimport { stringLengthTests, whenGatedSizeChecks } from \"./sizeable.js\";\n\n/** `re.lastIndex=0;` reset statement for stateful (g/y-flagged) regexes. */\nfunction lastIndexReset(regexVar: string, flags: string | undefined): string {\n return flags && /[gy]/.test(flags) ? `${regexVar}.lastIndex=0;` : \"\";\n}\n\n/**\n * `regexes.httpProtocol.source`. `parseURLObject` compares a url check's\n * protocol SOURCE against it — not the schema constructor — so any check whose\n * protocol is spelled this way gets the guard, `z.httpUrl()` or not.\n */\nconst HTTP_PROTOCOL_SOURCE = \"^https?$\";\n\n/**\n * Generate the url check, mirroring $ZodURL semantics:\n * trim → (for an http(s)-protocol check without normalize) require `://` →\n * new URL(trimmed) → optional hostname/protocol regex tests → write back\n * url.href (normalize) or the trimmed input with its tabs and newlines deleted.\n *\n * The `://` guard is `parseURLObject`'s: without it the URL parser accepts\n * `http:example.com`, and its rejection is a distinct issue (`note: \"Invalid\n * URL format\"`, no `pattern`) pushed BEFORE the parser runs. The deletion of\n * `\\t`, `\\n` and `\\r` (`stripTabAndNewline`) matches what the parser itself\n * drops before it reads the host, so the returned value names the host that was\n * validated.\n *\n * $ZodURL is another constructor that OVERRIDES the `??=`-installed default\n * check, so none of the issues below carries `origin` — and the two that do\n * carry a `pattern` use `regex.source`, not the default check's\n * `regex.toString()` (no delimiters, no flags). Both are reproduced verbatim.\n */\nfunction slowUrlCheck(check: CheckStringFormat, g: SlowGen): string {\n const trimmedVar = g.temp(\"ut\");\n const urlVar = g.temp(\"u\");\n let inner = \"\";\n if (check.hostname) {\n const re = g.regex(\"host\", check.hostname, check.hostnameFlags);\n inner += emit`\n ${lastIndexReset(re, check.hostnameFlags)}\n if(!${re}.test(${urlVar}.hostname)){\n ${invalidFormat(g, \"url\", {\n extra: `note:\"Invalid hostname\",pattern:${escapeString(check.hostname)}`,\n message: check.message,\n })}\n }`;\n }\n if (check.protocol) {\n const re = g.regex(\"proto\", check.protocol, check.protocolFlags);\n const protoExpr = `(${urlVar}.protocol.endsWith(\":\")?${urlVar}.protocol.slice(0,-1):${urlVar}.protocol)`;\n inner += emit`\n ${lastIndexReset(re, check.protocolFlags)}\n if(!${re}.test(${protoExpr})){\n ${invalidFormat(g, \"url\", {\n extra: `note:\"Invalid protocol\",pattern:${escapeString(check.protocol)}`,\n message: check.message,\n })}\n }`;\n }\n // Zod writes the value back even when hostname/protocol issues were pushed.\n const stripped = check.normalize\n ? `${urlVar}.href`\n : `${trimmedVar}.replace(${g.regex(\"tnl\", \"[\\\\t\\\\n\\\\r]\", \"g\")},\"\")`;\n inner += `${g.output}=${stripped};`;\n let parse = emit`\n var ${urlVar}=null;\n try{${urlVar}=new URL(${trimmedVar});}catch(_){}\n if(${urlVar}===null){\n ${invalidFormat(g, \"url\", { message: check.message })}\n }else{\n ${inner}\n }`;\n if (!check.normalize && check.protocol === HTTP_PROTOCOL_SOURCE) {\n const re = g.regex(\"httpUrl\", \"^https?:\\\\/\\\\/\", \"i\");\n parse = emit`\n if(!${re}.test(${trimmedVar})){\n ${invalidFormat(g, \"url\", { extra: `note:\"Invalid URL format\"`, message: check.message })}\n }else{\n ${parse}\n }`;\n }\n return emit`\n var ${trimmedVar}=${g.input}.trim();\n ${parse}`;\n}\n\nexport function slowString(ir: StringIR, g: SlowGen): string {\n let code = \"\";\n if (ir.coerce) {\n code += emit`try{${g.output}=String(${g.input});}catch(_){}`;\n }\n code += emit`\n if(typeof ${g.input}!==\"string\"){\n ${invalidType(g, \"string\")}\n ${whenGatedSizeChecks(ir.checks, g, \"length\")}\n }`;\n\n if (ir.checks.length > 0) {\n code += `else{`;\n // Insertion order mirrors zod's issue order for multi-failure inputs;\n // the slow path collects all issues with no short-circuit.\n for (const check of ir.checks) {\n switch (check.kind) {\n // Length is measured in code points where the unit count leaves the\n // verdict in doubt — see stringLengthTests.\n case \"min_length\":\n code += emit`\n if(${stringLengthTests.minFails(g.input, check.minimum, g.ctx)}){\n ${tooSmall(g, check.minimum, \"string\", true, { message: check.message })}\n }`;\n break;\n case \"max_length\":\n code += emit`\n if(${stringLengthTests.maxFails(g.input, check.maximum, g.ctx)}){\n ${tooBig(g, check.maximum, \"string\", true, { message: check.message })}\n }`;\n break;\n case \"length_equals\": {\n const length = g.temp(\"cl\");\n code += emit`\n var ${length}=${stringLengthTests.measure(g.input, check.length, g.ctx)};\n if(${length}<${check.length}){\n ${tooSmall(g, check.length, \"string\", true, { exact: true, message: check.message })}\n }else if(${length}>${check.length}){\n ${tooBig(g, check.length, \"string\", true, { exact: true, message: check.message })}\n }`;\n break;\n }\n // includes/starts_with/ends_with each carry `origin:\"string\"` but NO\n // `pattern`: $ZodCheckIncludes/StartsWith/EndsWith bypass\n // $ZodCheckStringFormat entirely (they init from $ZodCheck and assign\n // `inst._zod.check` directly), and the pattern they build is registered\n // in the bag for JSON Schema only, never put on the issue.\n case \"includes\":\n code += emit`\n if(!${g.input}.includes(${escapeString(check.includes)}${check.position !== undefined ? `,${check.position}` : \"\"})){\n ${invalidFormat(g, \"includes\", { origin: \"string\", extra: `includes:${escapeString(check.includes)}`, message: check.message })}\n }`;\n break;\n case \"starts_with\":\n code += emit`\n if(!${g.input}.startsWith(${escapeString(check.prefix)})){\n ${invalidFormat(g, \"starts_with\", { origin: \"string\", extra: `prefix:${escapeString(check.prefix)}`, message: check.message })}\n }`;\n break;\n case \"ends_with\":\n code += emit`\n if(!${g.input}.endsWith(${escapeString(check.suffix)})){\n ${invalidFormat(g, \"ends_with\", { origin: \"string\", extra: `suffix:${escapeString(check.suffix)}`, message: check.message })}\n }`;\n break;\n case \"refine_effect\":\n code += refineCheck(check, g.input, g);\n break;\n case \"super_refine_effect\":\n code += superRefineCheck(check, g.input, g);\n break;\n case \"overwrite_effect\":\n // $ZodCheckOverwrite: value = tx(value). Later checks read the\n // rewritten value because input aliases the output location.\n code += emit`${g.output}=${emitEffectFn(g.ctx, check.source)}(${g.input});`;\n break;\n case \"string_format\": {\n let prefix: string;\n let pattern: string;\n // Only the BUILT-IN z.url() gets the URL-parser check, and extraction\n // never gives that one a pattern. A `pattern` on a \"url\"-named check\n // therefore marks a custom format that merely borrowed the name\n // (`z.stringFormat(\"url\", /re/)`); it validates through its own regex,\n // so fall through and compile that instead of the URL parser.\n if (check.format === \"url\" && !check.pattern) {\n code += slowUrlCheck(check, g);\n continue;\n }\n if (check.format === \"email\") {\n pattern = check.pattern ?? EMAIL_REGEX_SOURCE;\n prefix = \"email\";\n } else if (check.format === \"regex\" && check.pattern) {\n pattern = check.pattern;\n prefix = \"str\";\n } else if (check.format === \"uuid\") {\n pattern = check.pattern ?? UUID_REGEX_SOURCE;\n prefix = \"uuid\";\n } else {\n if (check.pattern) {\n pattern = check.pattern;\n prefix = \"str\";\n } else {\n // Extraction guarantees a pattern for non-special formats;\n // defensive skip kept for hand-built IR.\n continue;\n }\n }\n // Zod's default email pattern is tested by the `__zcEmail` scanner, so\n // no RegExp is declared for it at all (see ZC_EMAIL_DECL); the issue\n // below still names the pattern, through the shared source string.\n const scanner = isDefaultEmailPattern(pattern, check.patternFlags)\n ? emitRuntimeHelper(g.ctx, \"__zcEmail\", ZC_EMAIL_DECL)\n : null;\n const regexVar = scanner === null ? g.regex(prefix, pattern, check.patternFlags) : null;\n // Zod's invalid_format shape depends on WHICH check instance ran.\n // `$ZodCheckStringFormat.init` installs the default pattern check with\n // `??=`, and that default pushes `origin:\"string\"` + `pattern`. A\n // constructor that OVERRIDES `inst._zod.check` pushes its own issue\n // instead — `$ZodCustomStringFormat` (z.stringFormat/z.hex/z.hostname/\n // z.hash) pushes a bare `{code, format, input}` because it validates\n // through `def.fn` and never reads `def.pattern`. We test the pattern\n // either way, so the issue shape is driven off the extracted flag.\n let extra: string | undefined;\n if (!check.bareIssue) {\n // When emitRegex swapped in a faster equivalent pattern (or the\n // scanner stands in for the RegExp), the runtime regex's toString()\n // would leak the rewrite into the issue. Reference the shared\n // original-pattern string instead (pattern came from RegExp.source,\n // so it matches zod's `.toString()` byte-for-byte).\n const rewritten = !check.patternFlags && fastTestSource(pattern) !== null;\n const patternExpr =\n rewritten || regexVar === null\n ? emitRegexSourceString(g.ctx, pattern)\n : `${regexVar}.toString()`;\n extra = `pattern:${patternExpr}`;\n }\n const test =\n regexVar === null ? `${scanner}(${g.input})` : `${regexVar}.test(${g.input})`;\n code += emit`\n ${regexVar === null ? \"\" : lastIndexReset(regexVar, check.patternFlags)}\n if(!${test}){\n ${invalidFormat(g, { expr: escapeString(check.format) }, { origin: check.bareIssue ? undefined : \"string\", extra, message: check.message })}\n }`;\n break;\n }\n }\n }\n code += `}`;\n }\n\n return `${code}\\n`;\n}\n\n/**\n * Boolean expression testing ONE compiled string check against `x`, or null when\n * the check is not expressible as a pure predicate (`z.url()`, which trims and\n * normalizes, and an unknown format with no pattern).\n *\n * Shared by the fast path — which sorts the checks cheapest-first and joins them\n * with `&&` — and by the build path, which emits them one statement at a time in\n * DECLARATION order so an interleaved `.trim()` rewrite is visible to the checks\n * that follow it (see buildString).\n */\nexport function fastStringCheck(check: CheckIR, x: string, ctx: CodeGenContext): string | null {\n switch (check.kind) {\n case \"min_length\":\n return stringLengthTests.min(x, check.minimum, ctx);\n case \"max_length\":\n return stringLengthTests.max(x, check.maximum, ctx);\n case \"length_equals\":\n return stringLengthTests.equals(x, check.length, ctx);\n case \"includes\":\n return check.position !== undefined\n ? `${x}.includes(${escapeString(check.includes)},${check.position})`\n : `${x}.includes(${escapeString(check.includes)})`;\n case \"starts_with\":\n return `${x}.startsWith(${escapeString(check.prefix)})`;\n case \"ends_with\":\n return `${x}.endsWith(${escapeString(check.suffix)})`;\n case \"string_format\": {\n // URL validation mutates (trims) and uses try/catch — not a predicate.\n // A patterned \"url\" check is a custom format that borrowed the name (see\n // buildString), and its regex IS a predicate.\n if (check.format === \"url\" && !check.pattern) return null;\n let pattern: string;\n let prefix: string;\n if (check.format === \"email\") {\n prefix = \"email\";\n pattern = check.pattern ?? EMAIL_REGEX_SOURCE;\n } else if (check.format === \"uuid\") {\n prefix = \"uuid\";\n pattern = check.pattern ?? UUID_REGEX_SOURCE;\n } else if (check.pattern) {\n prefix = \"re\";\n pattern = check.pattern;\n } else {\n // Unknown format without pattern — can't generate a check\n return null;\n }\n // Zod's default email pattern runs as a linear scan instead of a RegExp\n // (see ZC_EMAIL_DECL) — a plain call, so it needs no parens either.\n if (isDefaultEmailPattern(pattern, check.patternFlags)) {\n return `${emitRuntimeHelper(ctx, \"__zcEmail\", ZC_EMAIL_DECL)}(${x})`;\n }\n const v = emitRegex(ctx, prefix, pattern, check.patternFlags);\n // Stateful (g/y) regexes need lastIndex reset; comma expression keeps\n // this usable inside the boolean chain.\n return check.patternFlags && /[gy]/.test(check.patternFlags)\n ? `((${v}.lastIndex=0),${v}.test(${x}))`\n : `${v}.test(${x})`;\n }\n default:\n // A check kind this generator does not model (number/bigint/date/set\n // shapes never reach here from a string node).\n return null;\n }\n}\n\nexport function fastString(ir: StringIR, g: FastGen): string | null {\n if (ir.coerce) return null;\n // Overwrite effects rewrite the value — the fast path returns input\n // unchanged, so any mutation makes it ineligible.\n if (ir.checks.some((c) => c.kind === \"overwrite_effect\")) return null;\n\n const x = g.input;\n const parts: string[] = [`typeof ${x}===\"string\"`];\n const checks = ir.checks.filter(\n (c): c is CheckIR => c.kind !== \"refine_effect\" && c.kind !== \"overwrite_effect\",\n );\n\n for (const check of checks.sort(checkPriority)) {\n const expr = fastStringCheck(check, x, g.ctx);\n if (expr === null) return null;\n parts.push(expr);\n }\n\n // Refine effect checks (appended last — run after cheap checks short-circuit)\n for (const check of ir.checks) {\n if (check.kind === \"refine_effect\") {\n parts.push(fastRefineTest(check, x, g));\n } else if (check.kind === \"super_refine_effect\") {\n parts.push(superRefineFastTest(check, x, g));\n }\n }\n\n return parts.join(\"&&\");\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"template-literal.d.ts","names":[],"sources":["../../../../src/core/codegen/schemas/template-literal.ts"],"mappings":";;;iBAOgB,oBAAoB,IAAI,mBAAmB,GAAG;iBAyB9C,oBAAoB,IAAI,mBAAmB,GAAG"}
1
+ {"version":3,"file":"template-literal.d.ts","names":[],"sources":["../../../../src/core/codegen/schemas/template-literal.ts"],"mappings":";;;iBAOgB,oBAAoB,IAAI,mBAAmB,GAAG;iBAgC9C,oBAAoB,IAAI,mBAAmB,GAAG"}
@@ -10,7 +10,7 @@ function slowTemplateLiteral(ir, g) {
10
10
  if(typeof ${g.input}!=="string"){
11
11
  ${invalidType(g, "string")}
12
12
  }else if(!${regexVar}.test(${g.input})){
13
- ${invalidFormat(g, "template_literal", { extra: `pattern:${patternExpr}` })}
13
+ ${invalidFormat(g, "template_literal", { extra: `pattern:${patternExpr},continue:false` })}
14
14
  }`}\n`;
15
15
  }
16
16
  function fastTemplateLiteral(ir, g) {
@@ -1 +1 @@
1
- {"version":3,"file":"template-literal.js","names":[],"sources":["../../../../src/core/codegen/schemas/template-literal.ts"],"sourcesContent":["import type { TemplateLiteralIR } from \"../../types.js\";\nimport type { FastGen, SlowGen } from \"../context.js\";\nimport { emitConstant, escapeString } from \"../context.js\";\nimport { emit } from \"../emit.js\";\nimport { invalidFormat, invalidType } from \"../emit-issue.js\";\nimport { fastTestSource } from \"../well-known-regex.js\";\n\nexport function slowTemplateLiteral(ir: TemplateLiteralIR, g: SlowGen): string {\n const regexVar = g.regex(\"tl\", ir.pattern);\n // $ZodTemplateLiteral reports `pattern: inst._zod.pattern.source` — the BARE\n // source, with no enclosing slashes. That is the opposite of every string\n // FORMAT check, which zod reports as `def.pattern.toString()`; the shared\n // emitRegexSourceString helper (and its `<name>Src` virtual exports) produces\n // the slash-wrapped form for those, so it cannot serve this site.\n //\n // Same rewrite rule as slowString though: when emitRegex swapped in a faster\n // equivalent pattern, the runtime regex's own `.source` would leak the\n // rewrite, so the ORIGINAL source is emitted as a constant instead. IR\n // `pattern` IS a `.source` string (see extractTemplateLiteral), so it is\n // byte-identical to what zod reads.\n const patternExpr =\n fastTestSource(ir.pattern) === null\n ? `${regexVar}.source`\n : emitConstant(g.ctx, \"tls\", escapeString(ir.pattern));\n return `${emit`\n if(typeof ${g.input}!==\"string\"){\n ${invalidType(g, \"string\")}\n }else if(!${regexVar}.test(${g.input})){\n ${invalidFormat(g, \"template_literal\", { extra: `pattern:${patternExpr}` })}\n }`}\\n`;\n}\n\nexport function fastTemplateLiteral(ir: TemplateLiteralIR, g: FastGen): string | null {\n const regexVar = g.regex(\"tl\", ir.pattern);\n return `typeof ${g.input}===\"string\"&&${regexVar}.test(${g.input})`;\n}\n"],"mappings":";;;;;AAOA,SAAgB,oBAAoB,IAAuB,GAAoB;CAC7E,MAAM,WAAW,EAAE,MAAM,MAAM,GAAG,OAAO;CAYzC,MAAM,cACJ,eAAe,GAAG,OAAO,MAAM,OAC3B,GAAG,SAAS,WACZ,aAAa,EAAE,KAAK,OAAO,aAAa,GAAG,OAAO,CAAC;CACzD,OAAO,GAAG,IAAI;gBACA,EAAE,MAAM;QAChB,YAAY,GAAG,QAAQ,EAAE;gBACjB,SAAS,QAAQ,EAAE,MAAM;QACjC,cAAc,GAAG,oBAAoB,EAAE,OAAO,WAAW,cAAc,CAAC,EAAE;OAC3E;AACP;AAEA,SAAgB,oBAAoB,IAAuB,GAA2B;CACpF,MAAM,WAAW,EAAE,MAAM,MAAM,GAAG,OAAO;CACzC,OAAO,UAAU,EAAE,MAAM,eAAe,SAAS,QAAQ,EAAE,MAAM;AACnE"}
1
+ {"version":3,"file":"template-literal.js","names":[],"sources":["../../../../src/core/codegen/schemas/template-literal.ts"],"sourcesContent":["import type { TemplateLiteralIR } from \"../../types.js\";\nimport type { FastGen, SlowGen } from \"../context.js\";\nimport { emitConstant, escapeString } from \"../context.js\";\nimport { emit } from \"../emit.js\";\nimport { invalidFormat, invalidType } from \"../emit-issue.js\";\nimport { fastTestSource } from \"../well-known-regex.js\";\n\nexport function slowTemplateLiteral(ir: TemplateLiteralIR, g: SlowGen): string {\n const regexVar = g.regex(\"tl\", ir.pattern);\n // $ZodTemplateLiteral reports `pattern: inst._zod.pattern.source` — the BARE\n // source, with no enclosing slashes. That is the opposite of every string\n // FORMAT check, which zod reports as `def.pattern.toString()`; the shared\n // emitRegexSourceString helper (and its `<name>Src` virtual exports) produces\n // the slash-wrapped form for those, so it cannot serve this site.\n //\n // Same rewrite rule as slowString though: when emitRegex swapped in a faster\n // equivalent pattern, the runtime regex's own `.source` would leak the\n // rewrite, so the ORIGINAL source is emitted as a constant instead. IR\n // `pattern` IS a `.source` string (see extractTemplateLiteral), so it is\n // byte-identical to what zod reads.\n const patternExpr =\n fastTestSource(ir.pattern) === null\n ? `${regexVar}.source`\n : emitConstant(g.ctx, \"tls\", escapeString(ir.pattern));\n // The issue is pushed by the NODE (`$ZodTemplateLiteral._zod.parse`), not by\n // a `$ZodCheck`, so zod's carries no `continue: true` and `util.aborted`\n // counts it as aborting: a union option that fails only here goes inside\n // `invalid_union` rather than being surfaced as the sole non-aborted option,\n // and a container's `.refine()` does not run after it. Every other\n // `invalid_format` is check-raised and continuable, so the marker is set here\n // rather than in the shared factory; the finalizer deletes it, as zod's does.\n return `${emit`\n if(typeof ${g.input}!==\"string\"){\n ${invalidType(g, \"string\")}\n }else if(!${regexVar}.test(${g.input})){\n ${invalidFormat(g, \"template_literal\", { extra: `pattern:${patternExpr},continue:false` })}\n }`}\\n`;\n}\n\nexport function fastTemplateLiteral(ir: TemplateLiteralIR, g: FastGen): string | null {\n const regexVar = g.regex(\"tl\", ir.pattern);\n return `typeof ${g.input}===\"string\"&&${regexVar}.test(${g.input})`;\n}\n"],"mappings":";;;;;AAOA,SAAgB,oBAAoB,IAAuB,GAAoB;CAC7E,MAAM,WAAW,EAAE,MAAM,MAAM,GAAG,OAAO;CAYzC,MAAM,cACJ,eAAe,GAAG,OAAO,MAAM,OAC3B,GAAG,SAAS,WACZ,aAAa,EAAE,KAAK,OAAO,aAAa,GAAG,OAAO,CAAC;CAQzD,OAAO,GAAG,IAAI;gBACA,EAAE,MAAM;QAChB,YAAY,GAAG,QAAQ,EAAE;gBACjB,SAAS,QAAQ,EAAE,MAAM;QACjC,cAAc,GAAG,oBAAoB,EAAE,OAAO,WAAW,YAAY,iBAAiB,CAAC,EAAE;OAC1F;AACP;AAEA,SAAgB,oBAAoB,IAAuB,GAA2B;CACpF,MAAM,WAAW,EAAE,MAAM,MAAM,GAAG,OAAO;CACzC,OAAO,UAAU,EAAE,MAAM,eAAe,SAAS,QAAQ,EAAE,MAAM;AACnE"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/core/extract/index.ts"],"mappings":";;;;;;;;;iBAYgB,cAAc,oBAAoB,OAAO,aAAa"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/core/extract/index.ts"],"mappings":";;;;;;;;;iBAagB,cAAc,oBAAoB,OAAO,aAAa"}
@@ -1,3 +1,4 @@
1
+ import { assertSupportedZod } from "./zod-version.js";
1
2
  import { dispatch } from "./registry.js";
2
3
  //#region src/core/extract/index.ts
3
4
  /**
@@ -7,6 +8,7 @@ import { dispatch } from "./registry.js";
7
8
  * access paths for partial fallback (Zod delegation at runtime).
8
9
  */
9
10
  function extractSchema(zodSchema, refs) {
11
+ assertSupportedZod(zodSchema);
10
12
  return dispatch(zodSchema, "", refs, /* @__PURE__ */ new Set(), {
11
13
  root: zodSchema,
12
14
  targets: /* @__PURE__ */ new Map(),
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../src/core/extract/index.ts"],"sourcesContent":["import type { SchemaIR } from \"../types.js\";\nimport { dispatch } from \"./registry.js\";\nimport type { RecursionState, RefEntry } from \"./types.js\";\n\nexport type { RefEntry } from \"./types.js\";\n\n/**\n * Extract SchemaIR from a Zod schema by traversing its `_zod.def` and `_zod.bag`.\n *\n * When `fallbacks` is provided, non-compilable sub-schemas are collected with their\n * access paths for partial fallback (Zod delegation at runtime).\n */\nexport function extractSchema(zodSchema: unknown, refs?: RefEntry[]): SchemaIR {\n // Path, cycle-detection set, and recursion bookkeeping are internal to one\n // extraction — recursion re-enters through dispatch()/ctx.visit(), never back\n // through extractSchema — so they're always seeded fresh here.\n const rec: RecursionState = {\n root: zodSchema,\n targets: new Map<unknown, number>(),\n next: 1,\n };\n return dispatch(zodSchema, \"\", refs, new Set<unknown>(), rec);\n}\n"],"mappings":";;;;;;;;AAYA,SAAgB,cAAc,WAAoB,MAA6B;CAS7E,OAAO,SAAS,WAAW,IAAI,sBAAM,IAAI,IAAa,GAAG;EAJvD,MAAM;EACN,yBAAS,IAAI,IAAqB;EAClC,MAAM;CAEmD,CAAC;AAC9D"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../src/core/extract/index.ts"],"sourcesContent":["import type { SchemaIR } from \"../types.js\";\nimport { dispatch } from \"./registry.js\";\nimport type { RecursionState, RefEntry } from \"./types.js\";\nimport { assertSupportedZod } from \"./zod-version.js\";\n\nexport type { RefEntry } from \"./types.js\";\n\n/**\n * Extract SchemaIR from a Zod schema by traversing its `_zod.def` and `_zod.bag`.\n *\n * When `fallbacks` is provided, non-compilable sub-schemas are collected with their\n * access paths for partial fallback (Zod delegation at runtime).\n */\nexport function extractSchema(zodSchema: unknown, refs?: RefEntry[]): SchemaIR {\n // Refuse a zod whose semantics the emitted code does not reproduce (see\n // zod-version.ts). Once, at the root: every entry point reaches extraction\n // through here, and a schema's subtree comes from the same zod copy as its\n // root does.\n assertSupportedZod(zodSchema);\n // Path, cycle-detection set, and recursion bookkeeping are internal to one\n // extraction — recursion re-enters through dispatch()/ctx.visit(), never back\n // through extractSchema — so they're always seeded fresh here.\n const rec: RecursionState = {\n root: zodSchema,\n targets: new Map<unknown, number>(),\n next: 1,\n };\n return dispatch(zodSchema, \"\", refs, new Set<unknown>(), rec);\n}\n"],"mappings":";;;;;;;;;AAaA,SAAgB,cAAc,WAAoB,MAA6B;CAK7E,mBAAmB,SAAS;CAS5B,OAAO,SAAS,WAAW,IAAI,sBAAM,IAAI,IAAa,GAAG;EAJvD,MAAM;EACN,yBAAS,IAAI,IAAqB;EAClC,MAAM;CAEmD,CAAC;AAC9D"}
@@ -0,0 +1,78 @@
1
+ //#region src/core/extract/zod-version.d.ts
2
+ /**
3
+ * The zod release a schema was built by, and whether this compiler can stand
4
+ * in for it.
5
+ *
6
+ * Compiled validators reproduce zod 4.5's semantics byte-for-byte: the
7
+ * absent-key `expected: "nonoptional"` rule that 4.4 introduced, the
8
+ * code-point string lengths and tuple issue order of 4.5, the 4.5 format
9
+ * regexes. That fidelity is the contract, and it cuts both ways — a validator
10
+ * compiled here but installed on a schema from zod 4.3 accepts and rejects
11
+ * differently from the zod the application actually calls everywhere else,
12
+ * with nothing to say so. The peer range (`^4.5.0`) is meant to prevent that
13
+ * pairing, but only npm treats a violated peer range as an error; pnpm, yarn
14
+ * and bun warn and install anyway. This guard is the second line: one check at
15
+ * the root of extraction, which every entry point (CLI, build plugin, register
16
+ * hook, `jit()`) passes through, so an unsupported zod is refused with an
17
+ * explanation instead of compiled into subtly different validators.
18
+ *
19
+ * The version is read off the SCHEMA INSTANCE — `_zod.version`, which
20
+ * `$ZodType.init` stamps on every schema, classic and mini alike, since 4.0 —
21
+ * rather than off an imported zod module. A project can hold two zod copies
22
+ * (a hoisted one and a nested one, or a build-time and a runtime one), and the
23
+ * copy that built the schema is the one whose semantics its validator must
24
+ * match. A schema with no version at all is refused too: every zod 4 stamps
25
+ * one, so its absence means a zod older than this compiler has ever targeted.
26
+ * A value that is not a zod schema in the first place (no `_zod.def`) is not
27
+ * this guard's to judge — extraction reports it the way it always has, and
28
+ * calling it a version problem would send the user chasing the wrong fix.
29
+ */
30
+ /** Lowest zod release whose semantics the emitted validators reproduce. */
31
+ declare const MIN_ZOD_VERSION: {
32
+ readonly major: 4;
33
+ readonly minor: 5;
34
+ };
35
+ interface ZodVersion {
36
+ major: number;
37
+ minor: number;
38
+ patch: number;
39
+ }
40
+ /**
41
+ * `name` of the error {@link assertSupportedZod} throws. Matched by name, not
42
+ * by identity, so a second copy of this module in the graph still recognises it.
43
+ */
44
+ declare const UNSUPPORTED_ZOD_VERSION_ERROR = "UnsupportedZodVersionError";
45
+ /** The `_zod.version` a schema carries, or `undefined` when it has none (or is not a schema). */
46
+ declare function zodVersionOf(schema: unknown): ZodVersion | undefined;
47
+ /**
48
+ * Within the peer range: the same major, at or past the minimum minor. A
49
+ * hypothetical zod 5 is refused as well — its semantics are unknown here, and
50
+ * the promise is exactness, not best effort.
51
+ */
52
+ declare function isSupportedZodVersion(version: ZodVersion | undefined): boolean;
53
+ declare function unsupportedZodVersionMessage(version: ZodVersion | undefined): string;
54
+ /**
55
+ * Throw a recognisable error (see {@link isUnsupportedZodVersionError}) when
56
+ * `schema` is a zod schema from an unsupported zod. Anything that is not a zod
57
+ * schema at all passes through untouched, for the caller's own error path.
58
+ */
59
+ declare function assertSupportedZod(schema: unknown): void;
60
+ /**
61
+ * The predicate's target is deliberately narrower than `Error`: a caller that
62
+ * already holds an `Error` keeps it on the negative branch (a bare `error is
63
+ * Error` would leave `never` there).
64
+ */
65
+ declare function isUnsupportedZodVersionError(error: unknown): error is Error & {
66
+ name: typeof UNSUPPORTED_ZOD_VERSION_ERROR;
67
+ };
68
+ /**
69
+ * Print the refusal once per process. Every schema in an application fails the
70
+ * guard the same way, so one explanation is the useful amount — and the paths
71
+ * that call this (`jit()` at module scope, the plugin's per-export failure
72
+ * hook, the hoist compiler's catch-all) would otherwise either say nothing or
73
+ * say it once per export.
74
+ */
75
+ declare function warnUnsupportedZodOnce(message: string): void;
76
+ //#endregion
77
+ export { MIN_ZOD_VERSION, UNSUPPORTED_ZOD_VERSION_ERROR, ZodVersion, assertSupportedZod, isSupportedZodVersion, isUnsupportedZodVersionError, unsupportedZodVersionMessage, warnUnsupportedZodOnce, zodVersionOf };
78
+ //# sourceMappingURL=zod-version.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"zod-version.d.ts","names":[],"sources":["../../../src/core/extract/zod-version.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAgCa;WAAA;WAAA;;UAEI;EACf;EACA;EACA;;;;;;cAOW;;iBAGG,aAAa,kBAAkB;;;;;;iBAuB/B,sBAAsB,SAAS;iBAQ/B,6BAA6B,SAAS;;;;;;iBAoBtC,mBAAmB;;;;;;iBAcnB,6BACd,iBACC,SAAS;EAAU,aAAa;;;;;;;;;iBAcnB,uBAAuB"}
@@ -0,0 +1,109 @@
1
+ import { isZodSchema } from "../../is-zod-schema.js";
2
+ //#region src/core/extract/zod-version.ts
3
+ /**
4
+ * The zod release a schema was built by, and whether this compiler can stand
5
+ * in for it.
6
+ *
7
+ * Compiled validators reproduce zod 4.5's semantics byte-for-byte: the
8
+ * absent-key `expected: "nonoptional"` rule that 4.4 introduced, the
9
+ * code-point string lengths and tuple issue order of 4.5, the 4.5 format
10
+ * regexes. That fidelity is the contract, and it cuts both ways — a validator
11
+ * compiled here but installed on a schema from zod 4.3 accepts and rejects
12
+ * differently from the zod the application actually calls everywhere else,
13
+ * with nothing to say so. The peer range (`^4.5.0`) is meant to prevent that
14
+ * pairing, but only npm treats a violated peer range as an error; pnpm, yarn
15
+ * and bun warn and install anyway. This guard is the second line: one check at
16
+ * the root of extraction, which every entry point (CLI, build plugin, register
17
+ * hook, `jit()`) passes through, so an unsupported zod is refused with an
18
+ * explanation instead of compiled into subtly different validators.
19
+ *
20
+ * The version is read off the SCHEMA INSTANCE — `_zod.version`, which
21
+ * `$ZodType.init` stamps on every schema, classic and mini alike, since 4.0 —
22
+ * rather than off an imported zod module. A project can hold two zod copies
23
+ * (a hoisted one and a nested one, or a build-time and a runtime one), and the
24
+ * copy that built the schema is the one whose semantics its validator must
25
+ * match. A schema with no version at all is refused too: every zod 4 stamps
26
+ * one, so its absence means a zod older than this compiler has ever targeted.
27
+ * A value that is not a zod schema in the first place (no `_zod.def`) is not
28
+ * this guard's to judge — extraction reports it the way it always has, and
29
+ * calling it a version problem would send the user chasing the wrong fix.
30
+ */
31
+ /** Lowest zod release whose semantics the emitted validators reproduce. */
32
+ const MIN_ZOD_VERSION = {
33
+ major: 4,
34
+ minor: 5
35
+ };
36
+ /**
37
+ * `name` of the error {@link assertSupportedZod} throws. Matched by name, not
38
+ * by identity, so a second copy of this module in the graph still recognises it.
39
+ */
40
+ const UNSUPPORTED_ZOD_VERSION_ERROR = "UnsupportedZodVersionError";
41
+ /** The `_zod.version` a schema carries, or `undefined` when it has none (or is not a schema). */
42
+ function zodVersionOf(schema) {
43
+ if (typeof schema !== "object" || schema === null) return void 0;
44
+ try {
45
+ const internal = schema._zod;
46
+ if (typeof internal !== "object" || internal === null) return void 0;
47
+ const version = internal.version;
48
+ if (typeof version !== "object" || version === null) return void 0;
49
+ const { major, minor, patch } = version;
50
+ if (typeof major !== "number" || typeof minor !== "number" || typeof patch !== "number") return;
51
+ return {
52
+ major,
53
+ minor,
54
+ patch
55
+ };
56
+ } catch {
57
+ return;
58
+ }
59
+ }
60
+ /**
61
+ * Within the peer range: the same major, at or past the minimum minor. A
62
+ * hypothetical zod 5 is refused as well — its semantics are unknown here, and
63
+ * the promise is exactness, not best effort.
64
+ */
65
+ function isSupportedZodVersion(version) {
66
+ return version !== void 0 && version.major === MIN_ZOD_VERSION.major && version.minor >= MIN_ZOD_VERSION.minor;
67
+ }
68
+ function unsupportedZodVersionMessage(version) {
69
+ return `Unsupported zod version: this schema was built by ${version === void 0 ? "a zod that carries no _zod.version (older than 4.0, or not a zod schema)" : `zod ${version.major}.${version.minor}.${version.patch}`}, and this zod-compiler release requires zod ${`^${MIN_ZOD_VERSION.major}.${MIN_ZOD_VERSION.minor}.0`}. Compiled validators reproduce zod ${MIN_ZOD_VERSION.major}.${MIN_ZOD_VERSION.minor}'s semantics exactly (the absent-key \`expected: "nonoptional"\` rule, code-point string lengths, tuple issue order), so an older zod would accept and reject differently from the validator compiled for it. Upgrade zod to ${MIN_ZOD_VERSION.major}.${MIN_ZOD_VERSION.minor} or later, or stay on zod-compiler 1.x.`;
70
+ }
71
+ /**
72
+ * Throw a recognisable error (see {@link isUnsupportedZodVersionError}) when
73
+ * `schema` is a zod schema from an unsupported zod. Anything that is not a zod
74
+ * schema at all passes through untouched, for the caller's own error path.
75
+ */
76
+ function assertSupportedZod(schema) {
77
+ if (!isZodSchema(schema)) return;
78
+ const version = zodVersionOf(schema);
79
+ if (isSupportedZodVersion(version)) return;
80
+ const error = new Error(unsupportedZodVersionMessage(version));
81
+ error.name = UNSUPPORTED_ZOD_VERSION_ERROR;
82
+ throw error;
83
+ }
84
+ /**
85
+ * The predicate's target is deliberately narrower than `Error`: a caller that
86
+ * already holds an `Error` keeps it on the negative branch (a bare `error is
87
+ * Error` would leave `never` there).
88
+ */
89
+ function isUnsupportedZodVersionError(error) {
90
+ return error instanceof Error && error.name === "UnsupportedZodVersionError";
91
+ }
92
+ /** Messages already printed by {@link warnUnsupportedZodOnce}, per process. */
93
+ const warned = /* @__PURE__ */ new Set();
94
+ /**
95
+ * Print the refusal once per process. Every schema in an application fails the
96
+ * guard the same way, so one explanation is the useful amount — and the paths
97
+ * that call this (`jit()` at module scope, the plugin's per-export failure
98
+ * hook, the hoist compiler's catch-all) would otherwise either say nothing or
99
+ * say it once per export.
100
+ */
101
+ function warnUnsupportedZodOnce(message) {
102
+ if (warned.has(message)) return;
103
+ warned.add(message);
104
+ console.warn(`[zod-compiler] ${message}`);
105
+ }
106
+ //#endregion
107
+ export { MIN_ZOD_VERSION, UNSUPPORTED_ZOD_VERSION_ERROR, assertSupportedZod, isSupportedZodVersion, isUnsupportedZodVersionError, unsupportedZodVersionMessage, warnUnsupportedZodOnce, zodVersionOf };
108
+
109
+ //# sourceMappingURL=zod-version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"zod-version.js","names":[],"sources":["../../../src/core/extract/zod-version.ts"],"sourcesContent":["/**\n * The zod release a schema was built by, and whether this compiler can stand\n * in for it.\n *\n * Compiled validators reproduce zod 4.5's semantics byte-for-byte: the\n * absent-key `expected: \"nonoptional\"` rule that 4.4 introduced, the\n * code-point string lengths and tuple issue order of 4.5, the 4.5 format\n * regexes. That fidelity is the contract, and it cuts both ways — a validator\n * compiled here but installed on a schema from zod 4.3 accepts and rejects\n * differently from the zod the application actually calls everywhere else,\n * with nothing to say so. The peer range (`^4.5.0`) is meant to prevent that\n * pairing, but only npm treats a violated peer range as an error; pnpm, yarn\n * and bun warn and install anyway. This guard is the second line: one check at\n * the root of extraction, which every entry point (CLI, build plugin, register\n * hook, `jit()`) passes through, so an unsupported zod is refused with an\n * explanation instead of compiled into subtly different validators.\n *\n * The version is read off the SCHEMA INSTANCE — `_zod.version`, which\n * `$ZodType.init` stamps on every schema, classic and mini alike, since 4.0 —\n * rather than off an imported zod module. A project can hold two zod copies\n * (a hoisted one and a nested one, or a build-time and a runtime one), and the\n * copy that built the schema is the one whose semantics its validator must\n * match. A schema with no version at all is refused too: every zod 4 stamps\n * one, so its absence means a zod older than this compiler has ever targeted.\n * A value that is not a zod schema in the first place (no `_zod.def`) is not\n * this guard's to judge — extraction reports it the way it always has, and\n * calling it a version problem would send the user chasing the wrong fix.\n */\n\nimport { isZodSchema } from \"../../is-zod-schema.js\";\n\n/** Lowest zod release whose semantics the emitted validators reproduce. */\nexport const MIN_ZOD_VERSION = { major: 4, minor: 5 } as const;\n\nexport interface ZodVersion {\n major: number;\n minor: number;\n patch: number;\n}\n\n/**\n * `name` of the error {@link assertSupportedZod} throws. Matched by name, not\n * by identity, so a second copy of this module in the graph still recognises it.\n */\nexport const UNSUPPORTED_ZOD_VERSION_ERROR = \"UnsupportedZodVersionError\";\n\n/** The `_zod.version` a schema carries, or `undefined` when it has none (or is not a schema). */\nexport function zodVersionOf(schema: unknown): ZodVersion | undefined {\n if (typeof schema !== \"object\" || schema === null) return undefined;\n try {\n const internal = (schema as { _zod?: unknown })._zod;\n if (typeof internal !== \"object\" || internal === null) return undefined;\n const version = (internal as { version?: unknown }).version;\n if (typeof version !== \"object\" || version === null) return undefined;\n const { major, minor, patch } = version as Record<string, unknown>;\n if (typeof major !== \"number\" || typeof minor !== \"number\" || typeof patch !== \"number\") {\n return undefined;\n }\n return { major, minor, patch };\n } catch {\n // A Proxy trapping `get` — not a zod schema, and not one this can compile.\n return undefined;\n }\n}\n\n/**\n * Within the peer range: the same major, at or past the minimum minor. A\n * hypothetical zod 5 is refused as well — its semantics are unknown here, and\n * the promise is exactness, not best effort.\n */\nexport function isSupportedZodVersion(version: ZodVersion | undefined): boolean {\n return (\n version !== undefined &&\n version.major === MIN_ZOD_VERSION.major &&\n version.minor >= MIN_ZOD_VERSION.minor\n );\n}\n\nexport function unsupportedZodVersionMessage(version: ZodVersion | undefined): string {\n const found =\n version === undefined\n ? \"a zod that carries no _zod.version (older than 4.0, or not a zod schema)\"\n : `zod ${version.major}.${version.minor}.${version.patch}`;\n const required = `^${MIN_ZOD_VERSION.major}.${MIN_ZOD_VERSION.minor}.0`;\n return (\n `Unsupported zod version: this schema was built by ${found}, and this zod-compiler release requires zod ${required}. ` +\n `Compiled validators reproduce zod ${MIN_ZOD_VERSION.major}.${MIN_ZOD_VERSION.minor}'s semantics exactly ` +\n '(the absent-key `expected: \"nonoptional\"` rule, code-point string lengths, tuple issue order), ' +\n \"so an older zod would accept and reject differently from the validator compiled for it. \" +\n `Upgrade zod to ${MIN_ZOD_VERSION.major}.${MIN_ZOD_VERSION.minor} or later, or stay on zod-compiler 1.x.`\n );\n}\n\n/**\n * Throw a recognisable error (see {@link isUnsupportedZodVersionError}) when\n * `schema` is a zod schema from an unsupported zod. Anything that is not a zod\n * schema at all passes through untouched, for the caller's own error path.\n */\nexport function assertSupportedZod(schema: unknown): void {\n if (!isZodSchema(schema)) return;\n const version = zodVersionOf(schema);\n if (isSupportedZodVersion(version)) return;\n const error = new Error(unsupportedZodVersionMessage(version));\n error.name = UNSUPPORTED_ZOD_VERSION_ERROR;\n throw error;\n}\n\n/**\n * The predicate's target is deliberately narrower than `Error`: a caller that\n * already holds an `Error` keeps it on the negative branch (a bare `error is\n * Error` would leave `never` there).\n */\nexport function isUnsupportedZodVersionError(\n error: unknown,\n): error is Error & { name: typeof UNSUPPORTED_ZOD_VERSION_ERROR } {\n return error instanceof Error && error.name === UNSUPPORTED_ZOD_VERSION_ERROR;\n}\n\n/** Messages already printed by {@link warnUnsupportedZodOnce}, per process. */\nconst warned = new Set<string>();\n\n/**\n * Print the refusal once per process. Every schema in an application fails the\n * guard the same way, so one explanation is the useful amount — and the paths\n * that call this (`jit()` at module scope, the plugin's per-export failure\n * hook, the hoist compiler's catch-all) would otherwise either say nothing or\n * say it once per export.\n */\nexport function warnUnsupportedZodOnce(message: string): void {\n if (warned.has(message)) return;\n warned.add(message);\n // oxlint-disable-next-line no-console -- being heard is the point\n console.warn(`[zod-compiler] ${message}`);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCA,MAAa,kBAAkB;CAAE,OAAO;CAAG,OAAO;AAAE;;;;;AAYpD,MAAa,gCAAgC;;AAG7C,SAAgB,aAAa,QAAyC;CACpE,IAAI,OAAO,WAAW,YAAY,WAAW,MAAM,OAAO,KAAA;CAC1D,IAAI;EACF,MAAM,WAAY,OAA8B;EAChD,IAAI,OAAO,aAAa,YAAY,aAAa,MAAM,OAAO,KAAA;EAC9D,MAAM,UAAW,SAAmC;EACpD,IAAI,OAAO,YAAY,YAAY,YAAY,MAAM,OAAO,KAAA;EAC5D,MAAM,EAAE,OAAO,OAAO,UAAU;EAChC,IAAI,OAAO,UAAU,YAAY,OAAO,UAAU,YAAY,OAAO,UAAU,UAC7E;EAEF,OAAO;GAAE;GAAO;GAAO;EAAM;CAC/B,QAAQ;EAEN;CACF;AACF;;;;;;AAOA,SAAgB,sBAAsB,SAA0C;CAC9E,OACE,YAAY,KAAA,KACZ,QAAQ,UAAU,gBAAgB,SAClC,QAAQ,SAAS,gBAAgB;AAErC;AAEA,SAAgB,6BAA6B,SAAyC;CAMpF,OACE,qDALA,YAAY,KAAA,IACR,6EACA,OAAO,QAAQ,MAAM,GAAG,QAAQ,MAAM,GAAG,QAAQ,QAGM,+CAA+C,IAFvF,gBAAgB,MAAM,GAAG,gBAAgB,MAAM,IAEiD,sCAC9E,gBAAgB,MAAM,GAAG,gBAAgB,MAAM,+NAGlE,gBAAgB,MAAM,GAAG,gBAAgB,MAAM;AAErE;;;;;;AAOA,SAAgB,mBAAmB,QAAuB;CACxD,IAAI,CAAC,YAAY,MAAM,GAAG;CAC1B,MAAM,UAAU,aAAa,MAAM;CACnC,IAAI,sBAAsB,OAAO,GAAG;CACpC,MAAM,QAAQ,IAAI,MAAM,6BAA6B,OAAO,CAAC;CAC7D,MAAM,OAAO;CACb,MAAM;AACR;;;;;;AAOA,SAAgB,6BACd,OACiE;CACjE,OAAO,iBAAiB,SAAS,MAAM,SAAA;AACzC;;AAGA,MAAM,yBAAS,IAAI,IAAY;;;;;;;;AAS/B,SAAgB,uBAAuB,SAAuB;CAC5D,IAAI,OAAO,IAAI,OAAO,GAAG;CACzB,OAAO,IAAI,OAAO;CAElB,QAAQ,KAAK,kBAAkB,SAAS;AAC1C"}
package/dist/jit.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"jit.d.ts","names":[],"sources":["../src/jit.ts"],"mappings":";;;UAoFiB;;;;;;;EAOf;;EAEA;;;;;;;;;;;;;;;;;;;;;;;iBAwBc,IAAI,UAAU,SAC5B,QAAQ,GACR,UAAU,aACT,IAAI,eAAe,OAAO;;;;;;;;;;;;;;iBAoNb,OAAO,iBAAiB,UAAU"}
1
+ {"version":3,"file":"jit.d.ts","names":[],"sources":["../src/jit.ts"],"mappings":";;;UA2FiB;;;;;;;EAOf;;EAEA;;;;;;;;;;;;;;;;;;;;;;;iBAwBc,IAAI,UAAU,SAC5B,QAAQ,GACR,UAAU,aACT,IAAI,eAAe,OAAO;;;;;;;;;;;;;;iBAiOb,OAAO,iBAAiB,UAAU"}
package/dist/jit.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { isZodSchema } from "./is-zod-schema.js";
2
2
  import { FAILZ_CLASS_DECL, FAIL_CLASS_DECL, FINZ_DECL, FIN_DECL, FIN_DEFERRED_DECL, MK_VALIDATOR_DECL, ZOD_MSG_DECLARATION, generateIIFE } from "./core/iife.js";
3
+ import { isSupportedZodVersion, isUnsupportedZodVersionError, unsupportedZodVersionMessage, warnUnsupportedZodOnce, zodVersionOf } from "./core/extract/zod-version.js";
3
4
  import { compileSchemas } from "./core/pipeline.js";
4
5
  import { ZodRealError, config, core } from "zod";
5
6
  //#region src/jit.ts
@@ -99,6 +100,11 @@ const seen = /* @__PURE__ */ new WeakSet();
99
100
  function jit(schema, options) {
100
101
  const target = schema;
101
102
  if (seen.has(target)) return schema;
103
+ const version = zodVersionOf(schema);
104
+ if (isZodSchema(schema) && !isSupportedZodVersion(version)) {
105
+ warnUnsupportedZodOnce(unsupportedZodVersionMessage(version));
106
+ return schema;
107
+ }
102
108
  seen.add(target);
103
109
  if (options?.eager === true) {
104
110
  materialize(schema, options);
@@ -258,7 +264,9 @@ function materialize(schema, options) {
258
264
  if (!codegenAllowed()) return;
259
265
  try {
260
266
  buildValidator(schema, options);
261
- } catch {}
267
+ } catch (error) {
268
+ if (isUnsupportedZodVersionError(error)) warnUnsupportedZodOnce(error.message);
269
+ }
262
270
  }
263
271
  /**
264
272
  * Generate the validator and evaluate it, reproducing the module a
package/dist/jit.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"jit.js","names":["zodCore","zodConfig"],"sources":["../src/jit.ts"],"sourcesContent":["/**\n * Runtime compilation — the same extract → codegen pipeline the build plugin\n * runs, executed in-process and evaluated through `new Function`.\n *\n * The AOT paths (unplugin, CLI) need a build step to fire. Plenty of everyday\n * code has none: `tsx server.ts`, `node --experimental-strip-types`, a Jest\n * suite, a serverless handler bundled by someone else's toolchain, a library\n * that ships schemas to consumers. There `compile()` is a no-op and every parse\n * runs plain Zod. `jit()` closes that gap — one call, no build integration,\n * measured 3-25x on everyday schemas at ~0.1-0.2 ms of one-time compilation.\n *\n * Nothing here re-implements validation: {@link compileSchemas} and\n * {@link generateIIFE} are the exact modules the plugin and CLI use, so the\n * generated validator, its Zod parity and its performance are identical to what\n * a build would have emitted. The only difference is *when* the code is\n * produced.\n *\n * Compilation is LAZY by default: `jit()` installs accessors that compile on\n * the first read of a parse method and replace themselves with the compiled\n * ones. Importing a module of 500 schemas therefore costs nothing, and a\n * serverless invocation touching three of them pays for three.\n *\n * Zod itself keeps the parse methods on the PROTOTYPE (since 4.4): each is a\n * getter that binds the method on first read and installs the bound copy as an\n * own data property, so a fresh schema carries no own `parse` / `safeParse` at\n * all, while one that has been read already does. `jit()` meets both shapes —\n * it snapshots whatever the slots hold, fronts them with its own accessors, and\n * hands back exactly what it found whenever it has to step aside.\n *\n * Runtime code generation is not always permitted — a strict CSP without\n * `unsafe-eval`, some edge runtimes. Zod v4 has the same constraint (its object\n * fast-pass is itself a `new Function`) and already exposes the two switches\n * for it: the `core.util.allowsEval` probe and `z.config({ jitless: true })`.\n * `jit()` honours both and degrades to plain Zod, so one setting governs both\n * compilers. Those targets are where the build plugin belongs anyway — it emits\n * the same validator with no runtime evaluation at all.\n */\n\nimport { config as zodConfig, core as zodCore, ZodRealError, type output, type ZodType } from \"zod\";\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_MSG_DECLARATION,\n} from \"./core/iife.js\";\nimport { compileSchemas } from \"./core/pipeline.js\";\nimport type { CompiledSchema } from \"./core/types.js\";\nimport { isZodSchema } from \"./is-zod-schema.js\";\n\n/**\n * The declarations `ZOD_CONFIG_IMPORT` supplies to an emitted module, minus the\n * import itself — `zod`'s three bindings arrive as parameters instead, so the\n * evaluated code has no module scope to resolve. Byte-for-byte the same helper\n * source the CLI emitter writes into a `.compiled.ts`, so a JIT validator and\n * an AOT one share their entire runtime layer.\n */\nconst RUNTIME_PRELUDE = [\n ZOD_MSG_DECLARATION,\n FAIL_CLASS_DECL,\n MK_VALIDATOR_DECL,\n FIN_DECL,\n FIN_DEFERRED_DECL,\n FAILZ_CLASS_DECL,\n FINZ_DECL,\n].join(\"\\n\");\n\n/**\n * Methods `__zcMkv` installs. Each is fronted by a compile-on-read accessor\n * until the schema materializes.\n *\n * `~standard` earns its place: Zod builds it as a closure over `_zod.run`, not\n * over the schema's `safeParse` property, so a Standard Schema consumer (tRPC,\n * Hono, TanStack Form) that never touches `safeParse` would otherwise keep\n * running plain Zod forever behind a \"compiled\" schema.\n */\nconst SLOTS = [\"parse\", \"safeParse\", \"parseAsync\", \"safeParseAsync\", \"is\", \"~standard\"] as const;\n\n/** Schemas already handed to `jit()`, so a second call is a no-op rather than a recompile. */\nconst seen = new WeakSet<object>();\n\nexport interface JitOptions {\n /**\n * Compile immediately instead of on first use. Costs ~0.1-0.2 ms per schema\n * at import time; useful for a long-lived server that would rather pay during\n * startup than on the first request, or to surface a compilation failure\n * eagerly. Default `false`.\n */\n eager?: boolean | undefined;\n /** Use compact codegen and delegate cold error production to Zod. @default \"schema\" */\n output?: \"schema\" | \"compact\" | undefined;\n}\n\n/**\n * Compile `schema` in-process and install the compiled `parse` / `safeParse` /\n * `parseAsync` / `safeParseAsync` / `is` / `~standard` on it.\n *\n * Returns the SAME object — identity-preserving exactly as the build plugin is,\n * so `.shape`, `_zod`, `instanceof`, `z.toJSONSchema()`, `.meta()` and\n * composition into a larger schema all keep working, and every existing\n * reference to the schema picks the compiled methods up.\n *\n * ```ts\n * import { z } from \"zod\";\n * import { jit } from \"zod-compiler/jit\";\n *\n * export const UserSchema = jit(z.object({ name: z.string(), email: z.email() }));\n * UserSchema.safeParse(input); // compiled on this first call\n * ```\n *\n * Schemas the compiler cannot reproduce fall back to Zod per sub-schema, the\n * same way they do at build time; a schema that cannot be compiled at all is\n * left as plain Zod.\n */\nexport function jit<T extends ZodType>(\n schema: T,\n options?: JitOptions,\n): T & CompiledSchema<output<T>> {\n const target = schema as unknown as Record<string, unknown>;\n if (seen.has(target)) return schema as T & CompiledSchema<output<T>>;\n seen.add(target);\n\n if (options?.eager === true) {\n materialize(schema, options);\n return schema as T & CompiledSchema<output<T>>;\n }\n\n // Snapshot what each slot holds before anything is installed: materialize()\n // restores it before handing the object to `__zcMkv`, so the generated code\n // sees a pristine schema — it captures the original `parseAsync` /\n // `safeParseAsync` as its throw paths, and capturing a stub there would loop\n // back into itself. An untouched schema holds NOTHING here: Zod keeps the\n // methods on the prototype and only installs a bound own copy on first read,\n // so `undefined` is the common entry and means \"back to the prototype\". A\n // schema that was read before `jit()` — or that the build plugin's `__zcMkv`\n // already materialized — carries the copies, and those go back verbatim.\n const original = new Map<string, PropertyDescriptor | undefined>();\n try {\n for (const slot of SLOTS) {\n original.set(slot, Object.getOwnPropertyDescriptor(target, slot));\n }\n } catch {\n // The target answers a descriptor query with a throw — an exotic wrapper,\n // not anything Zod built. Without a snapshot there is nothing to roll back\n // to, so install nothing and hand back the schema exactly as it came.\n return schema as T & CompiledSchema<output<T>>;\n }\n\n // Installing the accessors is the step most likely to throw rather than\n // degrade: a slot locked non-configurable (a future Zod, another wrapper) makes\n // defineProperty raise, and `jit()` is called at module scope — so an\n // unhandled throw here takes down the importing app at boot. Roll back to\n // whatever Zod had and leave the schema alone instead.\n let pending = true;\n try {\n installAccessors(\n target,\n original,\n () => {\n if (!pending) return;\n pending = false;\n restore(target, original);\n materialize(schema, options);\n },\n () => {\n if (!pending) return;\n pending = false;\n // Restore EVERY slot, not just the one being written. A left-behind\n // accessor whose trigger has been cancelled would read `target[slot]`\n // and re-enter itself — unbounded recursion, which is what a later read\n // of an untouched slot (`~standard`, from a Standard Schema consumer)\n // would otherwise hit.\n //\n // Reached only when something WRITES a slot before anything reads one: a\n // test double, another wrapper, or an AOT `safeParse` assigned directly.\n // The build plugin's own `__zcMkv` does not land here — its first\n // statement READS `parseAsync`/`safeParseAsync` to capture their\n // originals, so it triggers materialization and then overwrites the\n // compiled-by-jit methods with the compiled-by-plugin ones.\n restore(target, original);\n },\n );\n } catch {\n pending = false;\n restore(target, original);\n }\n\n return schema as T & CompiledSchema<output<T>>;\n}\n\n/**\n * Front every installed method with a compile-on-read accessor. `trigger`\n * materializes the schema, which normally replaces these accessors with the\n * compiled methods (or restores what Zod had). When that replacement does not\n * take, the getter serves Zod's own method rather than re-reading the slot —\n * see the re-entrancy note in the body.\n */\nfunction installAccessors(\n target: Record<string, unknown>,\n original: ReadonlyMap<string, PropertyDescriptor | undefined>,\n trigger: () => void,\n cancel: () => void,\n): void {\n for (const slot of SLOTS) {\n // Re-entrancy is settled structurally rather than by inspection. Reading the\n // slot again is how this getter normally hands over — to the compiled method\n // materialize() installed, or to whatever restore() put back — but the\n // handover can fail to take: a target frozen after `jit()` refuses both, and\n // a second copy of this module in the graph leaves ITS accessor on the slot,\n // so the two bounce reads between them. `trigger()` is spent by then, so\n // either way the read recurses until the stack blows. While a read is already\n // in flight, or once the accessor is known to be stranded, serve Zod's own\n // method instead: a schema that cannot be compiled still parses.\n let reading = false;\n // A stranded accessor is permanent, so what it serves is resolved once.\n let stranded: { value: unknown } | undefined;\n const serveZod = (): unknown => {\n stranded ??= { value: fromZod(target, original, slot) };\n return stranded.value;\n };\n const read = function (): unknown {\n if (reading) return serveZod();\n reading = true;\n try {\n trigger();\n if (stillFrontedBy(target, slot, read)) return serveZod();\n return target[slot];\n } finally {\n reading = false;\n }\n };\n Object.defineProperty(target, slot, {\n configurable: true,\n // Keep the schema's own-key set as it was. A slot Zod already materialized\n // is an enumerable own copy, so the accessor fronting it is enumerable too;\n // an untouched slot has no own key at all, and `is` never exists on a Zod\n // schema, so those stay out of `Object.keys` — the non-enumerable\n // convention `compile()` already uses.\n enumerable: original.get(slot)?.enumerable ?? false,\n get: read,\n set(value: unknown) {\n // Someone overwrote a method before first use (a test double, another\n // wrapper). Their value wins, and compilation is cancelled outright —\n // materializing later would restore the snapshot over it. With the\n // accessor gone the write does what it would have without `jit()`:\n // overwrite the own copy, or run Zod's prototype setter, which installs\n // one. Only a target that refused the rollback still routes here, and a\n // direct define is the one way left to honour the write.\n cancel();\n if (!stillFrontedBy(target, slot, read)) {\n target[slot] = value;\n return;\n }\n Object.defineProperty(target, slot, {\n configurable: true,\n enumerable: original.get(slot)?.enumerable ?? false,\n value,\n writable: true,\n });\n },\n });\n }\n}\n\n/**\n * Is `slot` still fronted by this very accessor — i.e. did the replacement that\n * `trigger()` was supposed to perform not take? A target that will not answer\n * the question is assumed to still hold it, since reading the slot to find out\n * is the recursion being avoided.\n */\nfunction stillFrontedBy(\n target: Record<string, unknown>,\n slot: string,\n getter: () => unknown,\n): boolean {\n try {\n return Object.getOwnPropertyDescriptor(target, slot)?.get === getter;\n } catch {\n return true;\n }\n}\n\n/**\n * Zod's own value for `slot`, bypassing the accessor that fronts it.\n *\n * A slot the snapshot holds is answered from the snapshot. One it does not hold\n * lives on the prototype, where Zod's getter binds the method to its receiver\n * and installs the bound copy as an own property — on a target that accepts\n * the install, that also replaces the stranded accessor with the copy, which is\n * the handover materialize() could not make. A target that refuses the install\n * (frozen, or a wrapper that vetoes `defineProperty`) makes Zod's getter throw\n * instead; there the read goes through a stand-in that inherits from the target,\n * so the copy lands on the stand-in and the method reaches `_zod` through the\n * chain. `undefined` for `is`, which no plain Zod schema carries — the same\n * thing every other degradation path leaves there.\n */\nfunction fromZod(\n target: Record<string, unknown>,\n original: ReadonlyMap<string, PropertyDescriptor | undefined>,\n slot: string,\n): unknown {\n const descriptor = original.get(slot);\n if (descriptor !== undefined) {\n // A snapshot can hold another accessor (a second copy of this module\n // installed first), so invoke it rather than reading a `value` it lacks.\n return descriptor.get === undefined ? descriptor.value : descriptor.get.call(target);\n }\n const proto = Object.getPrototypeOf(target) as object | null;\n if (proto === null) return undefined;\n try {\n return Reflect.get(proto, slot, target);\n } catch {\n return Reflect.get(proto, slot, Object.create(target));\n }\n}\n\n/**\n * Compile every Zod schema found among an object's own values — typically a\n * module namespace, so a whole schema file opts in with one call:\n *\n * ```ts\n * import * as schemas from \"./schemas.js\";\n * jitAll(schemas);\n * ```\n *\n * The namespace object itself is never written to (a module namespace is\n * read-only); `jit()` mutates the schema objects it holds, which is what every\n * importer of that module already references.\n */\nexport function jitAll(schemas: object, options?: JitOptions): void {\n for (const value of Object.values(schemas)) {\n if (isZodSchema(value)) jit(value, options);\n }\n}\n\n/**\n * Put back what the snapshot holds, dropping the compile-on-read accessors: the\n * own copy Zod (or the build plugin) had installed, or nothing at all, so the\n * slot reads through to Zod's prototype getter again.\n */\nfunction restore(\n target: Record<string, unknown>,\n original: ReadonlyMap<string, PropertyDescriptor | undefined>,\n): void {\n for (const slot of SLOTS) {\n // Per slot, because this also runs as the rollback for a failed install: a\n // target that refuses one slot must not cost the others their restoration.\n // A slot left fronted by its accessor still reads correctly — the getter\n // serves Zod's own method — but it keeps a redundant indirection, so\n // restoring what can be restored is worth the try/catch.\n try {\n const descriptor = original.get(slot);\n if (descriptor === undefined) delete target[slot];\n else Object.defineProperty(target, slot, descriptor);\n } catch {\n // Nothing further to try for this slot.\n }\n }\n}\n\n/**\n * Whether runtime code generation is permitted here. Read per call, never\n * snapshotted: `z.config({ jitless: true })` runs in an entry point, after the\n * schema modules it imports have already been evaluated.\n */\nfunction codegenAllowed(): boolean {\n return zodCore.globalConfig.jitless !== true && zodCore.util.allowsEval.value;\n}\n\n/**\n * Run the pipeline and let the generated IIFE install its methods on `schema`.\n * Swallows failure: a schema that cannot be compiled keeps Zod's own methods,\n * which the caller already has, so there is nothing to report and nothing to\n * break.\n */\nfunction materialize(schema: unknown, options?: JitOptions): void {\n if (!codegenAllowed()) return;\n try {\n buildValidator(schema, options);\n } catch {\n // Left as plain Zod. Deliberately silent: `jit()` is an optimization, and a\n // schema using a construct the compiler declines is a supported outcome,\n // not an error.\n }\n}\n\n/**\n * Generate the validator and evaluate it, reproducing the module a\n * `.compiled.ts` would have been: helper preamble, the file-level shared block,\n * then the `__zcMkv` IIFE whose `__rf[]` bases and install target are the live\n * schema object passed in as `__schema`.\n */\nfunction buildValidator(schema: unknown, options?: JitOptions): void {\n const { schemas, shared } = compileSchemas([{ exportName: \"jit\", schema }], {\n compact: options?.output === \"compact\",\n mode: \"inline\",\n });\n const compiled = schemas[0];\n if (compiled === undefined) throw new Error(\"zod-compiler: schema produced no validator\");\n\n const body = [RUNTIME_PRELUDE, shared.code, `return ${generateIIFE(\"__schema\", compiled)};`].join(\n \"\\n\",\n );\n\n // The three bindings ZOD_CONFIG_IMPORT would have imported, passed in so the\n // evaluated code needs no module resolution of its own.\n // oxlint-disable-next-line no-new-func -- generating the validator IS the feature\n const factory = new Function(\n \"__zodCompilerConfig\",\n \"__zcCore\",\n \"__zcZodError\",\n \"__schema\",\n body,\n ) as (\n zodConfigFn: typeof zodConfig,\n zodCoreNs: typeof zodCore,\n zodErrorCtor: typeof ZodRealError,\n target: unknown,\n ) => unknown;\n\n factory(zodConfig, zodCore, ZodRealError, schema);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"jit.js","names":["zodCore","zodConfig"],"sources":["../src/jit.ts"],"sourcesContent":["/**\n * Runtime compilation — the same extract → codegen pipeline the build plugin\n * runs, executed in-process and evaluated through `new Function`.\n *\n * The AOT paths (unplugin, CLI) need a build step to fire. Plenty of everyday\n * code has none: `tsx server.ts`, `node --experimental-strip-types`, a Jest\n * suite, a serverless handler bundled by someone else's toolchain, a library\n * that ships schemas to consumers. There `compile()` is a no-op and every parse\n * runs plain Zod. `jit()` closes that gap — one call, no build integration,\n * measured 3-25x on everyday schemas at ~0.1-0.2 ms of one-time compilation.\n *\n * Nothing here re-implements validation: {@link compileSchemas} and\n * {@link generateIIFE} are the exact modules the plugin and CLI use, so the\n * generated validator, its Zod parity and its performance are identical to what\n * a build would have emitted. The only difference is *when* the code is\n * produced.\n *\n * Compilation is LAZY by default: `jit()` installs accessors that compile on\n * the first read of a parse method and replace themselves with the compiled\n * ones. Importing a module of 500 schemas therefore costs nothing, and a\n * serverless invocation touching three of them pays for three.\n *\n * Zod itself keeps the parse methods on the PROTOTYPE (since 4.4): each is a\n * getter that binds the method on first read and installs the bound copy as an\n * own data property, so a fresh schema carries no own `parse` / `safeParse` at\n * all, while one that has been read already does. `jit()` meets both shapes —\n * it snapshots whatever the slots hold, fronts them with its own accessors, and\n * hands back exactly what it found whenever it has to step aside.\n *\n * Runtime code generation is not always permitted — a strict CSP without\n * `unsafe-eval`, some edge runtimes. Zod v4 has the same constraint (its object\n * fast-pass is itself a `new Function`) and already exposes the two switches\n * for it: the `core.util.allowsEval` probe and `z.config({ jitless: true })`.\n * `jit()` honours both and degrades to plain Zod, so one setting governs both\n * compilers. Those targets are where the build plugin belongs anyway — it emits\n * the same validator with no runtime evaluation at all.\n */\n\nimport { config as zodConfig, core as zodCore, ZodRealError, type output, type ZodType } from \"zod\";\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_MSG_DECLARATION,\n} from \"./core/iife.js\";\nimport {\n isSupportedZodVersion,\n isUnsupportedZodVersionError,\n unsupportedZodVersionMessage,\n warnUnsupportedZodOnce,\n zodVersionOf,\n} from \"./core/extract/zod-version.js\";\nimport { compileSchemas } from \"./core/pipeline.js\";\nimport type { CompiledSchema } from \"./core/types.js\";\nimport { isZodSchema } from \"./is-zod-schema.js\";\n\n/**\n * The declarations `ZOD_CONFIG_IMPORT` supplies to an emitted module, minus the\n * import itself — `zod`'s three bindings arrive as parameters instead, so the\n * evaluated code has no module scope to resolve. Byte-for-byte the same helper\n * source the CLI emitter writes into a `.compiled.ts`, so a JIT validator and\n * an AOT one share their entire runtime layer.\n */\nconst RUNTIME_PRELUDE = [\n ZOD_MSG_DECLARATION,\n FAIL_CLASS_DECL,\n MK_VALIDATOR_DECL,\n FIN_DECL,\n FIN_DEFERRED_DECL,\n FAILZ_CLASS_DECL,\n FINZ_DECL,\n].join(\"\\n\");\n\n/**\n * Methods `__zcMkv` installs. Each is fronted by a compile-on-read accessor\n * until the schema materializes.\n *\n * `~standard` earns its place: Zod builds it as a closure over `_zod.run`, not\n * over the schema's `safeParse` property, so a Standard Schema consumer (tRPC,\n * Hono, TanStack Form) that never touches `safeParse` would otherwise keep\n * running plain Zod forever behind a \"compiled\" schema.\n */\nconst SLOTS = [\"parse\", \"safeParse\", \"parseAsync\", \"safeParseAsync\", \"is\", \"~standard\"] as const;\n\n/** Schemas already handed to `jit()`, so a second call is a no-op rather than a recompile. */\nconst seen = new WeakSet<object>();\n\nexport interface JitOptions {\n /**\n * Compile immediately instead of on first use. Costs ~0.1-0.2 ms per schema\n * at import time; useful for a long-lived server that would rather pay during\n * startup than on the first request, or to surface a compilation failure\n * eagerly. Default `false`.\n */\n eager?: boolean | undefined;\n /** Use compact codegen and delegate cold error production to Zod. @default \"schema\" */\n output?: \"schema\" | \"compact\" | undefined;\n}\n\n/**\n * Compile `schema` in-process and install the compiled `parse` / `safeParse` /\n * `parseAsync` / `safeParseAsync` / `is` / `~standard` on it.\n *\n * Returns the SAME object — identity-preserving exactly as the build plugin is,\n * so `.shape`, `_zod`, `instanceof`, `z.toJSONSchema()`, `.meta()` and\n * composition into a larger schema all keep working, and every existing\n * reference to the schema picks the compiled methods up.\n *\n * ```ts\n * import { z } from \"zod\";\n * import { jit } from \"zod-compiler/jit\";\n *\n * export const UserSchema = jit(z.object({ name: z.string(), email: z.email() }));\n * UserSchema.safeParse(input); // compiled on this first call\n * ```\n *\n * Schemas the compiler cannot reproduce fall back to Zod per sub-schema, the\n * same way they do at build time; a schema that cannot be compiled at all is\n * left as plain Zod.\n */\nexport function jit<T extends ZodType>(\n schema: T,\n options?: JitOptions,\n): T & CompiledSchema<output<T>> {\n const target = schema as unknown as Record<string, unknown>;\n if (seen.has(target)) return schema as T & CompiledSchema<output<T>>;\n\n // A schema built by a zod this release does not reproduce is left as plain\n // Zod — correct, just not faster — and said so once (see zod-version.ts).\n // Not thrown: `jit()` runs at module scope, where a throw takes the importing\n // app down at boot over what is a dependency-range problem. Checked before\n // anything is installed, so neither the eager path nor a later\n // compile-on-read accessor can reach the pipeline for it. A value that is not\n // a zod schema at all is not a version problem and takes the usual route.\n const version = zodVersionOf(schema);\n if (isZodSchema(schema) && !isSupportedZodVersion(version)) {\n warnUnsupportedZodOnce(unsupportedZodVersionMessage(version));\n return schema as T & CompiledSchema<output<T>>;\n }\n seen.add(target);\n\n if (options?.eager === true) {\n materialize(schema, options);\n return schema as T & CompiledSchema<output<T>>;\n }\n\n // Snapshot what each slot holds before anything is installed: materialize()\n // restores it before handing the object to `__zcMkv`, so the generated code\n // sees a pristine schema — it captures the original `parseAsync` /\n // `safeParseAsync` as its throw paths, and capturing a stub there would loop\n // back into itself. An untouched schema holds NOTHING here: Zod keeps the\n // methods on the prototype and only installs a bound own copy on first read,\n // so `undefined` is the common entry and means \"back to the prototype\". A\n // schema that was read before `jit()` — or that the build plugin's `__zcMkv`\n // already materialized — carries the copies, and those go back verbatim.\n const original = new Map<string, PropertyDescriptor | undefined>();\n try {\n for (const slot of SLOTS) {\n original.set(slot, Object.getOwnPropertyDescriptor(target, slot));\n }\n } catch {\n // The target answers a descriptor query with a throw — an exotic wrapper,\n // not anything Zod built. Without a snapshot there is nothing to roll back\n // to, so install nothing and hand back the schema exactly as it came.\n return schema as T & CompiledSchema<output<T>>;\n }\n\n // Installing the accessors is the step most likely to throw rather than\n // degrade: a slot locked non-configurable (a future Zod, another wrapper) makes\n // defineProperty raise, and `jit()` is called at module scope — so an\n // unhandled throw here takes down the importing app at boot. Roll back to\n // whatever Zod had and leave the schema alone instead.\n let pending = true;\n try {\n installAccessors(\n target,\n original,\n () => {\n if (!pending) return;\n pending = false;\n restore(target, original);\n materialize(schema, options);\n },\n () => {\n if (!pending) return;\n pending = false;\n // Restore EVERY slot, not just the one being written. A left-behind\n // accessor whose trigger has been cancelled would read `target[slot]`\n // and re-enter itself — unbounded recursion, which is what a later read\n // of an untouched slot (`~standard`, from a Standard Schema consumer)\n // would otherwise hit.\n //\n // Reached only when something WRITES a slot before anything reads one: a\n // test double, another wrapper, or an AOT `safeParse` assigned directly.\n // The build plugin's own `__zcMkv` does not land here — its first\n // statement READS `parseAsync`/`safeParseAsync` to capture their\n // originals, so it triggers materialization and then overwrites the\n // compiled-by-jit methods with the compiled-by-plugin ones.\n restore(target, original);\n },\n );\n } catch {\n pending = false;\n restore(target, original);\n }\n\n return schema as T & CompiledSchema<output<T>>;\n}\n\n/**\n * Front every installed method with a compile-on-read accessor. `trigger`\n * materializes the schema, which normally replaces these accessors with the\n * compiled methods (or restores what Zod had). When that replacement does not\n * take, the getter serves Zod's own method rather than re-reading the slot —\n * see the re-entrancy note in the body.\n */\nfunction installAccessors(\n target: Record<string, unknown>,\n original: ReadonlyMap<string, PropertyDescriptor | undefined>,\n trigger: () => void,\n cancel: () => void,\n): void {\n for (const slot of SLOTS) {\n // Re-entrancy is settled structurally rather than by inspection. Reading the\n // slot again is how this getter normally hands over — to the compiled method\n // materialize() installed, or to whatever restore() put back — but the\n // handover can fail to take: a target frozen after `jit()` refuses both, and\n // a second copy of this module in the graph leaves ITS accessor on the slot,\n // so the two bounce reads between them. `trigger()` is spent by then, so\n // either way the read recurses until the stack blows. While a read is already\n // in flight, or once the accessor is known to be stranded, serve Zod's own\n // method instead: a schema that cannot be compiled still parses.\n let reading = false;\n // A stranded accessor is permanent, so what it serves is resolved once.\n let stranded: { value: unknown } | undefined;\n const serveZod = (): unknown => {\n stranded ??= { value: fromZod(target, original, slot) };\n return stranded.value;\n };\n const read = function (): unknown {\n if (reading) return serveZod();\n reading = true;\n try {\n trigger();\n if (stillFrontedBy(target, slot, read)) return serveZod();\n return target[slot];\n } finally {\n reading = false;\n }\n };\n Object.defineProperty(target, slot, {\n configurable: true,\n // Keep the schema's own-key set as it was. A slot Zod already materialized\n // is an enumerable own copy, so the accessor fronting it is enumerable too;\n // an untouched slot has no own key at all, and `is` never exists on a Zod\n // schema, so those stay out of `Object.keys` — the non-enumerable\n // convention `compile()` already uses.\n enumerable: original.get(slot)?.enumerable ?? false,\n get: read,\n set(value: unknown) {\n // Someone overwrote a method before first use (a test double, another\n // wrapper). Their value wins, and compilation is cancelled outright —\n // materializing later would restore the snapshot over it. With the\n // accessor gone the write does what it would have without `jit()`:\n // overwrite the own copy, or run Zod's prototype setter, which installs\n // one. Only a target that refused the rollback still routes here, and a\n // direct define is the one way left to honour the write.\n cancel();\n if (!stillFrontedBy(target, slot, read)) {\n target[slot] = value;\n return;\n }\n Object.defineProperty(target, slot, {\n configurable: true,\n enumerable: original.get(slot)?.enumerable ?? false,\n value,\n writable: true,\n });\n },\n });\n }\n}\n\n/**\n * Is `slot` still fronted by this very accessor — i.e. did the replacement that\n * `trigger()` was supposed to perform not take? A target that will not answer\n * the question is assumed to still hold it, since reading the slot to find out\n * is the recursion being avoided.\n */\nfunction stillFrontedBy(\n target: Record<string, unknown>,\n slot: string,\n getter: () => unknown,\n): boolean {\n try {\n return Object.getOwnPropertyDescriptor(target, slot)?.get === getter;\n } catch {\n return true;\n }\n}\n\n/**\n * Zod's own value for `slot`, bypassing the accessor that fronts it.\n *\n * A slot the snapshot holds is answered from the snapshot. One it does not hold\n * lives on the prototype, where Zod's getter binds the method to its receiver\n * and installs the bound copy as an own property — on a target that accepts\n * the install, that also replaces the stranded accessor with the copy, which is\n * the handover materialize() could not make. A target that refuses the install\n * (frozen, or a wrapper that vetoes `defineProperty`) makes Zod's getter throw\n * instead; there the read goes through a stand-in that inherits from the target,\n * so the copy lands on the stand-in and the method reaches `_zod` through the\n * chain. `undefined` for `is`, which no plain Zod schema carries — the same\n * thing every other degradation path leaves there.\n */\nfunction fromZod(\n target: Record<string, unknown>,\n original: ReadonlyMap<string, PropertyDescriptor | undefined>,\n slot: string,\n): unknown {\n const descriptor = original.get(slot);\n if (descriptor !== undefined) {\n // A snapshot can hold another accessor (a second copy of this module\n // installed first), so invoke it rather than reading a `value` it lacks.\n return descriptor.get === undefined ? descriptor.value : descriptor.get.call(target);\n }\n const proto = Object.getPrototypeOf(target) as object | null;\n if (proto === null) return undefined;\n try {\n return Reflect.get(proto, slot, target);\n } catch {\n return Reflect.get(proto, slot, Object.create(target));\n }\n}\n\n/**\n * Compile every Zod schema found among an object's own values — typically a\n * module namespace, so a whole schema file opts in with one call:\n *\n * ```ts\n * import * as schemas from \"./schemas.js\";\n * jitAll(schemas);\n * ```\n *\n * The namespace object itself is never written to (a module namespace is\n * read-only); `jit()` mutates the schema objects it holds, which is what every\n * importer of that module already references.\n */\nexport function jitAll(schemas: object, options?: JitOptions): void {\n for (const value of Object.values(schemas)) {\n if (isZodSchema(value)) jit(value, options);\n }\n}\n\n/**\n * Put back what the snapshot holds, dropping the compile-on-read accessors: the\n * own copy Zod (or the build plugin) had installed, or nothing at all, so the\n * slot reads through to Zod's prototype getter again.\n */\nfunction restore(\n target: Record<string, unknown>,\n original: ReadonlyMap<string, PropertyDescriptor | undefined>,\n): void {\n for (const slot of SLOTS) {\n // Per slot, because this also runs as the rollback for a failed install: a\n // target that refuses one slot must not cost the others their restoration.\n // A slot left fronted by its accessor still reads correctly — the getter\n // serves Zod's own method — but it keeps a redundant indirection, so\n // restoring what can be restored is worth the try/catch.\n try {\n const descriptor = original.get(slot);\n if (descriptor === undefined) delete target[slot];\n else Object.defineProperty(target, slot, descriptor);\n } catch {\n // Nothing further to try for this slot.\n }\n }\n}\n\n/**\n * Whether runtime code generation is permitted here. Read per call, never\n * snapshotted: `z.config({ jitless: true })` runs in an entry point, after the\n * schema modules it imports have already been evaluated.\n */\nfunction codegenAllowed(): boolean {\n return zodCore.globalConfig.jitless !== true && zodCore.util.allowsEval.value;\n}\n\n/**\n * Run the pipeline and let the generated IIFE install its methods on `schema`.\n * Swallows failure: a schema that cannot be compiled keeps Zod's own methods,\n * which the caller already has, so there is nothing to report and nothing to\n * break.\n */\nfunction materialize(schema: unknown, options?: JitOptions): void {\n if (!codegenAllowed()) return;\n try {\n buildValidator(schema, options);\n } catch (error) {\n // Left as plain Zod. Deliberately silent: `jit()` is an optimization, and a\n // schema using a construct the compiler declines is a supported outcome,\n // not an error. The one exception is the zod version guard — a mismatched\n // zod is a configuration problem the user has to hear about. `jit()` itself\n // refuses such a schema before installing anything; this covers a caller\n // that reached the pipeline another way.\n if (isUnsupportedZodVersionError(error)) warnUnsupportedZodOnce(error.message);\n }\n}\n\n/**\n * Generate the validator and evaluate it, reproducing the module a\n * `.compiled.ts` would have been: helper preamble, the file-level shared block,\n * then the `__zcMkv` IIFE whose `__rf[]` bases and install target are the live\n * schema object passed in as `__schema`.\n */\nfunction buildValidator(schema: unknown, options?: JitOptions): void {\n const { schemas, shared } = compileSchemas([{ exportName: \"jit\", schema }], {\n compact: options?.output === \"compact\",\n mode: \"inline\",\n });\n const compiled = schemas[0];\n if (compiled === undefined) throw new Error(\"zod-compiler: schema produced no validator\");\n\n const body = [RUNTIME_PRELUDE, shared.code, `return ${generateIIFE(\"__schema\", compiled)};`].join(\n \"\\n\",\n );\n\n // The three bindings ZOD_CONFIG_IMPORT would have imported, passed in so the\n // evaluated code needs no module resolution of its own.\n // oxlint-disable-next-line no-new-func -- generating the validator IS the feature\n const factory = new Function(\n \"__zodCompilerConfig\",\n \"__zcCore\",\n \"__zcZodError\",\n \"__schema\",\n body,\n ) as (\n zodConfigFn: typeof zodConfig,\n zodCoreNs: typeof zodCore,\n zodErrorCtor: typeof ZodRealError,\n target: unknown,\n ) => unknown;\n\n factory(zodConfig, zodCore, ZodRealError, schema);\n}\n"],"mappings":"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"}
package/dist/runtime.d.ts CHANGED
@@ -30,6 +30,9 @@ export declare const __zcPfx: any;
30
30
  export declare const __zcCu: any;
31
31
  export declare const __zcSr: any;
32
32
  export declare const __zcSrOk: any;
33
+ export declare const __zcAsy: any;
34
+ export declare const __zcRd: any;
35
+ export declare const __zcRf: any;
33
36
  export declare const __zcReEmail: any;
34
37
  export declare const __zcReEmailSrc: any;
35
38
  export declare const __zcReUuid: any;
package/dist/runtime.js CHANGED
@@ -30,8 +30,11 @@ export function __zcPs(o){if(!Object.prototype.hasOwnProperty.call(o,"__proto__"
30
30
  export function __zcPlain(o){if(typeof o!=="object"||o===null||Array.isArray(o))return false;var c=o.constructor;if(c===Object||c===undefined||typeof c!=="function")return true;var p=c.prototype;if(typeof p!=="object"||p===null||Array.isArray(p))return false;return Object.prototype.hasOwnProperty.call(p,"isPrototypeOf");}
31
31
  export function __zcPfx(d,s,b,k){for(var i=0;i<s.length;i++){var x=s[i];x.path=b.concat(k,x.path);d.push(x);}}
32
32
  export function __zcCu(f,v){var r=f(v);if(r&&typeof r.then==="function"){throw new __zcCore.$ZodAsyncError();}return !!r;}
33
- export function __zcSr(f,v,p,e,m){var q={value:v,issues:[]};__zcSrRun(f,q);for(var i=0;i<q.issues.length;i++){var s=q.issues[i],t={};for(var k in s){if(k!=="inst"&&k!=="continue")t[k]=s[k];}if(s.continue!==true)q.aborted=true;t.path=s.path&&s.path.length?p.concat(s.path):p;if(t.message===undefined&&m!==undefined)t.message=m;e.push(t);}return q;}
33
+ export function __zcSr(f,v,p,e,m){var q={value:v,issues:[]};__zcSrRun(f,q);for(var i=0;i<q.issues.length;i++){var s=q.issues[i],t={};for(var k in s){if(k!=="inst"&&k!=="continue")t[k]=s[k];}if(s.continue!==true){q.aborted=true;t.continue=false;}t.path=s.path&&s.path.length?p.concat(s.path):p;if(t.message===undefined&&m!==undefined)t.message=m;e.push(t);}return q;}
34
34
  export function __zcSrOk(f,v){var p={value:v,issues:[]};__zcSrRun(f,p);return p.issues.length===0&&p.value===v;}
35
+ export function __zcAsy(){throw new __zcCore.$ZodAsyncError();}
36
+ export function __zcRd(z,v,c){var r=z.run({value:v,issues:[]},c);if(r instanceof Promise)throw new __zcCore.$ZodAsyncError();return r;}
37
+ export function __zcRf(s,c,e,p){var g=__zcCore.config();for(var i=0;i<s.length;i++){var q=s[i],f=__zcCore.util.finalizeIssue(q,c,g);f.path=p.concat(f.path);if(q.continue!==true)f.continue=false;e.push(f);}}
35
38
  export const __zcReEmail=new RegExp("^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$");
36
39
  export const __zcReEmailSrc="/^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$/";
37
40
  export const __zcReUuid=new RegExp("^([0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]-[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$");
@@ -1 +1 @@
1
- {"version":3,"file":"hoist-compile.d.ts","names":[],"sources":["../../src/unplugin/hoist-compile.ts"],"mappings":";;;;;UA8CiB;;EAEf;;EAEA;;EAEA,MAAM;;;;;;iBAyFc,sBACpB,kBAAkB,iBAClB,cACA,YACA,MAAM,cACL,QAAQ"}
1
+ {"version":3,"file":"hoist-compile.d.ts","names":[],"sources":["../../src/unplugin/hoist-compile.ts"],"mappings":";;;;;UAkDiB;;EAEf;;EAEA;;EAEA,MAAM;;;;;;iBA6Fc,sBACpB,kBAAkB,iBAClB,cACA,YACA,MAAM,cACL,QAAQ"}
@@ -1,5 +1,6 @@
1
1
  import { isZodSchema } from "../is-zod-schema.js";
2
2
  import { loadModule } from "../loader.js";
3
+ import { isUnsupportedZodVersionError, warnUnsupportedZodOnce } from "../core/extract/zod-version.js";
3
4
  import { generateValidator } from "../core/codegen/index.js";
4
5
  import { extractSchema } from "../core/extract/index.js";
5
6
  import { analyzeHoistedExpression, collectImportBindings } from "./hoist.js";
@@ -50,7 +51,8 @@ async function compileOne(schema, importDetails, id, mode, moduleCache) {
50
51
  refEntries
51
52
  }
52
53
  };
53
- } catch {
54
+ } catch (error) {
55
+ if (isUnsupportedZodVersionError(error)) warnUnsupportedZodOnce(error.message);
54
56
  return null;
55
57
  }
56
58
  }