void 0.22.0 → 0.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (276) hide show
  1. package/README.md +5 -1
  2. package/dist/{account-cmd-CjyxcGkM.mjs → account-cmd-C84Ee8cO.mjs} +4 -4
  3. package/dist/{scan-ClYmX3sa.mjs → application-analysis-BVsVqc11.mjs} +135 -18
  4. package/dist/application-routing-B7QEjqSR.mjs +27 -0
  5. package/dist/{auth-CZuiVsFh.mjs → auth-CCjt0hcq.mjs} +1 -1
  6. package/dist/{auth-DLNN0D3Z.mjs → auth-CSkdO2Bb.mjs} +4 -47
  7. package/dist/{auth-link-BLO4ptzo.mjs → auth-link-CioEg6uY.mjs} +4 -4
  8. package/dist/{auth-router-ZUg9MF_U.mjs → auth-router-BsR981d4.mjs} +4 -4
  9. package/dist/{better-auth-shared-rsBGBvWJ.mjs → better-auth-shared-hy6RPh9W.mjs} +13 -2
  10. package/dist/{build-cmd-BxR5FROK.mjs → build-cmd-LzvNJORH.mjs} +17 -5
  11. package/dist/{cache-D0sWhgKI.mjs → cache-C4MvnrMH.mjs} +2 -2
  12. package/dist/{cancel-deploy-D4NUqFbi.mjs → cancel-deploy-abUxpP2n.mjs} +2 -2
  13. package/dist/{cf-build-output-BJ6yGEIS.mjs → cf-build-output-BPqOT964.mjs} +2 -1
  14. package/dist/cf-build-output-_0HNWysu.mjs +2 -0
  15. package/dist/cli/cli.mjs +80 -455
  16. package/dist/cli/{cf-compat.mjs → cloudflare-operation-process.mjs} +442 -421
  17. package/dist/cli/env-schema-probe.d.mts +2 -1
  18. package/dist/cli/env-schema-probe.mjs +3 -3
  19. package/dist/client-Cu7jWiF1.mjs +2 -0
  20. package/dist/{client-BTZ3XkrB.mjs → client-RV8NVeB8.mjs} +140 -21
  21. package/dist/{cloudflare-auth-DQkqoMYa.mjs → cloudflare-auth-Qdc7tw8F.mjs} +41 -38
  22. package/dist/{cloudflare-cmd-BKlfGHAy.mjs → cloudflare-cmd-BcrVyTmJ.mjs} +5 -5
  23. package/dist/cloudflare-config-Bktvwtpf.mjs +182 -0
  24. package/dist/{cloudflare-connect-Ctmrw579.mjs → cloudflare-connect-B8uPZ4nx.mjs} +3 -3
  25. package/dist/{cloudflare-operations-BT6OWFBk.mjs → cloudflare-operations-AiWashgg.mjs} +1 -1
  26. package/dist/{cloudflare-operations-B9tzgjmf.mjs → cloudflare-operations-fxHb-byx.mjs} +116 -172
  27. package/dist/{preset-UHj9ARyP.mjs → cloudflare-process-B-wekeR6.mjs} +93 -6
  28. package/dist/{config-VavjpDnp.d.mts → config-BMHb8RCj.d.mts} +1 -0
  29. package/dist/config-C_XRIPx2.mjs +89 -0
  30. package/dist/config-entry.d.mts +1 -1
  31. package/dist/{connect-Dg-WkW-C.mjs → connect-Bd4kJd9U.mjs} +5 -5
  32. package/dist/{create-project-DdoqwFLF.mjs → create-project-Boczwj5r.mjs} +1 -1
  33. package/dist/{create-project-l9J7pbtm.mjs → create-project-bMf6ffLZ.mjs} +2 -2
  34. package/dist/{db-gp2sCXyN.mjs → db-8uG64XLl.mjs} +21 -21
  35. package/dist/{delete-TTedbH6B.mjs → delete-NvbiyeJf.mjs} +2 -2
  36. package/dist/{deploy-CH-o2CaZ.mjs → deploy-DzAIwqNU.mjs} +908 -582
  37. package/dist/{deploy-B19L2Bra.mjs → deploy-bjXdFCtn.mjs} +1 -1
  38. package/dist/{domain-JRF59P_r.mjs → domain-y5Tvydvo.mjs} +3 -3
  39. package/dist/{email-Bo6G9LOZ.mjs → email-B3umsW75.mjs} +13 -28
  40. package/dist/{env-BYOrWQnv.mjs → env-BS6qYHDb.mjs} +4 -4
  41. package/dist/{env-public-BxU_0yTL.d.mts → env-public-BX_r8HR6.d.mts} +1 -1
  42. package/dist/{env-validation-BB4GkLxn.mjs → env-validation-BPn7vk-V.mjs} +18 -71
  43. package/dist/{env-validation-BXge7uyK.mjs → env-validation-DbTg7-ar.mjs} +1 -1
  44. package/dist/{fetch-CXDChK7B.mjs → fetch-BIZJh7vR.mjs} +2 -2
  45. package/dist/{fetch-stream-AOByI7Ki.mjs → fetch-stream-IvCYKyQL.mjs} +24 -4
  46. package/dist/{gen-sCtlCOdA.mjs → gen-B580--vC.mjs} +2 -2
  47. package/dist/gen-BVaUUumi.mjs +2 -0
  48. package/dist/{github-cmd-0-7PexDq.mjs → github-cmd-v45BdfKX.mjs} +2 -2
  49. package/dist/{handler-HEcZsaij.d.mts → handler-CZ4nAylQ.d.mts} +1 -1
  50. package/dist/help-DofyZuY7.mjs +2 -0
  51. package/dist/{help-GKtwl07I.mjs → help-daGKjXGk.mjs} +229 -747
  52. package/dist/index.d.mts +1 -1
  53. package/dist/index.mjs +288 -1502
  54. package/dist/info-B97bTX9N.mjs +113 -0
  55. package/dist/{init-FZx3Elvz.mjs → init-Bvy7zrBo.mjs} +46 -15
  56. package/dist/limits-Bq5LG8Id.d.mts +27 -0
  57. package/dist/limits-Cjuk2VPm.mjs +68 -0
  58. package/dist/{link-BrQfb_CU.mjs → link-CDqqCjFl.mjs} +3 -3
  59. package/dist/{list-D44jmIAM.mjs → list-CZj0dzKY.mjs} +3 -3
  60. package/dist/{live-CKJlvlNp.d.mts → live-Chw1eIMv.d.mts} +1 -1
  61. package/dist/{local-d1-Bg9OzEEO.mjs → local-d1-2CMnpuW_.mjs} +2 -2
  62. package/dist/login-DYt_An22.mjs +2 -0
  63. package/dist/{login-CAsAsQ-_.mjs → login-UZKFM_u7.mjs} +3 -3
  64. package/dist/{logs-BjKvFnVM.mjs → logs-CUZ6t9t3.mjs} +3 -3
  65. package/dist/migrate-8_2u55MD.mjs +2 -0
  66. package/dist/{migrate-BPITvDJN.mjs → migrate-DHul7PRV.mjs} +2 -1
  67. package/dist/{node-Dt7z256D.mjs → node-BkyRWRx8.mjs} +1 -1
  68. package/dist/operator-args-CLgKGlwU.mjs +690 -0
  69. package/dist/{operator-cmd-BK5CCiT9.mjs → operator-cmd-DBA6dl0m.mjs} +68 -22
  70. package/dist/pages/client.d.mts +34 -2
  71. package/dist/pages/client.mjs +59 -3
  72. package/dist/pages/index.d.mts +1 -1
  73. package/dist/pages/index.mjs +1 -1
  74. package/dist/pages/islands-plugin.mjs +1 -1
  75. package/dist/pages/protocol.d.mts +2 -2
  76. package/dist/pages/protocol.mjs +2 -308
  77. package/dist/{parse-filename-DioPHiR9.mjs → parse-filename-CUbj-1MP.mjs} +35 -1
  78. package/dist/plan-D1Q5rf-r.mjs +2 -0
  79. package/dist/plan-NPpwZ_kc.mjs +58 -0
  80. package/dist/platform-args-BJdRtlLq.mjs +506 -0
  81. package/dist/platform-args-D3RXyR6h.mjs +2 -0
  82. package/dist/{platform-auth-config-BlN8xTdD.mjs → platform-auth-config-B56E9YP1.mjs} +3 -3
  83. package/dist/{platform-auth-protection-7d5aV2Jg.mjs → platform-auth-protection-BDWO_aER.mjs} +2 -2
  84. package/dist/{platform-auth-recovery-Dxij8ZbR.mjs → platform-auth-recovery-1gg4CSRe.mjs} +3 -3
  85. package/dist/{platform-cmd-E0FuL212.mjs → platform-cmd-Bt-1w6pY.mjs} +1 -1
  86. package/dist/{platform-cmd-B3hwKrFK.mjs → platform-cmd-DMcQStSc.mjs} +24 -3
  87. package/dist/{platform-domain-D6Xcy9ZX.mjs → platform-domain-BNkcz0OB.mjs} +2 -2
  88. package/dist/{platform-lifecycle-k0E0xoxx.mjs → platform-lifecycle-9OyBALhH.mjs} +327 -215
  89. package/dist/{platform-lifecycle-DMh_qrry.mjs → platform-lifecycle-BE6C_jxh.mjs} +1 -1
  90. package/dist/{platform-management-Brz_BDiT.mjs → platform-management-CjwLVQwN.mjs} +6 -3
  91. package/dist/{platform-management-DOtss0BN.mjs → platform-management-CnyTdcWX.mjs} +1 -1
  92. package/dist/platform-plans-config-BNGKGr4P.mjs +359 -0
  93. package/dist/{platform-recovery-BvtcXON5.mjs → platform-recovery-D6KSpuFm.mjs} +2 -2
  94. package/dist/{plugin-inference-BMfKRSqE.mjs → plugin-inference-CXWnn79A.mjs} +174 -64
  95. package/dist/{prepare-C-6YZyyg.mjs → prepare-B5Mkic5u.mjs} +1 -1
  96. package/dist/{prepare-CRhJbVrG.mjs → prepare-DOsL0CC9.mjs} +4 -20
  97. package/dist/prepare-cgvDMtSb.mjs +2 -0
  98. package/dist/{project-cmd-BZLCqOqw.mjs → project-cmd-CNzrqvBv.mjs} +16 -16
  99. package/dist/{project-team-BvgM0WoX.mjs → project-team-DQOWPfQT.mjs} +2 -2
  100. package/dist/{project-token-l5DqK6Az.mjs → project-token-CTDYU0Cc.mjs} +2 -2
  101. package/dist/{project-zero-trust-v6Mvpp8y.mjs → project-zero-trust-BNAkW-_0.mjs} +2 -2
  102. package/dist/{protocol-BBa6cstI.d.mts → protocol-CjF_iI9X.d.mts} +2 -2
  103. package/dist/protocol-U7bfjHmA.mjs +331 -0
  104. package/dist/{provision-Fr9pRqce.mjs → provision-C4ORE7G7.mjs} +1 -1
  105. package/dist/{provision-C4IGqkBf.mjs → provision-CJFgTZY8.mjs} +89 -198
  106. package/dist/{requests-DN-BbNiM.mjs → requests-MhxYnau8.mjs} +2 -2
  107. package/dist/resource-name-C7LVpcRm.mjs +11 -0
  108. package/dist/{rollback-D7rzSaZM.mjs → rollback-CJ6iSDoU.mjs} +3 -3
  109. package/dist/route-url-CG7U-cRN.mjs +15 -0
  110. package/dist/{runner-B8wXwWlo.mjs → runner-CXA9Fh8h.mjs} +1 -1
  111. package/dist/{runner-p-dMs2UN.mjs → runner-Ol0TNjk6.mjs} +2 -2
  112. package/dist/runtime/ai.d.mts +12 -8
  113. package/dist/runtime/ai.mjs +84 -17
  114. package/dist/runtime/better-auth-mysql.mjs +1 -1
  115. package/dist/runtime/better-auth-pg.mjs +1 -1
  116. package/dist/runtime/better-auth.mjs +1 -1
  117. package/dist/runtime/client-react.mjs +2 -2
  118. package/dist/runtime/client-solid.mjs +2 -2
  119. package/dist/runtime/client-svelte.mjs +2 -2
  120. package/dist/runtime/client-vue.mjs +2 -2
  121. package/dist/runtime/client.mjs +2 -2
  122. package/dist/runtime/durable.d.mts +3 -1
  123. package/dist/runtime/durable.mjs +4 -1
  124. package/dist/runtime/email/testing.mjs +1 -1
  125. package/dist/runtime/env-public.d.mts +1 -1
  126. package/dist/runtime/fetch-stream.mjs +1 -1
  127. package/dist/runtime/fetch.mjs +1 -1
  128. package/dist/runtime/handler.d.mts +1 -1
  129. package/dist/runtime/kv.mjs +0 -1
  130. package/dist/runtime/limits.d.mts +2 -0
  131. package/dist/runtime/limits.mjs +2 -0
  132. package/dist/runtime/live-client.d.mts +1 -1
  133. package/dist/runtime/live-server.mjs +25 -16
  134. package/dist/runtime/live.d.mts +1 -1
  135. package/dist/runtime/migration-handler.mjs +62 -42
  136. package/dist/runtime/route-url.d.mts +4 -0
  137. package/dist/runtime/route-url.mjs +2 -0
  138. package/dist/runtime/routing.d.mts +180 -0
  139. package/dist/runtime/routing.mjs +1082 -0
  140. package/dist/runtime/sandbox-container.d.mts +1 -1
  141. package/dist/runtime/sandbox-container.mjs +1 -1
  142. package/dist/runtime/sandbox.d.mts +3 -3
  143. package/dist/runtime/sandbox.mjs +75 -45
  144. package/dist/runtime/sse.mjs +1 -1
  145. package/dist/runtime/validator.d.mts +1 -1
  146. package/dist/runtime/ws-server.d.mts +4 -2
  147. package/dist/runtime/ws-server.mjs +27 -2
  148. package/dist/runtime/ws.d.mts +2 -2
  149. package/dist/runtime/ws.mjs +8 -6
  150. package/dist/{sandbox-qpNBT8a3.d.mts → sandbox-XZAqzFlG.d.mts} +11 -8
  151. package/dist/{sandbox-container-DdNEBfCc.d.mts → sandbox-container-Bo0eiFKz.d.mts} +2 -1
  152. package/dist/{sandbox-container-4fdqLnyb.mjs → sandbox-container-C6ItmVuN.mjs} +4 -2
  153. package/dist/{scan-4tfN-PSn.mjs → scan-C7okrLyM.mjs} +4 -35
  154. package/dist/{secret-BOtOl_cb.mjs → secret-Dli5fP0B.mjs} +4 -4
  155. package/dist/{sse-BaC1jXko.mjs → sse-CQNaDFFV.mjs} +6 -3
  156. package/dist/validate-Dq_L3s0S.mjs +2 -0
  157. package/dist/{validate-CIUwFpjB.mjs → validate-ctOrgiS3.mjs} +2 -1
  158. package/dist/{wrangler-DQF1vKyf.mjs → wrangler-7K-bW_DL.mjs} +8 -239
  159. package/dist/{ws-BoY7vQML.d.mts → ws-CL1w7GXU.d.mts} +13 -2
  160. package/package.json +15 -8
  161. package/skills/migrate-vite-cloudflare-to-void/SKILL.md +34 -157
  162. package/skills/void/SKILL.md +50 -135
  163. package/skills/void/docs/guide/ai.md +94 -84
  164. package/skills/void/docs/guide/app-types.md +3 -32
  165. package/skills/void/docs/guide/auth.md +12 -116
  166. package/skills/void/docs/guide/database/d1.md +9 -54
  167. package/skills/void/docs/guide/database/mysql.md +1 -1
  168. package/skills/void/docs/guide/database/postgresql.md +5 -26
  169. package/skills/void/docs/guide/database.md +23 -75
  170. package/skills/void/docs/guide/deployment.md +27 -113
  171. package/skills/void/docs/guide/durable-state.md +43 -18
  172. package/skills/void/docs/guide/edge/headers.md +3 -47
  173. package/skills/void/docs/guide/edge/prerendering.md +5 -20
  174. package/skills/void/docs/guide/edge/redirects.md +11 -64
  175. package/skills/void/docs/guide/edge/revalidation.md +5 -18
  176. package/skills/void/docs/guide/edge/rewrites.md +56 -284
  177. package/skills/void/docs/guide/edge/static-assets.md +22 -72
  178. package/skills/void/docs/guide/email/domains.md +112 -0
  179. package/skills/void/docs/guide/email/receiving.md +139 -0
  180. package/skills/void/docs/guide/email/sending.md +231 -0
  181. package/skills/void/docs/guide/email.md +13 -619
  182. package/skills/void/docs/guide/env-migration.md +11 -11
  183. package/skills/void/docs/guide/env-vars.md +9 -29
  184. package/skills/void/docs/guide/index.md +0 -15
  185. package/skills/void/docs/guide/jobs.md +3 -18
  186. package/skills/void/docs/guide/kv.md +5 -11
  187. package/skills/void/docs/guide/live.md +5 -56
  188. package/skills/void/docs/guide/pages-routing/actions-and-forms.md +78 -125
  189. package/skills/void/docs/guide/pages-routing/head.md +10 -10
  190. package/skills/void/docs/guide/pages-routing/islands.md +6 -36
  191. package/skills/void/docs/guide/pages-routing/layouts.md +6 -128
  192. package/skills/void/docs/guide/pages-routing/loaders.md +3 -19
  193. package/skills/void/docs/guide/pages-routing/markdown.md +13 -171
  194. package/skills/void/docs/guide/pages-routing/overview.md +7 -17
  195. package/skills/void/docs/guide/pages-routing/view-transitions.md +1 -1
  196. package/skills/void/docs/guide/platform/administration/access.md +1 -4
  197. package/skills/void/docs/guide/platform/administration/email.md +35 -8
  198. package/skills/void/docs/guide/platform/administration/operations.md +26 -4
  199. package/skills/void/docs/guide/platform/administration/plans.md +126 -0
  200. package/skills/void/docs/guide/platform/administration/projects.md +5 -2
  201. package/skills/void/docs/guide/platform/administration/zero-trust.md +23 -152
  202. package/skills/void/docs/guide/platform/development/runtime.md +3 -13
  203. package/skills/void/docs/guide/platform/development/schema-ci.md +0 -58
  204. package/skills/void/docs/guide/platform/installation/credentials.md +6 -4
  205. package/skills/void/docs/guide/platform/installation/domains.md +30 -2
  206. package/skills/void/docs/guide/platform/installation/first-deployment.md +2 -0
  207. package/skills/void/docs/guide/platform/installation/maintenance.md +3 -1
  208. package/skills/void/docs/guide/platform/installation/prerequisites.md +20 -15
  209. package/skills/void/docs/guide/platform/installation/setup.md +9 -5
  210. package/skills/void/docs/guide/platform-administration.md +1 -0
  211. package/skills/void/docs/guide/queues.md +7 -9
  212. package/skills/void/docs/guide/quickstart.md +38 -37
  213. package/skills/void/docs/guide/remote-dev.md +4 -9
  214. package/skills/void/docs/guide/sandboxes.md +29 -21
  215. package/skills/void/docs/guide/server-routing.md +9 -72
  216. package/skills/void/docs/guide/sse.md +4 -18
  217. package/skills/void/docs/guide/ssg.md +3 -15
  218. package/skills/void/docs/guide/ssr.md +14 -62
  219. package/skills/void/docs/guide/storage.md +9 -4
  220. package/skills/void/docs/guide/type-safety.md +3 -14
  221. package/skills/void/docs/guide/typed-fetch.md +3 -7
  222. package/skills/void/docs/guide/websockets.md +68 -40
  223. package/skills/void/docs/integrations/agents.md +3 -3
  224. package/skills/void/docs/integrations/cloudflare.md +85 -316
  225. package/skills/void/docs/integrations/frameworks/analog.md +5 -64
  226. package/skills/void/docs/integrations/frameworks/astro.md +4 -73
  227. package/skills/void/docs/integrations/frameworks/nuxt.md +5 -62
  228. package/skills/void/docs/integrations/frameworks/overview.md +11 -54
  229. package/skills/void/docs/integrations/frameworks/react-router.md +5 -60
  230. package/skills/void/docs/integrations/frameworks/sveltekit.md +6 -65
  231. package/skills/void/docs/integrations/frameworks/tanstack-start.md +4 -62
  232. package/skills/void/docs/integrations/nodejs-bun-deno.md +5 -69
  233. package/skills/void/docs/reference/api/auth.md +156 -0
  234. package/skills/void/docs/reference/api/client.md +87 -0
  235. package/skills/void/docs/reference/api/database.md +95 -0
  236. package/skills/void/docs/reference/api/durable.md +46 -0
  237. package/skills/void/docs/reference/api/env.md +50 -0
  238. package/skills/void/docs/reference/api/handlers.md +254 -0
  239. package/skills/void/docs/reference/api/pages.md +241 -0
  240. package/skills/void/docs/reference/api/plugin.md +39 -0
  241. package/skills/void/docs/reference/api/resources.md +109 -0
  242. package/skills/void/docs/reference/api/rewrites.md +76 -0
  243. package/skills/void/docs/reference/api/types.md +92 -0
  244. package/skills/void/docs/reference/api.md +56 -1218
  245. package/skills/void/docs/reference/cli/auth.md +88 -0
  246. package/skills/void/docs/reference/cli/database.md +128 -0
  247. package/skills/void/docs/reference/cli/deploy.md +85 -0
  248. package/skills/void/docs/reference/cli/domains.md +41 -0
  249. package/skills/void/docs/reference/cli/email.md +129 -0
  250. package/skills/void/docs/reference/cli/generate.md +116 -0
  251. package/skills/void/docs/reference/cli/github.md +189 -0
  252. package/skills/void/docs/reference/cli/platform-config.md +92 -0
  253. package/skills/void/docs/reference/cli/platform-email.md +81 -0
  254. package/skills/void/docs/reference/cli/platform-installation.md +127 -0
  255. package/skills/void/docs/reference/cli/platform-operations.md +90 -0
  256. package/skills/void/docs/reference/cli/platform-users.md +89 -0
  257. package/skills/void/docs/reference/cli/platform-zero-trust.md +45 -0
  258. package/skills/void/docs/reference/cli/platform.md +70 -0
  259. package/skills/void/docs/reference/cli/project.md +214 -0
  260. package/skills/void/docs/reference/cli/secrets.md +76 -0
  261. package/skills/void/docs/reference/cli/setup.md +70 -0
  262. package/skills/void/docs/reference/cli.md +32 -1682
  263. package/skills/void/docs/reference/config.md +12 -18
  264. package/skills/void/docs/reference/resource-inference.md +3 -58
  265. package/skills/void/docs/reference/structure.md +14 -41
  266. package/dist/canonical-json-DuDiiUsQ.mjs +0 -13
  267. package/dist/client-Czz8o5jP.mjs +0 -2
  268. package/dist/gen-CNJ62MM7.mjs +0 -2
  269. package/dist/help-CmZzxUba.mjs +0 -2
  270. package/dist/login-CGcRKEoi.mjs +0 -2
  271. package/dist/migrate-CYfbKkXh.mjs +0 -2
  272. package/dist/plan-BEZ8VJW0.mjs +0 -256
  273. package/dist/plan-DpuOr14e.mjs +0 -2
  274. package/dist/prepare-Bm3iq-u4.mjs +0 -2
  275. package/dist/validate-EKmJWxmy.mjs +0 -2
  276. /package/dist/cli/{cf-compat.d.mts → cloudflare-operation-process.d.mts} +0 -0
package/dist/index.mjs CHANGED
@@ -1,34 +1,37 @@
1
1
  import { n as __toESM } from "./rolldown-runtime-DXIUcv95.mjs";
2
2
  import { a as join, l as relative, n as dirname, u as resolve } from "./dist-BVqXeR_h.mjs";
