zod-compiler 1.23.0 → 1.23.2

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 (494) hide show
  1. package/README.md +9 -6
  2. package/dist/cli/commands/check.d.ts +10 -7
  3. package/dist/cli/commands/check.d.ts.map +1 -1
  4. package/dist/cli/commands/check.js +125 -148
  5. package/dist/cli/commands/check.js.map +1 -1
  6. package/dist/cli/commands/generate.d.ts +22 -19
  7. package/dist/cli/commands/generate.d.ts.map +1 -1
  8. package/dist/cli/commands/generate.js +102 -133
  9. package/dist/cli/commands/generate.js.map +1 -1
  10. package/dist/cli/commands/watch.d.ts +17 -15
  11. package/dist/cli/commands/watch.d.ts.map +1 -1
  12. package/dist/cli/commands/watch.js +126 -154
  13. package/dist/cli/commands/watch.js.map +1 -1
  14. package/dist/cli/emitter.d.ts +19 -16
  15. package/dist/cli/emitter.d.ts.map +1 -1
  16. package/dist/cli/emitter.js +55 -71
  17. package/dist/cli/emitter.js.map +1 -1
  18. package/dist/cli/errors.d.ts +4 -1
  19. package/dist/cli/errors.d.ts.map +1 -1
  20. package/dist/cli/errors.js +6 -2
  21. package/dist/cli/errors.js.map +1 -1
  22. package/dist/cli/index.d.ts +1 -3
  23. package/dist/cli/index.js +147 -160
  24. package/dist/cli/index.js.map +1 -1
  25. package/dist/cli/logger.d.ts +18 -15
  26. package/dist/cli/logger.d.ts.map +1 -1
  27. package/dist/cli/logger.js +38 -37
  28. package/dist/cli/logger.js.map +1 -1
  29. package/dist/core/codegen/build-path.d.ts +7 -41
  30. package/dist/core/codegen/build-path.d.ts.map +1 -1
  31. package/dist/core/codegen/build-path.js +481 -570
  32. package/dist/core/codegen/build-path.js.map +1 -1
  33. package/dist/core/codegen/context.d.ts +256 -253
  34. package/dist/core/codegen/context.d.ts.map +1 -1
  35. package/dist/core/codegen/context.js +363 -437
  36. package/dist/core/codegen/context.js.map +1 -1
  37. package/dist/core/codegen/dedupe.d.ts +22 -56
  38. package/dist/core/codegen/dedupe.d.ts.map +1 -1
  39. package/dist/core/codegen/dedupe.js +150 -242
  40. package/dist/core/codegen/dedupe.js.map +1 -1
  41. package/dist/core/codegen/emit-issue.d.ts +44 -68
  42. package/dist/core/codegen/emit-issue.d.ts.map +1 -1
  43. package/dist/core/codegen/emit-issue.js +76 -108
  44. package/dist/core/codegen/emit-issue.js.map +1 -1
  45. package/dist/core/codegen/emit.d.ts +4 -1
  46. package/dist/core/codegen/emit.d.ts.map +1 -1
  47. package/dist/core/codegen/emit.js +16 -13
  48. package/dist/core/codegen/emit.js.map +1 -1
  49. package/dist/core/codegen/fast-path.d.ts +7 -12
  50. package/dist/core/codegen/fast-path.d.ts.map +1 -1
  51. package/dist/core/codegen/fast-path.js +116 -145
  52. package/dist/core/codegen/fast-path.js.map +1 -1
  53. package/dist/core/codegen/fast-size.d.ts +12 -26
  54. package/dist/core/codegen/fast-size.d.ts.map +1 -1
  55. package/dist/core/codegen/fast-size.js +169 -244
  56. package/dist/core/codegen/fast-size.js.map +1 -1
  57. package/dist/core/codegen/index.d.ts +25 -23
  58. package/dist/core/codegen/index.d.ts.map +1 -1
  59. package/dist/core/codegen/index.js +239 -405
  60. package/dist/core/codegen/index.js.map +1 -1
  61. package/dist/core/codegen/issue-decls.d.ts +15 -12
  62. package/dist/core/codegen/issue-decls.d.ts.map +1 -1
  63. package/dist/core/codegen/issue-decls.js +131 -162
  64. package/dist/core/codegen/issue-decls.js.map +1 -1
  65. package/dist/core/codegen/regex-unroll.d.ts +4 -1
  66. package/dist/core/codegen/regex-unroll.d.ts.map +1 -1
  67. package/dist/core/codegen/regex-unroll.js +173 -197
  68. package/dist/core/codegen/regex-unroll.js.map +1 -1
  69. package/dist/core/codegen/schemas/any.d.ts +7 -4
  70. package/dist/core/codegen/schemas/any.d.ts.map +1 -1
  71. package/dist/core/codegen/schemas/any.js +8 -4
  72. package/dist/core/codegen/schemas/any.js.map +1 -1
  73. package/dist/core/codegen/schemas/array.d.ts +8 -5
  74. package/dist/core/codegen/schemas/array.d.ts.map +1 -1
  75. package/dist/core/codegen/schemas/array.js +77 -95
  76. package/dist/core/codegen/schemas/array.js.map +1 -1
  77. package/dist/core/codegen/schemas/bigint.d.ts +7 -4
  78. package/dist/core/codegen/schemas/bigint.d.ts.map +1 -1
  79. package/dist/core/codegen/schemas/bigint.js +44 -56
  80. package/dist/core/codegen/schemas/bigint.js.map +1 -1
  81. package/dist/core/codegen/schemas/boolean.d.ts +7 -4
  82. package/dist/core/codegen/schemas/boolean.d.ts.map +1 -1
  83. package/dist/core/codegen/schemas/boolean.js +12 -11
  84. package/dist/core/codegen/schemas/boolean.js.map +1 -1
  85. package/dist/core/codegen/schemas/catch.d.ts +8 -5
  86. package/dist/core/codegen/schemas/catch.d.ts.map +1 -1
  87. package/dist/core/codegen/schemas/catch.js +23 -23
  88. package/dist/core/codegen/schemas/catch.js.map +1 -1
  89. package/dist/core/codegen/schemas/date.d.ts +7 -4
  90. package/dist/core/codegen/schemas/date.d.ts.map +1 -1
  91. package/dist/core/codegen/schemas/date.js +49 -68
  92. package/dist/core/codegen/schemas/date.js.map +1 -1
  93. package/dist/core/codegen/schemas/default.d.ts +9 -6
  94. package/dist/core/codegen/schemas/default.d.ts.map +1 -1
  95. package/dist/core/codegen/schemas/default.js +29 -27
  96. package/dist/core/codegen/schemas/default.js.map +1 -1
  97. package/dist/core/codegen/schemas/discriminated-union.d.ts +12 -10
  98. package/dist/core/codegen/schemas/discriminated-union.d.ts.map +1 -1
  99. package/dist/core/codegen/schemas/discriminated-union.js +153 -178
  100. package/dist/core/codegen/schemas/discriminated-union.js.map +1 -1
  101. package/dist/core/codegen/schemas/effect.d.ts +9 -6
  102. package/dist/core/codegen/schemas/effect.d.ts.map +1 -1
  103. package/dist/core/codegen/schemas/effect.js +54 -67
  104. package/dist/core/codegen/schemas/effect.js.map +1 -1
  105. package/dist/core/codegen/schemas/enum.d.ts +7 -4
  106. package/dist/core/codegen/schemas/enum.d.ts.map +1 -1
  107. package/dist/core/codegen/schemas/enum.js +15 -21
  108. package/dist/core/codegen/schemas/enum.js.map +1 -1
  109. package/dist/core/codegen/schemas/fallback.d.ts +6 -3
  110. package/dist/core/codegen/schemas/fallback.d.ts.map +1 -1
  111. package/dist/core/codegen/schemas/fallback.js +14 -13
  112. package/dist/core/codegen/schemas/fallback.js.map +1 -1
  113. package/dist/core/codegen/schemas/file.d.ts +7 -4
  114. package/dist/core/codegen/schemas/file.d.ts.map +1 -1
  115. package/dist/core/codegen/schemas/file.js +51 -57
  116. package/dist/core/codegen/schemas/file.js.map +1 -1
  117. package/dist/core/codegen/schemas/intersection.d.ts +8 -5
  118. package/dist/core/codegen/schemas/intersection.d.ts.map +1 -1
  119. package/dist/core/codegen/schemas/intersection.js +16 -13
  120. package/dist/core/codegen/schemas/intersection.js.map +1 -1
  121. package/dist/core/codegen/schemas/literal.d.ts +7 -4
  122. package/dist/core/codegen/schemas/literal.d.ts.map +1 -1
  123. package/dist/core/codegen/schemas/literal.js +20 -23
  124. package/dist/core/codegen/schemas/literal.js.map +1 -1
  125. package/dist/core/codegen/schemas/map.d.ts +8 -5
  126. package/dist/core/codegen/schemas/map.d.ts.map +1 -1
  127. package/dist/core/codegen/schemas/map.js +61 -67
  128. package/dist/core/codegen/schemas/map.js.map +1 -1
  129. package/dist/core/codegen/schemas/nan.d.ts +7 -4
  130. package/dist/core/codegen/schemas/nan.d.ts.map +1 -1
  131. package/dist/core/codegen/schemas/nan.js +8 -4
  132. package/dist/core/codegen/schemas/nan.js.map +1 -1
  133. package/dist/core/codegen/schemas/never.d.ts +7 -4
  134. package/dist/core/codegen/schemas/never.d.ts.map +1 -1
  135. package/dist/core/codegen/schemas/never.js +8 -4
  136. package/dist/core/codegen/schemas/never.js.map +1 -1
  137. package/dist/core/codegen/schemas/null.d.ts +7 -4
  138. package/dist/core/codegen/schemas/null.d.ts.map +1 -1
  139. package/dist/core/codegen/schemas/null.js +8 -4
  140. package/dist/core/codegen/schemas/null.js.map +1 -1
  141. package/dist/core/codegen/schemas/nullable.d.ts +8 -5
  142. package/dist/core/codegen/schemas/nullable.d.ts.map +1 -1
  143. package/dist/core/codegen/schemas/nullable.js +8 -5
  144. package/dist/core/codegen/schemas/nullable.js.map +1 -1
  145. package/dist/core/codegen/schemas/number.d.ts +7 -4
  146. package/dist/core/codegen/schemas/number.d.ts.map +1 -1
  147. package/dist/core/codegen/schemas/number.js +120 -176
  148. package/dist/core/codegen/schemas/number.js.map +1 -1
  149. package/dist/core/codegen/schemas/object.d.ts +8 -5
  150. package/dist/core/codegen/schemas/object.d.ts.map +1 -1
  151. package/dist/core/codegen/schemas/object.js +144 -231
  152. package/dist/core/codegen/schemas/object.js.map +1 -1
  153. package/dist/core/codegen/schemas/optional.d.ts +9 -6
  154. package/dist/core/codegen/schemas/optional.d.ts.map +1 -1
  155. package/dist/core/codegen/schemas/optional.js +23 -31
  156. package/dist/core/codegen/schemas/optional.js.map +1 -1
  157. package/dist/core/codegen/schemas/pipe.d.ts +8 -5
  158. package/dist/core/codegen/schemas/pipe.d.ts.map +1 -1
  159. package/dist/core/codegen/schemas/pipe.js +20 -27
  160. package/dist/core/codegen/schemas/pipe.js.map +1 -1
  161. package/dist/core/codegen/schemas/readonly.d.ts +8 -5
  162. package/dist/core/codegen/schemas/readonly.d.ts.map +1 -1
  163. package/dist/core/codegen/schemas/readonly.js +8 -5
  164. package/dist/core/codegen/schemas/readonly.js.map +1 -1
  165. package/dist/core/codegen/schemas/record.d.ts +8 -5
  166. package/dist/core/codegen/schemas/record.d.ts.map +1 -1
  167. package/dist/core/codegen/schemas/record.js +52 -65
  168. package/dist/core/codegen/schemas/record.js.map +1 -1
  169. package/dist/core/codegen/schemas/recursive-ref.d.ts +9 -6
  170. package/dist/core/codegen/schemas/recursive-ref.d.ts.map +1 -1
  171. package/dist/core/codegen/schemas/recursive-ref.js +44 -44
  172. package/dist/core/codegen/schemas/recursive-ref.js.map +1 -1
  173. package/dist/core/codegen/schemas/set.d.ts +8 -5
  174. package/dist/core/codegen/schemas/set.d.ts.map +1 -1
  175. package/dist/core/codegen/schemas/set.js +61 -73
  176. package/dist/core/codegen/schemas/set.js.map +1 -1
  177. package/dist/core/codegen/schemas/string-bool.d.ts +6 -3
  178. package/dist/core/codegen/schemas/string-bool.d.ts.map +1 -1
  179. package/dist/core/codegen/schemas/string-bool.js +22 -23
  180. package/dist/core/codegen/schemas/string-bool.js.map +1 -1
  181. package/dist/core/codegen/schemas/string.d.ts +8 -5
  182. package/dist/core/codegen/schemas/string.d.ts.map +1 -1
  183. package/dist/core/codegen/schemas/string.js +168 -207
  184. package/dist/core/codegen/schemas/string.js.map +1 -1
  185. package/dist/core/codegen/schemas/symbol.d.ts +7 -4
  186. package/dist/core/codegen/schemas/symbol.d.ts.map +1 -1
  187. package/dist/core/codegen/schemas/symbol.js +8 -4
  188. package/dist/core/codegen/schemas/symbol.js.map +1 -1
  189. package/dist/core/codegen/schemas/template-literal.d.ts +7 -4
  190. package/dist/core/codegen/schemas/template-literal.d.ts.map +1 -1
  191. package/dist/core/codegen/schemas/template-literal.js +12 -13
  192. package/dist/core/codegen/schemas/template-literal.js.map +1 -1
  193. package/dist/core/codegen/schemas/tuple.d.ts +8 -5
  194. package/dist/core/codegen/schemas/tuple.d.ts.map +1 -1
  195. package/dist/core/codegen/schemas/tuple.js +84 -94
  196. package/dist/core/codegen/schemas/tuple.js.map +1 -1
  197. package/dist/core/codegen/schemas/undefined.d.ts +7 -4
  198. package/dist/core/codegen/schemas/undefined.d.ts.map +1 -1
  199. package/dist/core/codegen/schemas/undefined.js +8 -4
  200. package/dist/core/codegen/schemas/undefined.js.map +1 -1
  201. package/dist/core/codegen/schemas/union.d.ts +8 -5
  202. package/dist/core/codegen/schemas/union.d.ts.map +1 -1
  203. package/dist/core/codegen/schemas/union.js +49 -69
  204. package/dist/core/codegen/schemas/union.js.map +1 -1
  205. package/dist/core/codegen/schemas/unknown.d.ts +7 -4
  206. package/dist/core/codegen/schemas/unknown.d.ts.map +1 -1
  207. package/dist/core/codegen/schemas/unknown.js +8 -4
  208. package/dist/core/codegen/schemas/unknown.js.map +1 -1
  209. package/dist/core/codegen/schemas/void.d.ts +7 -4
  210. package/dist/core/codegen/schemas/void.d.ts.map +1 -1
  211. package/dist/core/codegen/schemas/void.js +8 -4
  212. package/dist/core/codegen/schemas/void.js.map +1 -1
  213. package/dist/core/codegen/slow-path.d.ts +7 -4
  214. package/dist/core/codegen/slow-path.d.ts.map +1 -1
  215. package/dist/core/codegen/slow-path.js +71 -96
  216. package/dist/core/codegen/slow-path.js.map +1 -1
  217. package/dist/core/codegen/well-known-regex.d.ts +22 -19
  218. package/dist/core/codegen/well-known-regex.d.ts.map +1 -1
  219. package/dist/core/codegen/well-known-regex.js +127 -96
  220. package/dist/core/codegen/well-known-regex.js.map +1 -1
  221. package/dist/core/compile.d.ts +7 -4
  222. package/dist/core/compile.d.ts.map +1 -1
  223. package/dist/core/compile.js +48 -48
  224. package/dist/core/compile.js.map +1 -1
  225. package/dist/core/diagnostic.d.ts +38 -39
  226. package/dist/core/diagnostic.d.ts.map +1 -1
  227. package/dist/core/diagnostic.js +140 -164
  228. package/dist/core/diagnostic.js.map +1 -1
  229. package/dist/core/extract/checks.d.ts +18 -15
  230. package/dist/core/extract/checks.d.ts.map +1 -1
  231. package/dist/core/extract/checks.js +318 -311
  232. package/dist/core/extract/checks.js.map +1 -1
  233. package/dist/core/extract/effects.d.ts +13 -10
  234. package/dist/core/extract/effects.d.ts.map +1 -1
  235. package/dist/core/extract/effects.js +153 -222
  236. package/dist/core/extract/effects.js.map +1 -1
  237. package/dist/core/extract/extractors/any.d.ts +5 -2
  238. package/dist/core/extract/extractors/any.d.ts.map +1 -1
  239. package/dist/core/extract/extractors/any.js +5 -1
  240. package/dist/core/extract/extractors/any.js.map +1 -1
  241. package/dist/core/extract/extractors/array.d.ts +6 -3
  242. package/dist/core/extract/extractors/array.d.ts.map +1 -1
  243. package/dist/core/extract/extractors/array.js +25 -20
  244. package/dist/core/extract/extractors/array.js.map +1 -1
  245. package/dist/core/extract/extractors/bigint.d.ts +6 -3
  246. package/dist/core/extract/extractors/bigint.d.ts.map +1 -1
  247. package/dist/core/extract/extractors/bigint.js +66 -64
  248. package/dist/core/extract/extractors/bigint.js.map +1 -1
  249. package/dist/core/extract/extractors/boolean.d.ts +5 -2
  250. package/dist/core/extract/extractors/boolean.d.ts.map +1 -1
  251. package/dist/core/extract/extractors/boolean.js +7 -3
  252. package/dist/core/extract/extractors/boolean.js.map +1 -1
  253. package/dist/core/extract/extractors/catch.d.ts +6 -3
  254. package/dist/core/extract/extractors/catch.d.ts.map +1 -1
  255. package/dist/core/extract/extractors/catch.js +26 -17
  256. package/dist/core/extract/extractors/catch.js.map +1 -1
  257. package/dist/core/extract/extractors/date.d.ts +6 -3
  258. package/dist/core/extract/extractors/date.d.ts.map +1 -1
  259. package/dist/core/extract/extractors/date.js +42 -46
  260. package/dist/core/extract/extractors/date.js.map +1 -1
  261. package/dist/core/extract/extractors/default.d.ts +6 -3
  262. package/dist/core/extract/extractors/default.d.ts.map +1 -1
  263. package/dist/core/extract/extractors/default.js +20 -14
  264. package/dist/core/extract/extractors/default.js.map +1 -1
  265. package/dist/core/extract/extractors/enum.d.ts +5 -2
  266. package/dist/core/extract/extractors/enum.d.ts.map +1 -1
  267. package/dist/core/extract/extractors/enum.js +12 -13
  268. package/dist/core/extract/extractors/enum.js.map +1 -1
  269. package/dist/core/extract/extractors/file.d.ts +6 -3
  270. package/dist/core/extract/extractors/file.d.ts.map +1 -1
  271. package/dist/core/extract/extractors/file.js +34 -28
  272. package/dist/core/extract/extractors/file.js.map +1 -1
  273. package/dist/core/extract/extractors/intersection.d.ts +5 -2
  274. package/dist/core/extract/extractors/intersection.d.ts.map +1 -1
  275. package/dist/core/extract/extractors/intersection.js +13 -11
  276. package/dist/core/extract/extractors/intersection.js.map +1 -1
  277. package/dist/core/extract/extractors/lazy.d.ts +6 -3
  278. package/dist/core/extract/extractors/lazy.d.ts.map +1 -1
  279. package/dist/core/extract/extractors/lazy.js +21 -30
  280. package/dist/core/extract/extractors/lazy.js.map +1 -1
  281. package/dist/core/extract/extractors/literal.d.ts +5 -2
  282. package/dist/core/extract/extractors/literal.d.ts.map +1 -1
  283. package/dist/core/extract/extractors/literal.js +8 -1
  284. package/dist/core/extract/extractors/literal.js.map +1 -1
  285. package/dist/core/extract/extractors/map.d.ts +6 -3
  286. package/dist/core/extract/extractors/map.d.ts.map +1 -1
  287. package/dist/core/extract/extractors/map.js +10 -4
  288. package/dist/core/extract/extractors/map.js.map +1 -1
  289. package/dist/core/extract/extractors/nan.d.ts +5 -2
  290. package/dist/core/extract/extractors/nan.d.ts.map +1 -1
  291. package/dist/core/extract/extractors/nan.js +5 -1
  292. package/dist/core/extract/extractors/nan.js.map +1 -1
  293. package/dist/core/extract/extractors/never.d.ts +5 -2
  294. package/dist/core/extract/extractors/never.d.ts.map +1 -1
  295. package/dist/core/extract/extractors/never.js +5 -1
  296. package/dist/core/extract/extractors/never.js.map +1 -1
  297. package/dist/core/extract/extractors/null.d.ts +5 -2
  298. package/dist/core/extract/extractors/null.d.ts.map +1 -1
  299. package/dist/core/extract/extractors/null.js +5 -1
  300. package/dist/core/extract/extractors/null.js.map +1 -1
  301. package/dist/core/extract/extractors/nullable.d.ts +5 -2
  302. package/dist/core/extract/extractors/nullable.d.ts.map +1 -1
  303. package/dist/core/extract/extractors/nullable.js +7 -3
  304. package/dist/core/extract/extractors/nullable.js.map +1 -1
  305. package/dist/core/extract/extractors/number.d.ts +6 -3
  306. package/dist/core/extract/extractors/number.d.ts.map +1 -1
  307. package/dist/core/extract/extractors/number.js +35 -35
  308. package/dist/core/extract/extractors/number.js.map +1 -1
  309. package/dist/core/extract/extractors/object.d.ts +6 -3
  310. package/dist/core/extract/extractors/object.d.ts.map +1 -1
  311. package/dist/core/extract/extractors/object.js +49 -76
  312. package/dist/core/extract/extractors/object.js.map +1 -1
  313. package/dist/core/extract/extractors/optional.d.ts +5 -2
  314. package/dist/core/extract/extractors/optional.d.ts.map +1 -1
  315. package/dist/core/extract/extractors/optional.js +10 -12
  316. package/dist/core/extract/extractors/optional.js.map +1 -1
  317. package/dist/core/extract/extractors/pipe.d.ts +6 -3
  318. package/dist/core/extract/extractors/pipe.d.ts.map +1 -1
  319. package/dist/core/extract/extractors/pipe.js +40 -41
  320. package/dist/core/extract/extractors/pipe.js.map +1 -1
  321. package/dist/core/extract/extractors/readonly.d.ts +5 -2
  322. package/dist/core/extract/extractors/readonly.d.ts.map +1 -1
  323. package/dist/core/extract/extractors/readonly.js +10 -6
  324. package/dist/core/extract/extractors/readonly.js.map +1 -1
  325. package/dist/core/extract/extractors/record.d.ts +6 -3
  326. package/dist/core/extract/extractors/record.d.ts.map +1 -1
  327. package/dist/core/extract/extractors/record.js +24 -35
  328. package/dist/core/extract/extractors/record.js.map +1 -1
  329. package/dist/core/extract/extractors/set.d.ts +6 -3
  330. package/dist/core/extract/extractors/set.d.ts.map +1 -1
  331. package/dist/core/extract/extractors/set.js +36 -30
  332. package/dist/core/extract/extractors/set.js.map +1 -1
  333. package/dist/core/extract/extractors/string-bool.d.ts +7 -4
  334. package/dist/core/extract/extractors/string-bool.d.ts.map +1 -1
  335. package/dist/core/extract/extractors/string-bool.js +66 -84
  336. package/dist/core/extract/extractors/string-bool.js.map +1 -1
  337. package/dist/core/extract/extractors/string.d.ts +6 -3
  338. package/dist/core/extract/extractors/string.d.ts.map +1 -1
  339. package/dist/core/extract/extractors/string.js +34 -37
  340. package/dist/core/extract/extractors/string.js.map +1 -1
  341. package/dist/core/extract/extractors/symbol.d.ts +5 -2
  342. package/dist/core/extract/extractors/symbol.d.ts.map +1 -1
  343. package/dist/core/extract/extractors/symbol.js +5 -1
  344. package/dist/core/extract/extractors/symbol.js.map +1 -1
  345. package/dist/core/extract/extractors/template-literal.d.ts +6 -3
  346. package/dist/core/extract/extractors/template-literal.d.ts.map +1 -1
  347. package/dist/core/extract/extractors/template-literal.js +11 -6
  348. package/dist/core/extract/extractors/template-literal.js.map +1 -1
  349. package/dist/core/extract/extractors/tuple.d.ts +6 -3
  350. package/dist/core/extract/extractors/tuple.d.ts.map +1 -1
  351. package/dist/core/extract/extractors/tuple.js +10 -4
  352. package/dist/core/extract/extractors/tuple.js.map +1 -1
  353. package/dist/core/extract/extractors/undefined.d.ts +5 -2
  354. package/dist/core/extract/extractors/undefined.d.ts.map +1 -1
  355. package/dist/core/extract/extractors/undefined.js +5 -1
  356. package/dist/core/extract/extractors/undefined.js.map +1 -1
  357. package/dist/core/extract/extractors/union.d.ts +6 -3
  358. package/dist/core/extract/extractors/union.d.ts.map +1 -1
  359. package/dist/core/extract/extractors/union.js +38 -64
  360. package/dist/core/extract/extractors/union.js.map +1 -1
  361. package/dist/core/extract/extractors/unknown.d.ts +5 -2
  362. package/dist/core/extract/extractors/unknown.d.ts.map +1 -1
  363. package/dist/core/extract/extractors/unknown.js +5 -1
  364. package/dist/core/extract/extractors/unknown.js.map +1 -1
  365. package/dist/core/extract/extractors/void.d.ts +5 -2
  366. package/dist/core/extract/extractors/void.d.ts.map +1 -1
  367. package/dist/core/extract/extractors/void.js +5 -1
  368. package/dist/core/extract/extractors/void.js.map +1 -1
  369. package/dist/core/extract/fallback.d.ts +6 -3
  370. package/dist/core/extract/fallback.d.ts.map +1 -1
  371. package/dist/core/extract/fallback.js +21 -7
  372. package/dist/core/extract/fallback.js.map +1 -1
  373. package/dist/core/extract/index.d.ts +6 -4
  374. package/dist/core/extract/index.d.ts.map +1 -1
  375. package/dist/core/extract/index.js +15 -15
  376. package/dist/core/extract/index.js.map +1 -1
  377. package/dist/core/extract/registry.d.ts +39 -36
  378. package/dist/core/extract/registry.d.ts.map +1 -1
  379. package/dist/core/extract/registry.js +96 -123
  380. package/dist/core/extract/registry.js.map +1 -1
  381. package/dist/core/extract/types.d.ts +124 -120
  382. package/dist/core/extract/types.d.ts.map +1 -1
  383. package/dist/core/extract/types.js +0 -1
  384. package/dist/core/iife.d.ts +14 -15
  385. package/dist/core/iife.d.ts.map +1 -1
  386. package/dist/core/iife.js +182 -206
  387. package/dist/core/iife.js.map +1 -1
  388. package/dist/core/pipeline.d.ts +33 -30
  389. package/dist/core/pipeline.d.ts.map +1 -1
  390. package/dist/core/pipeline.js +67 -74
  391. package/dist/core/pipeline.js.map +1 -1
  392. package/dist/core/types.d.ts +430 -427
  393. package/dist/core/types.d.ts.map +1 -1
  394. package/dist/core/types.js +0 -5
  395. package/dist/discovery.d.ts +8 -5
  396. package/dist/discovery.d.ts.map +1 -1
  397. package/dist/discovery.js +31 -32
  398. package/dist/discovery.js.map +1 -1
  399. package/dist/index.d.ts +4 -4
  400. package/dist/index.js +2 -2
  401. package/dist/jit.d.ts +15 -42
  402. package/dist/jit.d.ts.map +1 -1
  403. package/dist/jit.js +187 -216
  404. package/dist/jit.js.map +1 -1
  405. package/dist/loader.d.ts +14 -11
  406. package/dist/loader.d.ts.map +1 -1
  407. package/dist/loader.js +226 -258
  408. package/dist/loader.js.map +1 -1
  409. package/dist/static-filter.d.ts +4 -1
  410. package/dist/static-filter.d.ts.map +1 -1
  411. package/dist/static-filter.js +240 -367
  412. package/dist/static-filter.js.map +1 -1
  413. package/dist/swc.d.ts +38 -35
  414. package/dist/swc.d.ts.map +1 -1
  415. package/dist/swc.js +83 -76
  416. package/dist/swc.js.map +1 -1
  417. package/dist/unplugin/bun.d.ts +5 -2
  418. package/dist/unplugin/bun.d.ts.map +1 -1
  419. package/dist/unplugin/bun.js +5 -1
  420. package/dist/unplugin/bun.js.map +1 -1
  421. package/dist/unplugin/dep-graph.d.ts +10 -7
  422. package/dist/unplugin/dep-graph.d.ts.map +1 -1
  423. package/dist/unplugin/dep-graph.js +216 -252
  424. package/dist/unplugin/dep-graph.js.map +1 -1
  425. package/dist/unplugin/disk-cache.d.ts +121 -92
  426. package/dist/unplugin/disk-cache.d.ts.map +1 -1
  427. package/dist/unplugin/disk-cache.js +425 -444
  428. package/dist/unplugin/disk-cache.js.map +1 -1
  429. package/dist/unplugin/edits.d.ts +15 -12
  430. package/dist/unplugin/edits.d.ts.map +1 -1
  431. package/dist/unplugin/edits.js +24 -37
  432. package/dist/unplugin/edits.js.map +1 -1
  433. package/dist/unplugin/esbuild.d.ts +5 -2
  434. package/dist/unplugin/esbuild.d.ts.map +1 -1
  435. package/dist/unplugin/esbuild.js +5 -1
  436. package/dist/unplugin/esbuild.js.map +1 -1
  437. package/dist/unplugin/farm.d.ts +5 -2
  438. package/dist/unplugin/farm.d.ts.map +1 -1
  439. package/dist/unplugin/farm.js +5 -1
  440. package/dist/unplugin/farm.js.map +1 -1
  441. package/dist/unplugin/hoist-compile.d.ts +14 -42
  442. package/dist/unplugin/hoist-compile.d.ts.map +1 -1
  443. package/dist/unplugin/hoist-compile.js +67 -112
  444. package/dist/unplugin/hoist-compile.js.map +1 -1
  445. package/dist/unplugin/hoist.d.ts +56 -54
  446. package/dist/unplugin/hoist.d.ts.map +1 -1
  447. package/dist/unplugin/hoist.js +945 -1170
  448. package/dist/unplugin/hoist.js.map +1 -1
  449. package/dist/unplugin/index.d.ts +5 -3
  450. package/dist/unplugin/index.d.ts.map +1 -1
  451. package/dist/unplugin/index.js +175 -250
  452. package/dist/unplugin/index.js.map +1 -1
  453. package/dist/unplugin/rolldown.d.ts +5 -2
  454. package/dist/unplugin/rolldown.d.ts.map +1 -1
  455. package/dist/unplugin/rolldown.js +5 -1
  456. package/dist/unplugin/rolldown.js.map +1 -1
  457. package/dist/unplugin/rollup.d.ts +5 -2
  458. package/dist/unplugin/rollup.d.ts.map +1 -1
  459. package/dist/unplugin/rollup.js +5 -1
  460. package/dist/unplugin/rollup.js.map +1 -1
  461. package/dist/unplugin/rsbuild.d.ts +6 -3
  462. package/dist/unplugin/rsbuild.d.ts.map +1 -1
  463. package/dist/unplugin/rsbuild.js +15 -11
  464. package/dist/unplugin/rsbuild.js.map +1 -1
  465. package/dist/unplugin/rspack.d.ts +5 -2
  466. package/dist/unplugin/rspack.d.ts.map +1 -1
  467. package/dist/unplugin/rspack.js +5 -1
  468. package/dist/unplugin/rspack.js.map +1 -1
  469. package/dist/unplugin/transform.d.ts +30 -27
  470. package/dist/unplugin/transform.d.ts.map +1 -1
  471. package/dist/unplugin/transform.js +433 -620
  472. package/dist/unplugin/transform.js.map +1 -1
  473. package/dist/unplugin/types.d.ts +189 -184
  474. package/dist/unplugin/types.d.ts.map +1 -1
  475. package/dist/unplugin/types.js +22 -18
  476. package/dist/unplugin/types.js.map +1 -1
  477. package/dist/unplugin/virtual.d.ts +11 -8
  478. package/dist/unplugin/virtual.d.ts.map +1 -1
  479. package/dist/unplugin/virtual.js +65 -83
  480. package/dist/unplugin/virtual.js.map +1 -1
  481. package/dist/unplugin/vite.d.ts +5 -2
  482. package/dist/unplugin/vite.d.ts.map +1 -1
  483. package/dist/unplugin/vite.js +5 -1
  484. package/dist/unplugin/vite.js.map +1 -1
  485. package/dist/unplugin/webpack.d.ts +5 -2
  486. package/dist/unplugin/webpack.d.ts.map +1 -1
  487. package/dist/unplugin/webpack.js +5 -1
  488. package/dist/unplugin/webpack.js.map +1 -1
  489. package/package.json +23 -14
  490. package/dist/cli/index.d.ts.map +0 -1
  491. package/dist/core/extract/types.js.map +0 -1
  492. package/dist/core/types.js.map +0 -1
  493. package/dist/index.d.ts.map +0 -1
  494. package/dist/index.js.map +0 -1
