zod 4.5.4 → 4.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (347) hide show
  1. package/compile.cjs +19 -0
  2. package/index.cjs +19 -0
  3. package/locales/index.cjs +19 -0
  4. package/mini/index.cjs +19 -0
  5. package/package.json +8 -7
  6. package/src/v3/helpers/errorUtil.ts +1 -1
  7. package/src/v4/classic/checks.ts +0 -1
  8. package/src/v4/classic/external.ts +2 -0
  9. package/src/v4/classic/from-json-schema.ts +248 -25
  10. package/src/v4/classic/schemas.ts +255 -164
  11. package/src/v4/classic/tests/assignability.test.ts +59 -9
  12. package/src/v4/classic/tests/bigint.test.ts +6 -0
  13. package/src/v4/classic/tests/continuability.test.ts +2 -2
  14. package/src/v4/classic/tests/cyclic-data.test.ts +274 -0
  15. package/src/v4/classic/tests/enum.test.ts +9 -0
  16. package/src/v4/classic/tests/error.test.ts +130 -1
  17. package/src/v4/classic/tests/firstparty.test.ts +4 -0
  18. package/src/v4/classic/tests/from-json-schema.test.ts +157 -0
  19. package/src/v4/classic/tests/iban.test.ts +81 -0
  20. package/src/v4/classic/tests/instance-footprint.test.ts +18 -2
  21. package/src/v4/classic/tests/instanceof.test.ts +27 -7
  22. package/src/v4/classic/tests/issue-schema.test.ts +88 -56
  23. package/src/v4/classic/tests/object.test.ts +56 -0
  24. package/src/v4/classic/tests/optin-ladder.test.ts +3 -2
  25. package/src/v4/classic/tests/properties.test.ts +225 -0
  26. package/src/v4/classic/tests/recursive-types.test.ts +1 -1
  27. package/src/v4/classic/tests/standard-schema.test.ts +19 -0
  28. package/src/v4/classic/tests/string.test.ts +25 -0
  29. package/src/v4/classic/tests/template-literal.test.ts +33 -1
  30. package/src/v4/classic/tests/to-json-schema.test.ts +147 -3
  31. package/src/v4/classic/tests/validate.test.ts +569 -0
  32. package/src/v4/core/api.ts +30 -6
  33. package/src/v4/core/checks.ts +1 -101
  34. package/src/v4/core/compile.ts +193 -81
  35. package/src/v4/core/doc.ts +6 -2
  36. package/src/v4/core/errors.ts +3 -6
  37. package/src/v4/core/json-schema-generator.ts +2 -2
  38. package/src/v4/core/json-schema-processors.ts +226 -68
  39. package/src/v4/core/memoizer.ts +78 -28
  40. package/src/v4/core/parse.ts +37 -16
  41. package/src/v4/core/regexes.ts +10 -4
  42. package/src/v4/core/schemas.ts +314 -83
  43. package/src/v4/core/tests/cached.test.ts +54 -0
  44. package/src/v4/core/tests/compile-generative.test.ts +445 -0
  45. package/src/v4/core/tests/compile.test.ts +222 -2
  46. package/src/v4/core/tests/email-regex.test.ts +140 -0
  47. package/src/v4/core/tests/polyfill-collision.test.ts +46 -0
  48. package/src/v4/core/to-json-schema.ts +10 -8
  49. package/src/v4/core/util.ts +222 -147
  50. package/src/v4/core/versions.ts +2 -2
  51. package/src/v4/core/visit.ts +11 -0
  52. package/src/v4/locales/ar.ts +1 -0
  53. package/src/v4/locales/az.ts +1 -0
  54. package/src/v4/locales/be.ts +1 -0
  55. package/src/v4/locales/bg.ts +1 -0
  56. package/src/v4/locales/bn.ts +1 -0
  57. package/src/v4/locales/ca.ts +1 -0
  58. package/src/v4/locales/ckb.ts +1 -0
  59. package/src/v4/locales/cs.ts +1 -0
  60. package/src/v4/locales/da.ts +1 -0
  61. package/src/v4/locales/de.ts +1 -0
  62. package/src/v4/locales/el.ts +1 -0
  63. package/src/v4/locales/en.ts +1 -0
  64. package/src/v4/locales/eo.ts +1 -0
  65. package/src/v4/locales/es.ts +1 -0
  66. package/src/v4/locales/fa.ts +1 -0
  67. package/src/v4/locales/fi.ts +1 -0
  68. package/src/v4/locales/fr-CA.ts +1 -0
  69. package/src/v4/locales/fr.ts +1 -0
  70. package/src/v4/locales/gu.ts +1 -0
  71. package/src/v4/locales/he.ts +1 -0
  72. package/src/v4/locales/hi.ts +1 -0
  73. package/src/v4/locales/hr.ts +1 -0
  74. package/src/v4/locales/hu.ts +1 -0
  75. package/src/v4/locales/hy.ts +1 -0
  76. package/src/v4/locales/id.ts +1 -0
  77. package/src/v4/locales/is.ts +1 -0
  78. package/src/v4/locales/it.ts +1 -0
  79. package/src/v4/locales/ja.ts +1 -0
  80. package/src/v4/locales/ka.ts +1 -0
  81. package/src/v4/locales/km.ts +1 -0
  82. package/src/v4/locales/kn.ts +1 -0
  83. package/src/v4/locales/ko.ts +1 -0
  84. package/src/v4/locales/lt.ts +1 -0
  85. package/src/v4/locales/mk.ts +1 -0
  86. package/src/v4/locales/ms.ts +1 -0
  87. package/src/v4/locales/ne.ts +1 -0
  88. package/src/v4/locales/nl.ts +1 -0
  89. package/src/v4/locales/nn.ts +1 -0
  90. package/src/v4/locales/no.ts +1 -0
  91. package/src/v4/locales/ota.ts +1 -0
  92. package/src/v4/locales/pl.ts +1 -0
  93. package/src/v4/locales/ps.ts +1 -0
  94. package/src/v4/locales/pt-BR.ts +1 -0
  95. package/src/v4/locales/pt.ts +1 -0
  96. package/src/v4/locales/ro.ts +1 -0
  97. package/src/v4/locales/ru.ts +1 -0
  98. package/src/v4/locales/sk.ts +1 -0
  99. package/src/v4/locales/sl.ts +1 -0
  100. package/src/v4/locales/sv.ts +1 -0
  101. package/src/v4/locales/ta.ts +1 -0
  102. package/src/v4/locales/th.ts +1 -0
  103. package/src/v4/locales/tk.ts +1 -0
  104. package/src/v4/locales/tr.ts +1 -0
  105. package/src/v4/locales/uk.ts +1 -0
  106. package/src/v4/locales/ur.ts +1 -0
  107. package/src/v4/locales/uz.ts +1 -0
  108. package/src/v4/locales/vi.ts +1 -0
  109. package/src/v4/locales/yo.ts +1 -0
  110. package/src/v4/locales/zh-CN.ts +1 -0
  111. package/src/v4/locales/zh-TW.ts +1 -0
  112. package/src/v4/mini/checks.ts +0 -1
  113. package/src/v4/mini/external.ts +2 -0
  114. package/src/v4/mini/schemas.ts +38 -2
  115. package/src/v4/mini/tests/checks.test.ts +1 -1
  116. package/src/v4/mini/tests/computed.test.ts +11 -17
  117. package/src/v4/mini/tests/index.test.ts +8 -0
  118. package/src/v4/mini/tests/string.test.ts +16 -0
  119. package/v3/ZodError.cjs +19 -0
  120. package/v3/errors.cjs +19 -0
  121. package/v3/external.cjs +19 -0
  122. package/v3/helpers/enumUtil.cjs +19 -0
  123. package/v3/helpers/errorUtil.cjs +20 -1
  124. package/v3/helpers/errorUtil.js +1 -1
  125. package/v3/helpers/parseUtil.cjs +19 -0
  126. package/v3/helpers/partialUtil.cjs +19 -0
  127. package/v3/helpers/typeAliases.cjs +19 -0
  128. package/v3/helpers/util.cjs +19 -0
  129. package/v3/index.cjs +19 -0
  130. package/v3/standard-schema.cjs +19 -0
  131. package/v3/types.cjs +19 -0
  132. package/v4/classic/checks.cjs +20 -2
  133. package/v4/classic/checks.d.cts +1 -1
  134. package/v4/classic/checks.d.ts +1 -1
  135. package/v4/classic/checks.js +1 -1
  136. package/v4/classic/coerce.cjs +19 -0
  137. package/v4/classic/compat.cjs +19 -0
  138. package/v4/classic/deep-partial.cjs +19 -0
  139. package/v4/classic/errors.cjs +19 -0
  140. package/v4/classic/external.cjs +22 -1
  141. package/v4/classic/external.d.cts +1 -1
  142. package/v4/classic/external.d.ts +1 -1
  143. package/v4/classic/external.js +1 -1
  144. package/v4/classic/from-json-schema.cjs +264 -24
  145. package/v4/classic/from-json-schema.js +245 -24
  146. package/v4/classic/in-out.cjs +19 -0
  147. package/v4/classic/index.cjs +19 -0
  148. package/v4/classic/iso.cjs +19 -0
  149. package/v4/classic/parse.cjs +19 -0
  150. package/v4/classic/schemas.cjs +100 -31
  151. package/v4/classic/schemas.d.cts +17 -1
  152. package/v4/classic/schemas.d.ts +17 -1
  153. package/v4/classic/schemas.js +77 -29
  154. package/v4/core/api.cjs +37 -2
  155. package/v4/core/api.d.cts +6 -4
  156. package/v4/core/api.d.ts +6 -4
  157. package/v4/core/api.js +17 -2
  158. package/v4/core/checks.cjs +19 -96
  159. package/v4/core/checks.d.cts +1 -1
  160. package/v4/core/checks.d.ts +1 -1
  161. package/v4/core/checks.js +0 -96
  162. package/v4/core/compile.cjs +164 -65
  163. package/v4/core/compile.d.cts +18 -4
  164. package/v4/core/compile.d.ts +18 -4
  165. package/v4/core/compile.js +145 -66
  166. package/v4/core/core.cjs +19 -0
  167. package/v4/core/doc.cjs +26 -2
  168. package/v4/core/doc.js +7 -2
  169. package/v4/core/errors.cjs +21 -5
  170. package/v4/core/errors.js +2 -5
  171. package/v4/core/index.cjs +19 -0
  172. package/v4/core/json-schema-generator.cjs +20 -1
  173. package/v4/core/json-schema-generator.js +2 -2
  174. package/v4/core/json-schema-processors.cjs +215 -63
  175. package/v4/core/json-schema-processors.d.cts +17 -0
  176. package/v4/core/json-schema-processors.d.ts +17 -0
  177. package/v4/core/json-schema-processors.js +195 -64
  178. package/v4/core/json-schema.cjs +19 -0
  179. package/v4/core/memoizer.cjs +114 -23
  180. package/v4/core/memoizer.js +72 -23
  181. package/v4/core/parse.cjs +56 -16
  182. package/v4/core/parse.js +37 -16
  183. package/v4/core/regexes.cjs +29 -6
  184. package/v4/core/regexes.d.cts +2 -0
  185. package/v4/core/regexes.d.ts +2 -0
  186. package/v4/core/regexes.js +8 -4
  187. package/v4/core/registries.cjs +19 -0
  188. package/v4/core/schemas.cjs +285 -66
  189. package/v4/core/schemas.d.cts +34 -3
  190. package/v4/core/schemas.d.ts +34 -3
  191. package/v4/core/schemas.js +264 -65
  192. package/v4/core/standard-schema.cjs +19 -0
  193. package/v4/core/to-json-schema.cjs +29 -7
  194. package/v4/core/to-json-schema.d.cts +7 -3
  195. package/v4/core/to-json-schema.d.ts +7 -3
  196. package/v4/core/to-json-schema.js +8 -7
  197. package/v4/core/util.cjs +181 -143
  198. package/v4/core/util.d.cts +25 -4
  199. package/v4/core/util.d.ts +25 -4
  200. package/v4/core/util.js +160 -143
  201. package/v4/core/versions.cjs +21 -2
  202. package/v4/core/versions.d.cts +1 -1
  203. package/v4/core/versions.d.ts +1 -1
  204. package/v4/core/versions.js +2 -2
  205. package/v4/core/visit.cjs +31 -0
  206. package/v4/core/visit.js +12 -0
  207. package/v4/index.cjs +19 -0
  208. package/v4/locales/ar.cjs +1 -0
  209. package/v4/locales/ar.js +1 -0
  210. package/v4/locales/az.cjs +1 -0
  211. package/v4/locales/az.js +1 -0
  212. package/v4/locales/be.cjs +1 -0
  213. package/v4/locales/be.js +1 -0
  214. package/v4/locales/bg.cjs +1 -0
  215. package/v4/locales/bg.js +1 -0
  216. package/v4/locales/bn.cjs +1 -0
  217. package/v4/locales/bn.js +1 -0
  218. package/v4/locales/ca.cjs +1 -0
  219. package/v4/locales/ca.js +1 -0
  220. package/v4/locales/ckb.cjs +1 -0
  221. package/v4/locales/ckb.js +1 -0
  222. package/v4/locales/cs.cjs +1 -0
  223. package/v4/locales/cs.js +1 -0
  224. package/v4/locales/da.cjs +1 -0
  225. package/v4/locales/da.js +1 -0
  226. package/v4/locales/de.cjs +1 -0
  227. package/v4/locales/de.js +1 -0
  228. package/v4/locales/el.cjs +1 -0
  229. package/v4/locales/el.js +1 -0
  230. package/v4/locales/en.cjs +1 -0
  231. package/v4/locales/en.js +1 -0
  232. package/v4/locales/eo.cjs +1 -0
  233. package/v4/locales/eo.js +1 -0
  234. package/v4/locales/es.cjs +1 -0
  235. package/v4/locales/es.js +1 -0
  236. package/v4/locales/fa.cjs +1 -0
  237. package/v4/locales/fa.js +1 -0
  238. package/v4/locales/fi.cjs +1 -0
  239. package/v4/locales/fi.js +1 -0
  240. package/v4/locales/fr-CA.cjs +1 -0
  241. package/v4/locales/fr-CA.js +1 -0
  242. package/v4/locales/fr.cjs +1 -0
  243. package/v4/locales/fr.js +1 -0
  244. package/v4/locales/gu.cjs +1 -0
  245. package/v4/locales/gu.js +1 -0
  246. package/v4/locales/he.cjs +1 -0
  247. package/v4/locales/he.js +1 -0
  248. package/v4/locales/hi.cjs +1 -0
  249. package/v4/locales/hi.js +1 -0
  250. package/v4/locales/hr.cjs +1 -0
  251. package/v4/locales/hr.js +1 -0
  252. package/v4/locales/hu.cjs +1 -0
  253. package/v4/locales/hu.js +1 -0
  254. package/v4/locales/hy.cjs +1 -0
  255. package/v4/locales/hy.js +1 -0
  256. package/v4/locales/id.cjs +1 -0
  257. package/v4/locales/id.js +1 -0
  258. package/v4/locales/index.cjs +19 -0
  259. package/v4/locales/is.cjs +1 -0
  260. package/v4/locales/is.js +1 -0
  261. package/v4/locales/it.cjs +1 -0
  262. package/v4/locales/it.js +1 -0
  263. package/v4/locales/ja.cjs +1 -0
  264. package/v4/locales/ja.js +1 -0
  265. package/v4/locales/ka.cjs +1 -0
  266. package/v4/locales/ka.js +1 -0
  267. package/v4/locales/km.cjs +1 -0
  268. package/v4/locales/km.js +1 -0
  269. package/v4/locales/kn.cjs +1 -0
  270. package/v4/locales/kn.js +1 -0
  271. package/v4/locales/ko.cjs +1 -0
  272. package/v4/locales/ko.js +1 -0
  273. package/v4/locales/lt.cjs +1 -0
  274. package/v4/locales/lt.js +1 -0
  275. package/v4/locales/mk.cjs +1 -0
  276. package/v4/locales/mk.js +1 -0
  277. package/v4/locales/ms.cjs +1 -0
  278. package/v4/locales/ms.js +1 -0
  279. package/v4/locales/ne.cjs +1 -0
  280. package/v4/locales/ne.js +1 -0
  281. package/v4/locales/nl.cjs +1 -0
  282. package/v4/locales/nl.js +1 -0
  283. package/v4/locales/nn.cjs +1 -0
  284. package/v4/locales/nn.js +1 -0
  285. package/v4/locales/no.cjs +1 -0
  286. package/v4/locales/no.js +1 -0
  287. package/v4/locales/ota.cjs +1 -0
  288. package/v4/locales/ota.js +1 -0
  289. package/v4/locales/pl.cjs +1 -0
  290. package/v4/locales/pl.js +1 -0
  291. package/v4/locales/ps.cjs +1 -0
  292. package/v4/locales/ps.js +1 -0
  293. package/v4/locales/pt-BR.cjs +1 -0
  294. package/v4/locales/pt-BR.js +1 -0
  295. package/v4/locales/pt.cjs +1 -0
  296. package/v4/locales/pt.js +1 -0
  297. package/v4/locales/ro.cjs +1 -0
  298. package/v4/locales/ro.js +1 -0
  299. package/v4/locales/ru.cjs +1 -0
  300. package/v4/locales/ru.js +1 -0
  301. package/v4/locales/sk.cjs +1 -0
  302. package/v4/locales/sk.js +1 -0
  303. package/v4/locales/sl.cjs +1 -0
  304. package/v4/locales/sl.js +1 -0
  305. package/v4/locales/sv.cjs +1 -0
  306. package/v4/locales/sv.js +1 -0
  307. package/v4/locales/ta.cjs +1 -0
  308. package/v4/locales/ta.js +1 -0
  309. package/v4/locales/th.cjs +1 -0
  310. package/v4/locales/th.js +1 -0
  311. package/v4/locales/tk.cjs +1 -0
  312. package/v4/locales/tk.js +1 -0
  313. package/v4/locales/tr.cjs +1 -0
  314. package/v4/locales/tr.js +1 -0
  315. package/v4/locales/uk.cjs +1 -0
  316. package/v4/locales/uk.js +1 -0
  317. package/v4/locales/ur.cjs +1 -0
  318. package/v4/locales/ur.js +1 -0
  319. package/v4/locales/uz.cjs +1 -0
  320. package/v4/locales/uz.js +1 -0
  321. package/v4/locales/vi.cjs +1 -0
  322. package/v4/locales/vi.js +1 -0
  323. package/v4/locales/yo.cjs +1 -0
  324. package/v4/locales/yo.js +1 -0
  325. package/v4/locales/zh-CN.cjs +1 -0
  326. package/v4/locales/zh-CN.js +1 -0
  327. package/v4/locales/zh-TW.cjs +1 -0
  328. package/v4/locales/zh-TW.js +1 -0
  329. package/v4/mini/checks.cjs +20 -2
  330. package/v4/mini/checks.d.cts +1 -1
  331. package/v4/mini/checks.d.ts +1 -1
  332. package/v4/mini/checks.js +1 -1
  333. package/v4/mini/coerce.cjs +19 -0
  334. package/v4/mini/deep-partial.cjs +19 -0
  335. package/v4/mini/external.cjs +22 -1
  336. package/v4/mini/external.d.cts +1 -1
  337. package/v4/mini/external.d.ts +1 -1
  338. package/v4/mini/external.js +1 -1
  339. package/v4/mini/in-out.cjs +19 -0
  340. package/v4/mini/index.cjs +19 -0
  341. package/v4/mini/iso.cjs +19 -0
  342. package/v4/mini/parse.cjs +19 -0
  343. package/v4/mini/schemas.cjs +42 -4
  344. package/v4/mini/schemas.d.cts +8 -0
  345. package/v4/mini/schemas.d.ts +8 -0
  346. package/v4/mini/schemas.js +19 -2
  347. package/v4-mini/index.cjs +19 -0