3
3
  import { t as require_picocolors } from "./picocolors-BTps1_gs.mjs";
4
- import { G as resolveWorkerDirName, St as hasDocumentRoutes, V as resolveDistDir, ct as prerenderPagesNode, dt as collectRevalidate, ft as hasRevalidate, mt as SEND_EMAIL_BINDING, ot as generateQueueResolverSource, pt as scanDurableObjectModules, st as prerenderPages, ut as collectPages, wt as resolveAssetRoutingPolicy, xt as hasApiRoutes } from "./deploy-CH-o2CaZ.mjs";
5
- import { i as resolveProjectPaths, n as readProjectPaths, t as assertNoRootSourceConventionConflicts } from "./project-paths-GgcMozYz.mjs";
6
- import { n as loadVoidAuthConfig, t as findVoidAuthConfig } from "./config-DPByhVck.mjs";
4
+ import { d as walk, n as FRAMEWORK_SCAN_DIRS, p as applyBindingOverrides, t as DEFAULT_SCAN_DIRS, u as inferBindingsFromSource } from "./plugin-inference-CXWnn79A.mjs";
5
+ import { n as readProjectPaths, t as assertNoRootSourceConventionConflicts } from "./project-paths-GgcMozYz.mjs";
6
+ import { n as loadVoidAuthConfig } from "./config-DPByhVck.mjs";
7
+ import { d as isNodeTarget, m as readConfig, u as getDatabaseDialect } from "./config-Br_JZD6u.mjs";
8
+ import { i as isMemberExpression, n as isIdentifier, r as isLiteral } from "./ast-CPGPjb0V.mjs";
9
+ import { t as isRouteEnabledForEnvironment } from "./parse-filename-CUbj-1MP.mjs";
10
+ import { r as scanQueuesSync, s as scanJobsSync, t as analyzeApplicationSync } from "./application-analysis-BVsVqc11.mjs";
11
+ import { a as validateSsrEntries, n as SSR_SERVER_ENTRY_RELATIVE_PATHS, o as validateSsrEntry, t as SSR_CLIENT_ENTRY_RELATIVE_PATHS } from "./entry-CF5wvH4w.mjs";
12
+ import { r as hasEmailHandlers } from "./email--tEtMoj_.mjs";
13
+ import { i as resolveLayoutIds } from "./scan-C7okrLyM.mjs";
14
+ import { a as hasSandboxSqliteMigration, c as resolveSandboxConfig, i as assertSandboxNamespaceConfig, l as sandboxContainerConfig, n as DEFAULT_SANDBOX_CLASS_NAME, r as SANDBOX_MIGRATION_TAG } from "./config-C_XRIPx2.mjs";
15
+ import { Ct as hasDocumentRoutes, G as resolveWorkerDirName, St as hasApiRoutes, Tt as resolveAssetRoutingPolicy, V as resolveDistDir, ct as selectNativeVersionMetadataBinding, ft as collectPages, ht as SEND_EMAIL_BINDING, lt as prerenderPages, mt as hasRevalidate, ot as generateQueueResolverSource, pt as collectRevalidate, st as CLOUDFLARE_PRESERVE_BINDINGS_BUILD_ENV, ut as prerenderPagesNode } from "./deploy-DzAIwqNU.mjs";
7
16
  import { r as scopedAccessCredentials } from "./cf-access-DRsQRe6k.mjs";
8
- import { a as getApiUrl, c as getToken, o as getProxyUrl, u as isStagingMode } from "./auth-DLNN0D3Z.mjs";
17
+ import { a as getApiUrl, c as getToken, o as getProxyUrl, u as isStagingMode } from "./auth-CSkdO2Bb.mjs";
9
18
  import { r as ensurePlatformProxyAccess } from "./cf-access-P0iZnu0q.mjs";
10
19
  import { i as readDeploymentPlatform, o as readProjectConfig } from "./project-C0Fqu05O.mjs";
11
- import { d as isNodeTarget, h as resolveBindingNames, m as readConfig, u as getDatabaseDialect } from "./config-Br_JZD6u.mjs";
12
- import { B as materializeCloudflareConfig, C as readWranglerWebSocketTombstones, D as syncWranglerWebSockets, E as syncWranglerDurableObjects, H as restoreCloudflarePreviewPointer, I as resolveSandboxConfig, L as sandboxContainerConfig, M as SANDBOX_MIGRATION_TAG, N as assertSandboxNamespaceConfig, P as isSandboxEnabled, T as syncWranglerBindings, W as stashCloudflareDeployPointer, a as LIVE_MIGRATION_TAG, d as ensureWranglerNodejsAlsFlag, g as readExistingLiveBindingConfig, h as normalizeWranglerCompatibilityFlags, j as DEFAULT_SANDBOX_CLASS_NAME, l as ensureWranglerCompat, m as nextDurableObjectMigrationTag, p as hasDurableObjectSqliteMigration, u as ensureWranglerCompatibilityDate, w as resolveLiveBindingConfig, y as readWranglerCompat } from "./wrangler-DQF1vKyf.mjs";
20
+ import { a as restoreCloudflarePreviewPointer, r as materializeCloudflareConfig, s as stashCloudflareDeployPointer } from "./cloudflare-config-Bktvwtpf.mjs";
21
+ import { D as syncWranglerDurableObjects, E as syncWranglerBindings, O as syncWranglerWebSockets, T as resolveLiveBindingConfig, _ as readExistingLiveBindingConfig, a as LIVE_MIGRATION_TAG, b as readWranglerCompat, d as ensureWranglerCompatibilityDate, f as ensureWranglerNodejsAlsFlag, g as normalizeWranglerCompatibilityFlags, h as nextDurableObjectMigrationTag, m as hasDurableObjectSqliteMigration, p as findBindingNameOwner, u as ensureWranglerCompat, w as readWranglerWebSocketTombstones } from "./wrangler-7K-bW_DL.mjs";
13
22
  import { i as voidWarn, n as voidError, r as voidLog, t as setShowTimestamp } from "./log-ChfPKsVd.mjs";
14
23
  import { n as lintDuplicateSources, r as mergeRoutingRules, t as lintDestinationSplats } from "./headers-DWi2IXWx.mjs";
15
24
  import { n as ensureProjectTsconfig, r as writeFileIfChanged } from "./project-tsconfig-B8GeM0RM.mjs";
16
- import { i as isMemberExpression, n as isIdentifier, r as isLiteral } from "./ast-CPGPjb0V.mjs";
17
- import { i as resolveLayoutIds } from "./scan-4tfN-PSn.mjs";
18
- import { a as scanJobsSync, i as scanQueuesSync, n as scanRoutePatternsSync, r as scanRoutes, t as scanMiddlewareSync } from "./scan-ClYmX3sa.mjs";
19
- import { c as inferBindingsFromSource, i as inferProjectBindings, l as walk, n as FRAMEWORK_SCAN_DIRS, r as detectFramework, s as scanWebSocketRoutesSync, t as DEFAULT_SCAN_DIRS } from "./plugin-inference-BMfKRSqE.mjs";
20
- import { n as writeLocalD1PersistState, t as resolveLocalD1Target } from "./local-d1-Bg9OzEEO.mjs";
25
+ import { n as writeLocalD1PersistState, t as resolveLocalD1Target } from "./local-d1-2CMnpuW_.mjs";
21
26
  import { n as parseDotenvFile } from "./dotenv-VQxupEUv.mjs";
22
27
  import { i as generateDbDts, n as generateQueueTypes, r as DRIZZLE_OPERATORS, t as generateRouteTypes } from "./route-types-Clm4WD0B.mjs";
23
28
  import { t as discoverSchema } from "./discover-BcPPiF1o.mjs";
24
29
  import { _ as parseCapturedMessage, a as DEV_INBOX_ENV_VAR, c as DEV_INBOX_TOKEN_ENV_VAR, f as clearDevBuffer, g as listDevMessages, l as DEV_INBOX_TOKEN_HEADER, m as findDevMessage, n as DEV_INBOX_ACK_VALUE, o as DEV_INBOX_MAX_CAPTURE_BYTES, s as DEV_INBOX_PREFIX, t as DEV_INBOX_ACK_HEADER, u as DEV_INBOX_TOKEN_QUERY, v as pushToDevBuffer, y as registerEmailSink } from "./dev-inbox-P0u4tM8Y.mjs";
25
30
  import { t as MagicString } from "./dist-AoCzRTJE.mjs";
26
31
  import { n as findEnvFileForPaths, r as generateEnvTypes, t as findEnvFile } from "./env-types-C2_bIk_b.mjs";
27
- import { y as loadUserEnvFile } from "./env-validation-BB4GkLxn.mjs";
32
+ import { y as loadUserEnvFile } from "./env-validation-BPn7vk-V.mjs";
28
33
  import { a as loadLocalEnv, o as resolveRemoteMode, r as findLegacyEnvFiles, s as stripInternalEnvKeys, t as CLIENT_ENV_PREFIX$2 } from "./env-_v349JBd.mjs";
29
- import { t as isRouteEnabledForEnvironment } from "./parse-filename-DioPHiR9.mjs";
30
- import { a as validateSsrEntries, n as SSR_SERVER_ENTRY_RELATIVE_PATHS, o as validateSsrEntry, t as SSR_CLIENT_ENTRY_RELATIVE_PATHS } from "./entry-CF5wvH4w.mjs";
31
- import { a as scanEmailHandlersSync, r as hasEmailHandlers } from "./email--tEtMoj_.mjs";
34
+ import { n as completeApplicationAnalysis } from "./application-routing-B7QEjqSR.mjs";
32
35
  import { n as generateVoidAuthDrizzleSchema, t as generateVoidAuthDatabaseModule } from "./drizzle-Beb2Am5S.mjs";
33
36
  import { n as INTERNAL_BINDING_PREFIXES, t as INTERNAL_BINDING_EXACT_NAMES } from "./env-raw-Cx8ElDdj.mjs";
34
37
  import { n as defer } from "./defer-YsYDUoii.mjs";
@@ -40,9 +43,66 @@ import { appendSqliteClassMigration } from "@void/deploy-core";
40
43
  import { normalizePath, parseSync } from "vite";
41
44
  import { timingSafeEqual } from "node:crypto";
42
45
  import { homedir } from "node:os";
46
+ import { isDeepStrictEqual } from "node:util";
43
47
  import { init, parse } from "es-module-lexer";
44
- //#region src/pages/dev-css-assets.ts
48
+ import { compilePattern } from "@void/edge";
49
+ //#region src/cloudflare-durable-patch.ts
45
50
  var import_picocolors = /* @__PURE__ */ __toESM(require_picocolors(), 1);
51
+ function entries(value, label) {
52
+ if (value === void 0) return [];
53
+ if (!Array.isArray(value) || value.some((entry) => !entry || typeof entry !== "object" || Array.isArray(entry))) throw new Error(`Cloudflare ${label} configuration must be an array of objects.`);
54
+ return value;
55
+ }
56
+ function byIdentity(rows, field, label, unique = false) {
57
+ const map = /* @__PURE__ */ new Map();
58
+ for (const row of rows) {
59
+ const id = row[field];
60
+ if (typeof id !== "string" || !id) throw new Error(`Cloudflare ${label} is missing its ${field}.`);
61
+ const previous = map.get(id);
62
+ if (previous && unique) throw new Error(`Cloudflare ${label} ${JSON.stringify(id)} is configured more than once.`);
63
+ if (previous && !isDeepStrictEqual(previous, row)) throw new Error(`Cloudflare ${label} ${JSON.stringify(id)} has conflicting configuration.`);
64
+ if (!previous) map.set(id, row);
65
+ }
66
+ return map;
67
+ }
68
+ /** Finish cumulative feature planning without repeating the Cloudflare plugin's array fallback. */
69
+ function finalizeDurableObjectPatch(resolved, patch, generatedLocalBindings) {
70
+ const baselineObjects = resolved.durable_objects;
71
+ const pendingObjects = patch.durable_objects;
72
+ const baselineBindings = byIdentity(entries(baselineObjects?.bindings, "Durable Object bindings"), "name", "Durable Object binding", true);
73
+ const pendingBindings = byIdentity(entries(pendingObjects?.bindings, "Durable Object bindings"), "name", "Durable Object binding");
74
+ const history = entries(resolved.migrations, "Durable Object migrations");
75
+ const baselineMigrations = byIdentity(history, "tag", "Durable Object migration", true);
76
+ for (const local of generatedLocalBindings) for (const map of [baselineBindings, pendingBindings]) {
77
+ const existing = map.get(local.name);
78
+ if (existing && (existing.class_name !== local.class_name || existing.script_name !== void 0 || existing.environment !== void 0)) throw new Error(`Cloudflare generated Durable Object binding ${JSON.stringify(local.name)} conflicts with its configured identity.`);
79
+ }
80
+ if (pendingObjects?.bindings !== void 0) {
81
+ const additions = [];
82
+ for (const [name, row] of pendingBindings) {
83
+ const existing = baselineBindings.get(name);
84
+ if (existing && !isDeepStrictEqual(existing, row)) throw new Error(`Cloudflare Durable Object binding ${JSON.stringify(name)} has conflicting configuration.`);
85
+ if (!existing) additions.push(row);
86
+ }
87
+ patch.durable_objects = {
88
+ ...pendingObjects,
89
+ bindings: additions
90
+ };
91
+ }
92
+ if (patch.migrations !== void 0) {
93
+ const pending = byIdentity(entries(patch.migrations, "Durable Object migrations"), "tag", "Durable Object migration");
94
+ const additions = [];
95
+ for (const [tag, row] of pending) {
96
+ const previous = baselineMigrations.get(tag);
97
+ if (previous && !isDeepStrictEqual(previous, row)) throw new Error(`Cloudflare Durable Object migration ${JSON.stringify(tag)} has conflicting configuration.`);
98
+ if (!previous) additions.push(row);
99
+ }
100
+ patch.migrations = [...history, ...additions];
101
+ resolved.migrations = [];
102
+ }
103
+ }
104
+ //#endregion
105
+ //#region src/pages/dev-css-assets.ts
46
106
  const DEV_CSS_ASSET_MODULE_ID = "virtual:void-pages-dev-assets";
47
107
  const DEV_CSS_ASSET_ENDPOINT = "/__void/dev/pages-css";
48
108
  const DEV_CSS_ASSET_GUARD_HEADER = "X-Void-Dev-Asset-Request";