@@ -1,1242 +1,1017 @@
1
- import { Parser } from "acorn";
2
1
  import { applyEdits } from "./edits.js";
2
+ import { Parser } from "acorn";
3
+ //#region src/unplugin/hoist.ts
3
4
  /**
4
- * Hoist Zod schema construction out of functions to module scope —
5
- * equivalent of babel-plugin-zod-hoist.
6
- *
7
- * Schemas built inside function bodies are re-constructed on every call:
8
- *
9
- * function getSchema() {
10
- * return z.object({ name: z.string() }); // rebuilt per call
11
- * }
12
- *
13
- * becomes
14
- *
15
- * const _zh_94b7f5c1 = z.object({ name: z.string() });
16
- * function getSchema() {
17
- * return _zh_94b7f5c1; // built once
18
- * }
19
- *
20
- * Safety rules (babel-plugin-zod-hoist's `canSafelyHoist`, hardened for
21
- * lexical analysis):
22
- * - A free identifier must be an import or a KNOWN_GLOBALS member, and must
23
- * never be bound anywhere in the file (function params, locals, catch
24
- * clauses, class names, module-level const/let/var — hoisting above those
25
- * would change meaning or hit the TDZ). The babel plugin additionally
26
- * allows arbitrary unbound identifiers because it has real scope
27
- * information; this port's binding collector is lexical, so an unknown
28
- * bare name is treated as a possibly-missed binding rather than a global
29
- * (a wrong guess crashes at module load with a ReferenceError).
30
- * `this`/`super` disqualify anywhere. Eager `await`/`yield` also
31
- * disqualify (stricter than the babel plugin, which never encounters
32
- * them: hoisting one would emit top-level await / orphaned yield).
33
- * - Eligible roots: any binding imported from zod, an imported identifier
34
- * matching /ZodSchema$/, or an imported identifier whose chain contains
35
- * an inline z.* reference (e.g. `Base.extend({ a: z.string() })`).
36
- * - Nesting (babel's `isNestedInZodCall`): the interior of a zod-rooted
37
- * chain never hoists separately — it goes with the outer schema or not at
38
- * all. Chains rooted elsewhere (`sql.type(...)`, `api.get(...)`) do NOT
39
- * suppress their arguments: when the outer chain is rejected, an inner
40
- * `z.object({...})` still hoists on its own.
41
- * - Declarations are inserted at the top of the module (after shebang and
42
- * directive prologue). Imports are initialized before module code runs,
43
- * so referencing them from above their textual position is safe.
44
- * - Names are content-hashed, so identical schemas dedupe to one binding.
45
- *
46
- * The source is TypeScript, which acorn cannot fully parse — candidates are
47
- * located with a string/comment/depth-aware scanner and extracted with
48
- * parseExpressionAt (the same technique as the autoDiscover rewrite).
49
- * Anything unparseable (TS generics, `as` casts) is skipped: a miss leaves
50
- * the schema unhoisted, never breaks the code.
51
- */
5
+ * Hoist Zod schema construction out of functions to module scope —
6
+ * equivalent of babel-plugin-zod-hoist.
7
+ *
8
+ * Schemas built inside function bodies are re-constructed on every call:
9
+ *
10
+ * function getSchema() {
11
+ * return z.object({ name: z.string() }); // rebuilt per call
12
+ * }
13
+ *
14
+ * becomes
15
+ *
16
+ * const _zh_94b7f5c1 = z.object({ name: z.string() });
17
+ * function getSchema() {
18
+ * return _zh_94b7f5c1; // built once
19
+ * }
20
+ *
21
+ * Safety rules (babel-plugin-zod-hoist's `canSafelyHoist`, hardened for
22
+ * lexical analysis):
23
+ * - A free identifier must be an import or a KNOWN_GLOBALS member, and must
24
+ * never be bound anywhere in the file (function params, locals, catch
25
+ * clauses, class names, module-level const/let/var — hoisting above those
26
+ * would change meaning or hit the TDZ). The babel plugin additionally
27
+ * allows arbitrary unbound identifiers because it has real scope
28
+ * information; this port's binding collector is lexical, so an unknown
29
+ * bare name is treated as a possibly-missed binding rather than a global
30
+ * (a wrong guess crashes at module load with a ReferenceError).
31
+ * `this`/`super` disqualify anywhere. Eager `await`/`yield` also
32
+ * disqualify (stricter than the babel plugin, which never encounters
33
+ * them: hoisting one would emit top-level await / orphaned yield).
34
+ * - Eligible roots: any binding imported from zod, an imported identifier
35
+ * matching /ZodSchema$/, or an imported identifier whose chain contains
36
+ * an inline z.* reference (e.g. `Base.extend({ a: z.string() })`).
37
+ * - Nesting (babel's `isNestedInZodCall`): the interior of a zod-rooted
38
+ * chain never hoists separately — it goes with the outer schema or not at
39
+ * all. Chains rooted elsewhere (`sql.type(...)`, `api.get(...)`) do NOT
40
+ * suppress their arguments: when the outer chain is rejected, an inner
41
+ * `z.object({...})` still hoists on its own.
42
+ * - Declarations are inserted at the top of the module (after shebang and
43
+ * directive prologue). Imports are initialized before module code runs,
44
+ * so referencing them from above their textual position is safe.
45
+ * - Names are content-hashed, so identical schemas dedupe to one binding.
46
+ *
47
+ * The source is TypeScript, which acorn cannot fully parse — candidates are
48
+ * located with a string/comment/depth-aware scanner and extracted with
49
+ * parseExpressionAt (the same technique as the autoDiscover rewrite).
50
+ * Anything unparseable (TS generics, `as` casts) is skipped: a miss leaves
51
+ * the schema unhoisted, never breaks the code.
52
+ */
52
53
  /**
53
- * Imported identifiers matching this pattern are treated as schema roots.
54
- *
55
- * The default must keep implying a "Zod" substring: it is one of the three
56
- * triggers the transform hook's `code` filter (ZOD_MENTION in transform.ts)
57
- * is a superset of. A default that matched, say, `/Schema$/` would make
58
- * hoistable files without any "zod" mention invisible to bundlers with native
59
- * hook filters. (A *user-supplied* pattern is handled — it drops the filter.)
60
- */
61
- export const SCHEMA_NAME_PATTERN = /ZodSchema$/;
54
+ * Imported identifiers matching this pattern are treated as schema roots.
55
+ *
56
+ * The default must keep implying a "Zod" substring: it is one of the three
57
+ * triggers the transform hook's `code` filter (ZOD_MENTION in transform.ts)
58
+ * is a superset of. A default that matched, say, `/Schema$/` would make
59
+ * hoistable files without any "zod" mention invisible to bundlers with native
60
+ * hook filters. (A *user-supplied* pattern is handled — it drops the filter.)
61
+ */
62
+ const SCHEMA_NAME_PATTERN = /ZodSchema$/;
62
63
  /**
63
- * Module specifiers whose bindings count as the zod namespace. Every entry
64
- * must contain "zod" for the same reason as SCHEMA_NAME_PATTERN above; both
65
- * are pinned by `describe("code filter soundness")` in the transform tests.
66
- */
67
- export const ZOD_MODULES = new Set(["zod", "zod/v3", "zod/v4", "zod/mini", "zod/v4/mini"]);
64
+ * Module specifiers whose bindings count as the zod namespace. Every entry
65
+ * must contain "zod" for the same reason as SCHEMA_NAME_PATTERN above; both
66
+ * are pinned by `describe("code filter soundness")` in the transform tests.
67
+ */
68
+ const ZOD_MODULES = /* @__PURE__ */ new Set([
69
+ "zod",
70
+ "zod/v3",
71
+ "zod/v4",
72
+ "zod/mini",
73
+ "zod/v4/mini"
74
+ ]);
68
75
  /**
69
- * Collect runtime import bindings with a regex over import statements.
70
- * Type-only imports and `type` specifiers are excluded — they cannot be
71
- * referenced at runtime, so excluding them keeps the capture rule sound.
72
- */
73
- export function collectImportBindings(code) {
74
- const all = new Set();
75
- const zod = new Set();
76
- const details = new Map();
77
- const importPattern = /import\s+(type\s+)?([^'";]+?)\s+from\s*["']([^"']+)["']/g;
78
- for (const match of code.matchAll(importPattern)) {
79
- const [, typeOnly, clause, specifier] = match;
80
- if (typeOnly || clause === undefined || specifier === undefined)
81
- continue;
82
- const isZod = ZOD_MODULES.has(specifier);
83
- for (const { local, imported } of parseImportClause(clause)) {
84
- all.add(local);
85
- if (isZod)
86
- zod.add(local);
87
- details.set(local, { specifier, imported });
88
- }
89
- }
90
- return { all, zod, details };
76
+ * Collect runtime import bindings with a regex over import statements.
77
+ * Type-only imports and `type` specifiers are excluded — they cannot be
78
+ * referenced at runtime, so excluding them keeps the capture rule sound.
79
+ */
80
+ function collectImportBindings(code) {
81
+ const all = /* @__PURE__ */ new Set();
82
+ const zod = /* @__PURE__ */ new Set();
83
+ const details = /* @__PURE__ */ new Map();
84
+ for (const match of code.matchAll(/import\s+(type\s+)?([^'";]+?)\s+from\s*["']([^"']+)["']/g)) {
85
+ const [, typeOnly, clause, specifier] = match;
86
+ if (typeOnly || clause === void 0 || specifier === void 0) continue;
87
+ const isZod = ZOD_MODULES.has(specifier);
88
+ for (const { local, imported } of parseImportClause(clause)) {
89
+ all.add(local);
90
+ if (isZod) zod.add(local);
91
+ details.set(local, {
92
+ specifier,
93
+ imported
94
+ });
95
+ }
96
+ }
97
+ return {
98
+ all,
99
+ zod,
100
+ details
101
+ };
91
102
  }
92
103
  /** Extract local binding names (with their source export) from an import clause. */
93
104
  function parseImportClause(clause) {
94
- const names = [];
95
- const namedStart = clause.indexOf("{");
96
- // Default import and/or namespace import before the named group
97
- const head = namedStart === -1 ? clause : clause.slice(0, namedStart);
98
- for (const part of head.split(",")) {
99
- const trimmed = part.trim();
100
- if (!trimmed)
101
- continue;
102
- const ns = trimmed.match(/^\*\s*as\s+([A-Za-z_$][\w$]*)$/);
103
- if (ns?.[1]) {
104
- names.push({ local: ns[1], imported: "*" });
105
- }
106
- else if (/^[A-Za-z_$][\w$]*$/.test(trimmed)) {
107
- names.push({ local: trimmed, imported: "default" });
108
- }
109
- }
110
- if (namedStart !== -1) {
111
- const namedEnd = clause.indexOf("}", namedStart);
112
- const inner = clause.slice(namedStart + 1, namedEnd === -1 ? undefined : namedEnd);
113
- for (const part of inner.split(",")) {
114
- const spec = part.trim();
115
- if (!spec || spec.startsWith("type "))
116
- continue;
117
- // `a as b` binds b; plain `a` binds a
118
- const asMatch = spec.match(/^([A-Za-z_$][\w$]*)\s+as\s+([A-Za-z_$][\w$]*)$/);
119
- if (asMatch?.[1] && asMatch[2]) {
120
- names.push({ local: asMatch[2], imported: asMatch[1] });
121
- }
122
- else if (/^[A-Za-z_$][\w$]*$/.test(spec)) {
123
- names.push({ local: spec, imported: spec });
124
- }
125
- }
126
- }
127
- return names;
105
+ const names = [];
106
+ const namedStart = clause.indexOf("{");
107
+ const head = namedStart === -1 ? clause : clause.slice(0, namedStart);
108
+ for (const part of head.split(",")) {
109
+ const trimmed = part.trim();
110
+ if (!trimmed) continue;
111
+ const ns = trimmed.match(/^\*\s*as\s+([A-Za-z_$][\w$]*)$/);
112
+ if (ns?.[1]) names.push({
113
+ local: ns[1],
114
+ imported: "*"
115
+ });
116
+ else if (/^[A-Za-z_$][\w$]*$/.test(trimmed)) names.push({
117
+ local: trimmed,
118
+ imported: "default"
119
+ });
120
+ }
121
+ if (namedStart !== -1) {
122
+ const namedEnd = clause.indexOf("}", namedStart);
123
+ const inner = clause.slice(namedStart + 1, namedEnd === -1 ? void 0 : namedEnd);
124
+ for (const part of inner.split(",")) {
125
+ const spec = part.trim();
126
+ if (!spec || spec.startsWith("type ")) continue;
127
+ const asMatch = spec.match(/^([A-Za-z_$][\w$]*)\s+as\s+([A-Za-z_$][\w$]*)$/);
128
+ if (asMatch?.[1] && asMatch[2]) names.push({
129
+ local: asMatch[2],
130
+ imported: asMatch[1]
131
+ });
132
+ else if (/^[A-Za-z_$][\w$]*$/.test(spec)) names.push({
133
+ local: spec,
134
+ imported: spec
135
+ });
136
+ }
137
+ }
138
+ return names;
128
139
  }
129
140
  /** Deterministic FNV-1a 32-bit hash, hex-encoded. */
130
141
  function fnv1a(text) {
131
- let hash = 0x811c9dc5;
132
- for (let i = 0; i < text.length; i++) {
133
- hash ^= text.charCodeAt(i);
134
- hash = Math.imul(hash, 0x01000193);
135
- }
136
- return (hash >>> 0).toString(16).padStart(8, "0");
142
+ let hash = 2166136261;
143
+ for (let i = 0; i < text.length; i++) {
144
+ hash ^= text.charCodeAt(i);
145
+ hash = Math.imul(hash, 16777619);
146
+ }
147
+ return (hash >>> 0).toString(16).padStart(8, "0");
137
148
  }
138
149
  /**
139
- * Char-code identifier/whitespace classes for the scanner hot loops — a
140
- * regex `.test()` per character dominated scan time once the acorn parses
141
- * were gone. The ident classes are deliberately ASCII-only (`[A-Za-z_$]` /
142
- * `[\w$]`, matching the scanner's historical regexes); the space check falls
143
- * back to `/\s/` for the rare non-ASCII code points it matches (NBSP, BOM,
144
- * U+2028...).
145
- */
150
+ * Char-code identifier/whitespace classes for the scanner hot loops — a
151
+ * regex `.test()` per character dominated scan time once the acorn parses
152
+ * were gone. The ident classes are deliberately ASCII-only (`[A-Za-z_$]` /
153
+ * `[\w$]`, matching the scanner's historical regexes); the space check falls
154
+ * back to `/\s/` for the rare non-ASCII code points it matches (NBSP, BOM,
155
+ * U+2028...).
156
+ */
146
157
  function isIdentStartCode(c) {
147
- return (c >= 97 && c <= 122) || (c >= 65 && c <= 90) || c === 95 || c === 36;
158
+ return c >= 97 && c <= 122 || c >= 65 && c <= 90 || c === 95 || c === 36;
148
159
  }
149
160
  function isIdentPartCode(c) {
150
- return ((c >= 97 && c <= 122) || (c >= 65 && c <= 90) || (c >= 48 && c <= 57) || c === 95 || c === 36);
161
+ return c >= 97 && c <= 122 || c >= 65 && c <= 90 || c >= 48 && c <= 57 || c === 95 || c === 36;
151
162
  }
152
163
  function isSpaceCode(c) {
153
- if (c === 32 || (c >= 9 && c <= 13))
154
- return true;
155
- return c > 127 && /\s/.test(String.fromCharCode(c));
164
+ if (c === 32 || c >= 9 && c <= 13) return true;
165
+ return c > 127 && /\s/.test(String.fromCharCode(c));
156
166
  }
157
167
  /** After these tokens a `/` starts a regex literal, not division. */
158
- const REGEX_PRECEDING_KEYWORDS = new Set([
159
- "return",
160
- "typeof",
161
- "instanceof",
162
- "in",
163
- "of",
164
- "new",
165
- "delete",
166
- "void",
167
- "throw",
168
- "do",
169
- "else",
170
- "case",
171
- "yield",
172
- "await",
168
+ const REGEX_PRECEDING_KEYWORDS = /* @__PURE__ */ new Set([
169
+ "return",
170
+ "typeof",
171
+ "instanceof",
172
+ "in",
173
+ "of",
174
+ "new",
175
+ "delete",
176
+ "void",
177
+ "throw",
178
+ "do",
179
+ "else",
180
+ "case",
181
+ "yield",
182
+ "await"
173
183
  ]);
174
184
  /** Is `/` after this token division (true) or a regex literal (false)? */
175
185
  function isDivisionContext(lastToken) {
176
- if (lastToken === ")" || lastToken === "]")
177
- return true;
178
- if (/^["'`]$/.test(lastToken))
179
- return true;
180
- if (/^[\w$]+$/.test(lastToken))
181
- return !REGEX_PRECEDING_KEYWORDS.has(lastToken);
182
- return false;
186
+ if (lastToken === ")" || lastToken === "]") return true;
187
+ if (/^["'`]$/.test(lastToken)) return true;
188
+ if (/^[\w$]+$/.test(lastToken)) return !REGEX_PRECEDING_KEYWORDS.has(lastToken);
189
+ return false;
183
190
  }
184
191
  /**
185
- * Scan the source for candidate root identifiers (`z`, `FooZodSchema`, ...)
186
- * followed by a `.`, tracking string/template/comment state and nesting
187
- * depth. Depth 0 candidates are top-level initializers — already evaluated
188
- * once — and are recorded only so their extents mask nested candidates.
189
- */
192
+ * Scan the source for candidate root identifiers (`z`, `FooZodSchema`, ...)
193
+ * followed by a `.`, tracking string/template/comment state and nesting
194
+ * depth. Depth 0 candidates are top-level initializers — already evaluated
195
+ * once — and are recorded only so their extents mask nested candidates.
196
+ */
190
197
  function scanSource(code, roots) {
191
- const candidates = [];
192
- // Masked extents as flat [from, to) pairs, pushed in scan order (monotonic,
193
- // non-overlapping) — materialized into a stripped string only on demand.
194
- const maskRanges = [];
195
- const mask = (from, to) => {
196
- maskRanges.push(from, to);
197
- };
198
- let depth = 0;
199
- // Template literals interleave string and expression states; the stack
200
- // records the brace depth at which each `${` opened so the matching `}`
201
- // resumes string state.
202
- const templateStack = [];
203
- let lastToken = "";
204
- let i = 0;
205
- while (i < code.length) {
206
- const ch = code[i];
207
- const next = code[i + 1];
208
- // Comments
209
- if (ch === "/" && next === "/") {
210
- const nl = code.indexOf("\n", i);
211
- const end = nl === -1 ? code.length : nl + 1;
212
- mask(i, end);
213
- i = end;
214
- continue;
215
- }
216
- if (ch === "/" && next === "*") {
217
- const close = code.indexOf("*/", i + 2);
218
- const end = close === -1 ? code.length : close + 2;
219
- mask(i, end);
220
- i = end;
221
- continue;
222
- }
223
- if (ch === "/") {
224
- if (!isDivisionContext(lastToken)) {
225
- const end = skipRegexLiteral(code, i);
226
- mask(i, end);
227
- i = end;
228
- lastToken = ")"; // a regex literal is an operand
229
- continue;
230
- }
231
- lastToken = ch;
232
- i++;
233
- continue;
234
- }
235
- // Strings
236
- if (ch === '"' || ch === "'") {
237
- const end = skipString(code, i, ch);
238
- mask(i, end);
239
- i = end;
240
- lastToken = ch;
241
- continue;
242
- }
243
- // Template literals
244
- if (ch === "`") {
245
- const end = skipTemplateChunk(code, i + 1, templateStack, depth);
246
- mask(i, end);
247
- i = end;
248
- lastToken = "`";
249
- continue;
250
- }
251
- if (templateStack.length > 0 &&
252
- ch === "}" &&
253
- depth === templateStack[templateStack.length - 1]) {
254
- // End of a ${ } expression — back into template string state
255
- templateStack.pop();
256
- const end = skipTemplateChunk(code, i + 1, templateStack, depth);
257
- mask(i, end);
258
- i = end;
259
- lastToken = "`";
260
- continue;
261
- }
262
- if (ch === "(" || ch === "[" || ch === "{") {
263
- depth++;
264
- lastToken = ch;
265
- i++;
266
- continue;
267
- }
268
- if (ch === ")" || ch === "]" || ch === "}") {
269
- depth--;
270
- lastToken = ch;
271
- i++;
272
- continue;
273
- }
274
- if (isIdentStartCode(code.charCodeAt(i)) && !isIdentPartCode(code.charCodeAt(i - 1))) {
275
- let j = i + 1;
276
- while (j < code.length && isIdentPartCode(code.charCodeAt(j)))
277
- j++;
278
- const word = code.slice(i, j);
279
- // Skip whitespace to check for the member access
280
- let k = j;
281
- while (k < code.length && isSpaceCode(code.charCodeAt(k)))
282
- k++;
283
- if (roots.has(word) && code[k] === "." && lastToken !== ".") {
284
- candidates.push({ index: i, depth, name: word, afterArrow: lastToken === "=>" });
285
- }
286
- lastToken = word;
287
- i = j;
288
- continue;
289
- }
290
- if (!isSpaceCode(code.charCodeAt(i))) {
291
- lastToken = ch === ">" && lastToken === "=" ? "=>" : ch;
292
- }
293
- i++;
294
- }
295
- const stripped = () => {
296
- if (maskRanges.length === 0)
297
- return code;
298
- let out = "";
299
- let prev = 0;
300
- for (let r = 0; r < maskRanges.length; r += 2) {
301
- const from = maskRanges[r];
302
- const to = maskRanges[r + 1];
303
- out += code.slice(prev, from) + code.slice(from, to).replace(/[^\n]/g, " ");
304
- prev = to;
305
- }
306
- return out + code.slice(prev);
307
- };
308
- return { candidates, stripped };
198
+ const candidates = [];
199
+ const maskRanges = [];
200
+ const mask = (from, to) => {
201
+ maskRanges.push(from, to);
202
+ };
203
+ let depth = 0;
204
+ const templateStack = [];
205
+ let lastToken = "";
206
+ let i = 0;
207
+ while (i < code.length) {
208
+ const ch = code[i];
209
+ const next = code[i + 1];
210
+ if (ch === "/" && next === "/") {
211
+ const nl = code.indexOf("\n", i);
212
+ const end = nl === -1 ? code.length : nl + 1;
213
+ mask(i, end);
214
+ i = end;
215
+ continue;
216
+ }
217
+ if (ch === "/" && next === "*") {
218
+ const close = code.indexOf("*/", i + 2);
219
+ const end = close === -1 ? code.length : close + 2;
220
+ mask(i, end);
221
+ i = end;
222
+ continue;
223
+ }
224
+ if (ch === "/") {
225
+ if (!isDivisionContext(lastToken)) {
226
+ const end = skipRegexLiteral(code, i);
227
+ mask(i, end);
228
+ i = end;
229
+ lastToken = ")";
230
+ continue;
231
+ }
232
+ lastToken = ch;
233
+ i++;
234
+ continue;
235
+ }
236
+ if (ch === "\"" || ch === "'") {
237
+ const end = skipString(code, i, ch);
238
+ mask(i, end);
239
+ i = end;
240
+ lastToken = ch;
241
+ continue;
242
+ }
243
+ if (ch === "`") {
244
+ const end = skipTemplateChunk(code, i + 1, templateStack, depth);
245
+ mask(i, end);
246
+ i = end;
247
+ lastToken = "`";
248
+ continue;
249
+ }
250
+ if (templateStack.length > 0 && ch === "}" && depth === templateStack[templateStack.length - 1]) {
251
+ templateStack.pop();
252
+ const end = skipTemplateChunk(code, i + 1, templateStack, depth);
253
+ mask(i, end);
254
+ i = end;
255
+ lastToken = "`";
256
+ continue;
257
+ }
258
+ if (ch === "(" || ch === "[" || ch === "{") {
259
+ depth++;
260
+ lastToken = ch;
261
+ i++;
262
+ continue;
263
+ }
264
+ if (ch === ")" || ch === "]" || ch === "}") {
265
+ depth--;
266
+ lastToken = ch;
267
+ i++;
268
+ continue;
269
+ }
270
+ if (isIdentStartCode(code.charCodeAt(i)) && !isIdentPartCode(code.charCodeAt(i - 1))) {
271
+ let j = i + 1;
272
+ while (j < code.length && isIdentPartCode(code.charCodeAt(j))) j++;
273
+ const word = code.slice(i, j);
274
+ let k = j;
275
+ while (k < code.length && isSpaceCode(code.charCodeAt(k))) k++;
276
+ if (roots.has(word) && code[k] === "." && lastToken !== ".") candidates.push({
277
+ index: i,
278
+ depth,
279
+ name: word,
280
+ afterArrow: lastToken === "=>"
281
+ });
282
+ lastToken = word;
283
+ i = j;
284
+ continue;
285
+ }
286
+ if (!isSpaceCode(code.charCodeAt(i))) lastToken = ch === ">" && lastToken === "=" ? "=>" : ch;
287
+ i++;
288
+ }
289
+ const stripped = () => {
290
+ if (maskRanges.length === 0) return code;
291
+ let out = "";
292
+ let prev = 0;
293
+ for (let r = 0; r < maskRanges.length; r += 2) {
294
+ const from = maskRanges[r];
295
+ const to = maskRanges[r + 1];
296
+ out += code.slice(prev, from) + code.slice(from, to).replace(/[^\n]/g, " ");
297
+ prev = to;
298
+ }
299
+ return out + code.slice(prev);
300
+ };
301
+ return {
302
+ candidates,
303
+ stripped
304
+ };
309
305
  }
310
306
  function skipString(code, start, quote) {
311
- for (let i = start + 1; i < code.length; i++) {
312
- if (code[i] === "\\") {
313
- i++;
314
- }
315
- else if (code[i] === quote || code[i] === "\n") {
316
- return i + 1;
317
- }
318
- }
319
- return code.length;
307
+ for (let i = start + 1; i < code.length; i++) if (code[i] === "\\") i++;
308
+ else if (code[i] === quote || code[i] === "\n") return i + 1;
309
+ return code.length;
320
310
  }
321
311
  /**
322
- * Skip a template string chunk; returns the offset after the closing
323
- * `` ` `` or after a `${`, recording the current depth so the scanner can
324
- * recognize the matching `}` later.
325
- */
312
+ * Skip a template string chunk; returns the offset after the closing
313
+ * `` ` `` or after a `${`, recording the current depth so the scanner can
314
+ * recognize the matching `}` later.
315
+ */
326
316
  function skipTemplateChunk(code, start, templateStack, depth) {
327
- for (let i = start; i < code.length; i++) {
328
- if (code[i] === "\\") {
329
- i++;
330
- }
331
- else if (code[i] === "`") {
332
- return i + 1;
333
- }
334
- else if (code[i] === "$" && code[i + 1] === "{") {
335
- templateStack.push(depth);
336
- return i + 2;
337
- }
338
- }
339
- return code.length;
317
+ for (let i = start; i < code.length; i++) if (code[i] === "\\") i++;
318
+ else if (code[i] === "`") return i + 1;
319
+ else if (code[i] === "$" && code[i + 1] === "{") {
320
+ templateStack.push(depth);
321
+ return i + 2;
322
+ }
323
+ return code.length;
340
324
  }
341
325
  function skipRegexLiteral(code, start) {
342
- let inClass = false;
343
- for (let i = start + 1; i < code.length; i++) {
344
- const ch = code[i];
345
- if (ch === "\\") {
346
- i++;
347
- }
348
- else if (ch === "[") {
349
- inClass = true;
350
- }
351
- else if (ch === "]") {
352
- inClass = false;
353
- }
354
- else if (ch === "/" && !inClass) {
355
- return i + 1;
356
- }
357
- else if (ch === "\n") {
358
- // Not a regex after all (unterminated) — treat as division
359
- return start + 1;
360
- }
361
- }
362
- return code.length;
326
+ let inClass = false;
327
+ for (let i = start + 1; i < code.length; i++) {
328
+ const ch = code[i];
329
+ if (ch === "\\") i++;
330
+ else if (ch === "[") inClass = true;
331
+ else if (ch === "]") inClass = false;
332
+ else if (ch === "/" && !inClass) return i + 1;
333
+ else if (ch === "\n") return start + 1;
334
+ }
335
+ return code.length;
363
336
  }
364
337
  /**
365
- * Cheap chain-extent scan: from a root identifier, advance past the longest
366
- * member/call/tagged-template chain (`.x`, `?.x`, `!`, `(...)`, `[...]`,
367
- * `` `...` ``). Used to mask the interior of depth-0 chains WITHOUT an acorn
368
- * parse: schema modules are mostly top-level declarations, and parsing each
369
- * one only to discard it under the depth-0 rule dominated cold hoist cost in
370
- * a field report (hoist 37–46s vs discover 12–16s across ~7k transforms).
371
- * May overshoot an AST-exact end only across TS-only syntax (postfix `!`);
372
- * stops at anything else it does not recognize (`<` generics, operators) —
373
- * an undershoot leaves interior candidates to their own depth-0/eligibility
374
- * rules, an overshoot only widens the mask over an expression that already
375
- * evaluates once at module scope.
376
- */
338
+ * Cheap chain-extent scan: from a root identifier, advance past the longest
339
+ * member/call/tagged-template chain (`.x`, `?.x`, `!`, `(...)`, `[...]`,
340
+ * `` `...` ``). Used to mask the interior of depth-0 chains WITHOUT an acorn
341
+ * parse: schema modules are mostly top-level declarations, and parsing each
342
+ * one only to discard it under the depth-0 rule dominated cold hoist cost in
343
+ * a field report (hoist 37–46s vs discover 12–16s across ~7k transforms).
344
+ * May overshoot an AST-exact end only across TS-only syntax (postfix `!`);
345
+ * stops at anything else it does not recognize (`<` generics, operators) —
346
+ * an undershoot leaves interior candidates to their own depth-0/eligibility
347
+ * rules, an overshoot only widens the mask over an expression that already
348
+ * evaluates once at module scope.
349
+ */
377
350
  function findChainEnd(code, identStart) {
378
- let i = identStart;
379
- while (i < code.length && isIdentPartCode(code.charCodeAt(i)))
380
- i++;
381
- const skipTrivia = () => {
382
- for (;;) {
383
- while (i < code.length && isSpaceCode(code.charCodeAt(i)))
384
- i++;
385
- if (code[i] === "/" && code[i + 1] === "/") {
386
- const nl = code.indexOf("\n", i);
387
- i = nl === -1 ? code.length : nl + 1;
388
- }
389
- else if (code[i] === "/" && code[i + 1] === "*") {
390
- const close = code.indexOf("*/", i + 2);
391
- i = close === -1 ? code.length : close + 2;
392
- }
393
- else {
394
- return;
395
- }
396
- }
397
- };
398
- // Advance past one balanced construct starting at `(`, `[`, or a template
399
- // backtick — mirroring scanSource's string/template/regex/comment rules.
400
- const skipNested = () => {
401
- let depth = 0;
402
- const templateStack = [];
403
- let lastToken = "";
404
- while (i < code.length) {
405
- const ch = code[i];
406
- const next = code[i + 1];
407
- if (ch === "/" && next === "/") {
408
- const nl = code.indexOf("\n", i);
409
- i = nl === -1 ? code.length : nl + 1;
410
- continue;
411
- }
412
- if (ch === "/" && next === "*") {
413
- const close = code.indexOf("*/", i + 2);
414
- i = close === -1 ? code.length : close + 2;
415
- continue;
416
- }
417
- if (ch === "/") {
418
- if (!isDivisionContext(lastToken)) {
419
- i = skipRegexLiteral(code, i);
420
- lastToken = ")";
421
- continue;
422
- }
423
- lastToken = ch;
424
- i++;
425
- continue;
426
- }
427
- if (ch === '"' || ch === "'") {
428
- i = skipString(code, i, ch);
429
- lastToken = ch;
430
- continue;
431
- }
432
- if (ch === "`") {
433
- i = skipTemplateChunk(code, i + 1, templateStack, depth);
434
- lastToken = "`";
435
- if (depth === 0 && templateStack.length === 0)
436
- return;
437
- continue;
438
- }
439
- if (templateStack.length > 0 &&
440
- ch === "}" &&
441
- depth === templateStack[templateStack.length - 1]) {
442
- templateStack.pop();
443
- i = skipTemplateChunk(code, i + 1, templateStack, depth);
444
- lastToken = "`";
445
- if (depth === 0 && templateStack.length === 0)
446
- return;
447
- continue;
448
- }
449
- if (ch === "(" || ch === "[" || ch === "{") {
450
- depth++;
451
- lastToken = ch;
452
- i++;
453
- continue;
454
- }
455
- if (ch === ")" || ch === "]" || ch === "}") {
456
- depth--;
457
- lastToken = ch;
458
- i++;
459
- if (depth === 0 && templateStack.length === 0)
460
- return;
461
- continue;
462
- }
463
- if (isIdentStartCode(code.charCodeAt(i)) && !isIdentPartCode(code.charCodeAt(i - 1))) {
464
- let j = i + 1;
465
- while (j < code.length && isIdentPartCode(code.charCodeAt(j)))
466
- j++;
467
- lastToken = code.slice(i, j);
468
- i = j;
469
- continue;
470
- }
471
- if (!isSpaceCode(code.charCodeAt(i))) {
472
- lastToken = ch === ">" && lastToken === "=" ? "=>" : ch;
473
- }
474
- i++;
475
- }
476
- };
477
- for (;;) {
478
- skipTrivia();
479
- const ch = code[i];
480
- if (ch === "." || (ch === "?" && code[i + 1] === ".")) {
481
- i += ch === "." ? 1 : 2;
482
- skipTrivia();
483
- while (i < code.length && isIdentPartCode(code.charCodeAt(i)))
484
- i++;
485
- continue;
486
- }
487
- if (ch === "!") {
488
- i++;
489
- continue;
490
- }
491
- if (ch === "(" || ch === "[" || ch === "`") {
492
- skipNested();
493
- continue;
494
- }
495
- return i;
496
- }
351
+ let i = identStart;
352
+ while (i < code.length && isIdentPartCode(code.charCodeAt(i))) i++;
353
+ const skipTrivia = () => {
354
+ for (;;) {
355
+ while (i < code.length && isSpaceCode(code.charCodeAt(i))) i++;
356
+ if (code[i] === "/" && code[i + 1] === "/") {
357
+ const nl = code.indexOf("\n", i);
358
+ i = nl === -1 ? code.length : nl + 1;
359
+ } else if (code[i] === "/" && code[i + 1] === "*") {
360
+ const close = code.indexOf("*/", i + 2);
361
+ i = close === -1 ? code.length : close + 2;
362
+ } else return;
363
+ }
364
+ };
365
+ const skipNested = () => {
366
+ let depth = 0;
367
+ const templateStack = [];
368
+ let lastToken = "";
369
+ while (i < code.length) {
370
+ const ch = code[i];
371
+ const next = code[i + 1];
372
+ if (ch === "/" && next === "/") {
373
+ const nl = code.indexOf("\n", i);
374
+ i = nl === -1 ? code.length : nl + 1;
375
+ continue;
376
+ }
377
+ if (ch === "/" && next === "*") {
378
+ const close = code.indexOf("*/", i + 2);
379
+ i = close === -1 ? code.length : close + 2;
380
+ continue;
381
+ }
382
+ if (ch === "/") {
383
+ if (!isDivisionContext(lastToken)) {
384
+ i = skipRegexLiteral(code, i);
385
+ lastToken = ")";
386
+ continue;
387
+ }
388
+ lastToken = ch;
389
+ i++;
390
+ continue;
391
+ }
392
+ if (ch === "\"" || ch === "'") {
393
+ i = skipString(code, i, ch);
394
+ lastToken = ch;
395
+ continue;
396
+ }
397
+ if (ch === "`") {
398
+ i = skipTemplateChunk(code, i + 1, templateStack, depth);
399
+ lastToken = "`";
400
+ if (depth === 0 && templateStack.length === 0) return;
401
+ continue;
402
+ }
403
+ if (templateStack.length > 0 && ch === "}" && depth === templateStack[templateStack.length - 1]) {
404
+ templateStack.pop();
405
+ i = skipTemplateChunk(code, i + 1, templateStack, depth);
406
+ lastToken = "`";
407
+ if (depth === 0 && templateStack.length === 0) return;
408
+ continue;
409
+ }
410
+ if (ch === "(" || ch === "[" || ch === "{") {
411
+ depth++;
412
+ lastToken = ch;
413
+ i++;
414
+ continue;
415
+ }
416
+ if (ch === ")" || ch === "]" || ch === "}") {
417
+ depth--;
418
+ lastToken = ch;
419
+ i++;
420
+ if (depth === 0 && templateStack.length === 0) return;
421
+ continue;
422
+ }
423
+ if (isIdentStartCode(code.charCodeAt(i)) && !isIdentPartCode(code.charCodeAt(i - 1))) {
424
+ let j = i + 1;
425
+ while (j < code.length && isIdentPartCode(code.charCodeAt(j))) j++;
426
+ lastToken = code.slice(i, j);
427
+ i = j;
428
+ continue;
429
+ }
430
+ if (!isSpaceCode(code.charCodeAt(i))) lastToken = ch === ">" && lastToken === "=" ? "=>" : ch;
431
+ i++;
432
+ }
433
+ };
434
+ for (;;) {
435
+ skipTrivia();
436
+ const ch = code[i];
437
+ if (ch === "." || ch === "?" && code[i + 1] === ".") {
438
+ i += ch === "." ? 1 : 2;
439
+ skipTrivia();
440
+ while (i < code.length && isIdentPartCode(code.charCodeAt(i))) i++;
441
+ continue;
442
+ }
443
+ if (ch === "!") {
444
+ i++;
445
+ continue;
446
+ }
447
+ if (ch === "(" || ch === "[" || ch === "`") {
448
+ skipNested();
449
+ continue;
450
+ }
451
+ return i;
452
+ }
497
453
  }
498
454
  /**
499
- * Parse a single assignment-level expression at `pos` — the same entry point
500
- * acorn's own parseExpressionAt uses, one precedence level down. At
501
- * expression level a trailing comma in an argument position
502
- * (`sql.type(z.object({...}),\n)`) starts a sequence-expression parse that
503
- * throws on the surrounding `)`; assignment level treats the comma as
504
- * trailing garbage and stops cleanly. parseMaybeAssign is the entry point
505
- * the acorn plugin ecosystem overrides — stable across versions.
506
- */
455
+ * Parse a single assignment-level expression at `pos` — the same entry point
456
+ * acorn's own parseExpressionAt uses, one precedence level down. At
457
+ * expression level a trailing comma in an argument position
458
+ * (`sql.type(z.object({...}),\n)`) starts a sequence-expression parse that
459
+ * throws on the surrounding `)`; assignment level treats the comma as
460
+ * trailing garbage and stops cleanly. parseMaybeAssign is the entry point
461
+ * the acorn plugin ecosystem overrides — stable across versions.
462
+ */
507
463
  function parseAssignmentAt(code, pos) {
508
- const parser = new Parser({ ecmaVersion: "latest", sourceType: "module" }, code, pos);
509
- parser.nextToken();
510
- return parser.parseMaybeAssign();
464
+ const parser = new Parser({
465
+ ecmaVersion: "latest",
466
+ sourceType: "module"
467
+ }, code, pos);
468
+ parser.nextToken();
469
+ return parser.parseMaybeAssign();
511
470
  }
512
471
  /**
513
- * Narrow a parsed expression to the largest call chain starting at `start`.
514
- * The parse can overshoot into surrounding operators
515
- * (`z.string().min(1) || fallback` parses as a LogicalExpression) — descend
516
- * through same-start children until a CallExpression is found.
517
- */
472
+ * Narrow a parsed expression to the largest call chain starting at `start`.
473
+ * The parse can overshoot into surrounding operators
474
+ * (`z.string().min(1) || fallback` parses as a LogicalExpression) — descend
475
+ * through same-start children until a CallExpression is found.
476
+ */
518
477
  function narrowToCallChain(node, start) {
519
- let current = node;
520
- while (current.start === start) {
521
- if (current.type === "CallExpression")
522
- return current;
523
- const child = sameStartChild(current, start);
524
- if (!child)
525
- return null;
526
- current = child;
527
- }
528
- return null;
478
+ let current = node;
479
+ while (current.start === start) {
480
+ if (current.type === "CallExpression") return current;
481
+ const child = sameStartChild(current, start);
482
+ if (!child) return null;
483
+ current = child;
484
+ }
485
+ return null;
529
486
  }
530
487
  function sameStartChild(node, start) {
531
- const record = node;
532
- for (const key of ["left", "object", "callee", "test", "tag", "expression", "expressions"]) {
533
- const value = record[key];
534
- const child = Array.isArray(value) ? value[0] : value;
535
- if (typeof child === "object" &&
536
- child !== null &&
537
- child.start === start &&
538
- typeof child.type === "string") {
539
- return child;
540
- }
541
- }
542
- return null;
488
+ const record = node;
489
+ for (const key of [
490
+ "left",
491
+ "object",
492
+ "callee",
493
+ "test",
494
+ "tag",
495
+ "expression",
496
+ "expressions"
497
+ ]) {
498
+ const value = record[key];
499
+ const child = Array.isArray(value) ? value[0] : value;
500
+ if (typeof child === "object" && child !== null && child.start === start && typeof child.type === "string") return child;
501
+ }
502
+ return null;
543
503
  }
544
504
  /**
545
- * Walk a member/call chain down to its base identifier, collecting the
546
- * non-computed method names along the spine. Computed members
547
- * (`base[name]()`) are unanalyzable — the chain is rejected.
548
- */
505
+ * Walk a member/call chain down to its base identifier, collecting the
506
+ * non-computed method names along the spine. Computed members
507
+ * (`base[name]()`) are unanalyzable — the chain is rejected.
508
+ */
549
509
  function describeChain(node) {
550
- const methods = [];
551
- let current = node;
552
- while (true) {
553
- if (current.type === "CallExpression") {
554
- current = current.callee;
555
- }
556
- else if (current.type === "MemberExpression") {
557
- if (current.computed || current.property.type !== "Identifier")
558
- return null;
559
- methods.push(current.property.name);
560
- current = current.object;
561
- }
562
- else if (current.type === "Identifier") {
563
- return { root: current.name, methods };
564
- }
565
- else {
566
- return null;
567
- }
568
- }
510
+ const methods = [];
511
+ let current = node;
512
+ while (true) if (current.type === "CallExpression") current = current.callee;
513
+ else if (current.type === "MemberExpression") {
514
+ if (current.computed || current.property.type !== "Identifier") return null;
515
+ methods.push(current.property.name);
516
+ current = current.object;
517
+ } else if (current.type === "Identifier") return {
518
+ root: current.name,
519
+ methods
520
+ };
521
+ else return null;
569
522
  }
570
523
  /**
571
- * Combinators eligible on non-z chain bases (babel-plugin-zod-hoist's
572
- * SCHEMA_COMBINATOR_METHODS, verbatim) — `Base.extend({...})`,
573
- * `Base.pick({...})`, `UserZodSchema.optional()`, ...
574
- */
575
- const COMBINATOR_METHODS = new Set([
576
- "and",
577
- "array",
578
- "brand",
579
- "catchall",
580
- "deepPartial",
581
- "describe",
582
- "extend",
583
- "merge",
584
- "nullable",
585
- "nullish",
586
- "omit",
587
- "optional",
588
- "or",
589
- "partial",
590
- "passthrough",
591
- "pick",
592
- "readonly",
593
- "refine",
594
- "required",
595
- "strict",
596
- "strip",
597
- "superRefine",
598
- "transform",
524
+ * Combinators eligible on non-z chain bases (babel-plugin-zod-hoist's
525
+ * SCHEMA_COMBINATOR_METHODS, verbatim) — `Base.extend({...})`,
526
+ * `Base.pick({...})`, `UserZodSchema.optional()`, ...
527
+ */
528
+ const COMBINATOR_METHODS = /* @__PURE__ */ new Set([
529
+ "and",
530
+ "array",
531
+ "brand",
532
+ "catchall",
533
+ "deepPartial",
534
+ "describe",
535
+ "extend",
536
+ "merge",
537
+ "nullable",
538
+ "nullish",
539
+ "omit",
540
+ "optional",
541
+ "or",
542
+ "partial",
543
+ "passthrough",
544
+ "pick",
545
+ "readonly",
546
+ "refine",
547
+ "required",
548
+ "strict",
549
+ "strip",
550
+ "superRefine",
551
+ "transform"
599
552
  ]);
600
553
  /**
601
- * Methods that evaluate data rather than construct schemas. Hoisting one
602
- * would move the evaluation (and any throw) to module load.
603
- */
604
- const PARSE_METHODS = new Set([
605
- "parse",
606
- "safeParse",
607
- "parseAsync",
608
- "safeParseAsync",
609
- "decode",
610
- "encode",
611
- "decodeAsync",
612
- "encodeAsync",
554
+ * Methods that evaluate data rather than construct schemas. Hoisting one
555
+ * would move the evaluation (and any throw) to module load.
556
+ */
557
+ const PARSE_METHODS = /* @__PURE__ */ new Set([
558
+ "parse",
559
+ "safeParse",
560
+ "parseAsync",
561
+ "safeParseAsync",
562
+ "decode",
563
+ "encode",
564
+ "decodeAsync",
565
+ "encodeAsync"
613
566
  ]);
614
567
  /**
615
- * Standard globals a hoisted expression may reference (eager or deferred —
616
- * babel-parity behaviors like hoisting `z.date().default(new Date())` rely
617
- * on Date/Math being recognized).
618
- *
619
- * The babel plugin allows ANY unbound identifier because it has real scope
620
- * information; this port's binding collector is a lexical approximation, so
621
- * an unknown bare name must be assumed to be a binding the collector missed
622
- * — hoisting it would crash at module load with
623
- * `ReferenceError: <name> is not defined`. A fixed allowlist converts that
624
- * failure mode into a missed optimization.
625
- */
626
- const KNOWN_GLOBALS = new Set([
627
- "globalThis",
628
- "NaN",
629
- "Infinity",
630
- "Math",
631
- "Number",
632
- "String",
633
- "Boolean",
634
- "Array",
635
- "Object",
636
- "JSON",
637
- "Date",
638
- "RegExp",
639
- "BigInt",
640
- "Symbol",
641
- "Map",
642
- "Set",
643
- "WeakMap",
644
- "WeakSet",
645
- "Promise",
646
- "Proxy",
647
- "Reflect",
648
- "Intl",
649
- "Error",
650
- "TypeError",
651
- "RangeError",
652
- "SyntaxError",
653
- "EvalError",
654
- "URIError",
655
- "AggregateError",
656
- "ArrayBuffer",
657
- "Uint8Array",
658
- "parseInt",
659
- "parseFloat",
660
- "isNaN",
661
- "isFinite",
662
- "encodeURI",
663
- "decodeURI",
664
- "encodeURIComponent",
665
- "decodeURIComponent",
666
- "structuredClone",
667
- "URL",
668
- "URLSearchParams",
669
- "TextEncoder",
670
- "TextDecoder",
671
- "atob",
672
- "btoa",
673
- "crypto",
674
- "console",
675
- "process",
676
- "Buffer",
568
+ * Standard globals a hoisted expression may reference (eager or deferred —
569
+ * babel-parity behaviors like hoisting `z.date().default(new Date())` rely
570
+ * on Date/Math being recognized).
571
+ *
572
+ * The babel plugin allows ANY unbound identifier because it has real scope
573
+ * information; this port's binding collector is a lexical approximation, so
574
+ * an unknown bare name must be assumed to be a binding the collector missed
575
+ * — hoisting it would crash at module load with
576
+ * `ReferenceError: <name> is not defined`. A fixed allowlist converts that
577
+ * failure mode into a missed optimization.
578
+ */
579
+ const KNOWN_GLOBALS = /* @__PURE__ */ new Set([
580
+ "globalThis",
581
+ "NaN",
582
+ "Infinity",
583
+ "Math",
584
+ "Number",
585
+ "String",
586
+ "Boolean",
587
+ "Array",
588
+ "Object",
589
+ "JSON",
590
+ "Date",
591
+ "RegExp",
592
+ "BigInt",
593
+ "Symbol",
594
+ "Map",
595
+ "Set",
596
+ "WeakMap",
597
+ "WeakSet",
598
+ "Promise",
599
+ "Proxy",
600
+ "Reflect",
601
+ "Intl",
602
+ "Error",
603
+ "TypeError",
604
+ "RangeError",
605
+ "SyntaxError",
606
+ "EvalError",
607
+ "URIError",
608
+ "AggregateError",
609
+ "ArrayBuffer",
610
+ "Uint8Array",
611
+ "parseInt",
612
+ "parseFloat",
613
+ "isNaN",
614
+ "isFinite",
615
+ "encodeURI",
616
+ "decodeURI",
617
+ "encodeURIComponent",
618
+ "decodeURIComponent",
619
+ "structuredClone",
620
+ "URL",
621
+ "URLSearchParams",
622
+ "TextEncoder",
623
+ "TextDecoder",
624
+ "atob",
625
+ "btoa",
626
+ "crypto",
627
+ "console",
628
+ "process",
629
+ "Buffer"
677
630
  ]);
678
631
  /**
679
- * Scope-aware free-variable analysis of an expression. Nested function
680
- * params and local declarations are bound names, not captures — so
681
- * `z.string().refine((v) => v.length > 0)` has no free variables beyond `z`.
682
- * References inside nested function bodies are tracked separately: they
683
- * evaluate per call even after hoisting, so safe globals are allowed there.
684
- */
632
+ * Scope-aware free-variable analysis of an expression. Nested function
633
+ * params and local declarations are bound names, not captures — so
634
+ * `z.string().refine((v) => v.length > 0)` has no free variables beyond `z`.
635
+ * References inside nested function bodies are tracked separately: they
636
+ * evaluate per call even after hoisting, so safe globals are allowed there.
637
+ */
685
638
  function analyzeCaptures(expr) {
686
- const eagerFree = new Set();
687
- const deferredFree = new Set();
688
- let impure = false;
689
- function patternNames(node, into) {
690
- switch (node.type) {
691
- case "Identifier":
692
- into.add(node.name);
693
- return;
694
- case "ObjectPattern":
695
- for (const prop of node.properties) {
696
- if (prop.type === "Property")
697
- patternNames(prop.value, into);
698
- else
699
- patternNames(prop.argument, into);
700
- }
701
- return;
702
- case "ArrayPattern":
703
- for (const el of node.elements) {
704
- if (el)
705
- patternNames(el, into);
706
- }
707
- return;
708
- case "AssignmentPattern":
709
- patternNames(node.left, into);
710
- return;
711
- case "RestElement":
712
- patternNames(node.argument, into);
713
- return;
714
- default:
715
- return;
716
- }
717
- }
718
- function collectFunctionScope(body, into) {
719
- // Flatten block scoping into the function scope — over-approximating
720
- // bound names can only suppress a hoist's free set, and the failure
721
- // mode is a loud ReferenceError, never silent misvalidation.
722
- const stack = [body];
723
- while (stack.length > 0) {
724
- const node = stack.pop();
725
- if (!node || typeof node !== "object")
726
- continue;
727
- if (node.type === "VariableDeclaration") {
728
- for (const decl of node.declarations)
729
- patternNames(decl.id, into);
730
- }
731
- else if (node.type === "FunctionDeclaration" || node.type === "ClassDeclaration") {
732
- if (node.id)
733
- into.add(node.id.name);
734
- continue; // do not descend into nested declarations' bodies here
735
- }
736
- else if (node.type === "FunctionExpression" || node.type === "ArrowFunctionExpression") {
737
- continue; // nested functions get their own scope in visit()
738
- }
739
- for (const value of Object.values(node)) {
740
- if (Array.isArray(value)) {
741
- for (const item of value) {
742
- if (typeof item === "object" && item !== null && "type" in item) {
743
- stack.push(item);
744
- }
745
- }
746
- }
747
- else if (typeof value === "object" && value !== null && "type" in value) {
748
- stack.push(value);
749
- }
750
- }
751
- }
752
- }
753
- function visit(node, scopes, deferred) {
754
- switch (node.type) {
755
- case "Identifier": {
756
- const name = node.name;
757
- if (name !== "undefined" && !scopes.some((s) => s.has(name))) {
758
- (deferred ? deferredFree : eagerFree).add(name);
759
- }
760
- return;
761
- }
762
- case "ThisExpression":
763
- case "Super":
764
- // Arrows bind `this` lexically — hoisting changes it even when the
765
- // reference sits inside a callback. Always disqualifying.
766
- impure = true;
767
- return;
768
- case "AwaitExpression":
769
- case "YieldExpression":
770
- // Eager occurrences cannot be moved to module scope: hoisting would
771
- // emit top-level await (broken in CJS output) or an orphaned yield.
772
- // (Stricter than the babel plugin, whose suite never exercises
773
- // these.) Deferred occurrences run per call — fine to move.
774
- if (!deferred) {
775
- impure = true;
776
- return;
777
- }
778
- break;
779
- case "MemberExpression":
780
- visit(node.object, scopes, deferred);
781
- if (node.computed)
782
- visit(node.property, scopes, deferred);
783
- return;
784
- case "Property":
785
- if (node.computed)
786
- visit(node.key, scopes, deferred);
787
- visit(node.value, scopes, deferred);
788
- return;
789
- case "FunctionExpression":
790
- case "ArrowFunctionExpression": {
791
- const scope = new Set();
792
- for (const param of node.params)
793
- patternNames(param, scope);
794
- if (node.type === "FunctionExpression" && node.id)
795
- scope.add(node.id.name);
796
- collectFunctionScope(node.body, scope);
797
- visit(node.body, [...scopes, scope], true);
798
- return;
799
- }
800
- default:
801
- break;
802
- }
803
- for (const value of Object.values(node)) {
804
- if (Array.isArray(value)) {
805
- for (const item of value) {
806
- if (typeof item === "object" && item !== null && "type" in item) {
807
- visit(item, scopes, deferred);
808
- }
809
- }
810
- }
811
- else if (typeof value === "object" && value !== null && "type" in value) {
812
- visit(value, scopes, deferred);
813
- }
814
- }
815
- }
816
- visit(expr, [], false);
817
- return { eagerFree, deferredFree, impure };
639
+ const eagerFree = /* @__PURE__ */ new Set();
640
+ const deferredFree = /* @__PURE__ */ new Set();
641
+ let impure = false;
642
+ function patternNames(node, into) {
643
+ switch (node.type) {
644
+ case "Identifier":
645
+ into.add(node.name);
646
+ return;
647
+ case "ObjectPattern":
648
+ for (const prop of node.properties) if (prop.type === "Property") patternNames(prop.value, into);
649
+ else patternNames(prop.argument, into);
650
+ return;
651
+ case "ArrayPattern":
652
+ for (const el of node.elements) if (el) patternNames(el, into);
653
+ return;
654
+ case "AssignmentPattern":
655
+ patternNames(node.left, into);
656
+ return;
657
+ case "RestElement":
658
+ patternNames(node.argument, into);
659
+ return;
660
+ default: return;
661
+ }
662
+ }
663
+ function collectFunctionScope(body, into) {
664
+ const stack = [body];
665
+ while (stack.length > 0) {
666
+ const node = stack.pop();
667
+ if (!node || typeof node !== "object") continue;
668
+ if (node.type === "VariableDeclaration") for (const decl of node.declarations) patternNames(decl.id, into);
669
+ else if (node.type === "FunctionDeclaration" || node.type === "ClassDeclaration") {
670
+ if (node.id) into.add(node.id.name);
671
+ continue;
672
+ } else if (node.type === "FunctionExpression" || node.type === "ArrowFunctionExpression") continue;
673
+ for (const value of Object.values(node)) if (Array.isArray(value)) {
674
+ for (const item of value) if (typeof item === "object" && item !== null && "type" in item) stack.push(item);
675
+ } else if (typeof value === "object" && value !== null && "type" in value) stack.push(value);
676
+ }
677
+ }
678
+ function visit(node, scopes, deferred) {
679
+ switch (node.type) {
680
+ case "Identifier": {
681
+ const name = node.name;
682
+ if (name !== "undefined" && !scopes.some((s) => s.has(name))) (deferred ? deferredFree : eagerFree).add(name);
683
+ return;
684
+ }
685
+ case "ThisExpression":
686
+ case "Super":
687
+ impure = true;
688
+ return;
689
+ case "AwaitExpression":
690
+ case "YieldExpression":
691
+ if (!deferred) {
692
+ impure = true;
693
+ return;
694
+ }
695
+ break;
696
+ case "MemberExpression":
697
+ visit(node.object, scopes, deferred);
698
+ if (node.computed) visit(node.property, scopes, deferred);
699
+ return;
700
+ case "Property":
701
+ if (node.computed) visit(node.key, scopes, deferred);
702
+ visit(node.value, scopes, deferred);
703
+ return;
704
+ case "FunctionExpression":
705
+ case "ArrowFunctionExpression": {
706
+ const scope = /* @__PURE__ */ new Set();
707
+ for (const param of node.params) patternNames(param, scope);
708
+ if (node.type === "FunctionExpression" && node.id) scope.add(node.id.name);
709
+ collectFunctionScope(node.body, scope);
710
+ visit(node.body, [...scopes, scope], true);
711
+ return;
712
+ }
713
+ default: break;
714
+ }
715
+ for (const value of Object.values(node)) if (Array.isArray(value)) {
716
+ for (const item of value) if (typeof item === "object" && item !== null && "type" in item) visit(item, scopes, deferred);
717
+ } else if (typeof value === "object" && value !== null && "type" in value) visit(value, scopes, deferred);
718
+ }
719
+ visit(expr, [], false);
720
+ return {
721
+ eagerFree,
722
+ deferredFree,
723
+ impure
724
+ };
818
725
  }
819
726
  /** Offset after the shebang and directive prologue ("use client", ...). */
820
727
  function insertionOffset(code) {
821
- let i = 0;
822
- if (code.startsWith("#!")) {
823
- const nl = code.indexOf("\n");
824
- i = nl === -1 ? code.length : nl + 1;
825
- }
826
- while (true) {
827
- // Skip whitespace and comments between directives
828
- while (i < code.length) {
829
- const ch = code[i];
830
- if (/\s/.test(ch)) {
831
- i++;
832
- }
833
- else if (ch === "/" && code[i + 1] === "/") {
834
- const nl = code.indexOf("\n", i);
835
- i = nl === -1 ? code.length : nl + 1;
836
- }
837
- else if (ch === "/" && code[i + 1] === "*") {
838
- const end = code.indexOf("*/", i + 2);
839
- i = end === -1 ? code.length : end + 2;
840
- }
841
- else {
842
- break;
843
- }
844
- }
845
- const directive = code.slice(i).match(/^(["'])use [^"'\n]*\1\s*;?[^\S\n]*\n?/);
846
- if (!directive)
847
- return i;
848
- i += directive[0].length;
849
- }
728
+ let i = 0;
729
+ if (code.startsWith("#!")) {
730
+ const nl = code.indexOf("\n");
731
+ i = nl === -1 ? code.length : nl + 1;
732
+ }
733
+ while (true) {
734
+ while (i < code.length) {
735
+ const ch = code[i];
736
+ if (/\s/.test(ch)) i++;
737
+ else if (ch === "/" && code[i + 1] === "/") {
738
+ const nl = code.indexOf("\n", i);
739
+ i = nl === -1 ? code.length : nl + 1;
740
+ } else if (ch === "/" && code[i + 1] === "*") {
741
+ const end = code.indexOf("*/", i + 2);
742
+ i = end === -1 ? code.length : end + 2;
743
+ } else break;
744
+ }
745
+ const directive = code.slice(i).match(/^(["'])use [^"'\n]*\1\s*;?[^\S\n]*\n?/);
746
+ if (!directive) return i;
747
+ i += directive[0].length;
748
+ }
850
749
  }
851
750
  /** Keywords that precede `( ... ) {` without binding anything. */
852
751
  const NON_BINDING_KEYWORDS = "if|for|while|switch|return|typeof|await|yield|new|do|else|case|in|of|delete|void";
853
752
  /**
854
- * Conservative shadow detection: collect every identifier appearing in a
855
- * binding-like position — function/method/arrow parameter lists, catch
856
- * clauses, class names, const/let/var declarator patterns. The scanner has
857
- * no scope information, so an import referenced from a hoisted expression
858
- * must resolve to that import everywhere; a name that is ever re-bound
859
- * cannot be trusted and disqualifies hoists referencing it.
860
- *
861
- * Collection is depth-aware and multiline (balanced delimiter scanning, not
862
- * line-bounded regexes): multiline destructuring declarations and parameter
863
- * defaults containing calls are real production patterns whose bindings a
864
- * line-based collector misses — and a missed binding here used to mean a
865
- * hoist referencing it crashed at module load (`ReferenceError`).
866
- * Over-collection (type names, destructuring default values, for-of
867
- * iterables) is deliberate and safe: it can only suppress a hoist.
868
- */
753
+ * Conservative shadow detection: collect every identifier appearing in a
754
+ * binding-like position — function/method/arrow parameter lists, catch
755
+ * clauses, class names, const/let/var declarator patterns. The scanner has
756
+ * no scope information, so an import referenced from a hoisted expression
757
+ * must resolve to that import everywhere; a name that is ever re-bound
758
+ * cannot be trusted and disqualifies hoists referencing it.
759
+ *
760
+ * Collection is depth-aware and multiline (balanced delimiter scanning, not
761
+ * line-bounded regexes): multiline destructuring declarations and parameter
762
+ * defaults containing calls are real production patterns whose bindings a
763
+ * line-based collector misses — and a missed binding here used to mean a
764
+ * hoist referencing it crashed at module load (`ReferenceError`).
765
+ * Over-collection (type names, destructuring default values, for-of
766
+ * iterables) is deliberate and safe: it can only suppress a hoist.
767
+ */
869
768
  function collectBoundNames(code) {
870
- const bound = new Set();
871
- // Per top-level-comma piece, keep only the binding side: names before any
872
- // top-level `:` (type annotation) or `=` (default/initializer). Inside
873
- // destructuring patterns the `:`/`=` sit at depth > 0, so the whole
874
- // pattern is collected (renames and default values over-collect — safe).
875
- const addBindingSegment = (segment) => {
876
- let depth = 0;
877
- let pieceStart = 0;
878
- let cut = -1;
879
- const flush = (end) => {
880
- const prefix = segment.slice(pieceStart, cut === -1 ? end : cut);
881
- for (const id of prefix.matchAll(/[A-Za-z_$][\w$]*/g)) {
882
- bound.add(id[0]);
883
- }
884
- cut = -1;
885
- };
886
- for (let i = 0; i < segment.length; i++) {
887
- const ch = segment[i];
888
- if (ch === "(" || ch === "[" || ch === "{") {
889
- depth++;
890
- }
891
- else if (ch === ")" || ch === "]" || ch === "}") {
892
- depth--;
893
- }
894
- else if (depth === 0 && ch === ",") {
895
- flush(i);
896
- pieceStart = i + 1;
897
- }
898
- else if (depth === 0 && cut === -1 && (ch === ":" || ch === "=")) {
899
- cut = i;
900
- }
901
- }
902
- flush(segment.length);
903
- };
904
- /** Balanced `( ... )` span starting at `open` (must point at `(`). */
905
- const parenSpan = (open) => {
906
- let depth = 0;
907
- for (let i = open; i < code.length; i++) {
908
- const ch = code[i];
909
- if (ch === "(")
910
- depth++;
911
- else if (ch === ")") {
912
- depth--;
913
- if (depth === 0)
914
- return { inner: code.slice(open + 1, i), end: i };
915
- }
916
- }
917
- return null;
918
- };
919
- // function f(a, b) / function (a = call()) — balanced + multiline
920
- for (const m of code.matchAll(/\bfunction\b/g)) {
921
- let i = m.index + m[0].length;
922
- while (i < code.length && code[i] !== "(" && code[i] !== "{" && code[i] !== ";")
923
- i++;
924
- if (code[i] !== "(")
925
- continue;
926
- const span = parenSpan(i);
927
- if (span)
928
- addBindingSegment(span.inner);
929
- }
930
- // (a, b) => / (a = call()): Ret => — balanced params located from the arrow
931
- for (const m of code.matchAll(/=>/g)) {
932
- let i = m.index - 1;
933
- while (i >= 0 && /\s/.test(code[i]))
934
- i--;
935
- if (i < 0)
936
- continue;
937
- let closeAt = -1;
938
- if (code[i] === ")") {
939
- closeAt = i;
940
- }
941
- else {
942
- // Possible return-type annotation between `)` and `=>`:
943
- // `(a): Promise<T> =>`. Find the nearest `)` whose gap to the arrow
944
- // looks like a type annotation; give up otherwise (over-approximation
945
- // elsewhere keeps this safe).
946
- const before = code.slice(0, m.index);
947
- const lastClose = before.lastIndexOf(")");
948
- if (lastClose !== -1 && /^\s*:[^(){};]*$/.test(before.slice(lastClose + 1))) {
949
- closeAt = lastClose;
950
- }
951
- }
952
- if (closeAt === -1)
953
- continue;
954
- // walk back to the matching `(`
955
- let depth = 0;
956
- for (let j = closeAt; j >= 0; j--) {
957
- const ch = code[j];
958
- if (ch === ")")
959
- depth++;
960
- else if (ch === "(") {
961
- depth--;
962
- if (depth === 0) {
963
- addBindingSegment(code.slice(j + 1, closeAt));
964
- break;
965
- }
966
- }
967
- }
968
- }
969
- // bare arrow param: a =>
970
- for (const m of code.matchAll(/([A-Za-z_$][\w$]*)\s*=>/g)) {
971
- bound.add(m[1] ?? "");
972
- }
973
- // method(a, b) { / method(a = call()): Ret { — excluding control flow.
974
- // The balanced span must be directly followed by `{` (after an optional
975
- // return type), which call expressions essentially never are.
976
- const methodAnchor = new RegExp(String.raw `(?<![.\w$])(?!(?:${NON_BINDING_KEYWORDS})\b)[A-Za-z_$][\w$]*\s*\(`, "g");
977
- for (const m of code.matchAll(methodAnchor)) {
978
- const span = parenSpan(m.index + m[0].length - 1);
979
- if (!span)
980
- continue;
981
- const after = code.slice(span.end + 1);
982
- if (/^\s*(?::[^{};()]*)?\{/.test(after))
983
- addBindingSegment(span.inner);
984
- }
985
- // catch (e)
986
- for (const m of code.matchAll(/\bcatch\s*\(/g)) {
987
- const span = parenSpan(m.index + m[0].length - 1);
988
- if (span)
989
- addBindingSegment(span.inner);
990
- }
991
- // class names are TDZ bindings (function declarations hoist, classes don't)
992
- for (const m of code.matchAll(/\bclass\s+([A-Za-z_$][\w$]*)/g)) {
993
- bound.add(m[1] ?? "");
994
- }
995
- // const/let/var declarator patterns — balanced + multiline. The span runs
996
- // to the first top-level `;` (or an unbalanced closer: for-headers), so
997
- // `const {\n inputSchema,\n} = getSchemas();` collects inputSchema.
998
- for (const m of code.matchAll(/\b(?:const|let|var)\b/g)) {
999
- const start = m.index + m[0].length;
1000
- let depth = 0;
1001
- let end = code.length;
1002
- for (let i = start; i < code.length; i++) {
1003
- const ch = code[i];
1004
- if (ch === "(" || ch === "[" || ch === "{") {
1005
- depth++;
1006
- }
1007
- else if (ch === ")" || ch === "]" || ch === "}") {
1008
- depth--;
1009
- if (depth < 0) {
1010
- end = i;
1011
- break;
1012
- }
1013
- }
1014
- else if (depth === 0 && ch === ";") {
1015
- end = i;
1016
- break;
1017
- }
1018
- }
1019
- addBindingSegment(code.slice(start, end));
1020
- }
1021
- return bound;
769
+ const bound = /* @__PURE__ */ new Set();
770
+ const addBindingSegment = (segment) => {
771
+ let depth = 0;
772
+ let pieceStart = 0;
773
+ let cut = -1;
774
+ const flush = (end) => {
775
+ const prefix = segment.slice(pieceStart, cut === -1 ? end : cut);
776
+ for (const id of prefix.matchAll(/[A-Za-z_$][\w$]*/g)) bound.add(id[0]);
777
+ cut = -1;
778
+ };
779
+ for (let i = 0; i < segment.length; i++) {
780
+ const ch = segment[i];
781
+ if (ch === "(" || ch === "[" || ch === "{") depth++;
782
+ else if (ch === ")" || ch === "]" || ch === "}") depth--;
783
+ else if (depth === 0 && ch === ",") {
784
+ flush(i);
785
+ pieceStart = i + 1;
786
+ } else if (depth === 0 && cut === -1 && (ch === ":" || ch === "=")) cut = i;
787
+ }
788
+ flush(segment.length);
789
+ };
790
+ /** Balanced `( ... )` span starting at `open` (must point at `(`). */
791
+ const parenSpan = (open) => {
792
+ let depth = 0;
793
+ for (let i = open; i < code.length; i++) {
794
+ const ch = code[i];
795
+ if (ch === "(") depth++;
796
+ else if (ch === ")") {
797
+ depth--;
798
+ if (depth === 0) return {
799
+ inner: code.slice(open + 1, i),
800
+ end: i
801
+ };
802
+ }
803
+ }
804
+ return null;
805
+ };
806
+ for (const m of code.matchAll(/\bfunction\b/g)) {
807
+ let i = m.index + m[0].length;
808
+ while (i < code.length && code[i] !== "(" && code[i] !== "{" && code[i] !== ";") i++;
809
+ if (code[i] !== "(") continue;
810
+ const span = parenSpan(i);
811
+ if (span) addBindingSegment(span.inner);
812
+ }
813
+ for (const m of code.matchAll(/=>/g)) {
814
+ let i = m.index - 1;
815
+ while (i >= 0 && /\s/.test(code[i])) i--;
816
+ if (i < 0) continue;
817
+ let closeAt = -1;
818
+ if (code[i] === ")") closeAt = i;
819
+ else {
820
+ const before = code.slice(0, m.index);
821
+ const lastClose = before.lastIndexOf(")");
822
+ if (lastClose !== -1 && /^\s*:[^(){};]*$/.test(before.slice(lastClose + 1))) closeAt = lastClose;
823
+ }
824
+ if (closeAt === -1) continue;
825
+ let depth = 0;
826
+ for (let j = closeAt; j >= 0; j--) {
827
+ const ch = code[j];
828
+ if (ch === ")") depth++;
829
+ else if (ch === "(") {
830
+ depth--;
831
+ if (depth === 0) {
832
+ addBindingSegment(code.slice(j + 1, closeAt));
833
+ break;
834
+ }
835
+ }
836
+ }
837
+ }
838
+ for (const m of code.matchAll(/([A-Za-z_$][\w$]*)\s*=>/g)) bound.add(m[1] ?? "");
839
+ const methodAnchor = new RegExp(String.raw`(?<![.\w$])(?!(?:${NON_BINDING_KEYWORDS})\b)[A-Za-z_$][\w$]*\s*\(`, "g");
840
+ for (const m of code.matchAll(methodAnchor)) {
841
+ const span = parenSpan(m.index + m[0].length - 1);
842
+ if (!span) continue;
843
+ const after = code.slice(span.end + 1);
844
+ if (/^\s*(?::[^{};()]*)?\{/.test(after)) addBindingSegment(span.inner);
845
+ }
846
+ for (const m of code.matchAll(/\bcatch\s*\(/g)) {
847
+ const span = parenSpan(m.index + m[0].length - 1);
848
+ if (span) addBindingSegment(span.inner);
849
+ }
850
+ for (const m of code.matchAll(/\bclass\s+([A-Za-z_$][\w$]*)/g)) bound.add(m[1] ?? "");
851
+ for (const m of code.matchAll(/\b(?:const|let|var)\b/g)) {
852
+ const start = m.index + m[0].length;
853
+ let depth = 0;
854
+ let end = code.length;
855
+ for (let i = start; i < code.length; i++) {
856
+ const ch = code[i];
857
+ if (ch === "(" || ch === "[" || ch === "{") depth++;
858
+ else if (ch === ")" || ch === "]" || ch === "}") {
859
+ depth--;
860
+ if (depth < 0) {
861
+ end = i;
862
+ break;
863
+ }
864
+ } else if (depth === 0 && ch === ";") {
865
+ end = i;
866
+ break;
867
+ }
868
+ }
869
+ addBindingSegment(code.slice(start, end));
870
+ }
871
+ return bound;
1022
872
  }
1023
873
  /**
1024
- * Free-variable analysis of a hoisted expression's source text, for the
1025
- * build-time compile step. Returns null when the text does not parse (it
1026
- * always should — it was extracted by this module).
1027
- */
1028
- export function analyzeHoistedExpression(text) {
1029
- try {
1030
- const parsed = parseAssignmentAt(text, 0);
1031
- const { eagerFree, deferredFree, impure } = analyzeCaptures(parsed);
1032
- if (impure)
1033
- return null;
1034
- return { eagerFree, deferredFree };
1035
- }
1036
- catch {
1037
- return null;
1038
- }
874
+ * Free-variable analysis of a hoisted expression's source text, for the
875
+ * build-time compile step. Returns null when the text does not parse (it
876
+ * always should — it was extracted by this module).
877
+ */
878
+ function analyzeHoistedExpression(text) {
879
+ try {
880
+ const { eagerFree, deferredFree, impure } = analyzeCaptures(parseAssignmentAt(text, 0));
881
+ if (impure) return null;
882
+ return {
883
+ eagerFree,
884
+ deferredFree
885
+ };
886
+ } catch {
887
+ return null;
888
+ }
1039
889
  }
1040
890
  /**
1041
- * Hoist eligible Zod schema expressions to module scope.
1042
- * Returns the rewritten source, or null when nothing was hoisted.
1043
- */
1044
- export function hoistZodSchemas(code, options) {
1045
- return hoistZodSchemasMeta(code, options)?.code ?? null;
891
+ * Hoist eligible Zod schema expressions to module scope.
892
+ * Returns the rewritten source, or null when nothing was hoisted.
893
+ */
894
+ function hoistZodSchemas(code, options) {
895
+ return hoistZodSchemasMeta(code, options)?.code ?? null;
1046
896
  }
1047
897
  /**
1048
- * hoistZodSchemas + metadata about each hoisted declaration, so the
1049
- * transform can compile the hoisted schemas into optimized validators.
1050
- */
1051
- export function hoistZodSchemasMeta(code, options) {
1052
- // Idempotency: a file carrying hoisted declarations IS this pass's output.
1053
- // Plain hoists are naturally inert on re-runs (depth-0 masking), but a
1054
- // compiled hoisted decl embeds its original z.* expression inside the IIFE
1055
- // (depth > 0) — re-hoisting it would emit a duplicate _zh_ declaration.
1056
- if (/\bconst _zh_[0-9a-f]{8} = /.test(code))
1057
- return null;
1058
- const imports = collectImportBindings(code);
1059
- if (imports.all.size === 0)
1060
- return null;
1061
- const rawPattern = options?.schemaNamePattern;
1062
- const namePattern = rawPattern === null
1063
- ? null
1064
- : rawPattern === undefined
1065
- ? SCHEMA_NAME_PATTERN
1066
- : typeof rawPattern === "string"
1067
- ? new RegExp(rawPattern)
1068
- : rawPattern;
1069
- const roots = new Set(imports.zod);
1070
- if (namePattern) {
1071
- for (const name of imports.all) {
1072
- if (namePattern.test(name))
1073
- roots.add(name);
1074
- }
1075
- }
1076
- // Imported roots that only qualify via an inline z.* reference in the
1077
- // chain are validated per-expression below; scan them as candidates too.
1078
- if (imports.zod.size > 0) {
1079
- for (const name of imports.all)
1080
- roots.add(name);
1081
- }
1082
- if (roots.size === 0)
1083
- return null;
1084
- options?.onScan?.();
1085
- const { candidates, stripped } = scanSource(code, roots);
1086
- if (candidates.length === 0)
1087
- return null;
1088
- let boundNames;
1089
- function isShadowed(name) {
1090
- boundNames ??= collectBoundNames(stripped());
1091
- return boundNames.has(name);
1092
- }
1093
- const hoists = [];
1094
- const declByText = new Map();
1095
- let consumedUntil = 0;
1096
- for (const candidate of candidates) {
1097
- if (candidate.index < consumedUntil)
1098
- continue;
1099
- // Masking (babel-plugin-zod-hoist nesting semantics):
1100
- // - Depth-0 chains are top-level statements/initializers — already
1101
- // evaluated once per module load, nothing to gain — and their interior
1102
- // must not hoist separately either. Exception: concise arrow bodies
1103
- // (`const make = () => z.object(...)`) re-run per call.
1104
- // Their extent comes from the cheap scanner (findChainEnd), NOT acorn:
1105
- // schema modules are mostly top-level declarations, and an acorn parse
1106
- // per declaration only to discard it dominated cold hoist cost.
1107
- // - Zod-rooted chains mask their interior REGARDLESS of eligibility (an
1108
- // inner z.string() of `z.object({ a: z.string(), b: local })` belongs
1109
- // to the outer schema — babel's isNestedInZodCall).
1110
- // - Chains rooted elsewhere (`sql.type(...)`, `api.get(...)`,
1111
- // `Base.extend(...)`) mask their interior only when actually hoisted:
1112
- // a rejected outer chain leaves its arguments free, so the inner
1113
- // `z.object({...})` of `sql.type(z.object({...}))` hoists on its own.
1114
- if (candidate.depth === 0 && !candidate.afterArrow) {
1115
- consumedUntil = findChainEnd(code, candidate.index);
1116
- continue;
1117
- }
1118
- let parsed;
1119
- try {
1120
- parsed = parseAssignmentAt(code, candidate.index);
1121
- }
1122
- catch {
1123
- continue;
1124
- }
1125
- let chain = narrowToCallChain(parsed, candidate.index);
1126
- if (!chain)
1127
- continue;
1128
- const rootIsZod = imports.zod.has(candidate.name);
1129
- if (rootIsZod)
1130
- consumedUntil = chain.end;
1131
- // Peel trailing parse calls: for `z.object({...}).safeParse(input)`,
1132
- // hoist the construction and leave `.safeParse(input)` — with its
1133
- // local-variable arguments — at the call site.
1134
- let described = describeChain(chain);
1135
- while (chain !== null &&
1136
- described !== null &&
1137
- described.methods.length > 0 &&
1138
- PARSE_METHODS.has(described.methods[0])) {
1139
- const callee = chain.type === "CallExpression" ? chain.callee : null;
1140
- const inner = callee !== null && callee.type === "MemberExpression" ? callee.object : null;
1141
- chain = inner !== null && inner.type === "CallExpression" ? inner : null;
1142
- described = chain === null ? null : describeChain(chain);
1143
- }
1144
- if (chain === null || described === null)
1145
- continue;
1146
- // Tighten the zod-rooted mask to the peeled construction extent: the
1147
- // arguments of a peeled `.parse(...)` are not part of the schema, so
1148
- // candidates inside them stay free (babel traverses execution-method
1149
- // arguments normally).
1150
- if (rootIsZod)
1151
- consumedUntil = chain.end;
1152
- if (described.root !== candidate.name)
1153
- continue;
1154
- if (described.methods.some((m) => PARSE_METHODS.has(m)))
1155
- continue;
1156
- const rootMatchesPattern = namePattern?.test(candidate.name) === true;
1157
- // Non-z bases must look like schema derivation: the chain must START
1158
- // with a combinator (`Base.extend({...}).optional()` qualifies via
1159
- // extend), so an arbitrary imported object with a z-mentioning argument
1160
- // (`api.get(z.string())`) is never hoisted. describeChain records
1161
- // methods outermost-first — the deepest method is last.
1162
- const deepestMethod = described.methods[described.methods.length - 1];
1163
- if (!rootIsZod && (deepestMethod === undefined || !COMBINATOR_METHODS.has(deepestMethod))) {
1164
- continue;
1165
- }
1166
- const { eagerFree, deferredFree, impure } = analyzeCaptures(chain);
1167
- if (impure)
1168
- continue;
1169
- // Capture rule (babel-plugin-zod-hoist's canSafelyHoist, hardened): a
1170
- // free name is safe only when it is an import or a recognized standard
1171
- // global, and is never re-bound anywhere in the file (no scope info, so
1172
- // a name bound in ANY function cannot be trusted to mean the import —
1173
- // over-rejection only costs a missed hoist). The babel plugin also
1174
- // allows arbitrary unbound identifiers, but it has real scope analysis;
1175
- // here an unknown bare name is more likely a binding the lexical
1176
- // collector missed than a genuine global, and hoisting it would crash
1177
- // at module load (`ReferenceError: <name> is not defined`).
1178
- let eligible = true;
1179
- for (const name of eagerFree) {
1180
- if ((!imports.all.has(name) && !KNOWN_GLOBALS.has(name)) || isShadowed(name)) {
1181
- eligible = false;
1182
- break;
1183
- }
1184
- }
1185
- if (eligible) {
1186
- for (const name of deferredFree) {
1187
- if ((!imports.all.has(name) && !KNOWN_GLOBALS.has(name)) || isShadowed(name)) {
1188
- eligible = false;
1189
- break;
1190
- }
1191
- }
1192
- }
1193
- if (!eligible)
1194
- continue;
1195
- // Non-zod, non-pattern roots qualify only when the chain itself
1196
- // references a zod binding (`Base.extend({ a: z.string() })`).
1197
- if (!rootIsZod && !rootMatchesPattern) {
1198
- let referencesZod = false;
1199
- for (const name of eagerFree) {
1200
- if (imports.zod.has(name)) {
1201
- referencesZod = true;
1202
- break;
1203
- }
1204
- }
1205
- for (const name of deferredFree) {
1206
- if (imports.zod.has(name)) {
1207
- referencesZod = true;
1208
- break;
1209
- }
1210
- }
1211
- if (!referencesZod)
1212
- continue;
1213
- }
1214
- const text = code.slice(candidate.index, chain.end);
1215
- let declName = declByText.get(text);
1216
- if (!declName) {
1217
- declName = `_zh_${fnv1a(text)}`;
1218
- declByText.set(text, declName);
1219
- }
1220
- hoists.push({ start: candidate.index, end: chain.end, name: declName });
1221
- // Non-zod-rooted chains mask their interior only on success — the inner
1222
- // parts are consumed by this hoist's replacement.
1223
- consumedUntil = Math.max(consumedUntil, chain.end);
1224
- }
1225
- if (hoists.length === 0)
1226
- return null;
1227
- const decls = [...declByText.entries()]
1228
- .map(([text, name]) => `const ${name} = ${text};`)
1229
- .join("\n");
1230
- // The insertion offset is identical in input and output coordinates: the
1231
- // directive prologue precedes every statement, and all hoist replacements
1232
- // sit inside statements.
1233
- const edits = hoists.map((h) => ({ start: h.start, end: h.end, text: h.name }));
1234
- const insert = { offset: insertionOffset(code), text: `${decls}\n` };
1235
- return {
1236
- code: applyEdits(code, edits, insert),
1237
- schemas: [...declByText.entries()].map(([text, name]) => ({ name, text })),
1238
- edits,
1239
- insert,
1240
- };
898
+ * hoistZodSchemas + metadata about each hoisted declaration, so the
899
+ * transform can compile the hoisted schemas into optimized validators.
900
+ */
901
+ function hoistZodSchemasMeta(code, options) {
902
+ if (/\bconst _zh_[0-9a-f]{8} = /.test(code)) return null;
903
+ const imports = collectImportBindings(code);
904
+ if (imports.all.size === 0) return null;
905
+ const rawPattern = options?.schemaNamePattern;
906
+ const namePattern = rawPattern === null ? null : rawPattern === void 0 ? SCHEMA_NAME_PATTERN : typeof rawPattern === "string" ? new RegExp(rawPattern) : rawPattern;
907
+ const roots = new Set(imports.zod);
908
+ if (namePattern) {
909
+ for (const name of imports.all) if (namePattern.test(name)) roots.add(name);
910
+ }
911
+ if (imports.zod.size > 0) for (const name of imports.all) roots.add(name);
912
+ if (roots.size === 0) return null;
913
+ options?.onScan?.();
914
+ const { candidates, stripped } = scanSource(code, roots);
915
+ if (candidates.length === 0) return null;
916
+ let boundNames;
917
+ function isShadowed(name) {
918
+ boundNames ??= collectBoundNames(stripped());
919
+ return boundNames.has(name);
920
+ }
921
+ const hoists = [];
922
+ const declByText = /* @__PURE__ */ new Map();
923
+ let consumedUntil = 0;
924
+ for (const candidate of candidates) {
925
+ if (candidate.index < consumedUntil) continue;
926
+ if (candidate.depth === 0 && !candidate.afterArrow) {
927
+ consumedUntil = findChainEnd(code, candidate.index);
928
+ continue;
929
+ }
930
+ let parsed;
931
+ try {
932
+ parsed = parseAssignmentAt(code, candidate.index);
933
+ } catch {
934
+ continue;
935
+ }
936
+ let chain = narrowToCallChain(parsed, candidate.index);
937
+ if (!chain) continue;
938
+ const rootIsZod = imports.zod.has(candidate.name);
939
+ if (rootIsZod) consumedUntil = chain.end;
940
+ let described = describeChain(chain);
941
+ while (chain !== null && described !== null && described.methods.length > 0 && PARSE_METHODS.has(described.methods[0])) {
942
+ const callee = chain.type === "CallExpression" ? chain.callee : null;
943
+ const inner = callee !== null && callee.type === "MemberExpression" ? callee.object : null;
944
+ chain = inner !== null && inner.type === "CallExpression" ? inner : null;
945
+ described = chain === null ? null : describeChain(chain);
946
+ }
947
+ if (chain === null || described === null) continue;
948
+ if (rootIsZod) consumedUntil = chain.end;
949
+ if (described.root !== candidate.name) continue;
950
+ if (described.methods.some((m) => PARSE_METHODS.has(m))) continue;
951
+ const rootMatchesPattern = namePattern?.test(candidate.name) === true;
952
+ const deepestMethod = described.methods[described.methods.length - 1];
953
+ if (!rootIsZod && (deepestMethod === void 0 || !COMBINATOR_METHODS.has(deepestMethod))) continue;
954
+ const { eagerFree, deferredFree, impure } = analyzeCaptures(chain);
955
+ if (impure) continue;
956
+ let eligible = true;
957
+ for (const name of eagerFree) if (!imports.all.has(name) && !KNOWN_GLOBALS.has(name) || isShadowed(name)) {
958
+ eligible = false;
959
+ break;
960
+ }
961
+ if (eligible) {
962
+ for (const name of deferredFree) if (!imports.all.has(name) && !KNOWN_GLOBALS.has(name) || isShadowed(name)) {
963
+ eligible = false;
964
+ break;
965
+ }
966
+ }
967
+ if (!eligible) continue;
968
+ if (!rootIsZod && !rootMatchesPattern) {
969
+ let referencesZod = false;
970
+ for (const name of eagerFree) if (imports.zod.has(name)) {
971
+ referencesZod = true;
972
+ break;
973
+ }
974
+ for (const name of deferredFree) if (imports.zod.has(name)) {
975
+ referencesZod = true;
976
+ break;
977
+ }
978
+ if (!referencesZod) continue;
979
+ }
980
+ const text = code.slice(candidate.index, chain.end);
981
+ let declName = declByText.get(text);
982
+ if (!declName) {
983
+ declName = `_zh_${fnv1a(text)}`;
984
+ declByText.set(text, declName);
985
+ }
986
+ hoists.push({
987
+ start: candidate.index,
988
+ end: chain.end,
989
+ name: declName
990
+ });
991
+ consumedUntil = Math.max(consumedUntil, chain.end);
992
+ }
993
+ if (hoists.length === 0) return null;
994
+ const decls = [...declByText.entries()].map(([text, name]) => `const ${name} = ${text};`).join("\n");
995
+ const edits = hoists.map((h) => ({
996
+ start: h.start,
997
+ end: h.end,
998
+ text: h.name
999
+ }));
1000
+ const insert = {
1001
+ offset: insertionOffset(code),
1002
+ text: `${decls}\n`
1003
+ };
1004
+ return {
1005
+ code: applyEdits(code, edits, insert),
1006
+ schemas: [...declByText.entries()].map(([text, name]) => ({
1007
+ name,
1008
+ text
1009
+ })),
1010
+ edits,
1011
+ insert
1012
+ };
1241
1013
  }
1014
+ //#endregion
1015
+ export { SCHEMA_NAME_PATTERN, ZOD_MODULES, analyzeHoistedExpression, collectImportBindings, hoistZodSchemas, hoistZodSchemasMeta };
1016
+
1242
1017
  //# sourceMappingURL=hoist.js.map