@@ -25,6 +25,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
26
  exports.ZodCompileUnsupportedError = exports.ZodCompileAsyncError = exports.INVALID = void 0;
27
27
  exports.compile = compile;
28
+ exports.withParser = withParser;
28
29
  exports.compileFn = compileFn;
29
30
  const core_js_1 = require("./core.cjs");
30
31
  const doc_js_1 = require("./doc.cjs");
@@ -32,7 +33,7 @@ const memoizer_js_1 = require("./memoizer.cjs");
32
33
  const regexes = __importStar(require("./regexes.cjs"));
33
34
  const schemas_js_1 = require("./schemas.cjs");
34
35
  const util = __importStar(require("./util.cjs"));
35
- /** Sentinel value returned by the compiled fast path when validation fails. Internal. */
36
+ /** @internal Sentinel the compiled fast path returns when validation fails. */
36
37
  exports.INVALID = Symbol.for("zod.compile.invalid");
37
38
  // Set on the parse ctx when a compiled wrapper falls back to the runtime, so nested compiled wrappers skip their fast paths for the rest of that parse.
38
39
  const FALLBACK_FLAG = Symbol.for("zod.compile.fallback");
@@ -85,45 +86,9 @@ function compileValidator(schema, parser) {
85
86
  function compile(schema, options) {
86
87
  try {
87
88
  const parser = compileFn(schema);
88
- const clone = util.clone(schema);
89
- // Capture the source-of-truth runtime eagerly. If schema._zod.run is itself a shim installed by global-mode (`__originalRun` set), unwrap past it. Otherwise capturing the live property lazily would let a later self- replacement of schema._zod.run feed our wrapper back into itself.
90
- const liveRun = schema._zod.run;
91
- const originalRun = liveRun.__originalRun ?? liveRun;
92
- // Delegate to the *original* schema's run on bypass/fallback (not the
93
- // clone's). The original closed over its own `inst` at construction time;
94
- // issue payloads use that reference to derive things like the class name
95
- // for `z.instanceof(Test)`. Calling the clone's freshly-initialized run
96
- // would push issues with `inst === clone`, producing diverging error
97
- // messages from the original schema.
98
- const wrapped = (payload, ctx) => {
99
- if (ctx?.async ||
100
- ctx?.direction === "backward" ||
101
- ctx?.skipChecks ||
102
- ctx?.[FALLBACK_FLAG]) {
103
- return originalRun(payload, ctx);
104
- }
105
- // A memoized back-edge: only the runtime can close a reference cycle, and a transform on one must raise $ZodCyclicError from its own parse.
106
- if (ctx && (0, memoizer_js_1.isBackEdge)(ctx, payload.value)) {
107
- return originalRun(payload, ctx);
108
- }
109
- const out = parser(payload.value);
110
- if (out !== exports.INVALID) {
111
- payload.value = out;
112
- return payload;
113
- }
114
- // Mark this parse as runtime-driven: under global mode every nested schema carries its own compiled wrapper, and without the flag the parent's runtime fallback re-enters each child's fast path, running user callbacks a third time on invalid input.
115
- if (ctx)
116
- ctx[FALLBACK_FLAG] = true;
117
- return originalRun(payload, ctx);
118
- };
119
- // Let later compiles of (or through) this run unwrap to the true runtime — both the global shim and repeated z.compile calls rely on this. The bag also carries the parser and the validator, so the standalone validate can skip the payload and wrapper on the happy path.
120
- wrapped.__originalRun = originalRun;
121
- clone._zod.bag.fallbackRun = originalRun;
89
+ const clone = withParser(schema, parser);
90
+ // withParser leaves the parser as its own validator; the generated assert-only variant is better when we have one
122
91
  clone._zod.bag.validator = compileValidator(schema, parser);
123
- clone._zod.run = wrapped;
124
- // The fast parse/safeParse closures fall back through the source schema's methods. If the source is shim- or wrapper-managed, those methods route into a compiled run and would execute user callbacks a third time on invalid input — the plain method → wrapper path is exactly 2x, so skip.
125
- if (!liveRun.__originalRun)
126
- installCompiledUserMethods(clone, schema, parser);
127
92
  return clone;
128
93
  }
129
94
  catch (err) {
@@ -133,6 +98,59 @@ function compile(schema, options) {
133
98
  return schema;
134
99
  }
135
100
  }
101
+ /**
102
+ * Install an already-generated parser as a schema's fast path. Returns a clone; the original is
103
+ * unchanged.
104
+ *
105
+ * The parser takes the input and returns the parsed value, or `INVALID` to hand the parse to the
106
+ * runtime. It must be synchronous and forward-direction, and it must build fresh output rather than
107
+ * return its input — Zod cannot check either, and a wrong *success* is returned to the caller as-is.
108
+ *
109
+ * `compile()` is the ordinary entry point. This is for a build-time or native compiler that produces
110
+ * a parser where `new Function` is unavailable.
111
+ */
112
+ function withParser(schema, parser) {
113
+ // generated code never receives the parse context, so only the runtime can close a reference cycle; compileFn refuses these too
114
+ if ((0, memoizer_js_1.isRecursiveSchema)(schema)) {
115
+ throw new ZodCompileUnsupportedError("a schema whose subtree contains a reference cycle");
116
+ }
117
+ const clone = util.clone(schema);
118
+ // Capture the source-of-truth runtime eagerly. If schema._zod.run is itself a shim installed by global-mode (`__originalRun` set), unwrap past it. Otherwise capturing the live property lazily would let a later self- replacement of schema._zod.run feed our wrapper back into itself.
119
+ const liveRun = schema._zod.run;
120
+ const originalRun = liveRun.__originalRun ?? liveRun;
121
+ // Delegate to the *original* schema's run on bypass/fallback, not the clone's. The original closed over its own `inst` at construction time, and issue payloads use that reference to derive things like the class name for `z.instanceof(Test)`; calling the clone's freshly-initialized run would push issues with `inst === clone` and diverge from the original schema's error messages.
122
+ const wrapped = (payload, ctx) => {
123
+ if (ctx?.async ||
124
+ ctx?.direction === "backward" ||
125
+ ctx?.skipChecks ||
126
+ ctx?.[FALLBACK_FLAG]) {
127
+ return originalRun(payload, ctx);
128
+ }
129
+ // A memoized back-edge: only the runtime can close a reference cycle, and a transform on one must raise $ZodCyclicError from its own parse.
130
+ if (ctx && (0, memoizer_js_1.isBackEdge)(ctx, payload.value)) {
131
+ return originalRun(payload, ctx);
132
+ }
133
+ const out = parser(payload.value);
134
+ if (out !== exports.INVALID) {
135
+ payload.value = out;
136
+ return payload;
137
+ }
138
+ // Mark this parse as runtime-driven: under global mode every nested schema carries its own compiled wrapper, and without the flag the parent's runtime fallback re-enters each child's fast path, running user callbacks a third time on invalid input.
139
+ if (ctx)
140
+ ctx[FALLBACK_FLAG] = true;
141
+ return originalRun(payload, ctx);
142
+ };
143
+ // Let later compiles of (or through) this run unwrap to the true runtime — both the global shim and repeated z.compile calls rely on this. The bag also carries the parser and the validator, so the standalone validate can skip the payload and wrapper on the happy path.
144
+ wrapped.__originalRun = originalRun;
145
+ clone._zod.bag.fallbackRun = originalRun;
146
+ // a supplied parser answers `validate` too: one implementation means parse and validate cannot disagree, and its undefined `definite` keeps the runtime re-parse on every rejection
147
+ clone._zod.bag.validator = parser;
148
+ clone._zod.run = wrapped;
149
+ // The fast parse/safeParse closures fall back through the source schema's methods. If the source is shim- or wrapper-managed, those methods route into a compiled run and would execute user callbacks a third time on invalid input — the plain method → wrapper path is exactly 2x, so skip.
150
+ if (!liveRun.__originalRun)
151
+ installCompiledUserMethods(clone, schema, parser);
152
+ return clone;
153
+ }
136
154
  function installCompiledUserMethods(target, source, parser) {
137
155
  const targetAny = target;
138
156
  const sourceAny = source;
@@ -158,9 +176,8 @@ function installCompiledUserMethods(target, source, parser) {
158
176
  }
159
177
  }
160
178
  /**
161
- * Generate the standalone compiled function: a parser by default, a validator under
162
- * `assertOnly`. Returns either the parsed value, `true` where nothing reads the output,
163
- * or the `INVALID` sentinel. Internal — consumers should use `compile()`.
179
+ * @internal Generate the standalone compiled function: a parser by default, a validator under
180
+ * `assertOnly`. Returns the parsed value, `true` where nothing reads the output, or `INVALID`. Consumers use `compile()`.
164
181
  */
165
182
  function compileFn(schema, options) {
166
183
  // Cycle-breaking is keyed on the parse context, which generated code never receives. `shape` can be a getter that throws (z.pick() with an unrecognized mask key), so treat "can't tell" as recursive.
@@ -176,6 +193,7 @@ function compileFn(schema, options) {
176
193
  constants: new Map(),
177
194
  constantCounter: 0,
178
195
  varCounter: 0,
196
+ definite: true,
179
197
  };
180
198
  const doc = new doc_js_1.Doc(["input"]);
181
199
  const outputAccessor = generateCheck(doc, ctx, schema, "input", !options?.assertOnly);
@@ -204,6 +222,7 @@ function compileFn(schema, options) {
204
222
  if (options?.debug) {
205
223
  fn.code = fullCode;
206
224
  }
225
+ fn.definite = ctx.definite;
207
226
  return fn;
208
227
  }
209
228
  function addConstant(ctx, value) {
@@ -216,6 +235,11 @@ function addConstant(ctx, value) {
216
235
  ctx.constants.set(name, value);
217
236
  return name;
218
237
  }
238
+ /** Hoists a user-supplied callback. Anything the schema's author wrote can throw, and generated code can reject an earlier sibling before ever reaching it, so this clears `definite` — a rejection is then no longer proof that the interpreter would have rejected rather than thrown. */
239
+ function addUserConstant(ctx, fn) {
240
+ ctx.definite = false;
241
+ return addConstant(ctx, fn);
242
+ }
219
243
  function newVar(ctx) {
220
244
  return `v${ctx.varCounter++}`;
221
245
  }
@@ -251,6 +275,8 @@ function compileChild(doc, ctx, schema, accessor, needsValue = true) {
251
275
  }
252
276
  }
253
277
  function emitRuntimeIsland(doc, ctx, schema, accessor) {
278
+ // an islanded child answers INVALID for an async run too, which the interpreter throws for
279
+ ctx.definite = false;
254
280
  const schemaConst = addConstant(ctx, schema);
255
281
  const runConst = addConstant(ctx, runtimeRun);
256
282
  const outVar = newVar(ctx);
@@ -334,6 +360,9 @@ function generateChecks(doc, ctx, schema, accessor) {
334
360
  case "property":
335
361
  generatePropertyCheck(doc, ctx, def, currentAccessor);
336
362
  break;
363
+ case "properties":
364
+ generatePropertiesChecks(doc, ctx, def, currentAccessor, false);
365
+ break;
337
366
  case "overwrite": {
338
367
  // Overwrite transforms the value - create new variable for transformed result
339
368
  const newAccessor = newVar(ctx);
@@ -459,6 +488,26 @@ function generateMimeTypeCheck(doc, ctx, def, accessor) {
459
488
  doc.write(`if (!${mimeSet}.has(${accessor}.type)) return INVALID;`);
460
489
  }
461
490
  }
491
+ // asserts each named property in place; children compile assert-only because z.properties never rebuilds its input
492
+ function generatePropertiesChecks(doc, ctx, def, accessor, schemaRole) {
493
+ // a custom `when` gates the assertion at runtime; inside a union a wrongly-run branch is absorbed as a branch failure rather than falling back, so refuse at codegen the way the check role does
494
+ if (def.when) {
495
+ throw new ZodCompileUnsupportedError(`check with a custom "when" condition`);
496
+ }
497
+ // matches the runtime gate for whichever role this is: a schema rejects a primitive outright, a check only a nullish value
498
+ doc.write(schemaRole
499
+ ? `if (${accessor} === null || (typeof ${accessor} !== "object" && typeof ${accessor} !== "function")) return INVALID;`
500
+ : `if (${accessor} == null) return INVALID;`);
501
+ const shape = def.shape;
502
+ for (const key of Reflect.ownKeys(shape)) {
503
+ // a symbol has no source literal, so it is hoisted as a constant
504
+ const keyExpr = typeof key === "symbol" ? addConstant(ctx, key) : util.esc(key);
505
+ // cache the property read so a getter runs exactly once, matching the runtime
506
+ const inputVar = newVar(ctx);
507
+ doc.write(`const ${inputVar} = ${accessor}[${keyExpr}];`);
508
+ compileChild(doc, ctx, shape[key], inputVar, false);
509
+ }
510
+ }
462
511
  function generatePropertyCheck(doc, ctx, def, accessor) {
463
512
  const propAccessor = `${accessor}[${JSON.stringify(def.property)}]`;
464
513
  generateCheck(doc, ctx, def.schema, propAccessor);
@@ -491,7 +540,7 @@ function generateCustomRefineCheck(doc, ctx, check, accessor) {
491
540
  if (isAsyncFunction(def.fn)) {
492
541
  throw new ZodCompileAsyncError("z.compile: async .refine() predicates are not supported");
493
542
  }
494
- const fnConst = addConstant(ctx, def.fn);
543
+ const fnConst = addUserConstant(ctx, def.fn);
495
544
  const throwAsyncConst = addConstant(ctx, throwAsync);
496
545
  const resVar = newVar(ctx);
497
546
  doc.write(`const ${resVar} = ${fnConst}(${accessor});`);
@@ -519,7 +568,7 @@ function generateCustomRefineCheck(doc, ctx, check, accessor) {
519
568
  throwAsync();
520
569
  return fakePayload.issues.length === 0 ? fakePayload.value : exports.INVALID;
521
570
  };
522
- const helperConst = addConstant(ctx, helperFn);
571
+ const helperConst = addUserConstant(ctx, helperFn);
523
572
  const outVar = newVar(ctx);
524
573
  doc.write(`const ${outVar} = ${helperConst}(${accessor});`);
525
574
  doc.write(`if (${outVar} === INVALID) return INVALID;`);
@@ -596,6 +645,11 @@ function generateStringFormatCheck(doc, ctx, def, accessor) {
596
645
  doc.write(`if (!${validator}(${accessor})) return INVALID;`);
597
646
  return accessor;
598
647
  }
648
+ if (fmt === "iban") {
649
+ const validator = addConstant(ctx, schemas_js_1.isValidIBAN);
650
+ doc.write(`if (!${validator}(${accessor})) return INVALID;`);
651
+ return accessor;
652
+ }
599
653
  const formatDef = def;
600
654
  if (fmt === "url" ||
601
655
  fmt === "httpurl" ||
@@ -794,6 +848,10 @@ function generateCheck(doc, ctx, schema, accessor, needsValue = true) {
794
848
  case "custom":
795
849
  typeAccessor = generateCustomCheck(doc, ctx, schema, accessor);
796
850
  break;
851
+ case "properties":
852
+ generatePropertiesChecks(doc, ctx, schema._zod.def, accessor, true);
853
+ typeAccessor = accessor;
854
+ break;
797
855
  case "transform":
798
856
  typeAccessor = generateTransformCheck(doc, ctx, schema, accessor);
799
857
  break;
@@ -1511,6 +1569,8 @@ function literalEquality(ctx, accessor, value) {
1511
1569
  }
1512
1570
  function generateIntersectionCheck(doc, ctx, schema, accessor) {
1513
1571
  const def = schema._zod.def;
1572
+ // An unmergeable merge, and a child failing before the merge is even reached, both return INVALID for a case the interpreter answers with a throw.
1573
+ ctx.definite = false;
1514
1574
  const leftOutput = compileChild(doc, ctx, def.left, accessor);
1515
1575
  const rightOutput = compileChild(doc, ctx, def.right, accessor);
1516
1576
  // Hoist the runtime merge helper so recursive object/array merge semantics stay in one place. If the merge is invalid, return INVALID and let the runtime fallback construct canonical errors.
@@ -1580,14 +1640,15 @@ function generateRecordCheck(doc, ctx, schema, accessor) {
1580
1640
  // The runtime runs it against each own enumerable key and writes the value
1581
1641
  // under the key it produced, so compile it once and call it per key.
1582
1642
  const isLoose = def.mode === "loose";
1583
- const keyFast = addConstant(ctx, compileFn(def.keyType));
1643
+ // the key compiles in its own context, so carry its verdict out: a key schema that can answer INVALID undecidably makes this validator undecidable too
1644
+ const keyFn = compileFn(def.keyType);
1645
+ if (keyFn.definite === false)
1646
+ ctx.definite = false;
1647
+ const keyFast = addConstant(ctx, keyFn);
1584
1648
  const numericConst = addConstant(ctx, regexes.number);
1585
- const propIsEnumerableConst = addConstant(ctx, Object.prototype.propertyIsEnumerable);
1586
1649
  const outKeyVar = newVar(ctx);
1587
- doc.write(`for (const ${kVar} of Reflect.ownKeys(${accessor})) {`);
1588
- doc.indented((d) => {
1589
- d.write(`if (${kVar} === "__proto__") continue;`);
1590
- d.write(`if (!${propIsEnumerableConst}.call(${accessor}, ${kVar})) continue;`);
1650
+ // the body runs once per string key and once per symbol key, since a key schema can accept symbols
1651
+ emitOwnKeys(doc, ctx, accessor, kVar, (d) => {
1591
1652
  d.write(`let ${outKeyVar} = ${keyFast}(${kVar});`);
1592
1653
  // Numeric-string retry, mirroring the runtime: a key the schema rejects as a string is tried again as a number, so z.record(z.number(), …) matches the numeric keys JavaScript stringified on the way in.
1593
1654
  d.write(`if (${outKeyVar} === INVALID && typeof ${kVar} === "string" && ${numericConst}.test(${kVar})) ${outKeyVar} = ${keyFast}(Number(${kVar}));`);
@@ -1606,22 +1667,41 @@ function generateRecordCheck(doc, ctx, schema, accessor) {
1606
1667
  const valOutput = compileChild(d, ctx, def.valueType, valueVar);
1607
1668
  d.write(`${outputVar}[${outKeyVar}] = ${valOutput};`);
1608
1669
  });
1609
- doc.write(`}`);
1610
1670
  return outputVar;
1611
1671
  }
1612
- // Plain z.string() keys: iterate enumerable own keys and validate each value. Runtime uses Reflect.ownKeys so symbol keys participate in validation; matching that here prevents silently accepting objects with enumerable Symbol keys under z.record(z.string(), ...).
1613
- const propIsEnumerable = addConstant(ctx, Object.prototype.propertyIsEnumerable);
1614
- doc.write(`for (const ${kVar} of Reflect.ownKeys(${accessor})) {`);
1615
- doc.indented((d) => {
1616
- d.write(`if (${kVar} === "__proto__") continue;`);
1617
- d.write(`if (!${propIsEnumerable}.call(${accessor}, ${kVar})) continue;`);
1618
- d.write(`if (typeof ${kVar} !== "string") return INVALID;`);
1672
+ // Plain z.string() keys: every own enumerable string key's value is validated, and an own enumerable symbol key fails the string key schema, as it does in the runtime's Reflect.ownKeys walk.
1673
+ emitOwnKeys(doc, ctx, accessor, kVar, (d) => {
1619
1674
  d.write(`const ${valVar} = ${accessor}[${kVar}];`);
1620
1675
  const valOutput = compileChild(d, ctx, def.valueType, valVar);
1621
1676
  d.write(`${outputVar}[${kVar}] = ${valOutput};`);
1677
+ }, `return INVALID;`);
1678
+ return outputVar;
1679
+ }
1680
+ // Walks the own enumerable keys of a plain object in Reflect.ownKeys order — strings from getOwnPropertyNames, then symbols — instead of Reflect.ownKeys, whose accumulator made that walk 3–6x the cost of the loop it fed. Both snapshots are taken before any value is read and every key is rechecked with propertyIsEnumerable when visited, exactly the runtime's walk, so a getter that adds, deletes, hides or reveals a key mid-walk sees the runtime's verdict; for-in and Object.keys were no faster and each lost a case (for-in enumerates the prototype chain after the own keys, Object.keys drops a key that is non-enumerable at snapshot time). `body` is written once for the string loop and once for the symbol loop unless `onSymbol` replaces the latter.
1681
+ function emitOwnKeys(doc, ctx, accessor, kVar, body, onSymbol) {
1682
+ const propIsEnumerableConst = addConstant(ctx, Object.prototype.propertyIsEnumerable);
1683
+ const symsVar = newVar(ctx);
1684
+ const keysVar = newVar(ctx);
1685
+ const iVar = newVar(ctx);
1686
+ doc.write(`const ${symsVar} = Object.getOwnPropertySymbols(${accessor});`);
1687
+ doc.write(`const ${keysVar} = Object.getOwnPropertyNames(${accessor});`);
1688
+ doc.write(`for (let ${iVar} = 0; ${iVar} < ${keysVar}.length; ${iVar}++) {`);
1689
+ doc.indented((d) => {
1690
+ d.write(`const ${kVar} = ${keysVar}[${iVar}];`);
1691
+ d.write(`if (${kVar} === "__proto__" || !${propIsEnumerableConst}.call(${accessor}, ${kVar})) continue;`);
1692
+ body(d);
1693
+ });
1694
+ doc.write(`}`);
1695
+ doc.write(`for (let ${iVar} = 0; ${iVar} < ${symsVar}.length; ${iVar}++) {`);
1696
+ doc.indented((d) => {
1697
+ d.write(`const ${kVar} = ${symsVar}[${iVar}];`);
1698
+ d.write(`if (!${propIsEnumerableConst}.call(${accessor}, ${kVar})) continue;`);
1699
+ if (onSymbol)
1700
+ d.write(onSymbol);
1701
+ else
1702
+ body(d);
1622
1703
  });
1623
1704
  doc.write(`}`);
1624
- return outputVar;
1625
1705
  }
1626
1706
  function literalPropertyKey(ctx, key) {
1627
1707
  if (typeof key === "string")
@@ -1677,7 +1757,7 @@ function generateTemplateLiteralCheck(doc, ctx, schema, accessor) {
1677
1757
  function generateLazyCheck(doc, ctx, schema, accessor) {
1678
1758
  // For lazy schemas, we use a cached parser that falls back to runtime Zod parsing This handles recursive schemas correctly by avoiding infinite compilation loops
1679
1759
  const def = schema._zod.def;
1680
- const getterConst = addConstant(ctx, def.getter);
1760
+ const getterConst = addUserConstant(ctx, def.getter);
1681
1761
  const cacheConst = addConstant(ctx, { parser: null });
1682
1762
  doc.write(`if (!${cacheConst}.parser) {`);
1683
1763
  doc.indented((d) => {
@@ -1701,7 +1781,7 @@ function generatePipeCheck(doc, ctx, schema, accessor) {
1701
1781
  // Validate input type first
1702
1782
  const inputOutput = generateCheck(doc, ctx, def.in, accessor);
1703
1783
  if (def.transform) {
1704
- // Apply transform and validate output. The transform may read its second `payload` argument (codec transforms like z.stringbool() push issues there) so wrap the call in a helper that spoofs a payload. Pushed issues signal INVALID and the wrapper falls back to the runtime.
1784
+ // Apply transform and validate output. The transform may read its second `payload` argument (codec transforms like z.stringbool() push issues there) so wrap the call in a helper that spoofs a payload. Pushed issues signal INVALID and the wrapper falls back to the runtime, and a plain function handing back a promise answers INVALID too — union parity, but not a decidable rejection at the top level.
1705
1785
  if (isAsyncFunction(def.transform)) {
1706
1786
  throw new ZodCompileAsyncError("z.compile: async transforms in pipes are not supported");
1707
1787
  }
@@ -1715,7 +1795,7 @@ function generatePipeCheck(doc, ctx, schema, accessor) {
1715
1795
  return exports.INVALID;
1716
1796
  return fakePayload.issues.length === 0 ? result : exports.INVALID;
1717
1797
  };
1718
- const helperConst = addConstant(ctx, helperFn);
1798
+ const helperConst = addUserConstant(ctx, helperFn);
1719
1799
  const transformedVar = newVar(ctx);
1720
1800
  doc.write(`const ${transformedVar} = ${helperConst}(${inputOutput});`);
1721
1801
  doc.write(`if (${transformedVar} === INVALID) return INVALID;`);
@@ -1739,7 +1819,7 @@ function generateCustomCheck(doc, ctx, schema, accessor) {
1739
1819
  throw new ZodCompileAsyncError("z.compile: async custom predicates are not supported");
1740
1820
  }
1741
1821
  // Custom schema with a predicate function (e.g. z.instanceof). `isAsyncFunction` above is syntactic, so a plain function returning a promise reaches here, and a promise is truthy — it would read as a pass where the interpreter throws.
1742
- const fnConst = addConstant(ctx, def.fn);
1822
+ const fnConst = addUserConstant(ctx, def.fn);
1743
1823
  const throwAsyncConst = addConstant(ctx, throwAsync);
1744
1824
  const resVar = newVar(ctx);
1745
1825
  doc.write(`const ${resVar} = ${fnConst}(${accessor});`);
@@ -1776,7 +1856,7 @@ function generateCatchCheck(doc, ctx, schema, accessor) {
1776
1856
  });
1777
1857
  doc.write(`})();`);
1778
1858
  const innerConst = addConstant(ctx, def.innerType);
1779
- const catchConst = addConstant(ctx, def.catchValue);
1859
+ const catchConst = addUserConstant(ctx, def.catchValue);
1780
1860
  const catchHelperConst = addConstant(ctx, runtimeCatch);
1781
1861
  doc.write(`if (${outputVar} === INVALID) {`);
1782
1862
  doc.indented((d) => {
@@ -1803,7 +1883,7 @@ function generateTransformCheck(doc, ctx, schema, accessor) {
1803
1883
  return exports.INVALID;
1804
1884
  return fakePayload.issues.length === 0 ? result : exports.INVALID;
1805
1885
  };
1806
- const helperConst = addConstant(ctx, helperFn);
1886
+ const helperConst = addUserConstant(ctx, helperFn);
1807
1887
  const outputVar = newVar(ctx);
1808
1888
  doc.write(`const ${outputVar} = ${helperConst}(${accessor});`);
1809
1889
  doc.write(`if (${outputVar} === INVALID) return INVALID;`);
@@ -1811,3 +1891,22 @@ function generateTransformCheck(doc, ctx, schema, accessor) {
1811
1891
  }
1812
1892
  return accessor;
1813
1893
  }
1894
+
1895
+ // seal-cjs-exports
1896
+ (function () {
1897
+ var keys = Object.getOwnPropertyNames(exports);
1898
+ for (var i = 0; i < keys.length; i++) {
1899
+ var desc = Object.getOwnPropertyDescriptor(exports, keys[i]);
1900
+ if (!desc || !desc.get || !desc.configurable) continue;
1901
+ var value;
1902
+ try {
1903
+ value = desc.get();
1904
+ } catch (e) {
1905
+ continue;
1906
+ }
1907
+ // a circular require may not have settled this one yet, so leave it live
1908
+ if (value === undefined) continue;
1909
+ Object.defineProperty(exports, keys[i], { value: value, writable: false, enumerable: desc.enumerable, configurable: false });
1910
+ }
1911
+ Object.freeze(exports);
1912
+ })();
@@ -1,7 +1,8 @@
1
1
  import type * as core from "./core.cjs";
2
2
  import type { SomeType } from "./schemas.cjs";
3
- /** Sentinel value returned by the compiled fast path when validation fails. Internal. */
3
+ /** @internal Sentinel the compiled fast path returns when validation fails. */
4
4
  export declare const INVALID: unique symbol;
5
+ /** @internal */
5
6
  export type INVALID = typeof INVALID;
6
7
  interface CompileFnOptions {
7
8
  debug?: boolean | undefined;
@@ -10,6 +11,8 @@ interface CompileFnOptions {
10
11
  }
11
12
  type CompiledFn<T> = ((input: unknown) => T | INVALID) & {
12
13
  code?: string | undefined;
14
+ /** False when this function's INVALID does not strictly mean "the runtime would reject". */
15
+ definite?: boolean | undefined;
13
16
  };
14
17
  /** Raised when the schema contains async refinements or transforms. Surfaces only under `compile(schema, { strict: true })`. */
15
18
  export declare class ZodCompileAsyncError extends Error {
@@ -43,9 +46,20 @@ export interface CompileOptions {
43
46
  */
44
47
  export declare function compile<T extends SomeType>(schema: T, options?: CompileOptions): T;
45
48
  /**
46
- * Generate the standalone compiled function: a parser by default, a validator under
47
- * `assertOnly`. Returns either the parsed value, `true` where nothing reads the output,
48
- * or the `INVALID` sentinel. Internal — consumers should use `compile()`.
49
+ * Install an already-generated parser as a schema's fast path. Returns a clone; the original is
50
+ * unchanged.
51
+ *
52
+ * The parser takes the input and returns the parsed value, or `INVALID` to hand the parse to the
53
+ * runtime. It must be synchronous and forward-direction, and it must build fresh output rather than
54
+ * return its input — Zod cannot check either, and a wrong *success* is returned to the caller as-is.
55
+ *
56
+ * `compile()` is the ordinary entry point. This is for a build-time or native compiler that produces
57
+ * a parser where `new Function` is unavailable.
58
+ */
59
+ export declare function withParser<T extends SomeType>(schema: T, parser: (input: unknown) => core.output<T> | INVALID): T;
60
+ /**
61
+ * @internal Generate the standalone compiled function: a parser by default, a validator under
62
+ * `assertOnly`. Returns the parsed value, `true` where nothing reads the output, or `INVALID`. Consumers use `compile()`.
49
63
  */
50
64
  export declare function compileFn<T extends SomeType>(schema: T, options?: CompileFnOptions): CompiledFn<core.output<T>>;
51
65
  export {};
@@ -1,7 +1,8 @@
1
1
  import type * as core from "./core.js";
2
2
  import type { SomeType } from "./schemas.js";
3
- /** Sentinel value returned by the compiled fast path when validation fails. Internal. */
3
+ /** @internal Sentinel the compiled fast path returns when validation fails. */
4
4
  export declare const INVALID: unique symbol;
5
+ /** @internal */
5
6
  export type INVALID = typeof INVALID;
6
7
  interface CompileFnOptions {
7
8
  debug?: boolean | undefined;
@@ -10,6 +11,8 @@ interface CompileFnOptions {
10
11
  }
11
12
  type CompiledFn<T> = ((input: unknown) => T | INVALID) & {
12
13
  code?: string | undefined;
14
+ /** False when this function's INVALID does not strictly mean "the runtime would reject". */
15
+ definite?: boolean | undefined;
13
16
  };
14
17
  /** Raised when the schema contains async refinements or transforms. Surfaces only under `compile(schema, { strict: true })`. */
15
18
  export declare class ZodCompileAsyncError extends Error {
@@ -43,9 +46,20 @@ export interface CompileOptions {
43
46
  */
44
47
  export declare function compile<T extends SomeType>(schema: T, options?: CompileOptions): T;
45
48
  /**
46
- * Generate the standalone compiled function: a parser by default, a validator under
47
- * `assertOnly`. Returns either the parsed value, `true` where nothing reads the output,
48
- * or the `INVALID` sentinel. Internal — consumers should use `compile()`.
49
+ * Install an already-generated parser as a schema's fast path. Returns a clone; the original is
50
+ * unchanged.
51
+ *
52
+ * The parser takes the input and returns the parsed value, or `INVALID` to hand the parse to the
53
+ * runtime. It must be synchronous and forward-direction, and it must build fresh output rather than
54
+ * return its input — Zod cannot check either, and a wrong *success* is returned to the caller as-is.
55
+ *
56
+ * `compile()` is the ordinary entry point. This is for a build-time or native compiler that produces
57
+ * a parser where `new Function` is unavailable.
58
+ */
59
+ export declare function withParser<T extends SomeType>(schema: T, parser: (input: unknown) => core.output<T> | INVALID): T;
60
+ /**
61
+ * @internal Generate the standalone compiled function: a parser by default, a validator under
62
+ * `assertOnly`. Returns the parsed value, `true` where nothing reads the output, or `INVALID`. Consumers use `compile()`.
49
63
  */
50
64
  export declare function compileFn<T extends SomeType>(schema: T, options?: CompileFnOptions): CompiledFn<core.output<T>>;
51
65
  export {};