@@ -723,7 +783,7 @@ function createPrimaryDb(d1) {
723
783
  const migrationsDir = paths.migrationsDir;
724
784
  if (!(existsSync(migrationsDir) && readdirSync(migrationsDir).some((f) => f.endsWith(".sql")))) {
725
785
  if (dialect === "sqlite") {
726
- const { getApplicationTables, getMiniflareDatabasePath } = await import("./runner-B8wXwWlo.mjs");
786
+ const { getApplicationTables, getMiniflareDatabasePath } = await import("./runner-CXA9Fh8h.mjs");
727
787
  if ((await getApplicationTables(getMiniflareDatabasePath(options.localD1PersistRoot ?? join(root, ".void"), options.localD1DatabaseId ?? "local")).catch(() => [])).length > 0) return;
728
788
  }
729
789
  voidWarn(`Schema found but no migrations in ${paths.sourceRelative("db/migrations")}/.\n \`void db push\` syncs the schema to your local DB without creating migration files.
@@ -2005,7 +2065,7 @@ function migrationPlugin(root, dialect, databaseId = "local", persistRoot = join
2005
2065
  return;
2006
2066
  }
2007
2067
  const { collectMigrations } = await import("./collect-DLyFDiKW.mjs");
2008
- const { validateMigrations } = await import("./validate-EKmJWxmy.mjs");
2068
+ const { validateMigrations } = await import("./validate-Dq_L3s0S.mjs");
2009
2069
  const allMigrations = collectMigrations(migrationsDir);
2010
2070
  const appliedNames = dialect === "mysql" ? await import("./runner-mysql-CEG5JozK.mjs").then((runner) => runner.getMySqlAppliedMigrations(url)) : await import("./runner-pg-Bh4AgZdj.mjs").then((runner) => runner.getPgAppliedMigrations(url));
2011
2071
  const appliedSet = new Set(appliedNames);
@@ -2018,9 +2078,9 @@ function migrationPlugin(root, dialect, databaseId = "local", persistRoot = join
2018
2078
  const applied = dialect === "mysql" ? await import("./runner-mysql-CEG5JozK.mjs").then((runner) => runner.runMySqlMigrations(migrationsDir, url)) : await import("./runner-pg-Bh4AgZdj.mjs").then((runner) => runner.runPgMigrations(migrationsDir, url));
2019
2079
  if (applied.length > 0) voidLog(`Applied ${applied.length} migration(s): ${applied.join(", ")}`);
2020
2080
  } else if (hasSqlMigrations) {
2021
- const { runMigrations, getMiniflareDatabasePath, getAppliedMigrations } = await import("./runner-B8wXwWlo.mjs");
2081
+ const { runMigrations, getMiniflareDatabasePath, getAppliedMigrations } = await import("./runner-CXA9Fh8h.mjs");
2022
2082
  const { collectMigrations } = await import("./collect-DLyFDiKW.mjs");
2023
- const { validateMigrations } = await import("./validate-EKmJWxmy.mjs");
2083
+ const { validateMigrations } = await import("./validate-Dq_L3s0S.mjs");
2024
2084
  const dbPath = getMiniflareDatabasePath(persistRoot, databaseId);
2025
2085
  const allMigrations = collectMigrations(migrationsDir);
2026
2086
  const appliedRows = await getAppliedMigrations(dbPath);
@@ -2035,7 +2095,7 @@ function migrationPlugin(root, dialect, databaseId = "local", persistRoot = join
2035
2095
  if (applied.length > 0) voidLog(`Applied ${applied.length} migration(s): ${applied.join(", ")}`);
2036
2096
  }
2037
2097
  if (auth?.enabled) {
2038
- const { runLocalVoidAuthMigrations } = await import("./node-Dt7z256D.mjs");
2098
+ const { runLocalVoidAuthMigrations } = await import("./node-BkyRWRx8.mjs");
2039
2099
  await runLocalVoidAuthMigrations(root, dialect, persistRoot, databaseId, auth.configPath);
2040
2100
  voidLog("Applied Better Auth migrations");
2041
2101
  }
@@ -2326,569 +2386,33 @@ function restartPlugin() {
2326
2386
  };
2327
2387
  }
2328
2388
  //#endregion
2389
+ //#region src/client-asset-manifest.ts
2390
+ /** Attach cache provenance to the existing manifest without changing its entry inventory. */
2391
+ function stampClientAssetCachePolicy(bundle, manifestPath, headerRules = []) {
2392
+ const asset = bundle[manifestPath];
2393
+ if (asset?.type !== "asset") return;
2394
+ const fingerprinted = /* @__PURE__ */ new Set();
2395
+ const authoredCachePatterns = headerRules.filter((rule) => rule.headers.some(([name]) => name.toLowerCase() === "cache-control")).map((rule) => compilePattern(rule.pattern).regex);
2396
+ for (const item of Object.values(bundle)) if (item.type === "chunk" && typeof item.preliminaryFileName === "string" && item.preliminaryFileName !== item.fileName) {
2397
+ if (!authoredCachePatterns.some((pattern) => pattern.test("/" + item.fileName))) fingerprinted.add(item.fileName);
2398
+ }
2399
+ const manifest = JSON.parse(String(asset.source));
2400
+ for (const entry of Object.values(manifest)) if (entry.file && fingerprinted.has(entry.file)) entry.immutableFiles = [entry.file];
2401
+ else delete entry.immutableFiles;
2402
+ asset.source = JSON.stringify(manifest, null, 2);
2403
+ }
2404
+ //#endregion
2329
2405
  //#region src/router/compile.ts
2330
- /**
2331
- * Script tag injected into dev HTML to load the binding-hint virtual module.
2332
- * The virtual module (served by restartPlugin) listens for `void:new-binding`
2333
- * HMR events and shows a toast with a click-to-restart action.
2334
- */
2335
- const BINDING_HINT_SCRIPT = `<script type="module" src="/@id/virtual:void/binding-hint"><\/script>`;
2336
- const DEFAULT_ERROR_PAGE_FONT_STACK = "system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif";
2337
- const EDGE_MODULE_PATH = fileURLToPath(import.meta.resolve("@void/edge"));
2406
+ const ROUTE_URL_PATH = fileURLToPath(import.meta.resolve("#self/runtime/route-url"));
2407
+ const ROUTING_RUNTIME_PATH = fileURLToPath(import.meta.resolve("#self/runtime/routing"));
2338
2408
  function pushDefaultErrorPageHelpers(lines, options) {
2339
- const dev = options.dev === true;
2340
- lines.push(`const __VOID_ERROR_PAGE_FONT_STACK = ${JSON.stringify(DEFAULT_ERROR_PAGE_FONT_STACK)};`);
2341
- lines.push(`const __VOID_DEV = ${JSON.stringify(dev)};`);
2342
- lines.push(`const __VOID_PROJECT_ROOT = ${JSON.stringify(options.projectRoot)};`);
2343
- lines.push(`const __VOID_HOME_DIR = ${JSON.stringify(options.homeDir)};`);
2344
- lines.push(`function __voidEscapeHtml(value) {`);
2345
- lines.push(` return String(value).replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;");`);
2346
- lines.push(`}`);
2347
- lines.push("");
2348
- lines.push(`function __voidShouldServeHtmlErrorPage(request) {`);
2349
- lines.push(` if (request.method !== "GET" && request.method !== "HEAD") return false;`);
2350
- lines.push(` const url = new URL(request.url);`);
2351
- lines.push(` if (url.pathname === "/api" || url.pathname.startsWith("/api/")) return false;`);
2352
- lines.push(` if (/\\/[^/]+\\.[^/]+$/.test(url.pathname)) return false;`);
2353
- lines.push(` const destination = request.headers.get("sec-fetch-dest");`);
2354
- lines.push(` if (destination && destination !== "document" && destination !== "empty") return false;`);
2355
- lines.push(` const accept = request.headers.get("accept");`);
2356
- lines.push(` return !accept || accept.includes("text/html") || accept.includes("*/*");`);
2357
- lines.push(`}`);
2358
- lines.push("");
2359
- lines.push(`function __voidNormalizeFsPath(value) {`);
2360
- lines.push(` return typeof value === "string" ? value.replaceAll("\\\\", "/") : "";`);
2361
- lines.push(`}`);
2362
- lines.push("");
2363
- lines.push(`function __voidIsAbsolutePath(value) {`);
2364
- lines.push(` return value.startsWith("/") || /^[A-Za-z]:\\//.test(value);`);
2365
- lines.push(`}`);
2366
- lines.push("");
2367
- lines.push(`function __voidDisplayPath(value) {`);
2368
- lines.push(` const path = __voidNormalizeFsPath(value);`);
2369
- lines.push(` const homeDir = __voidNormalizeFsPath(__VOID_HOME_DIR);`);
2370
- lines.push(` const projectRoot = __voidNormalizeFsPath(__VOID_PROJECT_ROOT);`);
2371
- lines.push(` if (!path) return "";`);
2372
- lines.push(` if (projectRoot && (path === projectRoot || path.startsWith(projectRoot + "/"))) {`);
2373
- lines.push(` const suffix = path.slice(projectRoot.length).replace(/^\\/?/, "");`);
2374
- lines.push(` return suffix ? "./" + suffix : "./";`);
2375
- lines.push(` }`);
2376
- lines.push(` if (homeDir && (path === homeDir || path.startsWith(homeDir + "/"))) {`);
2377
- lines.push(` const suffix = path.slice(homeDir.length).replace(/^\\/?/, "");`);
2378
- lines.push(` return suffix ? "~/" + suffix : "~/";`);
2379
- lines.push(` }`);
2380
- lines.push(` return path;`);
2381
- lines.push(`}`);
2382
- lines.push("");
2383
- lines.push(`function __voidEditorHref(value, line, column) {`);
2384
- lines.push(` const path = __voidNormalizeFsPath(value);`);
2385
- lines.push(` if (!__voidIsAbsolutePath(path)) return "";`);
2386
- lines.push(` return "vscode://file/" + encodeURI(path).replaceAll("#", "%23").replaceAll("?", "%3F") + ":" + String(line) + ":" + String(column);`);
2387
- lines.push(`}`);
2388
- lines.push("");
2389
- lines.push(`function __voidCreateStackFrame(functionName, file, line, column, raw) {`);
2390
- lines.push(` const normalizedFile = __voidNormalizeFsPath(file);`);
2391
- lines.push(` const lineNumber = Number(line);`);
2392
- lines.push(` const columnNumber = Number(column);`);
2393
- lines.push(` if (!normalizedFile || !Number.isFinite(lineNumber) || lineNumber <= 0) return null;`);
2394
- lines.push(` const safeColumn = Number.isFinite(columnNumber) && columnNumber > 0 ? columnNumber : 1;`);
2395
- lines.push(` return {`);
2396
- lines.push(` functionName: functionName || "",`);
2397
- lines.push(` file: normalizedFile,`);
2398
- lines.push(` line: lineNumber,`);
2399
- lines.push(` column: safeColumn,`);
2400
- lines.push(` displayPath: __voidDisplayPath(normalizedFile),`);
2401
- lines.push(` href: __voidEditorHref(normalizedFile, lineNumber, safeColumn),`);
2402
- lines.push(` raw: raw || "",`);
2403
- lines.push(` };`);
2404
- lines.push(`}`);
2405
- lines.push("");
2406
- lines.push(`function __voidParseFrameLocation(value) {`);
2407
- lines.push(` const match = value.match(/^(.*):(\\d+):(\\d+)$/);`);
2408
- lines.push(` if (!match) return null;`);
2409
- lines.push(` return __voidCreateStackFrame("", match[1], Number(match[2]), Number(match[3]), value);`);
2410
- lines.push(`}`);
2411
- lines.push("");
2412
- lines.push(`function __voidParseStackFrames(stack) {`);
2413
- lines.push(` if (!stack) return [];`);
2414
- lines.push(` const frames = [];`);
2415
- lines.push(` for (const rawLine of stack.split(/\\n+/)) {`);
2416
- lines.push(` const line = rawLine.trim();`);
2417
- lines.push(` if (!line) continue;`);
2418
- lines.push(` let frame = null;`);
2419
- lines.push(` let match = line.match(/^at\\s+(?:async\\s+)?(.+?)\\s+\\((.+)\\)$/);`);
2420
- lines.push(` if (match) {`);
2421
- lines.push(` const location = __voidParseFrameLocation(match[2]);`);
2422
- lines.push(` frame = location ? { ...location, functionName: match[1] } : null;`);
2423
- lines.push(` } else {`);
2424
- lines.push(` match = line.match(/^at\\s+(.+)$/);`);
2425
- lines.push(` if (match) {`);
2426
- lines.push(` frame = __voidParseFrameLocation(match[1]);`);
2427
- lines.push(` } else {`);
2428
- lines.push(` match = line.match(/^(.*?)@(.+)$/);`);
2429
- lines.push(` if (match) {`);
2430
- lines.push(` const location = __voidParseFrameLocation(match[2]);`);
2431
- lines.push(` frame = location ? { ...location, functionName: match[1] } : null;`);
2432
- lines.push(` }`);
2433
- lines.push(` }`);
2434
- lines.push(` }`);
2435
- lines.push(` if (frame) frames.push({ ...frame, raw: line });`);
2436
- lines.push(` }`);
2437
- lines.push(` return frames;`);
2438
- lines.push(`}`);
2439
- lines.push("");
2440
- lines.push(`function __voidGetStackFrames(error) {`);
2441
- lines.push(` if (!(error instanceof Error)) return [];`);
2442
- lines.push(` if (!error.stack && typeof Error.captureStackTrace === "function") {`);
2443
- lines.push(` try {`);
2444
- lines.push(` Error.captureStackTrace(error, __voidGetStackFrames);`);
2445
- lines.push(` } catch {`);
2446
- lines.push(` // Ignore runtimes that reject captureStackTrace on thrown errors.`);
2447
- lines.push(` }`);
2448
- lines.push(` }`);
2449
- lines.push(` const originalPrepareStackTrace = Error.prepareStackTrace;`);
2450
- lines.push(` try {`);
2451
- lines.push(` Error.prepareStackTrace = (_, callSites) => callSites;`);
2452
- lines.push(` const structured = error.stack;`);
2453
- lines.push(` if (Array.isArray(structured)) {`);
2454
- lines.push(` const frames = [];`);
2455
- lines.push(` for (const callSite of structured) {`);
2456
- lines.push(` try {`);
2457
- lines.push(` const fileName = callSite.getFileName?.() || callSite.getScriptNameOrSourceURL?.();`);
2458
- lines.push(` const line = callSite.getLineNumber?.();`);
2459
- lines.push(` const column = callSite.getColumnNumber?.();`);
2460
- lines.push(` const functionName = callSite.getFunctionName?.() || callSite.getMethodName?.() || "";`);
2461
- lines.push(` const frame = __voidCreateStackFrame(functionName, fileName || "", line, column, String(callSite));`);
2462
- lines.push(` if (frame) frames.push(frame);`);
2463
- lines.push(` } catch {`);
2464
- lines.push(` // Ignore malformed CallSite entries and continue rendering.`);
2465
- lines.push(` }`);
2466
- lines.push(` }`);
2467
- lines.push(` if (frames.length > 0) return frames;`);
2468
- lines.push(` }`);
2469
- lines.push(` } catch {`);
2470
- lines.push(` // Fall through to string parsing.`);
2471
- lines.push(` } finally {`);
2472
- lines.push(` Error.prepareStackTrace = originalPrepareStackTrace;`);
2473
- lines.push(` }`);
2474
- lines.push(` return __voidParseStackFrames(typeof error.stack === "string" ? error.stack : "");`);
2475
- lines.push(`}`);
2476
- lines.push("");
2477
- lines.push(`function __voidDescribeThrownValue(value) {`);
2478
- lines.push(` if (value instanceof Error) {`);
2479
- lines.push(` return {`);
2480
- lines.push(` name: value.name || "Error",`);
2481
- lines.push(` message: value.message || "",`);
2482
- lines.push(` stack: typeof value.stack === "string" ? value.stack : "",`);
2483
- lines.push(` frames: __voidGetStackFrames(value),`);
2484
- lines.push(` };`);
2485
- lines.push(` }`);
2486
- lines.push(` if (typeof value === "string") {`);
2487
- lines.push(` return { name: "Thrown value", message: value, stack: "", frames: [] };`);
2488
- lines.push(` }`);
2489
- lines.push(` let message = "";`);
2490
- lines.push(` try {`);
2491
- lines.push(` if (typeof value === "object" && value !== null) {`);
2492
- lines.push(` message = JSON.stringify(value, null, 2) ?? String(value);`);
2493
- lines.push(` } else {`);
2494
- lines.push(` message = String(value);`);
2495
- lines.push(` }`);
2496
- lines.push(` } catch {`);
2497
- lines.push(` message = String(value);`);
2498
- lines.push(` }`);
2499
- lines.push(` return { name: "Thrown value", message, stack: "", frames: [] };`);
2500
- lines.push(`}`);
2501
- lines.push("");
2502
- lines.push(`function __voidRenderStack(entry) {`);
2503
- lines.push(` if (Array.isArray(entry.frames) && entry.frames.length > 0) {`);
2504
- lines.push(` const items = entry.frames.map((frame) => {`);
2505
- lines.push(` const name = frame.functionName || "(anonymous)";`);
2506
- lines.push(` const location = frame.displayPath + ":" + frame.line + ":" + frame.column;`);
2507
- lines.push(` const body = \`<span class="__void-error-frame-function">\${__voidEscapeHtml(name)}</span><span class="__void-error-frame-location">\${__voidEscapeHtml(location)}</span>\`;`);
2508
- lines.push(` if (frame.href) {`);
2509
- lines.push(` return \`<a class="__void-error-frame" href="\${__voidEscapeHtml(frame.href)}">\${body}</a>\`;`);
2510
- lines.push(` }`);
2511
- lines.push(` return \`<div class="__void-error-frame is-static">\${body}</div>\`;`);
2512
- lines.push(` }).join("");`);
2513
- lines.push(` return \`<div class="__void-error-stack"><div class="__void-error-stack-label">Stack trace</div><div class="__void-error-frames">\${items}</div></div>\`;`);
2514
- lines.push(` }`);
2515
- lines.push(` if (!entry.stack) return "";`);
2516
- lines.push(` return \`<div class="__void-error-stack"><div class="__void-error-stack-label">Stack trace</div><pre>\${__voidEscapeHtml(entry.stack)}</pre></div>\`;`);
2517
- lines.push(`}`);
2518
- lines.push("");
2519
- lines.push(`function __voidCollectErrorChain(error) {`);
2520
- lines.push(` const chain = [];`);
2521
- lines.push(` const seen = new Set();`);
2522
- lines.push(` let current = error;`);
2523
- lines.push(` let depth = 0;`);
2524
- lines.push(` while (current != null && depth < 8 && !seen.has(current)) {`);
2525
- lines.push(` seen.add(current);`);
2526
- lines.push(` const entry = __voidDescribeThrownValue(current);`);
2527
- lines.push(` chain.push({`);
2528
- lines.push(` label: depth === 0 ? "Error" : "Cause " + depth,`);
2529
- lines.push(` ...entry,`);
2530
- lines.push(` });`);
2531
- lines.push(` current = current instanceof Error ? current.cause : undefined;`);
2532
- lines.push(` depth += 1;`);
2533
- lines.push(` }`);
2534
- lines.push(` if (current != null) {`);
2535
- lines.push(` chain.push({`);
2536
- lines.push(` label: "Cause " + depth,`);
2537
- lines.push(` name: "Truncated",`);
2538
- lines.push(` message: "Additional nested causes were omitted.",`);
2539
- lines.push(` stack: "",`);
2540
- lines.push(` frames: [],`);
2541
- lines.push(` });`);
2542
- lines.push(` }`);
2543
- lines.push(` if (chain.length === 0) {`);
2544
- lines.push(` chain.push({`);
2545
- lines.push(` label: "Error",`);
2546
- lines.push(` name: "Unknown error",`);
2547
- lines.push(` message: "No error details were available.",`);
2548
- lines.push(` stack: "",`);
2549
- lines.push(` frames: [],`);
2550
- lines.push(` });`);
2551
- lines.push(` }`);
2552
- lines.push(` return chain;`);
2553
- lines.push(`}`);
2554
- lines.push("");
2555
- lines.push(`function __voidRenderDevErrorOverlay(request, status, title, error) {`);
2556
- lines.push(` const chain = __voidCollectErrorChain(error);`);
2557
- lines.push(` const errorCountLabel = chain.length + (chain.length === 1 ? " Error" : " Errors");`);
2558
- lines.push(` const sections = chain.map((entry, index) => {`);
2559
- lines.push(` const heading = entry.name || (index === 0 ? title : "Cause");`);
2560
- lines.push(` const message = entry.message || title;`);
2561
- lines.push(` const stack = __voidRenderStack(entry);`);
2562
- lines.push(` if (index === 0) {`);
2563
- lines.push(` return \`<section class="__void-error-section is-root"><p class="__void-error-message">\${__voidEscapeHtml(message)}</p>\${stack}</section>\`;`);
2564
- lines.push(` }`);
2565
- lines.push(` return \`<section class="__void-error-section"><div class="__void-error-kicker">\${__voidEscapeHtml(entry.label)}</div><h2>\${__voidEscapeHtml(heading)}</h2><p>\${__voidEscapeHtml(message)}</p>\${stack}</section>\`;`);
2566
- lines.push(` }).join("");`);
2567
- lines.push(` return \`<style>`);
2568
- lines.push(` .__void-error-overlay {`);
2569
- lines.push(` position: fixed;`);
2570
- lines.push(` inset: 0;`);
2571
- lines.push(` z-index: 2147483647;`);
2572
- lines.push(` pointer-events: none;`);
2573
- lines.push(` font-family: \${__VOID_ERROR_PAGE_FONT_STACK};`);
2574
- lines.push(` color: #f5f5f5;`);
2575
- lines.push(` }`);
2576
- lines.push(` .__void-error-backdrop {`);
2577
- lines.push(` position: absolute;`);
2578
- lines.push(` inset: 0;`);
2579
- lines.push(` background: rgba(10, 10, 10, 0.52);`);
2580
- lines.push(` backdrop-filter: blur(4px);`);
2581
- lines.push(` transition: opacity 180ms ease;`);
2582
- lines.push(` }`);
2583
- lines.push(` .__void-error-panel {`);
2584
- lines.push(` position: absolute;`);
2585
- lines.push(` inset: auto auto 24px 24px;`);
2586
- lines.push(` inline-size: min(760px, calc(100vw - 48px));`);
2587
- lines.push(` max-block-size: min(80dvh, 920px);`);
2588
- lines.push(` overflow: auto;`);
2589
- lines.push(` pointer-events: auto;`);
2590
- lines.push(` border-radius: 32px;`);
2591
- lines.push(` corner-shape: squircle;`);
2592
- lines.push(` border: 1px solid rgba(255, 255, 255, 0.14);`);
2593
- lines.push(` background: linear-gradient(180deg, rgba(24, 24, 27, 0.98), rgba(9, 9, 11, 0.98));`);
2594
- lines.push(` box-shadow: 0 24px 80px rgba(0, 0, 0, 0.45);`);
2595
- lines.push(` padding: 12px 16px;`);
2596
- lines.push(` transition: transform 180ms ease, opacity 180ms ease;`);
2597
- lines.push(` transform-origin: bottom left;`);
2598
- lines.push(` }`);
2599
- lines.push(` .__void-error-close {`);
2600
- lines.push(` position: absolute;`);
2601
- lines.push(` inset: 12px 12px auto auto;`);
2602
- lines.push(` inline-size: 36px;`);
2603
- lines.push(` block-size: 36px;`);
2604
- lines.push(` border: 0;`);
2605
- lines.push(` border-radius: 999px;`);
2606
- lines.push(` background: rgba(255, 255, 255, 0.08);`);
2607
- lines.push(` color: #fafafa;`);
2608
- lines.push(` cursor: pointer;`);
2609
- lines.push(` display: grid;`);
2610
- lines.push(` place-items: center;`);
2611
- lines.push(` padding: 0;`);
2612
- lines.push(` }`);
2613
- lines.push(` .__void-error-close:hover {`);
2614
- lines.push(` background: rgba(255, 255, 255, 0.14);`);
2615
- lines.push(` }`);
2616
- lines.push(` .__void-error-close svg {`);
2617
- lines.push(` inline-size: 16px;`);
2618
- lines.push(` block-size: 16px;`);
2619
- lines.push(` display: block;`);
2620
- lines.push(` }`);
2621
- lines.push(` .__void-error-minimized {`);
2622
- lines.push(` position: absolute;`);
2623
- lines.push(` inset: auto auto 24px 24px;`);
2624
- lines.push(` pointer-events: none;`);
2625
- lines.push(` opacity: 0;`);
2626
- lines.push(` transform: scale(0.92);`);
2627
- lines.push(` transform-origin: bottom left;`);
2628
- lines.push(` border: 1px solid rgba(248, 113, 113, 0.35);`);
2629
- lines.push(` border-radius: 32px;`);
2630
- lines.push(` corner-shape: squircle;`);
2631
- lines.push(` background: rgba(24, 24, 27, 0.96);`);
2632
- lines.push(` color: #fca5a5;`);
2633
- lines.push(` padding: 12px 8px;`);
2634
- lines.push(` box-shadow: 0 18px 36px rgba(0, 0, 0, 0.28);`);
2635
- lines.push(` cursor: pointer;`);
2636
- lines.push(` font: 700 13px/1 \${__VOID_ERROR_PAGE_FONT_STACK};`);
2637
- lines.push(` letter-spacing: 0.04em;`);
2638
- lines.push(` text-transform: uppercase;`);
2639
- lines.push(` transition: transform 180ms ease, opacity 180ms ease;`);
2640
- lines.push(` }`);
2641
- lines.push(` .__void-error-header {`);
2642
- lines.push(` display: flex;`);
2643
- lines.push(` flex-direction: column;`);
2644
- lines.push(` gap: 6px;`);
2645
- lines.push(` margin-block-end: 0;`);
2646
- lines.push(` padding-right: 52px;`);
2647
- lines.push(` }`);
2648
- lines.push(` .__void-error-status {`);
2649
- lines.push(` margin: 0;`);
2650
- lines.push(` color: #fca5a5;`);
2651
- lines.push(` font-size: 12px;`);
2652
- lines.push(` font-weight: 700;`);
2653
- lines.push(` letter-spacing: 0.12em;`);
2654
- lines.push(` text-transform: uppercase;`);
2655
- lines.push(` }`);
2656
- lines.push(` .__void-error-section {`);
2657
- lines.push(` border-top: 1px solid rgba(255, 255, 255, 0.08);`);
2658
- lines.push(` padding-top: 16px;`);
2659
- lines.push(` margin-top: 16px;`);
2660
- lines.push(` }`);
2661
- lines.push(` .__void-error-section.is-root {`);
2662
- lines.push(` border-top: 0;`);
2663
- lines.push(` padding-top: 0;`);
2664
- lines.push(` margin-top: 0;`);
2665
- lines.push(` }`);
2666
- lines.push(` .__void-error-message {`);
2667
- lines.push(` margin: 0;`);
2668
- lines.push(` color: #fff;`);
2669
- lines.push(` font-size: 1.7rem;`);
2670
- lines.push(` line-height: 1.15;`);
2671
- lines.push(` letter-spacing: -0.03em;`);
2672
- lines.push(` white-space: pre-wrap;`);
2673
- lines.push(` word-break: break-word;`);
2674
- lines.push(` }`);
2675
- lines.push(` .__void-error-kicker {`);
2676
- lines.push(` margin-bottom: 6px;`);
2677
- lines.push(` color: #fda4af;`);
2678
- lines.push(` font-size: 12px;`);
2679
- lines.push(` font-weight: 700;`);
2680
- lines.push(` letter-spacing: 0.08em;`);
2681
- lines.push(` text-transform: uppercase;`);
2682
- lines.push(` }`);
2683
- lines.push(` .__void-error-section h2 {`);
2684
- lines.push(` margin: 0 0 8px;`);
2685
- lines.push(` font-size: 1.05rem;`);
2686
- lines.push(` color: #fff;`);
2687
- lines.push(` }`);
2688
- lines.push(` .__void-error-section p {`);
2689
- lines.push(` margin: 0;`);
2690
- lines.push(` color: #e4e4e7;`);
2691
- lines.push(` white-space: pre-wrap;`);
2692
- lines.push(` word-break: break-word;`);
2693
- lines.push(` }`);
2694
- lines.push(` .__void-error-stack {`);
2695
- lines.push(` margin-top: 18px;`);
2696
- lines.push(` border: 1px solid rgba(255, 255, 255, 0.08);`);
2697
- lines.push(` border-radius: 32px;`);
2698
- lines.push(` background: rgba(255, 255, 255, 0.03);`);
2699
- lines.push(` corner-shape: squircle;`);
2700
- lines.push(` overflow: hidden;`);
2701
- lines.push(` }`);
2702
- lines.push(` .__void-error-stack-label {`);
2703
- lines.push(` padding: 12px 14px 10px;`);
2704
- lines.push(` color: #f4f4f5;`);
2705
- lines.push(` font-size: 12px;`);
2706
- lines.push(` font-weight: 700;`);
2707
- lines.push(` letter-spacing: 0.08em;`);
2708
- lines.push(` text-transform: uppercase;`);
2709
- lines.push(` border-bottom: 1px solid rgba(255, 255, 255, 0.08);`);
2710
- lines.push(` }`);
2711
- lines.push(` .__void-error-frames {`);
2712
- lines.push(` display: flex;`);
2713
- lines.push(` flex-direction: column;`);
2714
- lines.push(` }`);
2715
- lines.push(` .__void-error-frame {`);
2716
- lines.push(` display: flex;`);
2717
- lines.push(` align-items: baseline;`);
2718
- lines.push(` justify-content: space-between;`);
2719
- lines.push(` gap: 16px;`);
2720
- lines.push(` padding: 12px 14px;`);
2721
- lines.push(` color: inherit;`);
2722
- lines.push(` text-decoration: none;`);
2723
- lines.push(` border-top: 1px solid rgba(255, 255, 255, 0.06);`);
2724
- lines.push(` }`);
2725
- lines.push(` .__void-error-frame:first-child {`);
2726
- lines.push(` border-top: 0;`);
2727
- lines.push(` }`);
2728
- lines.push(` .__void-error-frame:hover {`);
2729
- lines.push(` background: rgba(255, 255, 255, 0.05);`);
2730
- lines.push(` }`);
2731
- lines.push(` .__void-error-frame.is-static {`);
2732
- lines.push(` cursor: default;`);
2733
- lines.push(` }`);
2734
- lines.push(` .__void-error-frame-function {`);
2735
- lines.push(` flex: 1 1 auto;`);
2736
- lines.push(` min-width: 0;`);
2737
- lines.push(` color: #fafafa;`);
2738
- lines.push(` font: 600 12px/1.45 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;`);
2739
- lines.push(` white-space: nowrap;`);
2740
- lines.push(` overflow: hidden;`);
2741
- lines.push(` text-overflow: ellipsis;`);
2742
- lines.push(` }`);
2743
- lines.push(` .__void-error-frame-location {`);
2744
- lines.push(` flex: 0 1 52%;`);
2745
- lines.push(` min-width: 0;`);
2746
- lines.push(` color: #fda4af;`);
2747
- lines.push(` font: 500 12px/1.45 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;`);
2748
- lines.push(` text-align: right;`);
2749
- lines.push(` white-space: nowrap;`);
2750
- lines.push(` overflow: hidden;`);
2751
- lines.push(` text-overflow: ellipsis;`);
2752
- lines.push(` }`);
2753
- lines.push(` .__void-error-section pre {`);
2754
- lines.push(` margin: 0;`);
2755
- lines.push(` padding: 12px 14px;`);
2756
- lines.push(` overflow: auto;`);
2757
- lines.push(` color: #e4e4e7;`);
2758
- lines.push(` font: 500 12px/1.6 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;`);
2759
- lines.push(` white-space: pre-wrap;`);
2760
- lines.push(` word-break: break-word;`);
2761
- lines.push(` }`);
2762
- lines.push(` .__void-error-overlay.is-minimized .__void-error-backdrop {`);
2763
- lines.push(` opacity: 0;`);
2764
- lines.push(` pointer-events: none;`);
2765
- lines.push(` }`);
2766
- lines.push(` .__void-error-overlay.is-minimized .__void-error-panel {`);
2767
- lines.push(` opacity: 0;`);
2768
- lines.push(` pointer-events: none;`);
2769
- lines.push(` transform: scale(0.92);`);
2770
- lines.push(` }`);
2771
- lines.push(` .__void-error-overlay.is-minimized .__void-error-minimized {`);
2772
- lines.push(` opacity: 1;`);
2773
- lines.push(` pointer-events: auto;`);
2774
- lines.push(` transform: scale(1);`);
2775
- lines.push(` }`);
2776
- lines.push(` @media (max-width: 720px) {`);
2777
- lines.push(` .__void-error-panel {`);
2778
- lines.push(` inset: auto 12px 12px 12px;`);
2779
- lines.push(` inline-size: auto;`);
2780
- lines.push(` max-block-size: min(70dvh, 920px);`);
2781
- lines.push(` padding: 16px;`);
2782
- lines.push(` }`);
2783
- lines.push(` .__void-error-minimized {`);
2784
- lines.push(` inset: auto auto 12px 12px;`);
2785
- lines.push(` }`);
2786
- lines.push(` .__void-error-frame {`);
2787
- lines.push(` flex-direction: column;`);
2788
- lines.push(` align-items: flex-start;`);
2789
- lines.push(` }`);
2790
- lines.push(` .__void-error-frame-location {`);
2791
- lines.push(` text-align: left;`);
2792
- lines.push(` }`);
2793
- lines.push(` }`);
2794
- lines.push(` </style>`);
2795
- lines.push(`<aside class="__void-error-overlay" data-void-error-overlay role="dialog" aria-label="Void dev error overlay"><div class="__void-error-backdrop" data-void-error-backdrop></div><section class="__void-error-panel"><button type="button" class="__void-error-close" data-void-error-close aria-label="Minimize error overlay"><svg viewBox="0 0 16 16" aria-hidden="true" focusable="false"><path d="M3.757 3.757 12.243 12.243M12.243 3.757 3.757 12.243" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round"/></svg></button><header class="__void-error-header"><p class="__void-error-status">\${__voidEscapeHtml(String(status) + ": " + title)}</p></header>\${sections}</section><button type="button" class="__void-error-minimized" data-void-error-toggle aria-label="Show dev error overlay" aria-expanded="true">\${__voidEscapeHtml(errorCountLabel)}</button><script>(function(){const script=document.currentScript;if(!(script instanceof HTMLScriptElement))return;const root=script.closest("[data-void-error-overlay]");if(!(root instanceof HTMLElement))return;const backdrop=root.querySelector("[data-void-error-backdrop]");const closeButton=root.querySelector("[data-void-error-close]");const toggle=root.querySelector("[data-void-error-toggle]");const setMinimized=(minimized)=>{root.classList.toggle("is-minimized", minimized);if(toggle instanceof HTMLElement)toggle.setAttribute("aria-expanded", minimized ? "false" : "true");};if(backdrop instanceof HTMLElement)backdrop.addEventListener("click",()=>setMinimized(true));if(closeButton instanceof HTMLElement)closeButton.addEventListener("click",()=>setMinimized(true));if(toggle instanceof HTMLElement)toggle.addEventListener("click",()=>setMinimized(false));})();<\/script></aside>\`;`);
2796
- lines.push(`}`);
2797
- lines.push("");
2798
- lines.push(`function __voidInjectDevErrorOverlay(html, overlay) {`);
2799
- lines.push(` return /<\\/body\\s*>/i.test(html) ? html.replace(/<\\/body\\s*>/i, overlay + "</body>") : html + overlay;`);
2800
- lines.push(`}`);
2801
- lines.push("");
2802
- lines.push(`function __voidGetErrorAssetCss(error) {`);
2803
- lines.push(` const tags = error && (typeof error === "object" || typeof error === "function") ? error.__voidPageAssetTags : null;`);
2804
- lines.push(` return tags && typeof tags.css === "string" ? tags.css : "";`);
2805
- lines.push(`}`);
2806
- lines.push("");
2807
- lines.push(`function __voidInjectErrorAssetCss(html, css) {`);
2808
- lines.push(` if (!css) return html;`);
2809
- lines.push(` return /<\\/head\\s*>/i.test(html) ? html.replace(/<\\/head\\s*>/i, css + "</head>") : css + html;`);
2810
- lines.push(`}`);
2811
- lines.push("");
2812
- lines.push(`function __voidRenderErrorPage(request, status, title, error) {`);
2813
- lines.push(` const heading = status + ": " + title;`);
2814
- lines.push(` const prefix = status + ": ";`);
2815
- lines.push(` const overlay = __VOID_DEV && status === 500 && error ? __voidRenderDevErrorOverlay(request, status, title, error) : "";`);
2816
- lines.push(` return \`<!doctype html>`);
2817
- lines.push(`<html lang="en">`);
2818
- lines.push(` <head>`);
2819
- lines.push(` <meta charset="utf-8">`);
2820
- lines.push(` <meta name="viewport" content="width=device-width, initial-scale=1">`);
2821
- lines.push(` <title>\${__voidEscapeHtml(heading)}</title>`);
2822
- lines.push(` \${__voidGetErrorAssetCss(error)}`);
2823
- lines.push(` <style>`);
2824
- lines.push(` :root {`);
2825
- lines.push(` color-scheme: light dark;`);
2826
- lines.push(` font-family: \${__VOID_ERROR_PAGE_FONT_STACK};`);
2827
- lines.push(` background: #f5f5f5;`);
2828
- lines.push(` color: #171717;`);
2829
- lines.push(` }`);
2830
- lines.push(` * { box-sizing: border-box; }`);
2831
- lines.push(` body {`);
2832
- lines.push(` margin: 0;`);
2833
- lines.push(` min-block-size: 100dvh;`);
2834
- lines.push(` display: grid;`);
2835
- lines.push(` place-items: center;`);
2836
- lines.push(` padding: 24px;`);
2837
- lines.push(` background: radial-gradient(circle at top, rgba(255, 255, 255, 0.96), rgba(245, 245, 245, 0.96) 52%), linear-gradient(180deg, #fafafa 0%, #f1f1f1 100%);`);
2838
- lines.push(` font: 500 16px/1.5 \${__VOID_ERROR_PAGE_FONT_STACK};`);
2839
- lines.push(` }`);
2840
- lines.push(` main {`);
2841
- lines.push(` inline-size: min(100%, 560px);`);
2842
- lines.push(` padding: 32px 36px;`);
2843
- lines.push(` border: 1px solid #d4d4d8;`);
2844
- lines.push(` border-radius: 32px;`);
2845
- lines.push(` corner-shape: squircle;`);
2846
- lines.push(` background: rgba(255, 255, 255, 0.88);`);
2847
- lines.push(` text-align: center;`);
2848
- lines.push(` backdrop-filter: blur(12px);`);
2849
- lines.push(` }`);
2850
- lines.push(` h1 {`);
2851
- lines.push(` margin: 0;`);
2852
- lines.push(` font: 400 clamp(1.5rem, 1.2rem + 1vw, 2rem) / 1.1 \${__VOID_ERROR_PAGE_FONT_STACK};`);
2853
- lines.push(` letter-spacing: -0.03em;`);
2854
- lines.push(` }`);
2855
- lines.push(` strong {`);
2856
- lines.push(` font-weight: 600;`);
2857
- lines.push(` }`);
2858
- lines.push(` @media (prefers-color-scheme: dark) {`);
2859
- lines.push(` :root {`);
2860
- lines.push(` background: #0a0a0a;`);
2861
- lines.push(` color: #f5f5f5;`);
2862
- lines.push(` }`);
2863
- lines.push(` body {`);
2864
- lines.push(` background: radial-gradient(circle at top, rgba(38, 38, 38, 0.96), rgba(10, 10, 10, 0.96) 52%), linear-gradient(180deg, #171717 0%, #0a0a0a 100%);`);
2865
- lines.push(` }`);
2866
- lines.push(` main {`);
2867
- lines.push(` border-color: #27272a;`);
2868
- lines.push(` background: rgba(23, 23, 23, 0.88);`);
2869
- lines.push(` }`);
2870
- lines.push(` }`);
2871
- lines.push(` </style>`);
2872
- lines.push(` </head>`);
2873
- lines.push(` <body>`);
2874
- lines.push(` <main>`);
2875
- lines.push(` <h1><strong>\${__voidEscapeHtml(prefix)}</strong>\${__voidEscapeHtml(title)}</h1>`);
2876
- lines.push(` </main>`);
2877
- lines.push(` \${overlay}`);
2878
- lines.push(` </body>`);
2879
- lines.push(`</html>\`;`);
2880
- lines.push(`}`);
2881
- lines.push("");
2882
- lines.push(`function __voidCreateErrorResponse(request, status, title, error) {`);
2883
- lines.push(` if (!__voidShouldServeHtmlErrorPage(request)) {`);
2884
- lines.push(` return new Response(title, { status });`);
2885
- lines.push(` }`);
2886
- lines.push(` return new Response(request.method === "HEAD" ? null : __voidRenderErrorPage(request, status, title, error), {`);
2887
- lines.push(` status,`);
2888
- lines.push(` headers: { "content-type": "text/html; charset=utf-8" },`);
2889
- lines.push(` });`);
2890
- lines.push(`}`);
2891
- lines.push("");
2409
+ lines.push(`const __errorRenderer = __createErrorRenderer(${JSON.stringify({
2410
+ dev: options.dev === true,
2411
+ projectRoot: options.projectRoot,
2412
+ homeDir: options.homeDir
2413
+ })});`);
2414
+ lines.push("const serveCustomErrorPage = __errorRenderer.serveCustomPage;");
2415
+ lines.push("app.onError(__errorRenderer.onError);");
2892
2416
  }
2893
2417
  /**
2894
2418
  * Generate the code for the virtual route table module (virtual:void-routes).
@@ -2903,8 +2427,7 @@ function compileRouteTable(scan, routesDir, middlewareDir, jobsDir, queuesDir, s
2903
2427
  const managedDispatch = options.nodeTarget !== true && options.dev !== true && options.managedDispatch === true;
2904
2428
  lines.push(`import { AsyncLocalStorage } from "node:async_hooks";`);
2905
2429
  lines.push(`import { Hono } from ${JSON.stringify(options.honoPath)};`);
2906
- lines.push(`import { convertReturnValue } from ${JSON.stringify(options.responsePath)};`);
2907
- lines.push(`import { VoidAssetRewriteError as __VoidAssetRewriteError } from ${JSON.stringify(options.handlerPath)};`);
2430
+ lines.push(`import { createRoutingRuntime as __createRoutingRuntime, createHttpRouteHandler as __createHttpRouteHandler, createErrorRenderer as __createErrorRenderer, createPageGetHandler as __createPageGetHandler, createPageMutationHandler as __createPageMutationHandler, createPagesFallback as __createPagesFallback, createModuleLoader as __createModuleLoader, createClientAssetTags as __createClientAssetTags, createManifestLoader as __createManifestLoader, createSsrFallback as __createSsrFallback, createAssetNotFound as __createAssetNotFound } from ${JSON.stringify(ROUTING_RUNTIME_PATH)};`);
2908
2431
  if (options.nodeTarget) lines.push(`const withRuntimeEnv = (_env, fn) => fn();`);
2909
2432
  else lines.push(`import { withRuntimeEnv } from ${JSON.stringify(options.runtimeEnvPath)};`);
2910
2433
  if (auth) {
@@ -2937,9 +2460,6 @@ function compileRouteTable(scan, routesDir, middlewareDir, jobsDir, queuesDir, s
2937
2460
  lines.push("");
2938
2461
  }
2939
2462
  lines.push(`const app = new Hono();`);
2940
- lines.push(`export const requestContext = new AsyncLocalStorage();`);
2941
- lines.push("const __voidOriginalUrls = new WeakMap();");
2942
- lines.push("const __voidFallbackHandled = new WeakSet();");
2943
2463
  const ASSET_EXTENSIONS = [
2944
2464
  "png",
2945
2465
  "jpg",
@@ -2978,81 +2498,15 @@ function compileRouteTable(scan, routesDir, middlewareDir, jobsDir, queuesDir, s
2978
2498
  if (m) usedExts.add(m[1].toLowerCase());
2979
2499
  }
2980
2500
  const blockedExts = ASSET_EXTENSIONS.filter((e) => !usedExts.has(e));
2981
- if (blockedExts.length > 0) lines.push(`const __voidAssetRewriteExtRE = /\\.(${blockedExts.join("|")})$/i;`);
2982
- else lines.push("const __voidAssetRewriteExtRE = /(?!)/;");
2983
- lines.push(`const __VOID_DEV_ROUTING = ${JSON.stringify(options.dev === true)};`);
2984
- lines.push("function __voidAnnotateRouting(response, trace) {");
2985
- lines.push(" if (!__VOID_DEV_ROUTING || !response) return response;");
2986
- lines.push(" const headers = new Headers(response.headers);");
2987
- lines.push(" headers.set(\"X-Void-Routing\", trace);");
2988
- lines.push(" return new Response(response.body, { status: response.status, statusText: response.statusText, headers });");
2989
- lines.push("}");
2990
- lines.push("");
2991
- lines.push("function __voidShouldMarkNoMatch(request) {");
2992
- lines.push(" const url = new URL(request.url);");
2993
- lines.push(" if (request.method !== \"GET\" && request.method !== \"HEAD\") return false;");
2994
- lines.push(" if (url.pathname === \"/api\" || url.pathname.startsWith(\"/api/\")) return false;");
2995
- lines.push(" if (/\\/[^/]+\\.[^/]+$/.test(url.pathname)) return false;");
2996
- lines.push(" return true;");
2997
- lines.push("}");
2998
- lines.push("function __voidMarkNoMatch(request, response) {");
2999
- lines.push(" if (!response || response.status !== 404 || !__voidShouldMarkNoMatch(request)) return response;");
3000
- lines.push(" const headers = new Headers(response.headers);");
3001
- lines.push(" headers.set(\"X-Void-No-Match\", \"1\");");
3002
- lines.push(" return new Response(response.body, { status: response.status, statusText: response.statusText, headers });");
3003
- lines.push("}");
3004
- lines.push("");
3005
- ensureMergeQueryHelperEmitted(lines);
3006
- lines.push("app.use(async (c, next) => {");
3007
- if (managedDispatch) {
3008
- lines.push(" if (!__voidOriginalUrls.has(c.req.raw)) {");
3009
- lines.push(" const __h = c.req.raw.headers.get(\"X-Void-Original-URL\");");
3010
- lines.push(" if (__h != null) {");
3011
- lines.push(" try { __voidOriginalUrls.set(c.req.raw, new URL(__h)); } catch {}");
3012
- lines.push(" }");
3013
- lines.push(" }");
3014
- }
3015
- lines.push(" c.rewrite = (path) => {");
3016
- lines.push(" if (!path.startsWith(\"/\") || path.startsWith(\"//\")) {");
3017
- lines.push(" throw new Error(\"c.rewrite() only accepts internal, path-absolute destinations — they must start with a single \\\"/\\\" (a leading \\\"//\\\" parses as protocol-relative and would proxy cross-origin); use fetch() for external URLs\");");
3018
- lines.push(" }");
3019
- lines.push(" const __qIdx = path.indexOf(\"?\");");
3020
- lines.push(" const __hIdx = path.indexOf(\"#\");");
3021
- lines.push(" const __firstDelim = __qIdx === -1 ? __hIdx : __hIdx === -1 ? __qIdx : Math.min(__qIdx, __hIdx);");
3022
- lines.push(" const __assetCheckPath = __firstDelim === -1 ? path : path.slice(0, __firstDelim);");
3023
- lines.push(" if (__voidAssetRewriteExtRE.test(__assetCheckPath)) {");
3024
- lines.push(" throw new __VoidAssetRewriteError(path);");
3025
- lines.push(" }");
3026
- lines.push(" const __pathOnly = __firstDelim === -1 ? path : path.slice(0, __firstDelim);");
3027
- lines.push(" const __searchOnly = __qIdx === -1 ? \"\" : path.slice(__qIdx, __hIdx === -1 ? path.length : __hIdx);");
3028
- lines.push(" const rewriteUrl = new URL(c.req.url);");
3029
- lines.push(" rewriteUrl.pathname = __pathOnly;");
3030
- lines.push(" if (__searchOnly) rewriteUrl.search = __searchOnly;");
3031
- lines.push(" const rewriteReq = new Request(rewriteUrl.toString(), c.req.raw);");
3032
- lines.push(" const __prior = __voidOriginalUrls.get(c.req.raw);");
3033
- lines.push(" __voidOriginalUrls.set(rewriteReq, __prior ?? new URL(c.req.url));");
3034
- if (options.nodeTarget) lines.push(" const __rewritePromise = app.fetch(rewriteReq, c.env);");
3035
- else lines.push(" const __rewritePromise = app.fetch(rewriteReq, c.env, c.executionCtx);");
3036
- lines.push(" if (!__VOID_DEV_ROUTING) return __rewritePromise;");
3037
- lines.push(" return __rewritePromise.then((res) => __voidAnnotateRouting(res, \"c.rewrite -> \" + path + \" (middleware)\"));");
3038
- lines.push(" };");
3039
- lines.push(" const __origRedirect = c.redirect.bind(c);");
3040
- lines.push(" c.redirect = (location, status) => {");
3041
- lines.push(" if (typeof location === \"string\" && location.startsWith(\"/\") && !location.startsWith(\"//\")) {");
3042
- lines.push(" const search = new URL(c.req.raw.url).search;");
3043
- lines.push(" return __origRedirect(__mergeQueryIntoLocation(location, search), status);");
3044
- lines.push(" }");
3045
- lines.push(" return __origRedirect(location, status);");
3046
- lines.push(" };");
3047
- lines.push(" c.originalUrl = () => __voidOriginalUrls.get(c.req.raw) ?? null;");
3048
- lines.push(" c.isRewritten = () => __voidOriginalUrls.has(c.req.raw);");
3049
- lines.push(" await next();");
3050
- lines.push("});");
3051
- lines.push("");
3052
- lines.push("app.use(async (c, next) => {");
3053
- if (options.nodeTarget) lines.push(" await requestContext.run({ request: c.req.raw }, next);");
3054
- else lines.push(" await requestContext.run({ request: c.req.raw, executionCtx: c.executionCtx }, next);");
3055
- lines.push("});");
2501
+ lines.push(`const __routingRuntime = __createRoutingRuntime(app, ${JSON.stringify({
2502
+ dev: options.dev === true,
2503
+ nodeTarget: options.nodeTarget === true,
2504
+ managedDispatch,
2505
+ blockedAssetExtensions: blockedExts
2506
+ })});`);
2507
+ lines.push("export const requestContext = __routingRuntime.requestContext;");
2508
+ lines.push("app.use(__routingRuntime.contextMiddleware);");
2509
+ lines.push("app.use(__routingRuntime.requestMiddleware);");
3056
2510
  lines.push("");
3057
2511
  const emitEdgeRules = !managedDispatch;
3058
2512
  if (emitEdgeRules && options.redirectRules?.length) compileRoutingRulesMiddleware(lines, options.redirectRules, options.dev === true, options.nodeTarget === true);
@@ -3086,30 +2540,15 @@ function compileRouteTable(scan, routesDir, middlewareDir, jobsDir, queuesDir, s
3086
2540
  const seenFiles = /* @__PURE__ */ new Set();
3087
2541
  for (const route of scan.routes) {
3088
2542
  const filePath = `${routesDir}/${route.filePath}`;
3089
- const varName = `_mod_${route.filePath.replace(/[^a-zA-Z0-9]/g, "_")}`;
3090
2543
  const loaderName = `_load_${route.filePath.replace(/[^a-zA-Z0-9]/g, "_")}`;
3091
2544
  if (!seenFiles.has(route.filePath)) {
3092
2545
  seenFiles.add(route.filePath);
3093
- if (options.dev !== true) lines.push(`let ${varName};`);
3094
- lines.push(`async function ${loaderName}() {`);
3095
- if (options.dev === true) lines.push(` return import(${JSON.stringify(filePath)});`);
3096
- else {
3097
- lines.push(` if (!${varName}) ${varName} = await import(${JSON.stringify(filePath)});`);
3098
- lines.push(` return ${varName};`);
3099
- }
3100
- lines.push(`}`);
2546
+ lines.push(`const ${loaderName} = __createModuleLoader(() => import(${JSON.stringify(filePath)}), ${JSON.stringify(options.dev !== true)});`);
3101
2547
  }
3102
- if (route.methods.length === 0) {
3103
- lines.push(`app.all(${JSON.stringify(route.pattern)}, async (c) => {`);
3104
- lines.push(` const mod = await ${loaderName}();`);
3105
- lines.push(` return convertReturnValue(await mod.default(c));`);
3106
- lines.push(`});`);
3107
- } else for (const method of route.methods) {
2548
+ if (route.methods.length === 0) lines.push(`app.all(${JSON.stringify(route.pattern)}, __createHttpRouteHandler(${loaderName}, "default"));`);
2549
+ else for (const method of route.methods) {
3108
2550
  const honoMethod = method.toLowerCase();
3109
- lines.push(`app.${honoMethod}(${JSON.stringify(route.pattern)}, async (c) => {`);
3110
- lines.push(` const mod = await ${loaderName}();`);
3111
- lines.push(` return convertReturnValue(await mod.${method}(c));`);
3112
- lines.push(`});`);
2551
+ lines.push(`app.${honoMethod}(${JSON.stringify(route.pattern)}, __createHttpRouteHandler(${loaderName}, ${JSON.stringify(method)}));`);
3113
2552
  }
3114
2553
  }
3115
2554
  lines.push("");
@@ -3120,7 +2559,8 @@ function compileRouteTable(scan, routesDir, middlewareDir, jobsDir, queuesDir, s
3120
2559
  pattern: route.pattern,
3121
2560
  params: route.params,
3122
2561
  className: route.className,
3123
- bindingName: route.bindingName
2562
+ bindingName: route.bindingName,
2563
+ ...route.name !== void 0 && { name: route.name }
3124
2564
  })}, ${auth ? "__voidAuthOptions" : "undefined"}, ${auth ? "__resolveVoidAuthState" : "undefined"});`);
3125
2565
  }
3126
2566
  lines.push("");
@@ -3128,10 +2568,12 @@ function compileRouteTable(scan, routesDir, middlewareDir, jobsDir, queuesDir, s
3128
2568
  pattern: route.pattern,
3129
2569
  params: route.params,
3130
2570
  className: route.className,
3131
- bindingName: route.bindingName
2571
+ bindingName: route.bindingName,
2572
+ ...route.name !== void 0 && { name: route.name }
3132
2573
  })))};`);
3133
2574
  lines.push("");
3134
2575
  }
2576
+ for (let i = 0; i < webSockets.length; i++) lines.push(`__voidWebSocketRoutes[${i}].key = websocket${i}.key;`);
3135
2577
  for (const className of options.webSocketTombstones ?? []) lines.push(`export const ${className} = __createWebSocketTombstoneDurableObject(${JSON.stringify(className)});`);
3136
2578
  if (options.webSocketTombstones?.length) lines.push("");
3137
2579
  if (options.hasLive) {
@@ -3139,150 +2581,20 @@ function compileRouteTable(scan, routesDir, middlewareDir, jobsDir, queuesDir, s
3139
2581
  lines.push("");
3140
2582
  }
3141
2583
  if (pages && scan.pages.pages.length > 0) compilePageRoutes(lines, scan, pages, options);
2584
+ for (let i = 0; i < webSockets.length; i++) lines.push(`app.all(${JSON.stringify(webSockets[i].pattern)}, (c) => __forwardWebSocketRequest(c.req.raw, c.env, __voidWebSocketRoutes[${i}]));`);
2585
+ if (webSockets.length > 0) lines.push("");
2586
+ if (pages && scan.pages.pages.length > 0) lines.push(`app.notFound(__createPagesFallback({ routing: __routingRuntime, errors: __errorRenderer, assetsDir: ${JSON.stringify(options.assetsDir)}, fallbackRules: ${JSON.stringify(emitEdgeRules && options.fallbackRules?.length ? options.dev ? options.fallbackRules : stripOriginForProd(options.fallbackRules) : void 0)} }));`);
3142
2587
  compilePrerenderCollector(lines, scan, ssr, options);
3143
2588
  if (ssr) {
3144
- const clientEntryUrl = `/${ssr.clientEntryRelativePath}`;
3145
- lines.push(`const SSR_CLIENT_ENTRY_ID = ${JSON.stringify(ssr.clientEntryRelativePath)};`);
3146
- lines.push(`const SSR_CLIENT_ENTRY_URL = ${JSON.stringify(clientEntryUrl)};`);
3147
- lines.push(`let cachedSsrManifest = null;`);
3148
- lines.push("");
3149
- lines.push(`function escapeHtml(value) {`);
3150
- lines.push(` return String(value).replace(/"/g, "&quot;");`);
3151
- lines.push(`}`);
3152
- lines.push("");
3153
- lines.push(`function getDevClientTags() {`);
3154
- lines.push(` const preloadTags = [\`<script type="module" src="/@vite/client"><\/script>\`];`);
3155
- lines.push(` preloadTags.push(\`${BINDING_HINT_SCRIPT}\`);`);
3156
- if (options.reactRefresh) lines.push(` preloadTags.push(\`<script type="module">
3157
- import RefreshRuntime from "/@react-refresh";
3158
- RefreshRuntime.injectIntoGlobalHook(window);
3159
- window.$RefreshReg$ = () => {};
3160
- window.$RefreshSig$ = () => (type) => type;
3161
- window.__vite_plugin_react_preamble_installed__ = true;
3162
- <\/script>\`);`);
3163
- lines.push(` const bodyTag = \`<script type="module" src="\${escapeHtml(SSR_CLIENT_ENTRY_URL)}"><\/script>\`;`);
3164
- lines.push(` return { css: "", preloads: preloadTags.join("\\n"), body: bodyTag };`);
3165
- lines.push(`}`);
3166
- lines.push("");
3167
- lines.push(`function collectManifestFiles(manifest, entryId) {`);
3168
- lines.push(` const seen = new Set();`);
3169
- lines.push(` const toVisit = [entryId];`);
3170
- lines.push(` while (toVisit.length > 0) {`);
3171
- lines.push(` const currentId = toVisit.pop();`);
3172
- lines.push(` if (seen.has(currentId)) continue;`);
3173
- lines.push(` seen.add(currentId);`);
3174
- lines.push(` const chunk = manifest[currentId];`);
3175
- lines.push(` if (!chunk || !Array.isArray(chunk.imports)) continue;`);
3176
- lines.push(` for (const importedId of chunk.imports) toVisit.push(importedId);`);
3177
- lines.push(` }`);
3178
- lines.push(` return Array.from(seen);`);
3179
- lines.push(`}`);
3180
- lines.push("");
3181
- lines.push(`async function loadSsrManifest(request, env) {`);
3182
- lines.push(` if (cachedSsrManifest) return cachedSsrManifest;`);
3183
- lines.push(` if (typeof globalThis.__VITE_MANIFEST__ === "object" && globalThis.__VITE_MANIFEST__) {`);
3184
- lines.push(` cachedSsrManifest = globalThis.__VITE_MANIFEST__;`);
3185
- lines.push(` return cachedSsrManifest;`);
3186
- lines.push(` }`);
3187
- lines.push(` const assets = env?.ASSETS;`);
3188
- lines.push(` if (!assets || typeof assets.fetch !== "function") return null;`);
3189
- lines.push(` const manifestUrl = new URL("/.vite/manifest.json", request.url);`);
3190
- lines.push(` const response = await assets.fetch(new Request(manifestUrl.toString()));`);
3191
- lines.push(` if (!response.ok) return null;`);
3192
- lines.push(` cachedSsrManifest = await response.json();`);
3193
- lines.push(` return cachedSsrManifest;`);
3194
- lines.push(`}`);
3195
- lines.push("");
3196
- lines.push(`async function getClientAssetTags(request, env) {`);
3197
- lines.push(` const manifest = await loadSsrManifest(request, env);`);
3198
- lines.push(` if (!manifest || typeof manifest !== "object") {`);
3199
- lines.push(` if (!import.meta.env.DEV) return { css: "", preloads: "", body: "" };`);
3200
- lines.push(` return getDevClientTags();`);
3201
- lines.push(` }`);
3202
- lines.push(` const entry = manifest[SSR_CLIENT_ENTRY_ID];`);
3203
- lines.push(` if (!entry || typeof entry !== "object" || typeof entry.file !== "string") {`);
3204
- lines.push(` return { css: "", preloads: "", body: "" };`);
3205
- lines.push(` }`);
3206
- lines.push(` const ids = collectManifestFiles(manifest, SSR_CLIENT_ENTRY_ID);`);
3207
- lines.push(` const cssFiles = new Set();`);
3208
- lines.push(` const preloadFiles = new Set();`);
3209
- lines.push(` for (const id of ids) {`);
3210
- lines.push(` const chunk = manifest[id];`);
3211
- lines.push(` if (!chunk || typeof chunk !== "object") continue;`);
3212
- lines.push(` if (Array.isArray(chunk.css)) {`);
3213
- lines.push(` for (const cssFile of chunk.css) cssFiles.add(cssFile);`);
3214
- lines.push(` }`);
3215
- lines.push(` if (id !== SSR_CLIENT_ENTRY_ID && typeof chunk.file === "string") {`);
3216
- lines.push(` preloadFiles.add(chunk.file);`);
3217
- lines.push(` }`);
3218
- lines.push(` }`);
3219
- lines.push(` const cssTags = [];`);
3220
- lines.push(` for (const cssFile of cssFiles) {`);
3221
- lines.push(` cssTags.push(\`<link rel="stylesheet" href="/\${escapeHtml(cssFile)}">\`);`);
3222
- lines.push(` }`);
3223
- lines.push(` const preloadTags = [];`);
3224
- lines.push(` for (const preloadFile of preloadFiles) {`);
3225
- lines.push(` preloadTags.push(\`<link rel="modulepreload" href="/\${escapeHtml(preloadFile)}">\`);`);
3226
- lines.push(` }`);
3227
- lines.push(` const bodyTag = \`<script type="module" src="/\${escapeHtml(entry.file)}"><\/script>\`;`);
3228
- lines.push(` return { css: cssTags.join("\\n"), preloads: preloadTags.join("\\n"), body: bodyTag };`);
3229
- lines.push(`}`);
3230
- lines.push("");
3231
- lines.push(`function shouldHandleSsrRequest(c) {`);
3232
- lines.push(` const path = c.req.path;`);
3233
- lines.push(` if (path === "/api" || path.startsWith("/api/")) return false;`);
3234
- lines.push(` if (/\\/[^/]+\\.[^/]+$/.test(path)) return false;`);
3235
- lines.push(` const destination = c.req.header("sec-fetch-dest");`);
3236
- lines.push(` if (destination && destination !== "document" && destination !== "empty") return false;`);
3237
- lines.push(` return true;`);
3238
- lines.push(`}`);
3239
- lines.push("");
3240
- lines.push(`async function fetchFromAssets(c) {`);
3241
- lines.push(` const assets = c.env?.ASSETS;`);
3242
- lines.push(` if (!assets || typeof assets.fetch !== "function") {`);
3243
- lines.push(` return __voidMarkNoMatch(c.req.raw, new Response("Not Found", { status: 404 }));`);
3244
- lines.push(` }`);
3245
- lines.push(` const response = await assets.fetch(c.req.raw);`);
3246
- lines.push(` return response.status === 404 ? __voidMarkNoMatch(c.req.raw, new Response("Not Found", { status: 404 })) : response;`);
3247
- lines.push(`}`);
3248
- lines.push("");
3249
- lines.push(`async function renderSsrResponse(c, mod) {`);
3250
- lines.push(` const render = typeof mod.render === "function" ? mod.render : mod.default;`);
3251
- lines.push(` if (typeof render !== "function") {`);
3252
- lines.push(` throw new Error("ssr: Invalid entry. Export render(c, assetTags).");`);
3253
- lines.push(` }`);
3254
- lines.push(` const assetTags = await getClientAssetTags(c.req.raw, c.env);`);
3255
- lines.push(` return render(c, assetTags);`);
3256
- lines.push(`}`);
3257
- lines.push("");
3258
- lines.push(`app.notFound(async (c) => {`);
3259
- if (options.nodeTarget && options.fallbackRules?.length) emitFallbackRulesCheck(lines, options.fallbackRules, options.dev === true, " ", options.nodeTarget === true);
3260
- lines.push(` if (!shouldHandleSsrRequest(c)) {`);
3261
- if (!options.nodeTarget && emitEdgeRules && options.fallbackRules?.length) {
3262
- lines.push(` const __assetRes = await fetchFromAssets(c);`);
3263
- lines.push(` if (__assetRes.status !== 404) return __assetRes;`);
3264
- emitFallbackRulesCheck(lines, options.fallbackRules, options.dev === true, " ", false);
3265
- lines.push(` return __assetRes;`);
3266
- } else lines.push(` return fetchFromAssets(c);`);
3267
- lines.push(` }`);
3268
- lines.push(` const mod = await import(${JSON.stringify(ssr.serverEntryPath)});`);
3269
- lines.push(` return renderSsrResponse(c, mod);`);
3270
- lines.push(`});`);
3271
- lines.push("");
3272
- } else if (emitEdgeRules && (options.fallbackRules?.length || !options.nodeTarget && options.headerRules?.length) && !(pages && scan.pages.pages.length > 0)) {
3273
- lines.push(`app.notFound(async (c) => {`);
3274
- if (!options.nodeTarget) {
3275
- lines.push(` const assets = c.env?.ASSETS;`);
3276
- lines.push(` if (assets && typeof assets.fetch === "function") {`);
3277
- lines.push(` const __assetRes = await assets.fetch(c.req.raw);`);
3278
- lines.push(` if (__assetRes.status !== 404) return __assetRes;`);
3279
- lines.push(` }`);
3280
- }
3281
- if (options.fallbackRules?.length) emitFallbackRulesCheck(lines, options.fallbackRules, options.dev === true, " ", options.nodeTarget === true);
3282
- lines.push(` return __voidMarkNoMatch(c.req.raw, new Response("Not Found", { status: 404 }));`);
3283
- lines.push(`});`);
3284
- lines.push("");
3285
- }
2589
+ lines.push(`const getClientAssetTags = __createClientAssetTags(${JSON.stringify({
2590
+ entryId: ssr.clientEntryRelativePath,
2591
+ entryUrl: "/" + ssr.clientEntryRelativePath,
2592
+ kind: "ssr",
2593
+ dev: options.dev === true,
2594
+ reactRefresh: options.reactRefresh
2595
+ })});`);
2596
+ lines.push(`app.notFound(__createSsrFallback({ routing: __routingRuntime, nodeTarget: ${JSON.stringify(options.nodeTarget === true)}, assetsDir: ${JSON.stringify(options.assetsDir)}, fallbackRules: ${JSON.stringify(emitEdgeRules && options.fallbackRules?.length ? options.dev ? options.fallbackRules : stripOriginForProd(options.fallbackRules) : void 0)}, load: () => import(${JSON.stringify(ssr.serverEntryPath)}), assets: getClientAssetTags }));`);
2597
+ } else if (emitEdgeRules && (options.fallbackRules?.length || !options.nodeTarget && options.headerRules?.length) && !(pages && scan.pages.pages.length > 0)) lines.push(`app.notFound(__createAssetNotFound({ routing: __routingRuntime, nodeTarget: ${JSON.stringify(options.nodeTarget === true)}, assetsDir: ${JSON.stringify(options.assetsDir)}, fallbackRules: ${JSON.stringify(options.fallbackRules?.length ? options.dev ? options.fallbackRules : stripOriginForProd(options.fallbackRules) : void 0)} }));`);
3286
2598
  if (scan.jobs.length > 0) {
3287
2599
  for (let i = 0; i < scan.jobs.length; i++) {
3288
2600
  const job = scan.jobs[i];
@@ -3617,8 +2929,6 @@ function compilePrerenderCollector(lines, scan, ssr, options) {
3617
2929
  lines.push("");
3618
2930
  }
3619
2931
  function compilePageRoutes(lines, scan, pages, options) {
3620
- lines.push(`import { handlePageGet, handlePageMutation } from ${JSON.stringify(pages.protocolPath)};`);
3621
- lines.push(`import { renderHeadToString, renderHtmlAttrs, renderBodyAttrs } from ${JSON.stringify(pages.headPath)};`);
3622
2932
  lines.push(`import * as __voidPagesRenderer from "virtual:void-pages-renderer";`);
3623
2933
  if (options.dev) lines.push(`import { getVoidPagesDevCss } from "virtual:void-pages-dev-assets";`);
3624
2934
  const hasIslandPages = scan.pages.pages.some((p) => p.renderMode === "island");
@@ -3632,42 +2942,6 @@ function compilePageRoutes(lines, scan, pages, options) {
3632
2942
  lines.push(`const __voidHeadConfig = ${JSON.stringify(pages.headConfig ?? null)};`);
3633
2943
  lines.push("");
3634
2944
  pushDefaultErrorPageHelpers(lines, options);
3635
- const clientEntryId = pages.clientEntryId;
3636
- lines.push(`const PAGES_CLIENT_ENTRY_ID = ${JSON.stringify(clientEntryId)};`);
3637
- lines.push(`const PAGES_CLIENT_ENTRY_URL = ${JSON.stringify("/@id/__x00__" + clientEntryId)};`);
3638
- lines.push(`let cachedPagesManifest = null;`);
3639
- lines.push("");
3640
- lines.push(`function escapeHtmlAttr(value) {`);
3641
- lines.push(` return String(value).replace(/"/g, "&quot;");`);
3642
- lines.push(`}`);
3643
- lines.push("");
3644
- lines.push(`function getPagesDevClientTags() {`);
3645
- lines.push(` const preloads = \`<script type="module" src="/@vite/client"><\/script>\\n${BINDING_HINT_SCRIPT}\`;`);
3646
- lines.push(` const bodyTag = \`<script type="module" src="\${escapeHtmlAttr(PAGES_CLIENT_ENTRY_URL)}"><\/script>\`;`);
3647
- lines.push(` return { css: "", preloads, body: bodyTag };`);
3648
- lines.push(`}`);
3649
- lines.push("");
3650
- if (options.dev) {
3651
- lines.push(`async function collectVoidDevCss(request, env, kind, componentId, rootPhases) {`);
3652
- lines.push(` const devCss = await getVoidPagesDevCss(request, env, { kind, componentId, rootPhases });`);
3653
- lines.push(` return Array.isArray(devCss) ? devCss : [];`);
3654
- lines.push(`}`);
3655
- lines.push("");
3656
- }
3657
- lines.push(`function collectPagesManifestFiles(manifest, entryId) {`);
3658
- lines.push(` const seen = new Set();`);
3659
- lines.push(` const toVisit = [entryId];`);
3660
- lines.push(` for (let index = 0; index < toVisit.length; index++) {`);
3661
- lines.push(` const currentId = toVisit[index];`);
3662
- lines.push(` if (seen.has(currentId)) continue;`);
3663
- lines.push(` seen.add(currentId);`);
3664
- lines.push(` const chunk = manifest[currentId];`);
3665
- lines.push(` if (!chunk || !Array.isArray(chunk.imports)) continue;`);
3666
- lines.push(` for (const importedId of chunk.imports) toVisit.push(importedId);`);
3667
- lines.push(` }`);
3668
- lines.push(` return Array.from(seen);`);
3669
- lines.push(`}`);
3670
- lines.push("");
3671
2945
  const relPagesDir = pages.pagesDirRelative;
3672
2946
  const pageCssKeys = {};
3673
2947
  const pageDevRootPhases = {};
@@ -3701,155 +2975,27 @@ function compilePageRoutes(lines, scan, pages, options) {
3701
2975
  pageCssKeys[page.componentId] = keys;
3702
2976
  pageDevRootPhases[page.componentId] = routeRootPhases.filter((phase) => phase.length > 0);
3703
2977
  }
3704
- lines.push(`const PAGE_CSS_KEYS = ${JSON.stringify(pageCssKeys)};`);
3705
- if (options.dev) lines.push(`const PAGE_DEV_ROOT_PHASES = ${JSON.stringify(pageDevRootPhases)};`);
3706
- lines.push("");
3707
- lines.push(`function collectRouteCss(manifest, entryId, pageKeys) {`);
3708
- lines.push(` const cssFiles = new Set();`);
3709
- lines.push(` const visited = new Set();`);
3710
- lines.push(` function visit(id) {`);
3711
- lines.push(` if (visited.has(id)) return;`);
3712
- lines.push(` visited.add(id);`);
3713
- lines.push(` const chunk = manifest[id];`);
3714
- lines.push(` if (!chunk) return;`);
3715
- lines.push(` if (Array.isArray(chunk.css)) {`);
3716
- lines.push(` for (const f of chunk.css) cssFiles.add(f);`);
3717
- lines.push(` }`);
3718
- lines.push(` if (Array.isArray(chunk.imports)) {`);
3719
- lines.push(` for (const i of chunk.imports) visit(i);`);
3720
- lines.push(` }`);
3721
- lines.push(` }`);
3722
- lines.push(` visit(entryId);`);
3723
- lines.push(` for (const key of pageKeys) {`);
3724
- lines.push(` visit(key);`);
3725
- lines.push(` }`);
3726
- lines.push(` return cssFiles;`);
3727
- lines.push(`}`);
3728
- lines.push("");
3729
- lines.push(`async function loadPagesManifest(request, env) {`);
3730
- lines.push(` if (cachedPagesManifest) return cachedPagesManifest;`);
3731
- lines.push(` if (typeof globalThis.__VITE_MANIFEST__ === "object" && globalThis.__VITE_MANIFEST__) {`);
3732
- lines.push(` cachedPagesManifest = globalThis.__VITE_MANIFEST__;`);
3733
- lines.push(` return cachedPagesManifest;`);
3734
- lines.push(` }`);
3735
- lines.push(` const assets = env?.ASSETS;`);
3736
- lines.push(` if (!assets || typeof assets.fetch !== "function") return null;`);
3737
- lines.push(` const manifestUrl = new URL("/.vite/manifest.json", request.url);`);
3738
- lines.push(` const response = await assets.fetch(new Request(manifestUrl.toString()));`);
3739
- lines.push(` if (!response.ok) return null;`);
3740
- lines.push(` cachedPagesManifest = await response.json();`);
3741
- lines.push(` return cachedPagesManifest;`);
3742
- lines.push(`}`);
3743
- lines.push("");
3744
- lines.push(`async function getPagesAssetTags(request, env, componentId) {`);
3745
- lines.push(` const manifest = await loadPagesManifest(request, env);`);
3746
- lines.push(` if (!manifest || typeof manifest !== "object") {`);
3747
- lines.push(` if (!import.meta.env.DEV) return { css: "", preloads: "", body: "" };`);
3748
- if (options.dev) {
3749
- lines.push(` const tags = getPagesDevClientTags();`);
3750
- lines.push(` return { ...tags, devCss: await collectVoidDevCss(request, env, "pages", componentId, PAGE_DEV_ROOT_PHASES[componentId] || [[PAGES_CLIENT_ENTRY_URL]]) };`);
3751
- } else lines.push(` return getPagesDevClientTags();`);
3752
- lines.push(` }`);
3753
- lines.push(` const entry = manifest[PAGES_CLIENT_ENTRY_ID];`);
3754
- lines.push(` if (!entry || typeof entry !== "object" || typeof entry.file !== "string") {`);
3755
- lines.push(` return { css: "", preloads: "", body: "" };`);
3756
- lines.push(` }`);
3757
- lines.push(` const ids = collectPagesManifestFiles(manifest, PAGES_CLIENT_ENTRY_ID);`);
3758
- lines.push(` const pageKeys = componentId ? (PAGE_CSS_KEYS[componentId] || []) : [];`);
3759
- lines.push(` const cssFiles = collectRouteCss(manifest, PAGES_CLIENT_ENTRY_ID, pageKeys);`);
3760
- lines.push(` const preloadFiles = new Set();`);
3761
- lines.push(` for (const id of ids) {`);
3762
- lines.push(` const chunk = manifest[id];`);
3763
- lines.push(` if (!chunk || typeof chunk !== "object") continue;`);
3764
- lines.push(` if (id !== PAGES_CLIENT_ENTRY_ID && typeof chunk.file === "string") {`);
3765
- lines.push(` preloadFiles.add(chunk.file);`);
3766
- lines.push(` }`);
3767
- lines.push(` }`);
3768
- lines.push(` const cssTags = [];`);
3769
- lines.push(` for (const cssFile of cssFiles) {`);
3770
- lines.push(` cssTags.push(\`<link rel="stylesheet" href="/\${escapeHtmlAttr(cssFile)}">\`);`);
3771
- lines.push(` }`);
3772
- lines.push(` const preloadTags = [];`);
3773
- lines.push(` for (const preloadFile of preloadFiles) {`);
3774
- lines.push(` preloadTags.push(\`<link rel="modulepreload" href="/\${escapeHtmlAttr(preloadFile)}">\`);`);
3775
- lines.push(` }`);
3776
- lines.push(` const bodyTag = \`<script type="module" src="/\${escapeHtmlAttr(entry.file)}"><\/script>\`;`);
3777
- lines.push(` return { css: cssTags.join("\\n"), preloads: preloadTags.join("\\n"), body: bodyTag };`);
3778
- lines.push(`}`);
3779
- lines.push("");
3780
- if (hasIslandPages && pages.islandClientEntryId) {
3781
- const islandEntryId = pages.islandClientEntryId;
3782
- lines.push(`const ISLANDS_CLIENT_ENTRY_ID = ${JSON.stringify(islandEntryId)};`);
3783
- lines.push(`const ISLANDS_CLIENT_ENTRY_URL = ${JSON.stringify("/@id/__x00__" + islandEntryId)};`);
3784
- if (pages.mdClientEntryId) {
3785
- lines.push(`const MD_CLIENT_ENTRY_ID = ${JSON.stringify(pages.mdClientEntryId)};`);
3786
- lines.push(`const MD_CLIENT_ENTRY_URL = ${JSON.stringify("/@id/__x00__" + pages.mdClientEntryId)};`);
3787
- }
3788
- lines.push("");
3789
- lines.push(`function getIslandsDevClientTags() {`);
3790
- lines.push(` const preloads = \`<script type="module" src="/@vite/client"><\/script>\\n${BINDING_HINT_SCRIPT}\`;`);
3791
- lines.push(` let bodyTag = \`<script type="module" src="\${escapeHtmlAttr(ISLANDS_CLIENT_ENTRY_URL)}"><\/script>\`;`);
3792
- if (pages.mdClientEntryId) lines.push(` bodyTag += \`\\n<script type="module" src="\${escapeHtmlAttr(MD_CLIENT_ENTRY_URL)}"><\/script>\`;`);
3793
- lines.push(` return { css: "", preloads, body: bodyTag };`);
3794
- lines.push(`}`);
3795
- lines.push("");
3796
- lines.push(`async function getIslandsAssetTags(request, env, componentId) {`);
3797
- lines.push(` const manifest = await loadPagesManifest(request, env);`);
3798
- lines.push(` if (!manifest || typeof manifest !== "object") {`);
3799
- lines.push(` if (!import.meta.env.DEV) return { css: "", preloads: "", body: "" };`);
3800
- if (options.dev) {
3801
- lines.push(` const tags = getIslandsDevClientTags();`);
3802
- lines.push(` return { ...tags, devCss: await collectVoidDevCss(request, env, "islands", componentId, PAGE_DEV_ROOT_PHASES[componentId] || [[ISLANDS_CLIENT_ENTRY_URL]]) };`);
3803
- } else lines.push(` return getIslandsDevClientTags();`);
3804
- lines.push(` }`);
3805
- lines.push(` const entry = manifest[ISLANDS_CLIENT_ENTRY_ID];`);
3806
- lines.push(` if (!entry || typeof entry !== "object" || typeof entry.file !== "string") {`);
3807
- lines.push(` return { css: "", preloads: "", body: "" };`);
3808
- lines.push(` }`);
3809
- lines.push(` const ids = collectPagesManifestFiles(manifest, ISLANDS_CLIENT_ENTRY_ID);`);
3810
- if (pages.mdClientEntryId) {
3811
- lines.push(` const mdEntry = manifest[MD_CLIENT_ENTRY_ID];`);
3812
- lines.push(` if (mdEntry && typeof mdEntry.file === "string") {`);
3813
- lines.push(` const mdIds = collectPagesManifestFiles(manifest, MD_CLIENT_ENTRY_ID);`);
3814
- lines.push(` for (const mdId of mdIds) ids.push(mdId);`);
3815
- lines.push(` }`);
3816
- }
3817
- lines.push(` const pageKeys = componentId ? (PAGE_CSS_KEYS[componentId] || []) : [];`);
3818
- lines.push(` const cssFiles = collectRouteCss(manifest, ISLANDS_CLIENT_ENTRY_ID, pageKeys);`);
3819
- if (pages.mdClientEntryId) {
3820
- lines.push(` if (mdEntry && typeof mdEntry.file === "string") {`);
3821
- lines.push(` const mdKeys = [];`);
3822
- lines.push(` const mdCss = collectRouteCss(manifest, MD_CLIENT_ENTRY_ID, mdKeys);`);
3823
- lines.push(` for (const f of mdCss) cssFiles.add(f);`);
3824
- lines.push(` }`);
3825
- }
3826
- lines.push(` const preloadFiles = new Set();`);
3827
- lines.push(` for (const id of ids) {`);
3828
- lines.push(` const chunk = manifest[id];`);
3829
- lines.push(` if (!chunk || typeof chunk !== "object") continue;`);
3830
- const excludeFromPreload = pages.mdClientEntryId ? `id !== ISLANDS_CLIENT_ENTRY_ID && id !== MD_CLIENT_ENTRY_ID` : `id !== ISLANDS_CLIENT_ENTRY_ID`;
3831
- lines.push(` if (${excludeFromPreload} && typeof chunk.file === "string") {`);
3832
- lines.push(` preloadFiles.add(chunk.file);`);
3833
- lines.push(` }`);
3834
- lines.push(` }`);
3835
- lines.push(` const cssTags = [];`);
3836
- lines.push(` for (const cssFile of cssFiles) {`);
3837
- lines.push(` cssTags.push(\`<link rel="stylesheet" href="/\${escapeHtmlAttr(cssFile)}">\`);`);
3838
- lines.push(` }`);
3839
- lines.push(` const preloadTags = [];`);
3840
- lines.push(` for (const preloadFile of preloadFiles) {`);
3841
- lines.push(` preloadTags.push(\`<link rel="modulepreload" href="/\${escapeHtmlAttr(preloadFile)}">\`);`);
3842
- lines.push(` }`);
3843
- lines.push(` let bodyTag = \`<script type="module" src="/\${escapeHtmlAttr(entry.file)}"><\/script>\`;`);
3844
- if (pages.mdClientEntryId) {
3845
- lines.push(` if (mdEntry && typeof mdEntry.file === "string") {`);
3846
- lines.push(` bodyTag += \`\\n<script type="module" src="/\${escapeHtmlAttr(mdEntry.file)}"><\/script>\`;`);
3847
- lines.push(` }`);
3848
- }
3849
- lines.push(` return { css: cssTags.join("\\n"), preloads: preloadTags.join("\\n"), body: bodyTag };`);
3850
- lines.push(`}`);
3851
- lines.push("");
3852
- }
2978
+ lines.push("const __loadPagesManifest = __createManifestLoader();");
2979
+ const assetMetadata = {
2980
+ pageCssKeys,
2981
+ devRootPhases: options.dev ? pageDevRootPhases : void 0,
2982
+ dev: options.dev === true
2983
+ };
2984
+ const devCssOption = options.dev ? ", devCss: getVoidPagesDevCss" : "";
2985
+ lines.push(`const getPagesAssetTags = __createClientAssetTags({ ...${JSON.stringify({
2986
+ ...assetMetadata,
2987
+ entryId: pages.clientEntryId,
2988
+ entryUrl: "/@id/__x00__" + pages.clientEntryId,
2989
+ kind: "pages"
2990
+ })}${devCssOption} }, __loadPagesManifest);`);
2991
+ if (hasIslandPages && pages.islandClientEntryId) lines.push(`const getIslandsAssetTags = __createClientAssetTags({ ...${JSON.stringify({
2992
+ ...assetMetadata,
2993
+ entryId: pages.islandClientEntryId,
2994
+ entryUrl: "/@id/__x00__" + pages.islandClientEntryId,
2995
+ extraEntryId: pages.mdClientEntryId,
2996
+ extraEntryUrl: pages.mdClientEntryId ? "/@id/__x00__" + pages.mdClientEntryId : void 0,
2997
+ kind: "islands"
2998
+ })}${devCssOption} }, __loadPagesManifest);`);
3853
2999
  const seenServerFiles = /* @__PURE__ */ new Set();
3854
3000
  for (const page of scan.pages.pages) {
3855
3001
  const safeId = page.componentId.replace(/[^a-zA-Z0-9]/g, "_");
@@ -3857,13 +3003,8 @@ function compilePageRoutes(lines, scan, pages, options) {
3857
3003
  if (page.serverPath) serverImportPath = `${pages.pagesDir}/${page.serverPath}`;
3858
3004
  if (serverImportPath && !seenServerFiles.has(serverImportPath)) {
3859
3005
  seenServerFiles.add(serverImportPath);
3860
- const varName = `_pmod_${safeId}`;
3861
3006
  const loaderName = `_pload_${safeId}`;
3862
- lines.push(`let ${varName};`);
3863
- lines.push(`async function ${loaderName}() {`);
3864
- lines.push(` if (!${varName}) ${varName} = await import(${JSON.stringify(serverImportPath)});`);
3865
- lines.push(` return ${varName};`);
3866
- lines.push(`}`);
3007
+ lines.push(`const ${loaderName} = __createModuleLoader(() => import(${JSON.stringify(serverImportPath)}));`);
3867
3008
  }
3868
3009
  let mdHeadRef = null;
3869
3010
  if (!serverImportPath && page.metadata && (page.metadata.title || page.metadata.description)) {
@@ -3879,105 +3020,11 @@ function compilePageRoutes(lines, scan, pages, options) {
3879
3020
  }
3880
3021
  const renderer = page.renderMode === "island" ? "renderIslandPage" : "renderPage";
3881
3022
  const assetTags = page.renderMode === "island" && pages.islandClientEntryId ? "getIslandsAssetTags" : "getPagesAssetTags";
3882
- const renderOptions = `, ${JSON.stringify({ renderMode: page.renderMode })}`;
3883
- lines.push(`app.get(${JSON.stringify(page.pattern)}, async (c) => {`);
3884
- if (serverImportPath) {
3885
- const loaderName = `_pload_${safeId}`;
3886
- lines.push(` const mod = await ${loaderName}();`);
3887
- lines.push(` return handlePageGet(mod.loader, mod.head, c, ${JSON.stringify(page.componentId)}, ${renderer}, ${assetTags}, __voidHeadConfig${renderOptions});`);
3888
- } else {
3889
- const headArg = mdHeadRef ?? "undefined";
3890
- lines.push(` return handlePageGet(undefined, ${headArg}, c, ${JSON.stringify(page.componentId)}, ${renderer}, ${assetTags}, __voidHeadConfig${renderOptions});`);
3891
- }
3892
- lines.push(`});`);
3893
- if (page.methods.includes("action") || page.methods.includes("actions")) {
3894
- const loaderName = `_pload_${safeId}`;
3895
- lines.push(`app.on(["POST", "PUT", "PATCH", "DELETE"], ${JSON.stringify(page.pattern)}, async (c) => {`);
3896
- lines.push(` const mod = await ${loaderName}();`);
3897
- if (page.methods.includes("actions")) {
3898
- lines.push(` const actionName = new URL(c.req.url).searchParams.keys().next().value;`);
3899
- lines.push(` const handler = actionName ? mod.actions?.[actionName] : mod.actions?.default;`);
3900
- lines.push(` if (!handler) return new Response("Unknown action" + (actionName ? ": " + actionName : ""), { status: 404 });`);
3901
- } else lines.push(` const handler = mod.action;`);
3902
- lines.push(` return handlePageMutation(handler, mod.loader, mod.head, c, ${JSON.stringify(page.componentId)}, ${renderer}, ${assetTags}, __voidHeadConfig${renderOptions});`);
3903
- lines.push(`});`);
3904
- }
3023
+ const routeOptions = `{ ${serverImportPath ? "load: _pload_" + safeId + ", " : ""}${mdHeadRef ? "head: " + mdHeadRef + ", " : ""}componentId: ${JSON.stringify(page.componentId)}, render: ${renderer}, assets: ${assetTags}, headConfig: __voidHeadConfig, renderOptions: ${JSON.stringify({ renderMode: page.renderMode })} }`;
3024
+ lines.push(`app.get(${JSON.stringify(page.pattern)}, __createPageGetHandler(${routeOptions}));`);
3025
+ if (page.methods.includes("action") || page.methods.includes("actions")) lines.push(`app.on(["POST", "PUT", "PATCH", "DELETE"], ${JSON.stringify(page.pattern)}, __createPageMutationHandler({ ...${routeOptions}, namedActions: ${JSON.stringify(page.methods.includes("actions"))} }));`);
3905
3026
  }
3906
3027
  lines.push("");
3907
- lines.push(`async function fetchPagesAsset(c) {`);
3908
- lines.push(` if (c.req.method !== "GET" && c.req.method !== "HEAD") {`);
3909
- lines.push(` return new Response("Not Found", { status: 404 });`);
3910
- lines.push(` }`);
3911
- lines.push(` const assets = c.env?.ASSETS;`);
3912
- lines.push(` if (!assets || typeof assets.fetch !== "function") {`);
3913
- lines.push(` return __voidMarkNoMatch(c.req.raw, new Response("Not Found", { status: 404 }));`);
3914
- lines.push(` }`);
3915
- lines.push(` return assets.fetch(c.req.raw);`);
3916
- lines.push(`}`);
3917
- lines.push("");
3918
- lines.push(`async function serveCustomErrorPage(c, status, fallbackText, error) {`);
3919
- lines.push(` try {`);
3920
- lines.push(` const assets = c.env?.ASSETS;`);
3921
- lines.push(` if (assets && typeof assets.fetch === "function") {`);
3922
- lines.push(` const errReq = new Request(new URL("/" + status + ".html", c.req.url));`);
3923
- lines.push(` const errRes = await assets.fetch(errReq);`);
3924
- lines.push(` if (errRes.ok) {`);
3925
- lines.push(` const assetCss = __voidGetErrorAssetCss(error);`);
3926
- lines.push(` if (assetCss) {`);
3927
- lines.push(` const html = __voidInjectErrorAssetCss(await errRes.text(), assetCss);`);
3928
- lines.push(` const body = __VOID_DEV && status === 500 && error && __voidShouldServeHtmlErrorPage(c.req.raw) ? __voidInjectDevErrorOverlay(html, __voidRenderDevErrorOverlay(c.req.raw, status, fallbackText, error)) : html;`);
3929
- lines.push(` return new Response(c.req.method === "HEAD" ? null : body, {`);
3930
- lines.push(` status,`);
3931
- lines.push(` headers: { "content-type": "text/html; charset=utf-8" },`);
3932
- lines.push(` });`);
3933
- lines.push(` }`);
3934
- lines.push(` if (__VOID_DEV && status === 500 && error && __voidShouldServeHtmlErrorPage(c.req.raw)) {`);
3935
- lines.push(` const overlay = __voidRenderDevErrorOverlay(c.req.raw, status, fallbackText, error);`);
3936
- lines.push(` const html = await errRes.text();`);
3937
- lines.push(` return new Response(c.req.method === "HEAD" ? null : __voidInjectDevErrorOverlay(html, overlay), {`);
3938
- lines.push(` status,`);
3939
- lines.push(` headers: { "content-type": "text/html; charset=utf-8" },`);
3940
- lines.push(` });`);
3941
- lines.push(` }`);
3942
- lines.push(` return new Response(errRes.body, { status, headers: { "content-type": "text/html; charset=utf-8" } });`);
3943
- lines.push(` }`);
3944
- lines.push(` }`);
3945
- lines.push(` } catch {}`);
3946
- lines.push(` return __voidCreateErrorResponse(c.req.raw, status, fallbackText, error);`);
3947
- lines.push(`}`);
3948
- lines.push("");
3949
- lines.push(`app.onError((err, c) => {`);
3950
- lines.push(` if (err && typeof err === "object" && "getResponse" in err) return err.getResponse();`);
3951
- lines.push(` console.error(err);`);
3952
- lines.push(` return serveCustomErrorPage(c, 500, "Internal Server Error", err);`);
3953
- lines.push(`});`);
3954
- lines.push("");
3955
- lines.push(`app.notFound(async (c) => {`);
3956
- lines.push(` const path = c.req.path;`);
3957
- lines.push(` if (path === "/api" || path.startsWith("/api/")) {`);
3958
- lines.push(` return c.text("Not Found", 404);`);
3959
- lines.push(` }`);
3960
- lines.push(` if (c.req.method !== "GET" && c.req.method !== "HEAD") {`);
3961
- lines.push(` return c.text("Not Found", 404);`);
3962
- lines.push(` }`);
3963
- lines.push(` const assetRes = await fetchPagesAsset(c);`);
3964
- lines.push(` if (assetRes.status !== 404) return assetRes;`);
3965
- if (!(options.nodeTarget !== true && options.dev !== true && options.managedDispatch === true) && options.fallbackRules?.length) emitFallbackRulesCheck(lines, options.fallbackRules, options.dev === true, " ", options.nodeTarget === true);
3966
- lines.push(` if (path.includes("/.")) {`);
3967
- lines.push(` return serveCustomErrorPage(c, 404, "Not Found");`);
3968
- lines.push(` }`);
3969
- lines.push(` const lastSeg = path.substring(path.lastIndexOf("/") + 1);`);
3970
- lines.push(` if (lastSeg.includes(".")) {`);
3971
- lines.push(` return serveCustomErrorPage(c, 404, "Not Found");`);
3972
- lines.push(` }`);
3973
- lines.push(` if (path !== "/" && path.endsWith("/")) {`);
3974
- lines.push(` const url = new URL(c.req.url);`);
3975
- lines.push(` url.pathname = path.slice(0, -1);`);
3976
- lines.push(` return Response.redirect(url.href, 301);`);
3977
- lines.push(` }`);
3978
- lines.push(` return __voidMarkNoMatch(c.req.raw, await serveCustomErrorPage(c, 404, "Not Found"));`);
3979
- lines.push(`});`);
3980
- lines.push("");
3981
3028
  }
3982
3029
  /**
3983
3030
  * Generate the asset fallthrough helper shared by native Void workers and
@@ -3996,75 +3043,12 @@ function compilePageRoutes(lines, scan, pages, options) {
3996
3043
  * anything other than the SPA shell.
3997
3044
  */
3998
3045
  function compileAssetFallbackHelper(assetsDir = "assets", serveSpaFallback = false, notFound = "none") {
3999
- const fallthroughCode = serveSpaFallback ? ` // SPA fallback: when HTML-owning features make
4000
- // assetConfig.not_found_handling = 'none', the asset binding returns 404
4001
- // instead of falling back to index.html itself. Do that fallback here, after
4002
- // user routes/middleware have run, so auth gates and OAuth callbacks see the request first.
4003
- // Pages and SSR apps leave this disabled so intentional HTML 404s stay 404.
4004
- const accept = request.headers.get("accept") ?? "";
4005
- if (accept.includes("text/html")) {
4006
- const indexUrl = new URL("/index.html", request.url);
4007
- const indexAsset = await env.ASSETS.fetch(new Request(indexUrl, { method: request.method }));
4008
- if (indexAsset.status === 200) {
4009
- const res = new Response(indexAsset.body, {
4010
- status: 200,
4011
- headers: indexAsset.headers,
4012
- });
4013
- res.headers.set("Cache-Control", "no-store");
4014
- res.headers.set("Content-Type", "text/html; charset=utf-8");
4015
- return res;
4016
- }
4017
- }
4018
- return response;` : notFound === "404-page" ? ` const accept = request.headers.get("accept") ?? "";
4019
- const assetContentType = asset.headers.get("content-type") ?? "";
4020
- if (accept.includes("text/html") && assetContentType.includes("text/html")) {
4021
- const res = new Response(asset.body, asset);
4022
- res.headers.set("Cache-Control", "no-store");
4023
- return res;
4024
- }
4025
- return response;` : ` return response;`;
4026
- return `
4027
- const __voidAssetContentTypes = {
4028
- ".avif": "image/avif",
4029
- ".css": "text/css; charset=utf-8",
4030
- ".gif": "image/gif",
4031
- ".html": "text/html; charset=utf-8",
4032
- ".ico": "image/x-icon",
4033
- ".jpeg": "image/jpeg",
4034
- ".jpg": "image/jpeg",
4035
- ".js": "text/javascript; charset=utf-8",
4036
- ".json": "application/json; charset=utf-8",
4037
- ".mjs": "text/javascript; charset=utf-8",
4038
- ".png": "image/png",
4039
- ".svg": "image/svg+xml",
4040
- ".txt": "text/plain; charset=utf-8",
4041
- ".wasm": "application/wasm",
4042
- ".webp": "image/webp",
4043
- ".woff": "font/woff",
4044
- ".woff2": "font/woff2",
4045
- };
4046
-
4047
- async function serveWithAssets(request, env, response) {
4048
- if (response.status !== 404 || !env.ASSETS || (request.method !== "GET" && request.method !== "HEAD")) return response;
4049
- const asset = await env.ASSETS.fetch(new Request(request.url, { method: request.method, headers: request.headers }));
4050
- if (asset.status !== 404) {
4051
- const res = new Response(asset.body, asset);
4052
- const pathname = new URL(request.url).pathname;
4053
- // Directly uploaded assets can reach the binding without a MIME type.
4054
- if (!res.headers.get("Content-Type")) {
4055
- const filename = pathname.slice(pathname.lastIndexOf("/") + 1);
4056
- const contentType = __voidAssetContentTypes[filename.slice(filename.lastIndexOf(".")).toLowerCase()];
4057
- if (contentType) res.headers.set("Content-Type", contentType);
4058
- }
4059
- if (pathname.startsWith(${JSON.stringify("/" + assetsDir + "/")})) {
4060
- res.headers.set("Cache-Control", "public, max-age=31536000, immutable");
4061
- } else {
4062
- res.headers.set("Cache-Control", "no-store");
4063
- }
4064
- return res;
4065
- }
4066
- ${fallthroughCode}
4067
- }
3046
+ return `import { createAssetFallback as __createAssetFallback } from ${JSON.stringify(ROUTING_RUNTIME_PATH)};
3047
+ const serveWithAssets = __createAssetFallback(${JSON.stringify({
3048
+ assetsDir,
3049
+ serveSpaFallback,
3050
+ notFound
3051
+ })});
4068
3052
  `;
4069
3053
  }
4070
3054
  /**
@@ -4086,7 +3070,7 @@ function deriveEmailRuntimePath(runtimeEnvPath) {
4086
3070
  return runtimeEnvPath.replace(/_?env(\.[^/]+)?$/, (_m, ext) => "email" + (ext ?? ""));
4087
3071
  }
4088
3072
  function compileWorkerEntry(options = {}) {
4089
- const { hasQueues = false, remote, assetsDir = "assets", webSocketClasses = [], runtimeEnvPath = "void/_env", runtimeEmailPath, envSchemaModule, sandbox, serveSpaFallback = false, hasEmail = false, live, isr, notFound = "none", durableObjects = [] } = options;
3073
+ const { hasQueues = false, versionMetadataBinding, remote, assetsDir = "assets", webSocketClasses = [], runtimeEnvPath = "void/_env", runtimeEmailPath, envSchemaModule, sandbox, serveSpaFallback = false, hasEmail = false, live, isr, notFound = "none", durableObjects = [] } = options;
4090
3074
  const remotePath = remote?.remotePath;
4091
3075
  const remoteBindingNames = JSON.stringify(remote?.bindingNames);
4092
3076
  const createRemoteEnvCall = `createRemoteEnv(env${remote?.bindingNames ? `, ${remoteBindingNames}` : ""})`;
@@ -4104,88 +3088,24 @@ function compileWorkerEntry(options = {}) {
4104
3088
  const liveRuntimeImport = hasLive ? `import { __setLiveBindingName } from "void/live";\n` : "";
4105
3089
  const liveExport = hasLive ? liveClassName === "VoidLiveStreamDurableObject" ? `export { VoidLiveStreamDurableObject };\n__setLiveBindingName(${JSON.stringify(liveBindingName)});\n` : `export { VoidLiveStreamDurableObject as ${liveClassName} };\n__setLiveBindingName(${JSON.stringify(liveBindingName)});\n` : "";
4106
3090
  const durableObjectImports = durableObjects.map(({ filePath }, index) => `import __voidDurableObject${index} from ${JSON.stringify(filePath)};`).join("\n");
4107
- const durableObjectExports = durableObjects.map(({ bindingName, className }, index) => `__voidDurableObject${index}.__bind(${JSON.stringify(bindingName)});\nexport const ${className} = __voidDurableObject${index}.class;`).join("\n");
3091
+ const durableObjectExports = durableObjects.map(({ bindingName, className, name }, index) => `__voidDurableObject${index}.__bind(${JSON.stringify(bindingName)}${name !== void 0 ? `, ${JSON.stringify(name)}` : ""});\nexport const ${className} = __voidDurableObject${index}.class;`).join("\n");
4108
3092
  const runtimeEnvImport = `import { withRuntimeEnv } from ${JSON.stringify(runtimeEnvPath)};\n`;
4109
3093
  const remoteImport = remote ? `import { createRemoteEnv } from ${JSON.stringify(remote.remotePath)};\n` : "";
4110
3094
  const envSchemaImport = envSchemaModule ? `import ${JSON.stringify(envSchemaModule.importPath)};\nimport { _validateEnvOnce } from ${JSON.stringify(envSchemaModule.helperPath)};\n` : "";
4111
3095
  const envValidateCall = envSchemaModule ? " await _validateEnvOnce(env);\n" : "";
4112
- const fetchEnvValidateCall = envSchemaModule ? " if (request.method !== \"POST\" || new URL(request.url).pathname !== \"/__void/prerender-paths\") await _validateEnvOnce(env);\n" : "";
4113
3096
  const exactNames = isr ? INTERNAL_BINDING_EXACT_NAMES : [];
4114
- const prefixCheck = [...INTERNAL_BINDING_PREFIXES.map((p) => `prop.startsWith(${JSON.stringify(p)})`), ...exactNames.map((n) => `prop === ${JSON.stringify(n)}`)].join(" || ");
4115
- const filterBindingsHelper = `
4116
- function __filterInternalBindings(env) {
4117
- return new Proxy(env, {
4118
- get(target, prop, receiver) {
4119
- if (typeof prop === "string" && (${prefixCheck})) return undefined;
4120
- return Reflect.get(target, prop, receiver);
4121
- },
4122
- has(target, prop) {
4123
- if (typeof prop === "string" && (${prefixCheck})) return false;
4124
- return Reflect.has(target, prop);
4125
- },
4126
- ownKeys(target) {
4127
- return Reflect.ownKeys(target).filter(
4128
- (key) => typeof key !== "string" || (${[...INTERNAL_BINDING_PREFIXES.map((p) => `!key.startsWith(${JSON.stringify(p)})`), ...exactNames.map((n) => `key !== ${JSON.stringify(n)}`)].join(" && ")})
4129
- );
4130
- },
4131
- getOwnPropertyDescriptor(target, prop) {
4132
- if (typeof prop === "string" && (${prefixCheck})) return undefined;
4133
- return Reflect.getOwnPropertyDescriptor(target, prop);
4134
- },
4135
- });
4136
- }
3097
+ const filterBindingsHelper = `import { filterInternalBindings as __filterBindings, createWorkerFetch as __createWorkerFetch } from ${JSON.stringify(ROUTING_RUNTIME_PATH)};
3098
+ const __filterInternalBindings = (env) => __filterBindings(env, ${JSON.stringify(INTERNAL_BINDING_PREFIXES)}, ${JSON.stringify(exactNames)});
4137
3099
  `;
4138
3100
  const assetHelper = compileAssetFallbackHelper(assetsDir, serveSpaFallback, notFound);
4139
3101
  const isrImport = isr ? `import { handleIsr } from ${JSON.stringify(isr.runtimePath)};\nimport { __VOID_ISR_REVALIDATE, __VOID_ISR_PAGES, __VOID_ISR_PATH_REVALIDATE, __VOID_ISR_DEPLOYMENT_ID } from 'virtual:void-routes';\n` : "";
4140
- const isrEnvCapture = isr ? ` env.__VOID_ISR_DEPLOYMENT_ID ??= __VOID_ISR_DEPLOYMENT_ID;\n env.__VOID_ISR_HOST = new URL(request.url).hostname;\n` : "";
4141
3102
  const isrDeploymentStamp = isr ? ` env.__VOID_ISR_DEPLOYMENT_ID ??= __VOID_ISR_DEPLOYMENT_ID;\n` : "";
4142
- const renderBlock = isr ? ` const __render = async (req) => serveWithAssets(req, env, await app.fetch(req, userEnv, ctx));
4143
- if (env.ISR_CACHE && request.headers.get("upgrade")?.toLowerCase() !== "websocket") {
4144
- const __isr = await handleIsr(request, env, ctx, { revalidate: __VOID_ISR_REVALIDATE, pages: __VOID_ISR_PAGES, pathRevalidate: __VOID_ISR_PATH_REVALIDATE, deploymentId: __VOID_ISR_DEPLOYMENT_ID, queryAllowlist: ${JSON.stringify(isr?.queryAllowlist)} }, __render);
4145
- if (__isr) return __isr;
4146
- }
4147
- return __render(request);` : ` return serveWithAssets(request, env, await app.fetch(request, userEnv, ctx));`;
4148
- const fetchHandler = remotePath ? `async (request, env, ctx) => {
4149
- ${fetchEnvValidateCall} if (env.__VOID_REMOTE === "1") env = ${createRemoteEnvCall};
4150
- ${isrEnvCapture} return __withRawEnv(env, () => {
4151
- const userEnv = __filterInternalBindings(env);
4152
- return withRuntimeEnv(env, async () => {
4153
- const internal = await __handleInternal(request, env, ctx);
4154
- if (internal) return internal;
4155
- ${renderBlock}
4156
- });
4157
- });
4158
- }` : `async (request, env, ctx) => {
4159
- ${fetchEnvValidateCall}${isrEnvCapture} return __withRawEnv(env, () => {
4160
- const userEnv = __filterInternalBindings(env);
4161
- return withRuntimeEnv(env, async () => {
4162
- const internal = await __handleInternal(request, env, ctx);
4163
- if (internal) return internal;
4164
- ${renderBlock}
4165
- });
4166
- });
4167
- }`;
4168
- const internalRouteHelper = `async function __handleInternal(request, env, ctx) {
4169
- const url = new URL(request.url);
4170
- ${hasEmail ? `if (url.pathname === "/__void/email/receipt/v1") return __handleEmailReceipt(request, env, ctx);` : ""}
4171
- // Readiness probe — platform polls this to confirm the worker is live after WfP upload.
4172
- // Handled here (before app.fetch) so user middleware cannot block it.
4173
- if (request.method === "GET" && url.pathname === "/__void/ready") {
4174
- return Response.json({ ready: true });
4175
- }
4176
- const routeInternal = await __voidHandleInternalRoute(request, env, ctx);
4177
- if (routeInternal) return routeInternal;
4178
- if (request.method !== "POST" || url.pathname !== "/__void/prerender-paths") return null;
4179
- const __expected = env.__VOID_PROXY_TOKEN;
4180
- if (__expected) {
4181
- const __token = request.headers.get("x-void-internal");
4182
- if (!__token || __token !== __expected) {
4183
- return Response.json({ error: "unauthorized" }, { status: 401 });
4184
- }
4185
- }
4186
- const paths = await __voidCollectPrerenderPaths(request, env, ctx);
4187
- return Response.json({ paths });
4188
- }`;
3103
+ const fetchHandler = `__createWorkerFetch({
3104
+ app, assets: serveWithAssets, withRawEnv: __withRawEnv, withRuntimeEnv,
3105
+ filterBindings: __filterInternalBindings,
3106
+ internalRoute: __voidHandleInternalRoute,
3107
+ collectPrerenderPaths: __voidCollectPrerenderPaths${versionMetadataBinding ? ", versionMetadataBinding: " + JSON.stringify(versionMetadataBinding) : ""}${envSchemaModule ? ", validateEnv: _validateEnvOnce" : ""}${remotePath ? ", remoteEnv: (env) => " + createRemoteEnvCall : ""}${hasEmail ? ", emailReceipt: __handleEmailReceipt" : ""}${isr ? ", isr: { deploymentId: __VOID_ISR_DEPLOYMENT_ID, handle: (request, env, ctx, render) => handleIsr(request, env, ctx, { revalidate: __VOID_ISR_REVALIDATE, pages: __VOID_ISR_PAGES, pathRevalidate: __VOID_ISR_PATH_REVALIDATE, deploymentId: __VOID_ISR_DEPLOYMENT_ID, queryAllowlist: " + JSON.stringify(isr.queryAllowlist) + " }, render) }" : ""}
3108
+ })`;
4189
3109
  const scheduledHandler = remotePath ? `async function handleScheduled(controller, env, ctx) {
4190
3110
  ${envValidateCall} if (env.__VOID_REMOTE === "1") env = ${createRemoteEnvCall};
4191
3111
  ${isrDeploymentStamp} const userEnv = __filterInternalBindings(env);
@@ -4253,7 +3173,6 @@ ${hasQueues ? ` async queue(batch) { return __voidQueue(batch, this.env, this.c
4253
3173
  }\n` : ""}}`;
4254
3174
  if (hasQueues) return `${sandboxImport}${entryImport}${liveRuntimeImport}import app, { scheduled, __voidCollectPrerenderPaths, __voidHandleInternalRoute, __withRawEnv, __processQueue${emailImport}${webSocketClasses.length > 0 ? `, ${webSocketClasses.join(", ")}` : ""}${liveRouteImport} } from 'virtual:void-routes';
4255
3175
  ${durableObjectImports}\n${runtimeEnvImport}${emailProxyImport}${envSchemaImport}${remoteImport}${isrImport}${filterBindingsHelper}${assetHelper}
4256
- ${internalRouteHelper}
4257
3176
  ${fetchDeclaration}
4258
3177
  ${scheduledHandler}
4259
3178
  ${emailHandler}
@@ -4286,7 +3205,6 @@ ${durableObjectExports}
4286
3205
  ${entryClass}`;
4287
3206
  return `${sandboxImport}${entryImport}${liveRuntimeImport}import app, { scheduled, __voidCollectPrerenderPaths, __voidHandleInternalRoute, __withRawEnv${emailImport}${webSocketClasses.length > 0 ? `, ${webSocketClasses.join(", ")}` : ""}${liveRouteImport} } from 'virtual:void-routes';
4288
3207
  ${durableObjectImports}\n${runtimeEnvImport}${emailProxyImport}${envSchemaImport}${remoteImport}${isrImport}${filterBindingsHelper}${assetHelper}
4289
- ${internalRouteHelper}
4290
3208
  ${fetchDeclaration}
4291
3209
  ${scheduledHandler}
4292
3210
  ${emailHandler}
@@ -4370,6 +3288,7 @@ export { auth, createAuthClient } from ${JSON.stringify(authClientPath)};`;
4370
3288
  }
4371
3289
  function compileNodeClient(authClientPath) {
4372
3290
  return `import app, { requestContext } from "virtual:void-routes";
3291
+ import { interpolateRouteParams } from ${JSON.stringify(ROUTE_URL_PATH)};
4373
3292
  export { auth, createAuthClient } from ${JSON.stringify(authClientPath)};
4374
3293
 
4375
3294
  export class FetchError extends Error {
@@ -4383,12 +3302,7 @@ export class FetchError extends Error {
4383
3302
  }
4384
3303
 
4385
3304
  export async function fetch(path, options) {
4386
- let url = path;
4387
- if (options?.params) {
4388
- for (const [key, value] of Object.entries(options.params)) {
4389
- url = url.replace(":" + key, encodeURIComponent(value));
4390
- }
4391
- }
3305
+ let url = interpolateRouteParams(path, options?.params);
4392
3306
 
4393
3307
  if (options?.query) {
4394
3308
  const qs = new URLSearchParams(options.query).toString();
@@ -4435,180 +3349,22 @@ export async function fetch(path, options) {
4435
3349
  return data;
4436
3350
  }`;
4437
3351
  }
4438
- /** Import the shared cached routing helpers only for modules that use rules. */
4439
- function ensureCompilePatternEmitted(lines) {
4440
- if (lines.some((line) => line.includes("compilePattern as __compilePattern"))) return;
4441
- lines.push(`import { compilePattern as __compilePattern, substituteParams as __substituteParams } from ${JSON.stringify(EDGE_MODULE_PATH)};`);
4442
- lines.push("const __matchPatternWarned = new Set();");
4443
- lines.push("function __matchPattern(pattern, pathname) {");
4444
- lines.push(" try {");
4445
- lines.push(" return __compilePattern(pattern).regex.test(pathname);");
4446
- lines.push(" } catch (err) {");
4447
- lines.push(" if (!__matchPatternWarned.has(pattern)) {");
4448
- lines.push(" __matchPatternWarned.add(pattern);");
4449
- lines.push(" console.warn(`[void] failed to compile route pattern ${JSON.stringify(pattern)}: ${err && err.message ? err.message : err}`);");
4450
- lines.push(" }");
4451
- lines.push(" return false;");
4452
- lines.push(" }");
4453
- lines.push("}");
4454
- lines.push("");
4455
- }
4456
- function ensureMergeQueryHelperEmitted(lines) {
4457
- if (lines.some((line) => line.includes("mergeQueryIntoLocation as __mergeQueryIntoLocation"))) return;
4458
- lines.push(`import { mergeQueryIntoLocation as __mergeQueryIntoLocation } from ${JSON.stringify(EDGE_MODULE_PATH)};`);
4459
- }
4460
- /**
4461
- * Shared body for routing-rule evaluation: match rules in order (last wins),
4462
- * substitute captures into destination, handle rewrite (200) or redirect (3xx).
4463
- * Used by both the pre-pipeline routing middleware and the post-pipeline
4464
- * fallback (notFound) middleware.
4465
- */
4466
- function emitApplyRoutingRules(lines, rulesVar, indent, nodeTarget, markFallbackHandled = false) {
4467
- lines.push(`${indent}let matched;`);
4468
- lines.push(`${indent}for (const rule of ${rulesVar}) {`);
4469
- lines.push(`${indent} if (rule.host && rule.host !== requestHost) continue;`);
4470
- lines.push(`${indent} let regex;`);
4471
- lines.push(`${indent} try {`);
4472
- lines.push(`${indent} ({ regex } = __compilePattern(rule.source));`);
4473
- lines.push(`${indent} } catch (err) {`);
4474
- lines.push(`${indent} if (!__matchPatternWarned.has(rule.source)) {`);
4475
- lines.push(`${indent} __matchPatternWarned.add(rule.source);`);
4476
- lines.push(`${indent} console.warn(\`[void] skipping routing rule with invalid source \${JSON.stringify(rule.source)}: \${err && err.message ? err.message : err}\`);`);
4477
- lines.push(`${indent} }`);
4478
- lines.push(`${indent} continue;`);
4479
- lines.push(`${indent} }`);
4480
- lines.push(`${indent} const m = regex.exec(pathname);`);
4481
- lines.push(`${indent} if (m) { matched = { rule, params: m.groups || {} }; break; }`);
4482
- lines.push(`${indent}}`);
4483
- lines.push(`${indent}if (matched) {`);
4484
- lines.push(`${indent} const dest = __substituteParams(matched.rule.destination, matched.params);`);
4485
- lines.push(`${indent} if (matched.rule.status === 200) {`);
4486
- lines.push(`${indent} const __qIdx = dest.indexOf("?");`);
4487
- lines.push(`${indent} const __pathOnly = __qIdx === -1 ? dest : dest.slice(0, __qIdx);`);
4488
- lines.push(`${indent} const __searchOnly = __qIdx === -1 ? "" : dest.slice(__qIdx);`);
4489
- lines.push(`${indent} const rewriteUrl = new URL(c.req.url);`);
4490
- lines.push(`${indent} rewriteUrl.pathname = __pathOnly;`);
4491
- lines.push(`${indent} if (__searchOnly) rewriteUrl.search = __searchOnly;`);
4492
- lines.push(`${indent} const rewriteReq = new Request(rewriteUrl.toString(), c.req.raw);`);
4493
- lines.push(`${indent} const __prior = __voidOriginalUrls.get(c.req.raw);`);
4494
- lines.push(`${indent} __voidOriginalUrls.set(rewriteReq, __prior ?? new URL(c.req.url));`);
4495
- if (markFallbackHandled) lines.push(`${indent} __voidFallbackHandled.add(rewriteReq);`);
4496
- if (nodeTarget) lines.push(`${indent} const __r = await app.fetch(rewriteReq, c.env);`);
4497
- else lines.push(`${indent} const __r = await app.fetch(rewriteReq, c.env, c.executionCtx);`);
4498
- lines.push(`${indent} if (!__VOID_DEV_ROUTING) return __r;`);
4499
- lines.push(`${indent} const __kind = matched.rule.force === true ? "rewrite" : "fallback";`);
4500
- lines.push(`${indent} const __trace = __kind + "[" + matched.rule.source + "] -> " + dest + " (" + (matched.rule.origin || "unknown") + ")";`);
4501
- lines.push(`${indent} return __voidAnnotateRouting(__r, __trace);`);
4502
- lines.push(`${indent} }`);
4503
- lines.push(`${indent} const location = __mergeQueryIntoLocation(dest, new URL(c.req.url).search);`);
4504
- lines.push(`${indent} const __redir = c.redirect(location, matched.rule.status);`);
4505
- lines.push(`${indent} if (!__VOID_DEV_ROUTING) return __redir;`);
4506
- lines.push(`${indent} const __rtrace = "redirect[" + matched.rule.source + "] -> " + dest + " " + matched.rule.status + " (" + (matched.rule.origin || "unknown") + ")";`);
4507
- lines.push(`${indent} return __voidAnnotateRouting(__redir, __rtrace);`);
4508
- lines.push(`${indent}}`);
4509
- }
4510
- /**
4511
- * Strip dev-only `origin` metadata from a rule list before embedding in the
4512
- * generated worker code. Keeps production bundles free of authoring hints.
4513
- *
4514
- * Keep in sync with `stripDevOnlyRuleFields` in `cli/package.ts`. This helper
4515
- * intentionally preserves `force` because the Node/Bun/Deno-target codegen
4516
- * reads it at runtime to label the `X-Void-Routing` trace header as either
4517
- * `rewrite[...]` (force) or `fallback[...]`. The CLI version strips both
4518
- * fields because the deploy manifest never transmits either to the dispatch
4519
- * worker (phase is implied by which bucket the rule ships in).
4520
- */
4521
3352
  function stripOriginForProd(rules) {
4522
3353
  return rules.map(({ origin: _origin, ...rest }) => rest);
4523
3354
  }
4524
- /**
4525
- * Emit routing rules middleware — handles both redirects (3xx) and rewrites (200).
4526
- * Last match wins. Rewrites re-dispatch with a guard header to prevent loops.
4527
- * Redirects preserve the request's query string in the Location header.
4528
- *
4529
- * When `dev === true` the per-rule `origin` metadata is preserved in the
4530
- * compiled rule table and a matched rule's trace is emitted on the
4531
- * `X-Void-Routing` response header. In production the origin field is
4532
- * stripped and no trace header is emitted.
4533
- */
4534
- function compileRoutingRulesMiddleware(lines, rules, dev, nodeTarget) {
4535
- ensureCompilePatternEmitted(lines);
3355
+ function compileRoutingRulesMiddleware(lines, rules, dev, _nodeTarget) {
4536
3356
  lines.push("// Routing rules: redirects + rewrites (applied before route handlers)");
4537
3357
  lines.push(`const __routingRules = ${JSON.stringify(dev ? rules : stripOriginForProd(rules))};`);
4538
- lines.push("app.use(\"*\", async (c, next) => {");
4539
- lines.push(" if (__voidOriginalUrls.has(c.req.raw)) return next();");
4540
- lines.push(" const __reqUrl = new URL(c.req.url);");
4541
- lines.push(" const pathname = __reqUrl.pathname;");
4542
- lines.push(" const requestHost = __reqUrl.hostname;");
4543
- emitApplyRoutingRules(lines, "__routingRules", " ", nodeTarget);
4544
- if (dev) {
4545
- lines.push(" await next();");
4546
- lines.push(" if (__VOID_DEV_ROUTING && c.res && !c.res.headers.has(\"X-Void-Routing\")) {");
4547
- lines.push(" try { c.res.headers.set(\"X-Void-Routing\", \"pass-through\"); } catch {}");
4548
- lines.push(" }");
4549
- } else lines.push(" return next();");
4550
- lines.push("});");
4551
- lines.push("");
4552
- }
4553
- /**
4554
- * Emit a fallback-rule check inside Hono's `notFound` hook. Fires only when
4555
- * the pipeline didn't match a route — the "asset-miss / no route matched"
4556
- * phase. Re-dispatches through `app.fetch` on a rule match so the re-dispatched
4557
- * request runs through the full middleware + route stack with
4558
- * `X-Void-Original-URL` set; falls through to the caller's existing notFound
4559
- * body when no rule matches.
4560
- *
4561
- * Indent `indent` so the emitted statements nest cleanly within the caller's
4562
- * block. Expects `__matchPattern`, `__voidOriginalUrls`, `__mergeQueryIntoLocation`,
4563
- * `__substituteParams`, and `__voidAnnotateRouting` to already be in scope —
4564
- * which they are, because `compileRoutingRulesMiddleware` runs earlier in
4565
- * compile order and emits every one of them.
4566
- */
4567
- function emitFallbackRulesCheck(lines, rules, dev, indent, nodeTarget) {
4568
- ensureCompilePatternEmitted(lines);
4569
- const tableMarker = "// Fallback rules (applied on no-match, post-route)";
4570
- if (!lines.includes(tableMarker)) {
4571
- lines.push(tableMarker);
4572
- lines.push(`const __fallbackRules = ${JSON.stringify(dev ? rules : stripOriginForProd(rules))};`);
4573
- lines.push("");
4574
- }
4575
- lines.push(`${indent}if (!__voidFallbackHandled.has(c.req.raw)) {`);
4576
- lines.push(`${indent} const __reqUrl = new URL(c.req.url);`);
4577
- lines.push(`${indent} const pathname = __reqUrl.pathname;`);
4578
- lines.push(`${indent} const requestHost = __reqUrl.hostname;`);
4579
- emitApplyRoutingRules(lines, "__fallbackRules", `${indent} `, nodeTarget, true);
4580
- lines.push(`${indent}}`);
3358
+ lines.push("app.use(\"*\", __routingRuntime.routingMiddleware(__routingRules));");
4581
3359
  }
4582
- /**
4583
- * Emit header middleware — applies matching header rules to every response.
4584
- * All matching rules merge; last match wins for same header name.
4585
- */
4586
3360
  function compileHeaderMiddleware(lines, rules) {
4587
- ensureCompilePatternEmitted(lines);
4588
3361
  lines.push("// Header rules (applied to responses)");
4589
3362
  lines.push(`const __headerRules = ${JSON.stringify(rules)};`);
4590
- lines.push("app.use(\"*\", async (c, next) => {");
4591
- lines.push(" await next();");
4592
- lines.push(" const pathname = new URL(c.req.url).pathname;");
4593
- lines.push(" const matched = [];");
4594
- lines.push(" for (const rule of __headerRules) {");
4595
- lines.push(" if (__matchPattern(rule.pattern, pathname)) matched.push(...rule.headers);");
4596
- lines.push(" }");
4597
- lines.push(" if (matched.length === 0) return;");
4598
- lines.push(" const headers = new Headers(c.res.headers);");
4599
- lines.push(" for (const [name, value] of matched) {");
4600
- lines.push(" headers.set(name, value);");
4601
- lines.push(" }");
4602
- lines.push(" c.res = new Response(c.res.body, {");
4603
- lines.push(" headers,");
4604
- lines.push(" status: c.res.status,");
4605
- lines.push(" statusText: c.res.statusText,");
4606
- lines.push(" });");
4607
- lines.push("});");
4608
- lines.push("");
3363
+ lines.push("app.use(\"*\", __routingRuntime.headerMiddleware(__headerRules));");
4609
3364
  }
4610
3365
  function compileWorkerClient(authClientPath) {
4611
3366
  return `import app, { requestContext } from "virtual:void-routes";
3367
+ import { interpolateRouteParams } from ${JSON.stringify(ROUTE_URL_PATH)};
4612
3368
  import { env } from "cloudflare:workers";
4613
3369
  export { auth, createAuthClient } from ${JSON.stringify(authClientPath)};
4614
3370
 
@@ -4623,12 +3379,7 @@ export class FetchError extends Error {
4623
3379
  }
4624
3380
 
4625
3381
  export async function fetch(path, options) {
4626
- let url = path;
4627
- if (options?.params) {
4628
- for (const [key, value] of Object.entries(options.params)) {
4629
- url = url.replace(":" + key, encodeURIComponent(value));
4630
- }
4631
- }
3382
+ let url = interpolateRouteParams(path, options?.params);
4632
3383
 
4633
3384
  if (options?.query) {
4634
3385
  const qs = new URLSearchParams(options.query).toString();
@@ -4734,13 +3485,20 @@ function routingPlugin(root, options) {
4734
3485
  const dts = generateQueueTypes(scan.queues, queuesDir, outDir);
4735
3486
  writeFileIfChanged(join(outDir, "queues.d.ts"), dts);
4736
3487
  }
4737
- async function rescan() {
4738
- scan = await scanRoutes(root, {
4739
- output: options.output,
4740
- paths,
4741
- environment: routeEnvironment
4742
- });
4743
- authConfigPath = findVoidAuthConfig(root, paths);
3488
+ async function rescan(refresh = false) {
3489
+ let analysis = options.getApplicationAnalysis?.(routeEnvironment, refresh);
3490
+ if (!analysis) {
3491
+ const config = readConfig(root);
3492
+ analysis = analyzeApplicationSync(root, {
3493
+ config: {
3494
+ ...config,
3495
+ output: options.output ?? config.output
3496
+ },
3497
+ environment: routeEnvironment
3498
+ });
3499
+ }
3500
+ scan = (await completeApplicationAnalysis(analysis)).scan;
3501
+ authConfigPath = analysis.authConfigPath;
4744
3502
  const entries = validateSsrEntries(root, paths);
4745
3503
  ssr = entries ? {
4746
3504
  serverEntryPath: entries.server.absolutePath,
@@ -4776,8 +3534,6 @@ function routingPlugin(root, options) {
4776
3534
  }
4777
3535
  const compileOptions = {
4778
3536
  honoPath: resolveFile("hono"),
4779
- responsePath: resolveFile("#self/response"),
4780
- handlerPath: resolveFile("#self/handler"),
4781
3537
  runtimeEnvPath: resolveFile("#self/_env"),
4782
3538
  runtimeEmailPath: resolveFile("#self/email"),
4783
3539
  emailDir,
@@ -4884,8 +3640,6 @@ function routingPlugin(root, options) {
4884
3640
  return {
4885
3641
  pagesDir,
4886
3642
  pagesDirRelative: relative(root, pagesDir).replaceAll("\\", "/"),
4887
- protocolPath: resolveFile("#self/pages-protocol"),
4888
- headPath: resolveFile("#self/pages-head"),
4889
3643
  clientEntryId: "virtual:void-pages-client",
4890
3644
  islandClientEntryId: hasIslandPages ? "virtual:void-islands-client" : void 0,
4891
3645
  mdClientEntryId,
@@ -4935,6 +3689,7 @@ function routingPlugin(root, options) {
4935
3689
  writeFileIfChanged(join(outDir, "app.ts"), compileNodeApp(options.target, compileOptions.honoPath, getEnvSchemaModule()));
4936
3690
  writeFileIfChanged(join(outDir, "index.ts"), compileNodeServer(options.target));
4937
3691
  } else writeFileIfChanged(join(outDir, "entry.ts"), compileWorkerEntry({
3692
+ versionMetadataBinding: options.getVersionMetadataBinding?.(),
4938
3693
  remote,
4939
3694
  webSocketClasses: options.websocketTombstones,
4940
3695
  runtimeEnvPath: compileOptions.runtimeEnvPath,
@@ -4956,6 +3711,7 @@ function routingPlugin(root, options) {
4956
3711
  resolvedConfig = config;
4957
3712
  authClientPath = resolveAuthClientPath(config);
4958
3713
  compileOptions.dev = config.command === "serve";
3714
+ compileOptions.assetsDir = config.build.assetsDir;
4959
3715
  compileOptions.reactRefresh = config.plugins.some((plugin) => plugin.name === "vite:react-babel" || plugin.name === "vite:react-refresh" || plugin.name === "vite:react-swc");
4960
3716
  const resolvedPublicDir = config.publicDir && config.publicDir.length > 0 ? config.publicDir : null;
4961
3717
  if (resolvedPublicDir !== publicDir) {
@@ -4984,12 +3740,19 @@ function routingPlugin(root, options) {
4984
3740
  }
4985
3741
  }) } };
4986
3742
  const entries = validateSsrEntries(root, paths);
4987
- if (!entries || env.command !== "build") return;
3743
+ if (env.command !== "build") return;
4988
3744
  return { build: {
4989
- manifest: true,
4990
- rollupOptions: { input: entries.client.absolutePath }
3745
+ manifest: entries ? true : _.build?.manifest ?? true,
3746
+ ...entries ? { rollupOptions: { input: entries.client.absolutePath } } : {}
4991
3747
  } };
4992
3748
  },
3749
+ generateBundle: {
3750
+ order: "post",
3751
+ handler(_output, bundle) {
3752
+ const manifest = this.environment.config.build.manifest;
3753
+ if (this.environment.name === "client" && manifest) stampClientAssetCachePolicy(bundle, typeof manifest === "string" ? manifest : ".vite/manifest.json", compileOptions.headerRules);
3754
+ }
3755
+ },
4993
3756
  async buildStart() {
4994
3757
  await rescan();
4995
3758
  if (options.target && (scan?.websockets?.length ?? 0) > 0) throw new Error("routing: WebSocket routes require the default Cloudflare target.");
@@ -5001,7 +3764,7 @@ function routingPlugin(root, options) {
5001
3764
  const migrationsDir = paths.migrationsDir;
5002
3765
  if (existsSync(migrationsDir) || compileOptions.auth) {
5003
3766
  const { collectMigrations } = await import("./collect-DLyFDiKW.mjs");
5004
- const { buildMigrationPlanBundle } = await import("./plan-DpuOr14e.mjs");
3767
+ const { buildMigrationPlanBundle } = await import("./plan-D1Q5rf-r.mjs");
5005
3768
  const migrations = existsSync(migrationsDir) ? collectMigrations(migrationsDir) : [];
5006
3769
  const dialect = getDatabaseDialect(readConfig(root));
5007
3770
  compileOptions.migrationHandlerPath = resolveFile(dialect === "postgresql" ? "#self/runtime/migration-handler-pg" : dialect === "mysql" ? "#self/runtime/migration-handler-mysql" : "#self/runtime/migration-handler");
@@ -5026,6 +3789,7 @@ function routingPlugin(root, options) {
5026
3789
  queryAllowlist: buildConfig.routing?.revalidateQueryAllowlist
5027
3790
  } : void 0;
5028
3791
  writeFileIfChanged(join(outDir, "entry.ts"), compileWorkerEntry({
3792
+ versionMetadataBinding: options.getVersionMetadataBinding?.(),
5029
3793
  hasQueues: scan.queues.length > 0,
5030
3794
  remote,
5031
3795
  assetsDir: resolvedConfig?.build.assetsDir,
@@ -5080,7 +3844,7 @@ function routingPlugin(root, options) {
5080
3844
  const sourceConventionChanged = isInDirectory(normalizedPath, normalizedRoutesDir) || isInDirectory(normalizedPath, normalizedMiddlewareDir) || isInDirectory(normalizedPath, normalizedJobsDir) || isInDirectory(normalizedPath, normalizedQueuesDir) || isInDirectory(normalizedPath, normalizedEmailDir) || isInDirectory(normalizedPath, normalizedPagesDir) || isPotentialAuthConfigPath(normalizedPath) || isPotentialEnvFilePath(normalizedPath);
5081
3845
  if (!sourceConventionChanged && !isInDirectory(normalizedPath, normalizedSsrDir) && !isPotentialEnvFilePath(normalizedPath)) return;
5082
3846
  if (!sourceConventionChanged && isInDirectory(normalizedPath, normalizedSsrDir) && !ssrEntryAbsPaths.has(normalizedPath)) return;
5083
- await rescan();
3847
+ await rescan(true);
5084
3848
  resolveAuthCompileOptions();
5085
3849
  if (event !== "change" && options.onDevAssetRoutingPolicyChange?.(resolveCurrentAssetRoutingPolicy()) === true) {
5086
3850
  await devServer.restart();
@@ -5093,6 +3857,7 @@ function routingPlugin(root, options) {
5093
3857
  writeFileIfChanged(join(outDir, "app.ts"), compileNodeApp(options.target, compileOptions.honoPath, getEnvSchemaModule()));
5094
3858
  writeFileIfChanged(join(outDir, "index.ts"), compileNodeServer(options.target));
5095
3859
  } else writeFileIfChanged(join(outDir, "entry.ts"), compileWorkerEntry({
3860
+ versionMetadataBinding: options.getVersionMetadataBinding?.(),
5096
3861
  hasQueues: scan.queues.length > 0,
5097
3862
  remote,
5098
3863
  assetsDir: resolvedConfig?.build.assetsDir,
@@ -5572,7 +4337,7 @@ function readVoidDevCredentials(root) {
5572
4337
  */
5573
4338
  async function runAiSetupPrompt(root, token, apiUrl, server) {
5574
4339
  const { select, text, isCancel, log } = await import("./dist-BuDuKZJv.mjs");
5575
- const { PlatformClient } = await import("./client-Czz8o5jP.mjs");
4340
+ const { PlatformClient } = await import("./client-Cu7jWiF1.mjs");
5576
4341
  const { attachSelectedPlatform, writeProjectConfig } = await import("./project-BuUwfj6f.mjs");
5577
4342
  const { inferDefaultSlug } = await import("./resolve-project-DtbidV4y.mjs");
5578
4343
  const client = new PlatformClient(token, apiUrl);
@@ -5601,7 +4366,7 @@ async function runAiSetupPrompt(root, token, apiUrl, server) {
5601
4366
  let slug;
5602
4367
  if (result === "__create__") {
5603
4368
  const { validateProjectSlug } = await import("./project-slug-DofjTFd-.mjs");
5604
- const { createProjectWithSlugRetry } = await import("./create-project-DdoqwFLF.mjs");
4369
+ const { createProjectWithSlugRetry } = await import("./create-project-Boczwj5r.mjs");
5605
4370
  let created;
5606
4371
  try {
5607
4372
  created = await createProjectWithSlugRetry(client, inferDefaultSlug(root), async (defaultSlug) => {
@@ -5687,15 +4452,26 @@ function voidPlugin(options) {
5687
4452
  }
5688
4453
  }
5689
4454
  };
5690
- const paths = resolveProjectPaths(root, config);
4455
+ let application = analyzeApplicationSync(root, { config });
4456
+ const { paths, dialect, bindingNames, authConfigPath } = application;
4457
+ const analyses = /* @__PURE__ */ new Map([[void 0, application]]);
4458
+ const getApplicationAnalysis = (environment, refresh = false) => {
4459
+ let result = refresh ? void 0 : analyses.get(environment);
4460
+ if (!result) {
4461
+ result = analyzeApplicationSync(root, {
4462
+ config,
4463
+ environment
4464
+ });
4465
+ analyses.set(environment, result);
4466
+ }
4467
+ application = result;
4468
+ return result;
4469
+ };
5691
4470
  let routeEnvironment = "prod";
5692
4471
  assertNoRootSourceConventionConflicts(paths);
5693
- const dialect = getDatabaseDialect(config);
5694
- const detected = detectFramework(root);
4472
+ const detected = application.framework;
5695
4473
  const framework = detected?.class === "a" ? detected.name : void 0;
5696
4474
  const scanDirs = config.inference?.scanDirs ?? (detected ? FRAMEWORK_SCAN_DIRS : void 0);
5697
- const inferenceOptions = config.inference?.bindings ? { bindings: config.inference.bindings } : void 0;
5698
- const bindingNames = resolveBindingNames(config.inference?.bindings);
5699
4475
  const frameworkOwnsCloudflareRuntime = detected !== void 0 && (detected.class === "b" || detected.class === "c");
5700
4476
  const localD1PersistRoot = frameworkOwnsCloudflareRuntime ? join(root, ".wrangler", "state") : options?.persistTo ?? join(root, ".void");
5701
4477
  const localD1 = resolveLocalD1Target(root, {
@@ -5703,22 +4479,13 @@ function voidPlugin(options) {
5703
4479
  persistRoot: localD1PersistRoot
5704
4480
  });
5705
4481
  writeLocalD1PersistState(root, !isNodeTarget(config.target) && !frameworkOwnsCloudflareRuntime ? options?.persistTo : void 0);
5706
- const inferredBindings = inferProjectBindings(root, {
5707
- ...inferenceOptions,
5708
- paths
5709
- }, scanDirs);
5710
- const sandboxEnabled = isSandboxEnabled(config);
5711
- let bindings = sandboxEnabled ? {
5712
- ...inferredBindings,
5713
- needsSandbox: true
5714
- } : inferredBindings;
4482
+ let bindings = application.bindings;
5715
4483
  const sandboxConfig = bindings.needsSandbox ? resolveSandboxConfig(config, root) : void 0;
5716
- const authConfigPath = findVoidAuthConfig(root, paths);
5717
- let authEnabled = bindings.needsAuth || authConfigPath !== null || config.auth !== void 0;
4484
+ let authEnabled = application.authEnabled;
5718
4485
  if (detected && authEnabled) throw new Error("auth: Void-managed Better Auth is only supported in Void apps. Use Better Auth's official integration for this framework instead.");
5719
4486
  if (detected && bindings.needsSandbox) throw new Error("sandbox: Cloudflare Sandboxes are currently supported in Void apps only.");
5720
4487
  if (detected && bindings.needsLive) throw new Error("live: void/live is currently supported in Void apps only.");
5721
- const hasInboundEmail = hasEmailHandlers(scanEmailHandlersSync(paths.sourceRoot));
4488
+ const hasInboundEmail = hasEmailHandlers(application.email);
5722
4489
  if (detected && hasInboundEmail) throw new Error("email: inbound email handlers are only supported in Void apps. Remove the email/ directory — `sendEmail` from void/email keeps working.");
5723
4490
  const STUB_PREFIX = "\0void-client-stub:";
5724
4491
  const SERVER_ONLY_STUBS = {
@@ -5795,9 +4562,9 @@ function voidPlugin(options) {
5795
4562
  if (name !== "client") return { optimizeDeps: { exclude: ["void"] } };
5796
4563
  }
5797
4564
  };
5798
- const queues = framework ? [] : scanQueuesSync(root, paths.queuesDir);
5799
- const websocketRoutes = framework ? [] : scanWebSocketRoutesSync(root, paths);
5800
- const durableObjects = scanDurableObjectModules(root);
4565
+ const queues = framework ? [] : application.queues;
4566
+ const websocketRoutes = framework ? [] : application.allWebsockets;
4567
+ const durableObjects = application.durableObjects;
5801
4568
  if (detected && durableObjects.length > 0) throw new Error("durable: durable-objects/ is currently supported in Void apps only, not framework adapter mode.");
5802
4569
  for (const module of durableObjects) {
5803
4570
  const websocketCollision = websocketRoutes.find((route) => route.bindingName === module.bindingName || route.className === module.className);
@@ -5846,7 +4613,7 @@ function voidPlugin(options) {
5846
4613
  if (command !== "serve") return;
5847
4614
  if (syncWranglerBindings(root, {
5848
4615
  ...bindings,
5849
- needsD1: dialect === "sqlite" && bindings.needsD1
4616
+ needsD1: dialect === "sqlite" && application.needsDatabase
5850
4617
  }, {
5851
4618
  bindingNames,
5852
4619
  ...directCloudflareDestination && bindings.needsAI ? { directCloudflareAi: { gateway: config.ai?.gateway } } : {},
@@ -5922,12 +4689,13 @@ function voidPlugin(options) {
5922
4689
  }
5923
4690
  const remoteMode = resolveRemoteMode(config.remote);
5924
4691
  const workerConfig = {};
5925
- const jobs = scanJobsSync(root, paths.cronsDir);
4692
+ const jobs = application.jobs;
5926
4693
  if (jobs.length > 0) workerConfig.triggers = { crons: [...new Set(jobs.flatMap((job) => job.crons))] };
5927
4694
  let envSchemaFacts;
5928
4695
  let assetRouting;
5929
4696
  if (config.worker?.vars) workerConfig.vars = { ...config.worker.vars };
5930
4697
  let viteCommand = "build";
4698
+ let versionMetadataBinding;
5931
4699
  const wranglerCompat = isNodeTarget(config.target) ? void 0 : readWranglerCompat(root, config);
5932
4700
  if (wranglerCompat) {
5933
4701
  workerConfig.compatibility_date = wranglerCompat.compatibilityDate;
@@ -5965,7 +4733,7 @@ function voidPlugin(options) {
5965
4733
  }
5966
4734
  const d1Name = bindingNames?.d1 ?? "DB";
5967
4735
  const d1 = [];
5968
- if (dialect === "sqlite" && (bindings.needsD1 || authEnabled) && !hasBinding(resolved.d1_databases, d1Name)) d1.push({
4736
+ if (dialect === "sqlite" && application.needsDatabase && !hasBinding(resolved.d1_databases, d1Name)) d1.push({
5969
4737
  binding: d1Name,
5970
4738
  database_name: "default",
5971
4739
  database_id: "local"
@@ -6082,7 +4850,7 @@ function voidPlugin(options) {
6082
4850
  resolved.containers = [];
6083
4851
  const currentMigrations = result.migrations ?? resolved.migrations;
6084
4852
  const existingMigrations = Array.isArray(currentMigrations) ? currentMigrations : [];
6085
- if (!existingMigrations.some((migration) => migration.tag === "void-sandbox-v2" || migration.new_sqlite_classes?.includes(sandboxConfig.className))) result.migrations = [...existingMigrations, {
4853
+ if (!hasSandboxSqliteMigration(existingMigrations, sandboxConfig.className)) result.migrations = [...existingMigrations, {
6086
4854
  tag: SANDBOX_MIGRATION_TAG,
6087
4855
  new_sqlite_classes: [sandboxConfig.className]
6088
4856
  }];
@@ -6124,6 +4892,33 @@ function voidPlugin(options) {
6124
4892
  result.vars = vars;
6125
4893
  }
6126
4894
  }
4895
+ versionMetadataBinding = selectNativeVersionMetadataBinding(resolved, {
4896
+ nativeBuild: viteCommand === "build" && process.env["VOID_CLOUDFLARE_DEPLOY_BUILD"] === "1",
4897
+ preserveBindings: process.env[CLOUDFLARE_PRESERVE_BINDINGS_BUILD_ENV] === "1"
4898
+ });
4899
+ if (versionMetadataBinding) {
4900
+ const owner = findBindingNameOwner(result, "version_metadata", versionMetadataBinding);
4901
+ if (owner) throw new Error(`Cloudflare version metadata binding ${versionMetadataBinding} conflicts with ${owner}.`);
4902
+ if (!resolved.version_metadata) result.version_metadata = { binding: versionMetadataBinding };
4903
+ }
4904
+ finalizeDurableObjectPatch(resolved, result, [
4905
+ ...environmentWebsocketRoutes.map((route) => ({
4906
+ name: route.bindingName,
4907
+ class_name: route.className
4908
+ })),
4909
+ ...durableObjects.map((module) => ({
4910
+ name: module.bindingName,
4911
+ class_name: module.className
4912
+ })),
4913
+ ...bindings.needsSandbox && sandboxConfig ? [{
4914
+ name: sandboxConfig.binding,
4915
+ class_name: sandboxConfig.className
4916
+ }] : [],
4917
+ ...shouldEmitLive() && liveConfig ? [{
4918
+ name: liveConfig.bindingName,
4919
+ class_name: liveConfig.className
4920
+ }] : []
4921
+ ]);
6127
4922
  return result;
6128
4923
  }
6129
4924
  function applyEnvSchema(facts) {
@@ -6134,16 +4929,9 @@ function voidPlugin(options) {
6134
4929
  config(userConfig, { command, isPreview }) {
6135
4930
  viteCommand = command;
6136
4931
  routeEnvironment = command === "serve" && !isPreview ? "dev" : "prod";
6137
- const environmentBindings = inferProjectBindings(root, {
6138
- ...inferenceOptions,
6139
- paths,
6140
- environment: routeEnvironment
6141
- }, scanDirs);
6142
- bindings = sandboxEnabled ? {
6143
- ...environmentBindings,
6144
- needsSandbox: true
6145
- } : environmentBindings;
6146
- authEnabled = bindings.needsAuth || authConfigPath !== null || config.auth !== void 0;
4932
+ application = getApplicationAnalysis(routeEnvironment);
4933
+ bindings = application.bindings;
4934
+ authEnabled = application.authEnabled;
6147
4935
  if (command === "serve" && directCloudflareDestination && bindings.needsAI) process.env.CLOUDFLARE_AUTH_USE_KEYRING = "true";
6148
4936
  if (!framework && !isNodeTarget(config.target)) {
6149
4937
  managedCloudflareBuild = command === "build" && Boolean(process.env.VOID_DEPLOY_PROJECT_ID);
@@ -6222,13 +5010,11 @@ function voidPlugin(options) {
6222
5010
  }
6223
5011
  }
6224
5012
  };
6225
- const autoDetectBindings = !inferenceOptions;
6226
5013
  const autoDetectAuth = !authEnabled;
6227
5014
  const bindingWatchPlugin = {
6228
5015
  name: "void:binding-watch",
6229
5016
  apply: "serve",
6230
5017
  configureServer(server) {
6231
- if (!autoDetectBindings && !autoDetectAuth) return;
6232
5018
  const watchDirs = [.../* @__PURE__ */ new Set([...scanDirs ?? DEFAULT_SCAN_DIRS, "src"])].map((d) => join(root, d));
6233
5019
  let hintShown = false;
6234
5020
  const check = (path) => {
@@ -6236,16 +5022,14 @@ function voidPlugin(options) {
6236
5022
  if (!watchDirs.some((d) => path.startsWith(d))) return;
6237
5023
  try {
6238
5024
  const code = readFileSync(path, "utf-8");
6239
- const fileBindings = inferBindingsFromSource(code, path.split("/").pop());
5025
+ const fileBindings = applyBindingOverrides(inferBindingsFromSource(code, path.split("/").pop()), config.inference?.bindings);
6240
5026
  const newBindings = [];
6241
- if (autoDetectBindings) {
6242
- if (fileBindings.needsD1 && !bindings.needsD1) newBindings.push("D1 (void/db)");
6243
- if (fileBindings.needsKV && !bindings.needsKV) newBindings.push("KV (void/kv)");
6244
- if (fileBindings.needsR2 && !bindings.needsR2) newBindings.push("R2 (void/storage)");
6245
- if (fileBindings.needsAI && !bindings.needsAI) newBindings.push("AI (void/ai)");
6246
- if (fileBindings.needsSandbox && !bindings.needsSandbox) newBindings.push("Sandbox (void/sandbox)");
6247
- if (fileBindings.needsEmail && !bindings.needsEmail) newBindings.push("Email (void/email)");
6248
- }
5027
+ if (fileBindings.needsD1 && !bindings.needsD1) newBindings.push("D1 (void/db)");
5028
+ if (fileBindings.needsKV && !bindings.needsKV) newBindings.push("KV (void/kv)");
5029
+ if (fileBindings.needsR2 && !bindings.needsR2) newBindings.push("R2 (void/storage)");
5030
+ if (fileBindings.needsAI && !bindings.needsAI) newBindings.push("AI (void/ai)");
5031
+ if (fileBindings.needsSandbox && !bindings.needsSandbox) newBindings.push("Sandbox (void/sandbox)");
5032
+ if (fileBindings.needsEmail && !bindings.needsEmail) newBindings.push("Email (void/email)");
6249
5033
  if (autoDetectAuth && fileBindings.needsAuth) newBindings.push("Auth (void/auth)");
6250
5034
  if (newBindings.length > 0) {
6251
5035
  hintShown = true;
@@ -6315,14 +5099,14 @@ function voidPlugin(options) {
6315
5099
  clientStubsPlugin,
6316
5100
  serverRuntimeOptimizerPlugin,
6317
5101
  bindingRuntimePlugin(bindingNames),
6318
- drizzlePlugin(root, false, getDatabaseDialect(config), {
5102
+ drizzlePlugin(root, false, dialect, {
6319
5103
  d1BindingName: bindingNames?.d1,
6320
5104
  forceVirtualDb: authEnabled || bindingNames?.d1 !== void 0,
6321
5105
  localD1DatabaseId: localD1.databaseId,
6322
5106
  localD1PersistRoot: localD1.persistRoot,
6323
5107
  redirectDbTypePaths
6324
5108
  }),
6325
- migrationPlugin(root, getDatabaseDialect(config), localD1.databaseId, localD1.persistRoot),
5109
+ migrationPlugin(root, dialect, localD1.databaseId, localD1.persistRoot),
6326
5110
  ...vinextCompat ? [vinextCompat] : [],
6327
5111
  frameworkBuildWrapperPlugin,
6328
5112
  frameworkTriggersPlugin(root, { devTriggerToken }),
@@ -6358,6 +5142,7 @@ function voidPlugin(options) {
6358
5142
  envSchemaPlugin(root),
6359
5143
  ...pagesDevCssAssetsPlugin(root, devTriggerToken),
6360
5144
  routingPlugin(root, {
5145
+ getApplicationAnalysis,
6361
5146
  isAuthEnabled: () => false,
6362
5147
  devTriggerToken,
6363
5148
  headConfig: config.head,
@@ -6377,18 +5162,17 @@ function voidPlugin(options) {
6377
5162
  if (normalizedFlags && normalizedFlags !== existingFlags) workerConfig.compatibility_flags = normalizedFlags;
6378
5163
  const ssrEntry = validateSsrEntry(root, paths);
6379
5164
  const hasPages = existsSync(paths.pagesDir);
6380
- const hasMiddleware = scanMiddlewareSync(root, paths).length > 0;
6381
5165
  let assetRoutingPublicDir = join(root, "public");
6382
5166
  let managedCloudflareBuild = false;
6383
5167
  function resolveConfiguredAssetRoutingPolicy() {
6384
- const routePatterns = scanRoutePatternsSync(root, paths, routeEnvironment);
5168
+ const routePatterns = application.routes;
6385
5169
  const environmentWebsocketRoutes = websocketRoutes.filter((route) => isRouteEnabledForEnvironment(route, routeEnvironment));
6386
5170
  const policy = resolveAssetRoutingPolicy({
6387
5171
  isSsr: Boolean(ssrEntry),
6388
5172
  hasPages,
6389
5173
  hasApiRoutes: hasApiRoutes(routePatterns) || hasApiRoutes(environmentWebsocketRoutes) || authEnabled,
6390
5174
  hasDocumentRoutes: hasDocumentRoutes(routePatterns),
6391
- hasMiddleware,
5175
+ hasMiddleware: application.middleware.length > 0,
6392
5176
  hasWebSockets: hasDocumentRoutes(environmentWebsocketRoutes),
6393
5177
  authEnabled,
6394
5178
  liveEnabled: shouldEmitLive() && liveConfig !== void 0,
@@ -6441,7 +5225,9 @@ function voidPlugin(options) {
6441
5225
  ...bindings.needsSandbox ? [createSandboxSdkResolvePlugin()] : [],
6442
5226
  ...pagesDevCssAssetsPlugin(root, devTriggerToken),
6443
5227
  routingPlugin(root, {
5228
+ getApplicationAnalysis,
6444
5229
  isAuthEnabled: () => authEnabled,
5230
+ getVersionMetadataBinding: () => versionMetadataBinding,
6445
5231
  devTriggerToken,
6446
5232
  headConfig: config.head,
6447
5233
  output: config.output,