void 0.27.0 → 0.28.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 (283) hide show
  1. package/README.md +3 -1
  2. package/dist/{account-cmd-l-FM7Ioq.mjs → account-cmd-Ci00cncT.mjs} +5 -5
  3. package/dist/{agents-B_pX_HmQ.mjs → agents-CuNtT0D_.mjs} +5 -2
  4. package/dist/{application-analysis-DKy02UY0.mjs → application-analysis-D72ZQfMZ.mjs} +118 -135
  5. package/dist/{application-routing-DQyUh_5S.mjs → application-routing-Dy589Vgn.mjs} +1 -2
  6. package/dist/atomic-write-Dq6R0BPN.mjs +18 -0
  7. package/dist/{auth-Dn2vw-SG.mjs → auth-B6iOCjKI.mjs} +23 -56
  8. package/dist/{auth-link-vz9Z2kmG.mjs → auth-link-DWr6Afao.mjs} +10 -10
  9. package/dist/{auth-migrations-BwHgeEsD.mjs → auth-migrations-Cgs0k6lS.mjs} +28 -5
  10. package/dist/{auth-router-DvsCUVw4.mjs → auth-router-DP14wVkZ.mjs} +4 -4
  11. package/dist/auth-wn6F8dB8.mjs +2 -0
  12. package/dist/base64-DVrOndmI.mjs +16 -0
  13. package/dist/{better-auth-shared-CPvWD3nG.d.mts → better-auth-shared-B74NJIus.d.mts} +8 -13
  14. package/dist/{better-auth-shared-DPpj8zxc.mjs → better-auth-shared-CMXlZG7W.mjs} +56 -68
  15. package/dist/{build-cmd-D6we0VjO.mjs → build-cmd-Cr3FJxv0.mjs} +5 -5
  16. package/dist/{cache-CZRdzKx1.mjs → cache-D0Tt28cn.mjs} +5 -5
  17. package/dist/{cancel-deploy-CQ3NnMvf.mjs → cancel-deploy-CJKvk7AN.mjs} +4 -4
  18. package/dist/{cf-access-TWNzXltp.mjs → cf-access-BM9G0lhO.mjs} +4 -3
  19. package/dist/{cf-access-BcIBSKqG.mjs → cf-access-CWP4avfP.mjs} +3 -7
  20. package/dist/cf-build-output-2u583yJK.mjs +2 -0
  21. package/dist/{cf-build-output-DjvB_872.mjs → cf-build-output-Bc8i3dzE.mjs} +2 -2
  22. package/dist/cf-user-agent-ChjQp2MU.mjs +33 -0
  23. package/dist/cli/cli.mjs +198 -311
  24. package/dist/cli/cloudflare-operation-process.mjs +41 -15
  25. package/dist/cli/env-schema-probe.d.mts +5 -43
  26. package/dist/cli/env-schema-probe.mjs +14 -80
  27. package/dist/client-C1BjRn3g.mjs +2 -0
  28. package/dist/{client-DlDJuY0s.mjs → client-DM9Kcf4e.mjs} +161 -415
  29. package/dist/{cloudflare-auth-CuxfF6OA.mjs → cloudflare-auth-CqFBDo52.mjs} +12 -39
  30. package/dist/{cloudflare-cmd-lHqNlJGW.mjs → cloudflare-cmd-CTrn-lXJ.mjs} +6 -5
  31. package/dist/{cloudflare-config-BmhBv3HV.mjs → cloudflare-config-DV60XFFK.mjs} +16 -28
  32. package/dist/{cloudflare-connect-2G3rL2rP.mjs → cloudflare-connect-BosmCNlq.mjs} +3 -3
  33. package/dist/{cloudflare-operations-CwI1bChl.mjs → cloudflare-operations-BKdSfNBN.mjs} +26 -34
  34. package/dist/{cloudflare-operations-BlYLlowZ.mjs → cloudflare-operations-Ds-lX3Ts.mjs} +1 -1
  35. package/dist/{cloudflare-process-2-TfIEzB.mjs → cloudflare-process-CeDWJRhj.mjs} +12 -7
  36. package/dist/collect-NUlJMpLY.mjs +2 -0
  37. package/dist/{collect-DiTn9yr6.mjs → collect-xjffdCdk.mjs} +1 -1
  38. package/dist/{config-CSa15FvD.d.mts → config-7qoq2p9v.d.mts} +2 -2
  39. package/dist/{config-CLYAosnQ.mjs → config-BEm9vRvS.mjs} +11 -5
  40. package/dist/{config-DiowPT80.mjs → config-Bx_1SpnO.mjs} +87 -177
  41. package/dist/config-CNnrSMYm.mjs +2 -0
  42. package/dist/{config-DPByhVck.mjs → config-D0GY5ItR.mjs} +1 -1
  43. package/dist/config-entry.d.mts +1 -1
  44. package/dist/{connect-BfPBHHm-.mjs → connect-nukQSoEO.mjs} +8 -8
  45. package/dist/{create-project-BdXEFKal.mjs → create-project-D4APeBwX.mjs} +7 -7
  46. package/dist/{create-project-qFDC45zg.mjs → create-project-DL7YXpjj.mjs} +1 -1
  47. package/dist/{db-Xs80hcaA.mjs → db-27RztQLy.mjs} +173 -263
  48. package/dist/{delete-d2vuou3j.mjs → delete-BbsZFZIw.mjs} +5 -5
  49. package/dist/deploy-B06EQq4t.mjs +6009 -0
  50. package/dist/deploy-Db2ALnQP.mjs +3 -0
  51. package/dist/deploy-managed-static-CGswbcay.mjs +2277 -0
  52. package/dist/deploy-transport-BiicfoQW.mjs +180 -0
  53. package/dist/deploy.d.mts +10 -0
  54. package/dist/deploy.mjs +82 -0
  55. package/dist/dev-inbox-Rd6j_8vM.mjs +217 -0
  56. package/dist/discover-CTUiSsfG.mjs +2 -0
  57. package/dist/{discover-CkCYv9T_.mjs → discover-D2PGT63u.mjs} +2 -2
  58. package/dist/{dist-BVqXeR_h.mjs → dist-ipQi0Q8y.mjs} +2 -3
  59. package/dist/{domain-BsDUBAvt.mjs → domain-Bfq9n03H.mjs} +7 -22
  60. package/dist/{dotenv-BfU6eqFt.mjs → dotenv-CNazY3-w.mjs} +4 -16
  61. package/dist/{email-d_Aux1vM.mjs → email-BcjSyAL0.mjs} +4 -20
  62. package/dist/{email-_lGAHOhp.mjs → email-DIwaQU4P.mjs} +99 -191
  63. package/dist/email-cloudflare-CH053RxK.mjs +1096 -0
  64. package/dist/email-protocol-D9nTvhCp.mjs +82 -0
  65. package/dist/{entry-CMAkqBmU.mjs → entry-ehmBvs5w.mjs} +2 -2
  66. package/dist/{env-BxocywBB.mjs → env-BJjULvL0.mjs} +2 -2
  67. package/dist/{env-DMA3cXZt.mjs → env-BhdWMrNy.mjs} +2 -13
  68. package/dist/{env-C74QepDE.mjs → env-C6ipBLp3.mjs} +8 -8
  69. package/dist/{env-public-DR7ZM6d-.d.mts → env-public-CCdykygU.d.mts} +6 -23
  70. package/dist/{env-raw-jZpP5n47.mjs → env-raw-Cklzcde3.mjs} +3 -20
  71. package/dist/{env-types-CwXgeMgL.mjs → env-types-DS2_y4X8.mjs} +2 -2
  72. package/dist/{env-validation-CrVNjsPm.mjs → env-validation-CTn-HhG1.mjs} +1 -1
  73. package/dist/env-validation-cE0zcmzO.mjs +486 -0
  74. package/dist/{gen-DtkQhvQg.mjs → gen-CnN1Xidx.mjs} +131 -253
  75. package/dist/gen-F8pSZnhc.mjs +2 -0
  76. package/dist/{generate-GDbL7sUr.mjs → generate-Dat0UTry.mjs} +38 -4
  77. package/dist/generate-Rii9klHB.mjs +2 -0
  78. package/dist/generated-wrangler-config-DeWj5F9Y.mjs +18 -0
  79. package/dist/{github-cmd-DaDdBbSS.mjs → github-cmd-BdkU4Nhe.mjs} +27 -71
  80. package/dist/{handler-BHAn2fZJ.mjs → handler-BZ1t7-Rv.mjs} +2 -2
  81. package/dist/{handler-CNAwjRcW.d.mts → handler-_PqY82xe.d.mts} +1 -1
  82. package/dist/{headers-DlfR78Nu.mjs → headers-Di1FsD3e.mjs} +26 -81
  83. package/dist/{help-0bTe_lID.mjs → help-Bug7pyK_.mjs} +18 -10
  84. package/dist/help-s9q7LTcu.mjs +2 -0
  85. package/dist/{inbound-PfQDLXc5.mjs → inbound-DmkTQeWp.mjs} +71 -222
  86. package/dist/{inbound-CH5Mksyy.d.mts → inbound-brj2-TM5.d.mts} +19 -58
  87. package/dist/index.d.mts +2 -18
  88. package/dist/index.mjs +200 -496
  89. package/dist/{info-PYWwkWyt.mjs → info-CujPwtMe.mjs} +5 -5
  90. package/dist/{init-DaBGmaXC.mjs → init-ZWOJvc-Z.mjs} +179 -388
  91. package/dist/isr-config-DPjXM8J2.mjs +194 -0
  92. package/dist/{link-C6fjafep.mjs → link-UEc7bnF4.mjs} +8 -8
  93. package/dist/{list-BTFBlqKl.mjs → list-CuWeOnzk.mjs} +6 -17
  94. package/dist/{live-CgQuTpqD.mjs → live-BxLX-JqJ.mjs} +19 -17
  95. package/dist/{live-Du8jXwOW.d.mts → live-DJONVlQK.d.mts} +1 -1
  96. package/dist/load-user-env-DD5qveNU.mjs +49 -0
  97. package/dist/{local-d1-ga5O_idV.mjs → local-d1-BM3p74mm.mjs} +6 -6
  98. package/dist/{login-GKcNUmtI.mjs → login-CZ2Cqa-D.mjs} +11 -11
  99. package/dist/login-DhK7o1oJ.mjs +2 -0
  100. package/dist/{logs-BiMSULmc.mjs → logs-TihRcLTk.mjs} +5 -5
  101. package/dist/migrate-BgT-hmu8.mjs +2 -0
  102. package/dist/{migrate-NLsjBbuM.mjs → migrate-uFwojusJ.mjs} +69 -21
  103. package/dist/migration-handler-Cg0Y4EPu.mjs +470 -0
  104. package/dist/{migration-handler-DM4clYj5.d.mts → migration-handler-CwlEQUoo.d.mts} +17 -26
  105. package/dist/{mime-DxCznlJq.mjs → mime-srOklVVv.mjs} +92 -395
  106. package/dist/{node-DJicPvPj.mjs → node-DoKbo1SZ.mjs} +8 -24
  107. package/dist/{operator-args-DOBhIaIg.mjs → operator-args-UnE8Y2eK.mjs} +27 -26
  108. package/dist/{operator-auth-BEZ_u0Cz.mjs → operator-auth-Cr2zCc-J.mjs} +2 -2
  109. package/dist/{operator-client-DbDv4vtE.mjs → operator-client-C-ROjk1I.mjs} +4 -4
  110. package/dist/{operator-cmd-BT4hgavL.mjs → operator-cmd-C5lCctnc.mjs} +8 -8
  111. package/dist/operator-cmd-Cjk5DiRx.mjs +2 -0
  112. package/dist/{output-C50ag2r3.mjs → output-FNHKw5Ac.mjs} +36 -5
  113. package/dist/{package-json-DXfiT1jV.mjs → package-json-BjYqR-So.mjs} +1 -1
  114. package/dist/pages/client.d.mts +1 -1
  115. package/dist/pages/client.mjs +91 -5
  116. package/dist/pages/index.d.mts +1 -2
  117. package/dist/pages/index.mjs +6 -6
  118. package/dist/pages/islands-plugin.mjs +5 -83
  119. package/dist/pages/protocol.d.mts +2 -2
  120. package/dist/pages/protocol.mjs +1 -1
  121. package/dist/pages/serialize.mjs +1 -1
  122. package/dist/{platform-args-DUeXY9Om.mjs → platform-args-C6Mb_I3a.mjs} +34 -58
  123. package/dist/platform-args-Cm7x-fot.mjs +2 -0
  124. package/dist/{platform-auth-config-CkSx3usH.mjs → platform-auth-config-CJmNkFT2.mjs} +10 -11
  125. package/dist/{platform-auth-protection-BJimB_p9.mjs → platform-auth-protection-D5wvsI-Y.mjs} +36 -26
  126. package/dist/{platform-auth-recovery-BU6izFAU.mjs → platform-auth-recovery-D_0I3n-1.mjs} +8 -9
  127. package/dist/{platform-cmd-BbmJiq5O.mjs → platform-cmd-Cuj4oUVo.mjs} +1 -1
  128. package/dist/{platform-cmd-BbY1dWiM.mjs → platform-cmd-DxxZO6e5.mjs} +15 -15
  129. package/dist/{platform-discovery-DIYz8V63.mjs → platform-discovery-CHhNs8Nn.mjs} +1 -1
  130. package/dist/{platform-domain-CHVS6cV0.mjs → platform-domain-zLXnW1G_.mjs} +5 -5
  131. package/dist/{platform-lifecycle-DzCwqhFq.mjs → platform-lifecycle-DOW-wLfx.mjs} +1398 -2043
  132. package/dist/{platform-lifecycle-ByAlpkhV.mjs → platform-lifecycle-_gfnjUBr.mjs} +1 -1
  133. package/dist/{platform-management-CBOT4BSM.mjs → platform-management-CYrLvTGH.mjs} +1 -1
  134. package/dist/{platform-management-CuuVDhyt.mjs → platform-management-t7HKy4-U.mjs} +632 -124
  135. package/dist/{platform-plans-config-CN-heS4q.mjs → platform-plans-config-CNH6zbPX.mjs} +15 -11
  136. package/dist/{platform-recovery-CskSJgLh.mjs → platform-recovery-DeucI7A9.mjs} +6 -9
  137. package/dist/{platform-registry-Cjv2Qf0r.mjs → platform-registry-B9mWX9LO.mjs} +13 -18
  138. package/dist/{platform-setup-BBxRxmFC.mjs → platform-setup-CTf6MMT9.mjs} +19 -26
  139. package/dist/{plugin-inference-BlQbOL0P.mjs → plugin-inference-DsARdQKE.mjs} +18 -33
  140. package/dist/{prepare-Dq9hTIbo.mjs → prepare-C4zfwks4.mjs} +3 -3
  141. package/dist/{prepare-Do96654b.mjs → prepare-CSH9dKTI.mjs} +11 -13
  142. package/dist/prepare-dr9uxQSV.mjs +2 -0
  143. package/dist/{prerender-render-Ct20jftc.mjs → prerender-render-Bfsumdkv.mjs} +8 -2
  144. package/dist/prerender-render.d.mts +2 -0
  145. package/dist/prerender-render.mjs +2 -2
  146. package/dist/project-DiiOBZPF.mjs +2 -0
  147. package/dist/{project-cmd-DaoRrn-8.mjs → project-cmd-Dq75AXzy.mjs} +19 -19
  148. package/dist/{project-paths-GgcMozYz.mjs → project-paths-DMvEeSau.mjs} +9 -14
  149. package/dist/{project-BAm2aB6Q.mjs → project-rqDnVsJN.mjs} +8 -4
  150. package/dist/{project-team-Q_lCA7Io.mjs → project-team-B3_QcStG.mjs} +6 -6
  151. package/dist/{project-token-BArgK9o1.mjs → project-token-CvsRvv2I.mjs} +5 -5
  152. package/dist/{project-tsconfig-CVJhNMxs.mjs → project-tsconfig-bveqhlYA.mjs} +3 -5
  153. package/dist/{project-zero-trust-KO9Hu2Pq.mjs → project-zero-trust-D1ICiwN_.mjs} +5 -5
  154. package/dist/{protocol-BPZaNqBo.d.mts → protocol-4H7V_3Os.d.mts} +1 -1
  155. package/dist/{protocol-CfaUwNs8.mjs → protocol-RNP0u7UY.mjs} +9 -3
  156. package/dist/{provision-BfaLiWbj.mjs → provision-DDh7ITVS.mjs} +118 -865
  157. package/dist/{requests-C7Oeoh5u.mjs → requests-3CL3BuZh.mjs} +4 -4
  158. package/dist/resolve-project-B9Hr0D3n.mjs +2 -0
  159. package/dist/resolve-project-C_Cu7E8a.mjs +48 -0
  160. package/dist/{rollback-DVAtrLAl.mjs → rollback-Ce1d_0J9.mjs} +7 -17
  161. package/dist/{route-types-CbtsIeFn.mjs → route-types-IrBuwJ7u.mjs} +35 -70
  162. package/dist/routing-assets-VkrKIbxE.mjs +139 -0
  163. package/dist/{runner-9wjsSZx-.mjs → runner-B5huK2eC.mjs} +1 -1
  164. package/dist/{runner-DMBKSrRk.mjs → runner-DcVDrzuR.mjs} +7 -28
  165. package/dist/{runner-mysql-CEzKtmFb.mjs → runner-mysql-CCtyI0p6.mjs} +4 -3
  166. package/dist/runner-mysql-CaJq-hd6.mjs +2 -0
  167. package/dist/runner-pg-BJhFZZG4.mjs +2 -0
  168. package/dist/{runner-pg-DV8p_zjA.mjs → runner-pg-CPd-CB_F.mjs} +1 -1
  169. package/dist/runtime/ai.mjs +9 -22
  170. package/dist/runtime/better-auth-mysql.d.mts +2 -5
  171. package/dist/runtime/better-auth-mysql.mjs +6 -31
  172. package/dist/runtime/better-auth-pg.d.mts +2 -5
  173. package/dist/runtime/better-auth-pg.mjs +6 -32
  174. package/dist/runtime/better-auth.d.mts +2 -4
  175. package/dist/runtime/better-auth.mjs +9 -19
  176. package/dist/runtime/db.mjs +1 -1
  177. package/dist/runtime/durable.d.mts +16 -0
  178. package/dist/runtime/durable.mjs +26 -2
  179. package/dist/runtime/email/testing.d.mts +1 -1
  180. package/dist/runtime/email/testing.mjs +9 -23
  181. package/dist/runtime/email-protocol.d.mts +12 -0
  182. package/dist/runtime/email-protocol.mjs +2 -70
  183. package/dist/runtime/email.d.mts +1 -1
  184. package/dist/runtime/email.mjs +79 -221
  185. package/dist/runtime/env-public.d.mts +1 -1
  186. package/dist/runtime/env-public.mjs +12 -38
  187. package/dist/runtime/env.d.mts +1 -12
  188. package/dist/runtime/env.mjs +1 -1
  189. package/dist/runtime/handler.d.mts +1 -1
  190. package/dist/runtime/handler.mjs +1 -1
  191. package/dist/runtime/isr.mjs +1 -1
  192. package/dist/runtime/kv.mjs +1 -1
  193. package/dist/runtime/live-client.d.mts +1 -1
  194. package/dist/runtime/live-server.mjs +1 -16
  195. package/dist/runtime/live.d.mts +1 -1
  196. package/dist/runtime/live.mjs +1 -1
  197. package/dist/runtime/migration-handler-mysql.d.mts +2 -2
  198. package/dist/runtime/migration-handler-mysql.mjs +3 -2
  199. package/dist/runtime/migration-handler-pg.d.mts +2 -2
  200. package/dist/runtime/migration-handler-pg.mjs +1 -1
  201. package/dist/runtime/migration-handler.d.mts +2 -2
  202. package/dist/runtime/migration-handler.mjs +2 -470
  203. package/dist/runtime/queues.mjs +1 -1
  204. package/dist/runtime/remote/binding-handler.mjs +62 -62
  205. package/dist/runtime/remote/index.mjs +16 -77
  206. package/dist/runtime/routing.d.mts +1 -4
  207. package/dist/runtime/routing.mjs +82 -218
  208. package/dist/runtime/sandbox-container.d.mts +2 -2
  209. package/dist/runtime/sandbox-container.mjs +2 -2
  210. package/dist/runtime/sandbox.d.mts +2 -2
  211. package/dist/runtime/sandbox.mjs +13 -6
  212. package/dist/runtime/storage.mjs +1 -1
  213. package/dist/runtime/validator.d.mts +1 -1
  214. package/dist/runtime/ws-server.d.mts +2 -3
  215. package/dist/runtime/ws-server.mjs +6 -28
  216. package/dist/runtime/ws.d.mts +1 -1
  217. package/dist/{sandbox-container-Bo0eiFKz.d.mts → sandbox-container-ChQRum-j.d.mts} +3 -1
  218. package/dist/{sandbox-container-C6ItmVuN.mjs → sandbox-container-DBKIqDEK.mjs} +12 -1
  219. package/dist/{sandbox-C5LFoJMf.d.mts → sandbox-q3waMc2T.d.mts} +1 -1
  220. package/dist/{scan-C3uDzz6J.mjs → scan-C0BMdmEd.mjs} +84 -7
  221. package/dist/{secret-BvtB7IjY.mjs → secret-B5J8bBsI.mjs} +62 -80
  222. package/dist/{serialize-BPvnNQuA.mjs → serialize-BtQyaYoC.mjs} +10 -4
  223. package/dist/{skills-BgVMvQdy.mjs → skills-BJsan98C.mjs} +2 -2
  224. package/dist/{subcommand-prompt-BSlnD1fI.mjs → subcommand-prompt-gQ-NDA-u.mjs} +38 -43
  225. package/dist/sveltekit.mjs +1 -1
  226. package/dist/validate-C9xtFOYR.mjs +2 -0
  227. package/dist/{validate-C9qJArv7.mjs → validate-CheZGRE7.mjs} +4 -8
  228. package/dist/version-metadata-DIrqEHQo.mjs +73 -0
  229. package/dist/{wrangler-D9KTuqnv.mjs → wrangler-BYs07Rxy.mjs} +119 -378
  230. package/dist/{ws-CChrrAU-.d.mts → ws-aKVYB-fA.d.mts} +1 -1
  231. package/dist/yarn-pnp-DLbEFMT0.mjs +92 -0
  232. package/docs/guide/auth.md +2 -0
  233. package/docs/guide/database/postgresql.md +2 -0
  234. package/docs/guide/database.md +2 -0
  235. package/docs/guide/durable-state.md +24 -0
  236. package/docs/guide/platform/administration/access.md +4 -0
  237. package/docs/guide/platform/administration/connected-apps.md +55 -0
  238. package/docs/guide/platform/installation/credentials.md +3 -1
  239. package/docs/guide/quickstart.md +2 -0
  240. package/docs/guide/sandboxes.md +2 -0
  241. package/docs/reference/api/deploy.md +23 -0
  242. package/docs/reference/api/pages.md +2 -0
  243. package/docs/reference/api.md +2 -1
  244. package/docs/reference/cli/database.md +9 -3
  245. package/docs/reference/cli/platform-installation.md +1 -1
  246. package/docs/reference/cli/setup.md +2 -0
  247. package/package.json +13 -16
  248. package/skills/void/SKILL.md +1 -0
  249. package/dist/auth-LMJcNESe.mjs +0 -2
  250. package/dist/cf-build-output-H9a97vME.mjs +0 -2
  251. package/dist/cf-user-agent-lKblH3zU.mjs +0 -17
  252. package/dist/client-tso2OfcG.mjs +0 -2
  253. package/dist/collect-DLyFDiKW.mjs +0 -2
  254. package/dist/config-5r-YpMC-.mjs +0 -2
  255. package/dist/config-B_ggY-IO.mjs +0 -89
  256. package/dist/config-BtSFvXZx.mjs +0 -2
  257. package/dist/config-write-AHGesphx.mjs +0 -61
  258. package/dist/deploy-Bqe1PYBw.mjs +0 -10458
  259. package/dist/deploy-VsWsVQkw.mjs +0 -2
  260. package/dist/dev-inbox-CK-UuPob.mjs +0 -297
  261. package/dist/discover-EDUf6JJw.mjs +0 -2
  262. package/dist/dist-_UUlL6bg.mjs +0 -2
  263. package/dist/env-validation-Dxdx_5wo.mjs +0 -951
  264. package/dist/gen-dA9hW7AV.mjs +0 -2
  265. package/dist/head-client-DzmJGN4C.mjs +0 -90
  266. package/dist/help-DfQYVfGY.mjs +0 -2
  267. package/dist/login-mx_ydhmp.mjs +0 -2
  268. package/dist/migrate-BHp07yJE.mjs +0 -2
  269. package/dist/operator-cmd-CwBB-1yb.mjs +0 -2
  270. package/dist/pages/head-client.d.mts +0 -13
  271. package/dist/pages/head-client.mjs +0 -2
  272. package/dist/platform-args-D4E1PjVw.mjs +0 -2
  273. package/dist/prepare-DRUV-g3X.mjs +0 -2
  274. package/dist/project-DedqCp59.mjs +0 -2
  275. package/dist/provision-Wu9ZBk9L.mjs +0 -2
  276. package/dist/resolve-project-BIeYs9Cw.mjs +0 -2
  277. package/dist/resolve-project-CP8rZs_p.mjs +0 -28
  278. package/dist/runner-mysql-CkFqZ6CE.mjs +0 -2
  279. package/dist/runner-pg-BGYRFdRp.mjs +0 -2
  280. package/dist/runtime/env-helpers.d.mts +0 -2
  281. package/dist/runtime/env-helpers.mjs +0 -2
  282. package/dist/validate-BJr9LfXy.mjs +0 -2
  283. package/dist/yarn-pnp-CUX_iTPA.mjs +0 -188
@@ -1,10 +1,10 @@
1
- import { i as normalizeEmail, n as MimeError, o as validateAddressParts, r as buildMime } from "./mime-DxCznlJq.mjs";
2
- import { a as getRawRuntimeEnv } from "./env-raw-jZpP5n47.mjs";
1
+ import { t as base64ToBytes } from "./base64-DVrOndmI.mjs";
2
+ import { c as validateAddressParts, i as indexOfControl, n as MimeError, o as normalizeEmail, r as buildMime } from "./mime-srOklVVv.mjs";
3
+ import { a as getRawRuntimeEnv } from "./env-raw-Cklzcde3.mjs";
4
+ import { o as withTimeout } from "./email-protocol-D9nTvhCp.mjs";
3
5
  import { EMAIL_MAX_ACTIONS, EMAIL_MAX_INBOUND_BYTES, EMAIL_MAX_INBOUND_HEADERS, EMAIL_MAX_METADATA_BYTES, EMAIL_MAX_REPLY_BYTES, EMAIL_MAX_RESPONSE_BYTES } from "@void/platform/email-protocol";
4
6
  //#region src/runtime/email/inbound.ts
5
- const VALID_SLUG = /^[a-z0-9](?:[a-z0-9-]{0,54}[a-z0-9])?$/;
6
7
  const MAX_ACTIONS = EMAIL_MAX_ACTIONS;
7
- const MAX_ACTION_ADDRESS_LENGTH = 320;
8
8
  const MAX_ACTION_METADATA_BYTES = EMAIL_MAX_METADATA_BYTES;
9
9
  /** Bounds on a forward's headers. */
10
10
  const MAX_FORWARD_HEADERS = 32;
@@ -17,6 +17,8 @@ const MAX_INBOUND_HEADERS = EMAIL_MAX_INBOUND_HEADERS;
17
17
  const MAX_REPLY_BYTES = EMAIL_MAX_REPLY_BYTES;
18
18
  const EMAIL_STREAM_DEADLINE_MS = 15e3;
19
19
  const EMAIL_ACTION_TERMINAL_BYTES = 5;
20
+ const INBOUND_PROVIDER_DEADLINE_MS = 3e4;
21
+ const INBOUND_ACTION_BATCH_DEADLINE_MS = 6e4;
20
22
  const actionEncoder = new TextEncoder();
21
23
  function emailActionWireSize(action) {
22
24
  return 5 + actionEncoder.encode(JSON.stringify(action.type === "reply" ? {
@@ -25,28 +27,25 @@ function emailActionWireSize(action) {
25
27
  to: action.to
26
28
  } : action)).byteLength + (action.type === "reply" ? 5 + action.raw.byteLength : 0);
27
29
  }
28
- function readRawProjectSlug() {
29
- let raw;
30
+ /** The raw env, or `undefined` outside a worker or SSR request. */
31
+ function tryGetRawRuntimeEnv() {
30
32
  try {
31
- raw = getRawRuntimeEnv()?.__VOID_PROJECT_SLUG;
33
+ return getRawRuntimeEnv();
32
34
  } catch {
33
35
  return;
34
36
  }
37
+ }
38
+ /** A non-empty string env var. */
39
+ function readEnvString(name) {
40
+ const raw = tryGetRawRuntimeEnv()?.[name];
35
41
  return typeof raw === "string" && raw.length > 0 ? raw : void 0;
36
42
  }
37
- function tryReadProjectSlug() {
38
- const raw = readRawProjectSlug();
43
+ const VALID_SLUG = /^[a-z0-9](?:[a-z0-9-]{0,54}[a-z0-9])?$/;
44
+ /** `__VOID_PROJECT_SLUG` when it can head a sender address. */
45
+ function readProjectSlug() {
46
+ const raw = readEnvString("__VOID_PROJECT_SLUG");
39
47
  return raw !== void 0 && VALID_SLUG.test(raw) ? raw : void 0;
40
48
  }
41
- function tryReadEmailDomain() {
42
- let raw;
43
- try {
44
- raw = getRawRuntimeEnv()?.__VOID_EMAIL_DOMAIN;
45
- } catch {
46
- return;
47
- }
48
- return typeof raw === "string" && raw.length > 0 ? raw : void 0;
49
- }
50
49
  function readRelayDomain(message) {
51
50
  const raw = message.__voidRelayDomain;
52
51
  return typeof raw === "string" && raw.length > 0 ? raw : void 0;
@@ -71,13 +70,9 @@ var ParseEmailError = class extends Error {
71
70
  }
72
71
  };
73
72
  /**
74
- * Parse a `ForwardableEmailMessage` into structured fields. postal-mime is
75
- * loaded lazily so workers that never call this don't bundle it.
76
- *
77
- * For proxy messages (built via `createMessageProxy`) the raw bytes are
78
- * cached on first read so subsequent `parseEmail`/`message.raw` accesses
79
- * still work. For real CF `ForwardableEmailMessage`s the raw stream is
80
- * one-shot.
73
+ * Parse a `ForwardableEmailMessage` into structured fields with postal-mime,
74
+ * loaded on first use. A native Cloudflare message's `raw` stream is
75
+ * one-shot, so parse it once.
81
76
  */
82
77
  async function parseEmail(message) {
83
78
  if (message.rawSize > MAX_INBOUND_BYTES) throw new ParseEmailError("INBOUND_TOO_LARGE", `parseEmail: message size ${message.rawSize} bytes exceeds maximum of ${MAX_INBOUND_BYTES} bytes.`);
@@ -91,14 +86,7 @@ async function parseEmail(message) {
91
86
  }
92
87
  }
93
88
  const proxyRawCache = /* @__PURE__ */ new WeakMap();
94
- /**
95
- * Remove the platform-injected `<slug>+` prefix from a recipient address.
96
- * The platform's shared sender (e.g. `mail.example.com`) rewrites every recipient to
97
- * `<slug>+<tag>@<domain>`; user handlers expect `<tag>@<domain>`. If the
98
- * slug is unknown, missing, or doesn't match the local-part prefix, the
99
- * address is returned unchanged so callers without slug context (e.g. the
100
- * test harness when no slug is set) don't accidentally mangle the address.
101
- */
89
+ /** Remove a leading `<slug>+` (case-insensitive) from the local part. */
102
90
  function stripSlugFromAddress(address, slug) {
103
91
  if (!slug) return address;
104
92
  const atIdx = address.indexOf("@");
@@ -119,21 +107,16 @@ function queueFull() {
119
107
  return new MimeError("MIME_ERROR", `email: handler queued more than ${MAX_ACTIONS} actions for one message.`);
120
108
  }
121
109
  function addressTooLong(field, length) {
122
- return new MimeError(field === "from" ? "INVALID_FROM" : "INVALID_TO", `${field} address is ${length} characters, over the ${MAX_ACTION_ADDRESS_LENGTH}-character limit.`);
110
+ return new MimeError(field === "from" ? "INVALID_FROM" : "INVALID_TO", `${field} address is ${length} characters, over the 320-character limit.`);
123
111
  }
124
112
  function invalidForwardHeaders(cause) {
125
113
  const detail = cause instanceof Error ? cause.message.slice(0, 320) : "not a valid header set";
126
114
  return new MimeError("MIME_ERROR", `forward: invalid header — ${detail}`);
127
115
  }
128
116
  /**
129
- * The router's `forwardHeadersWithinBounds`, as a throw. It runs on the
130
- * record about to be recorded — the very object the router receives, so the
131
- * count is the router's count: a `Headers` folded its duplicate names before
132
- * it got here, and a record keeps `X-A` and `x-a` as two, both there and
133
- * here. Runs after the `new Headers()` validity check, so every name is a
134
- * token and every value is header-safe; what is left is size. The router
135
- * drops the WHOLE list on any of these — a handler that passed here and
136
- * failed there deployed as one whose managed delivery performed no actions.
117
+ * The router's `forwardHeadersWithinBounds`, as a throw: the router drops the
118
+ * whole action list on a violation, so refuse it at the handler's own call.
119
+ * Counts the record as stored (a `Headers` has already folded duplicates).
137
120
  */
138
121
  function assertForwardHeadersWithinBounds(headers) {
139
122
  const names = Object.keys(headers);
@@ -146,25 +129,9 @@ function assertForwardHeadersWithinBounds(headers) {
146
129
  }
147
130
  }
148
131
  /**
149
- * The router's rule for a reject reason (`validateActions` in
150
- * `email-router.ts`: `sanitize(raw, MAX_REJECT_REASON_LENGTH)`, and
151
- * `'rejected by handler'` for an empty one), applied when the reason is
152
- * RECORDED so the native replay carries the string the managed one does.
153
- *
154
- * The reason goes into the SMTP reply to the connecting client, and a
155
- * handler may build it from the inbound message: a remote sender's CRLF is
156
- * then a line injected into that reply, and a multi-megabyte reason is a
157
- * transient-heap amplifier. The router already refuses both; normalizing at
158
- * record time covers the native `setReject()` replay on your own account
159
- * too. NORMALIZED rather than refused, unlike the forward bounds
160
- * above: a reject is the handler's terminal decision, and throwing out of
161
- * it would drop that decision and bounce the message as a dispatch error
162
- * (see the `MAX_ACTIONS` note in `setReject`). Slice FIRST, then replace: a
163
- * global replace materializes ~66 bytes per match, so the slice is what
164
- * bounds the work (see `prefixReplySubject`). The result can be SHORTER
165
- * than the cap: a run of controls inside the window collapses to one space
166
- * and the window is not refilled from beyond it — the router's own trade,
167
- * and it is DSN text.
132
+ * The router's reject-reason rule, applied at record time so native replay
133
+ * sends the same string. Normalized rather than refused, since a throw would
134
+ * drop the reject; slice before replace to bound the work.
168
135
  */
169
136
  function normalizeRejectReason(reason) {
170
137
  const raw = typeof reason === "string" ? reason : "";
@@ -178,14 +145,7 @@ async function readStreamToBytes(stream, limit = Infinity, onOverflow = replyToo
178
145
  const deadline = Date.now() + EMAIL_STREAM_DEADLINE_MS;
179
146
  try {
180
147
  for (;;) {
181
- const remaining = deadline - Date.now();
182
- if (remaining <= 0) throw new MimeError("MIME_ERROR", "email stream timed out");
183
- let timer;
184
- const { value, done } = await Promise.race([reader.read(), new Promise((_, reject) => {
185
- timer = setTimeout(() => reject(new MimeError("MIME_ERROR", "email stream timed out")), remaining);
186
- })]).finally(() => {
187
- if (timer !== void 0) clearTimeout(timer);
188
- });
148
+ const { value, done } = await withTimeout(deadline - Date.now(), () => reader.read(), () => new MimeError("MIME_ERROR", "email stream timed out"));
189
149
  if (done) break;
190
150
  total += value.byteLength;
191
151
  if (total > limit) throw onOverflow(total);
@@ -214,23 +174,10 @@ function bytesToReadableStream(bytes) {
214
174
  } });
215
175
  }
216
176
  /**
217
- * Build a proxy `ForwardableEmailMessage` from an envelope. The proxy's
218
- * `setReject` / `forward` / `reply` methods don't dispatch directly — they
219
- * record `EmailAction` entries that the router (which holds the real
220
- * message) enacts after the handler returns.
221
- *
222
- * `reply()` accepts a duck-typed `{ from, to, raw }` with `raw` a
223
- * `Uint8Array` or `ReadableStream` — what `replyEmail()` passes. It does NOT
224
- * accept a native `EmailMessage` from `cloudflare:email`: that class exposes
225
- * only `from` and `to` (workers-types declares nothing else, and the body
226
- * has no public accessor), so its bytes cannot be recorded here, and nothing
227
- * could encode them for the gateway. The reply MIME bytes are
228
- * buffered before being recorded so the action is fully self-contained.
229
- *
230
- * When `opts.slug` is provided, `message.to` is rewritten to remove the
231
- * platform-injected `<slug>+` prefix so handlers see `<tag>@<domain>`
232
- * instead of `<slug>+<tag>@<domain>`. The original wire-form recipient is
233
- * preserved on a non-enumerable `__voidPlatformTo` property.
177
+ * Build the message a handler sees from an envelope. `setReject`, `forward`
178
+ * and `reply` record `EmailAction`s instead of dispatching; the caller enacts
179
+ * them after the handler returns. `reply()` takes `{ from, to, raw }`, which
180
+ * `replyEmail()` passes: a native `EmailMessage` has no readable body.
234
181
  */
235
182
  function createMessageProxy(envelope, opts = {}) {
236
183
  const actions = [];
@@ -309,7 +256,7 @@ function createMessageProxy(envelope, opts = {}) {
309
256
  return;
310
257
  }
311
258
  assertQueueHasRoom();
312
- if (to.length > MAX_ACTION_ADDRESS_LENGTH) throw addressTooLong("to", to.length);
259
+ if (to.length > 320) throw addressTooLong("to", to.length);
313
260
  validateAddressParts("to", to);
314
261
  let headersObj;
315
262
  if (fwdHeaders instanceof Headers) headersObj = Object.fromEntries(fwdHeaders.entries());
@@ -336,8 +283,8 @@ function createMessageProxy(envelope, opts = {}) {
336
283
  return;
337
284
  }
338
285
  assertQueueHasRoom();
339
- if (reply.from.length > MAX_ACTION_ADDRESS_LENGTH) throw addressTooLong("from", reply.from.length);
340
- if (reply.to.length > MAX_ACTION_ADDRESS_LENGTH) throw addressTooLong("to", reply.to.length);
286
+ if (reply.from.length > 320) throw addressTooLong("from", reply.from.length);
287
+ if (reply.to.length > 320) throw addressTooLong("to", reply.to.length);
341
288
  validateAddressParts("from", reply.from);
342
289
  validateAddressParts("to", reply.to);
343
290
  pendingReplies++;
@@ -402,11 +349,8 @@ function createMessageProxy(envelope, opts = {}) {
402
349
  };
403
350
  }
404
351
  /**
405
- * Whether `Name: value` can be emitted without breaking RFC 5322 §2.1.1.
406
- *
407
- * Folding only happens at whitespace (§3.2.2), so the widest unbreakable run
408
- * is what decides it — a `References` chain of ordinary ids folds fine however
409
- * long, while one oversized id inside it does not.
352
+ * Whether `Name: value` fits RFC 5322's 998-octet line. Folding happens only
353
+ * at SP or HTAB, so the widest unbroken run decides.
410
354
  */
411
355
  function fitsHeaderLine(name, value) {
412
356
  if (!value) return false;
@@ -429,36 +373,11 @@ function fitsHeaderLine(name, value) {
429
373
  return true;
430
374
  }
431
375
  /**
432
- * Whether `value` carries a C0 control other than HTAB, or DEL. The
433
- * sibling of `fitsHeaderLine` for the other way a remote-controlled id can
434
- * be unrepresentable: a threading value is emitted verbatim, so a control
435
- * inside it would reach the reply's `In-Reply-To` / `References` line raw —
436
- * `\x01` and DEL pass a WHATWG `Headers`, which refuses only CR, LF and
437
- * NUL — and an RFC 5322 §3.6.4 `msg-id` is `dot-atom-text`, which admits no
438
- * control at all. HTAB is not one here: it is the whitespace that separates
439
- * ids (§3.2.2 FWS), the same break `fitsHeaderLine` and `replyReferences`
440
- * cut at. One pass, no allocation, so it costs nothing a hostile header can
441
- * multiply; never a throw, for the same reason as the line guard.
442
- */
443
- function hasControl(value) {
444
- for (let i = 0; i < value.length; i++) {
445
- const c = value.charCodeAt(i);
446
- if (c < 32 && c !== 9 || c === 127) return true;
447
- }
448
- return false;
449
- }
450
- /**
451
- * `chain` without any id that `hasControl` refuses, the rest in their order
452
- * and joined by single spaces; the chain itself when there is nothing to
453
- * drop, without allocating. Only ONE id is lost — the others still thread —
454
- * whereas an id no line can carry drops the whole chain for the parent's id
455
- * (`replyReferences`), because that guard is about the rendered line and
456
- * this one is about one token. Called only on a chain already cut to
457
- * `MAX_REPLY_REFERENCES_CHARS`, so the per-id slices in the rare bad case
458
- * are bounded by that budget, not by the header a remote sender delivered.
376
+ * `chain` without the ids that hold a control character, joined by single
377
+ * spaces. Called only on a chain already cut to `MAX_REPLY_REFERENCES_CHARS`.
459
378
  */
460
379
  function dropControlIds(chain) {
461
- if (!hasControl(chain)) return chain;
380
+ if (indexOfControl(chain) === -1) return chain;
462
381
  const kept = [];
463
382
  let start = -1;
464
383
  let tainted = false;
@@ -476,21 +395,9 @@ function dropControlIds(chain) {
476
395
  return kept.join(" ");
477
396
  }
478
397
  /**
479
- * Longest decoded inbound `Subject` the default reply subject is built from;
480
- * anything longer falls back to a bare `Re:`.
481
- *
482
- * RFC 5322 §2.1.1 caps a header LINE at 998 octets, and only folding lets a
483
- * header run past it — so a subject is something that fits on a line or
484
- * two. Real ones are tens to hundreds of characters; the longest automated
485
- * ones (a ticket title under a stack of list tags) reach a few hundred, and
486
- * Exchange rejects past 255. Four thousand keeps every one of those with an
487
- * order of magnitude to spare and refuses the shape that is only a subject
488
- * in name. What the bound buys is proportional cost: the control-character
489
- * replacements below cost 66 bytes of heap per match, so at this size they
490
- * cost at most 135 KB, and the reply's own `Subject` line is at most ~20 KB
491
- * — 4096 code units x 3 UTF-8 octets, base64'd in 45-octet encoded-words
492
- * with their framing — against a `MAX_MESSAGE_BYTES` of 5 MiB, so the
493
- * subject alone can never push the reply over the limit.
398
+ * Longest decoded inbound subject the default reply subject is built from;
399
+ * longer falls back to a bare `Re:`. Real subjects are far shorter, and the
400
+ * bound keeps the control-character replacement cheap.
494
401
  */
495
402
  const MAX_REPLY_SUBJECT_CHARS = 4096;
496
403
  function prefixReplySubject(original) {
@@ -503,36 +410,15 @@ function prefixReplySubject(original) {
503
410
  return prefixed;
504
411
  }
505
412
  /**
506
- * Longest `References` value a reply carries, in UTF-16 code units — the
507
- * measure `MAX_REPLY_SUBJECT_CHARS` uses. It is checked on `length` alone,
508
- * so a chain the size of the inbound message costs one property read before
509
- * anything is scanned or sliced.
510
- *
511
- * RFC 5322 puts no limit on the field, but everything downstream does. RFC
512
- * 5537 §3.4.4 has a followup agent trim it to 998 characters, and Postfix's
513
- * `header_size_limit` discards header bytes past 100 KiB. A message-id is
514
- * tens of characters, so 8 KiB carries a chain over a hundred replies deep
515
- * with every id intact — an order of magnitude past any conversation — and
516
- * a value this size, folded and encoded, is at most ~25 KB of a 5 MiB
517
- * reply, so the chain alone can never push the reply over the limit.
518
- * Unbounded, it could: the inbound header can be the whole 10 MiB message,
519
- * and short ids pass the line guard — every id folds — yet `foldHeader`'s
520
- * continuations would put the rendered reply over `MAX_MESSAGE_BYTES`.
521
- *
522
- * Past the bound the NEWEST ids are kept, whole, and the parent's id still
523
- * ends the chain. That is what a mail client threads on: it links the reply
524
- * under any id it recognises, and the parent is also `In-Reply-To`. The
525
- * root id RFC 5537 keeps is a Netnews convention (a newsreader identifies a
526
- * thread by it); in mail it would spend the budget on an id older than
527
- * every client in the conversation.
413
+ * Longest `References` value a reply carries, in UTF-16 code units. 8 KiB
414
+ * keeps any real thread whole; past it the newest ids are kept, since mail
415
+ * clients thread on any id they recognise and the parent is `In-Reply-To`.
528
416
  */
529
417
  const MAX_REPLY_REFERENCES_CHARS = 8192;
530
418
  /**
531
- * The `References` value a reply carries, or `''` when nothing can be
532
- * threaded. In order: the whole inbound chain continued by the parent's
533
- * `messageId` when it fits `MAX_REPLY_REFERENCES_CHARS`; otherwise the
534
- * newest ids of the chain that fit, none of them split; and the parent's id
535
- * alone (which may be empty) when even those hold an id no line can carry.
419
+ * The reply's `References`, or `''`: the inbound chain plus the parent's id,
420
+ * trimmed to its newest whole ids, or the parent's id alone when an id
421
+ * cannot fit a line.
536
422
  */
537
423
  function replyReferences(originalReferences, messageId) {
538
424
  const parent = messageId ? ` ${messageId}` : "";
@@ -552,15 +438,8 @@ function replyReferences(originalReferences, messageId) {
552
438
  return fitsHeaderLine("References", chain) ? chain : messageId;
553
439
  }
554
440
  /**
555
- * Minimal RFC 2047 encoded-word decoder. Handles `=?charset?B?base64?=`
556
- * and `=?charset?Q?quoted-printable?=` segments separated by optional
557
- * whitespace. Unknown charsets pass through (best-effort UTF-8 decode);
558
- * malformed inputs return the original.
559
- *
560
- * Scope is intentionally narrow — used only for cosmetic subject
561
- * normalization in `prefixReplySubject`. Anything that needs robust
562
- * decoding (e.g. searching subject text) should use postal-mime's
563
- * parsed view via `parseEmail`.
441
+ * Minimal RFC 2047 decoder for the reply subject: B and Q encoded-words,
442
+ * unknown charsets read as UTF-8, malformed input returned unchanged.
564
443
  */
565
444
  function decodeRfc2047(value) {
566
445
  if (!value.includes("=?")) return value;
@@ -569,7 +448,7 @@ function decodeRfc2047(value) {
569
448
  let last = 0;
570
449
  for (const m of value.matchAll(/=\?([\w-]+)\?([BbQq])\?([^?]*)\?=(?:\s+(?==\?))?/g)) {
571
450
  const [match, charset, enc, payload] = m;
572
- const bytes = enc.toUpperCase() === "B" ? base64Decode(payload) : quotedPrintableDecode(payload);
451
+ const bytes = enc.toUpperCase() === "B" ? base64ToBytes(payload) : quotedPrintableDecode(payload);
573
452
  let decoder;
574
453
  try {
575
454
  decoder = new TextDecoder(charset || "utf-8", { fatal: false });
@@ -585,12 +464,6 @@ function decodeRfc2047(value) {
585
464
  return value;
586
465
  }
587
466
  }
588
- function base64Decode(b64) {
589
- const binary = atob(b64);
590
- const out = new Uint8Array(binary.length);
591
- for (let i = 0; i < binary.length; i++) out[i] = binary.charCodeAt(i);
592
- return out;
593
- }
594
467
  function quotedPrintableDecode(qp) {
595
468
  const out = new Uint8Array(qp.length);
596
469
  let kept = 0;
@@ -608,13 +481,8 @@ function quotedPrintableDecode(qp) {
608
481
  return out.subarray(0, kept);
609
482
  }
610
483
  /**
611
- * Pure helper: build the reply MIME from an inbound message + reply opts,
612
- * with `Subject: Re: …` (no double-prefix), `In-Reply-To`, and `References`
613
- * threaded from the original. Threading is best-effort (the inbound values
614
- * are remote-sender controlled): an id no header line can carry is dropped,
615
- * and a `References` chain over `MAX_REPLY_REFERENCES_CHARS` is trimmed to
616
- * its newest ids. Exposed separately so the dispatch step (`message.reply`)
617
- * can be tested without `cloudflare:email`.
484
+ * Build the reply MIME for `replyEmail`: `Re:` subject and best-effort
485
+ * `In-Reply-To` / `References` threading from the inbound message.
618
486
  */
619
487
  async function buildReplyMessage(message, opts) {
620
488
  const headers = message.headers;
@@ -625,18 +493,18 @@ async function buildReplyMessage(message, opts) {
625
493
  if (opts.from !== void 0) fromAddr = opts.from;
626
494
  else if (readRelayDomain(message) !== void 0) fromAddr = message.to;
627
495
  else {
628
- const slug = tryReadProjectSlug();
496
+ const slug = readProjectSlug();
629
497
  if (slug) {
630
- const domain = tryReadEmailDomain();
498
+ const domain = readEnvString("__VOID_EMAIL_DOMAIN");
631
499
  if (!domain) throw new Error("replyEmail: 'from' is required when __VOID_PROJECT_SLUG is set but __VOID_EMAIL_DOMAIN is not. Set `from` explicitly, or deploy via Void so the platform-injected __VOID_PROJECT_SLUG and __VOID_EMAIL_DOMAIN can default it to <slug>+noreply@<domain>.");
632
500
  fromAddr = `${slug}+noreply@${domain}`;
633
- } else if (readRawProjectSlug() !== void 0) throw new Error("replyEmail: 'from' is required — this project's slug cannot build a default reply sender (`<slug>+noreply@<domain>` must stay within the 64-octet local part, so the slug must be at most 56 characters). Set `from` explicitly.");
501
+ } else if (readEnvString("__VOID_PROJECT_SLUG") !== void 0) throw new Error("replyEmail: 'from' is required — this project's slug cannot build a default reply sender (`<slug>+noreply@<domain>` must stay within the 64-octet local part, so the slug must be at most 56 characters). Set `from` explicitly.");
634
502
  else fromAddr = message.to;
635
503
  }
636
504
  const toAddr = opts.to ?? message.from;
637
505
  const subject = opts.subject ?? prefixReplySubject(originalSubject);
638
506
  const threading = {};
639
- const messageId = fitsHeaderLine("In-Reply-To", originalMessageId) && !hasControl(originalMessageId) ? originalMessageId : "";
507
+ const messageId = fitsHeaderLine("In-Reply-To", originalMessageId) && indexOfControl(originalMessageId) === -1 ? originalMessageId : "";
640
508
  if (messageId) threading.inReplyTo = messageId;
641
509
  const references = replyReferences(originalReferences, messageId);
642
510
  if (references) threading.references = references;
@@ -686,50 +554,31 @@ function isForwardableEmailMessage(value) {
686
554
  const m = value;
687
555
  return typeof m.setReject === "function" && typeof m.forward === "function" && typeof m.reply === "function";
688
556
  }
689
- const INBOUND_PROVIDER_DEADLINE_MS = 3e4;
690
- const INBOUND_ACTION_BATCH_DEADLINE_MS = 6e4;
691
- function createInboundProviderDeadline() {
692
- const deadline = Date.now() + INBOUND_ACTION_BATCH_DEADLINE_MS;
693
- return { async run(submit) {
694
- const remaining = Math.min(INBOUND_PROVIDER_DEADLINE_MS, deadline - Date.now());
695
- if (remaining <= 0) throw new Error("email action batch deadline elapsed before provider submission");
696
- const work = submit();
697
- let timer;
698
- try {
699
- return await Promise.race([work, new Promise((_, reject) => {
700
- timer = setTimeout(() => reject(/* @__PURE__ */ new Error("email action provider timed out; outcome unknown, do not retry automatically")), remaining);
701
- })]);
702
- } finally {
703
- if (timer !== void 0) clearTimeout(timer);
704
- }
705
- } };
706
- }
707
557
  /**
708
- * Replay recorded `EmailAction`s on a real `ForwardableEmailMessage`, in
709
- * order. The proxy already made `setReject` terminal (earlier forward/reply
710
- * entries are purged, later ones dropped), so a reject is never followed by
711
- * anything. `reply` needs a genuine `EmailMessage` — Cloudflare rejects a
712
- * duck-typed object — so `cloudflare:email` is loaded here, and only when
713
- * a reply was recorded.
714
- *
715
- * The proxy already validated forward headers and normalized reject reasons.
716
- * Provider refusals still propagate to the native event caller.
558
+ * Replay recorded actions on a native message, in order. The proxy already
559
+ * made `setReject` terminal and validated the rest. `reply` needs a real
560
+ * `EmailMessage`, so `cloudflare:email` loads only when one was recorded.
717
561
  */
718
562
  async function enactEmailActions(message, actions) {
719
- const providerDeadline = createInboundProviderDeadline();
563
+ const deadline = Date.now() + INBOUND_ACTION_BATCH_DEADLINE_MS;
564
+ const submit = async (run) => {
565
+ const remaining = Math.min(INBOUND_PROVIDER_DEADLINE_MS, deadline - Date.now());
566
+ if (remaining <= 0) throw new Error("email action batch deadline elapsed before provider submission");
567
+ return withTimeout(remaining, run, () => /* @__PURE__ */ new Error("email action provider timed out; outcome unknown, do not retry automatically"));
568
+ };
720
569
  for (const action of actions) switch (action.type) {
721
570
  case "reject":
722
571
  message.setReject(action.reason);
723
572
  break;
724
573
  case "forward":
725
- await providerDeadline.run(() => message.forward(action.to, action.headers ? new Headers(action.headers) : void 0));
574
+ await submit(() => message.forward(action.to, action.headers ? new Headers(action.headers) : void 0));
726
575
  break;
727
576
  case "reply": {
728
577
  const { EmailMessage } = await import("cloudflare:email");
729
- await providerDeadline.run(() => message.reply(new EmailMessage(action.from, action.to, bytesToReadableStream(action.raw))));
578
+ await submit(() => message.reply(new EmailMessage(action.from, action.to, bytesToReadableStream(action.raw))));
730
579
  break;
731
580
  }
732
581
  }
733
582
  }
734
583
  //#endregion
735
- export { createMessageProxy as a, isForwardableEmailMessage as c, bytesToReadableStream as i, parseEmail as l, MAX_INBOUND_HEADERS as n, defineEmail as o, ParseEmailError as r, enactEmailActions as s, MAX_INBOUND_BYTES as t, replyEmail as u };
584
+ export { createMessageProxy as a, isForwardableEmailMessage as c, readProjectSlug as d, replyEmail as f, bytesToReadableStream as i, parseEmail as l, MAX_INBOUND_HEADERS as n, defineEmail as o, tryGetRawRuntimeEnv as p, ParseEmailError as r, enactEmailActions as s, MAX_INBOUND_BYTES as t, readEnvString as u };
@@ -1,3 +1,4 @@
1
+ import { EmailWireAction } from "@void/platform/email-protocol";
1
2
  import { Email } from "postal-mime";
2
3
  //#region src/runtime/email/types.d.ts
3
4
  /**
@@ -19,12 +20,11 @@ interface Attachment {
19
20
  }
20
21
  interface SendEmailOptions {
21
22
  /**
22
- * Sender envelope address. Optional — when omitted, the framework
23
- * substitutes `<__VOID_PROJECT_SLUG>+noreply@<__VOID_EMAIL_DOMAIN>`
24
- * from the two platform-injected bindings (the project slug and the
25
- * mail domain configured for this environment). Outside a deployed
26
- * worker, or whenever either binding is missing, `sendEmail` returns
27
- * `INVALID_FROM` — it never falls back to a baked-in domain.
23
+ * Sender envelope address. Optional. When omitted, `void dev` and
24
+ * `void deploy --platform cloudflare` use `email.from` from void.config.ts,
25
+ * and a Void platform deploy uses `<project-slug>+noreply@<mail-domain>`.
26
+ * Without either, `sendEmail` returns `INVALID_FROM`; it never falls back
27
+ * to a baked-in domain.
28
28
  */
29
29
  from?: Address;
30
30
  to: Address | Array<Address>;
@@ -200,13 +200,9 @@ declare class ParseEmailError extends Error {
200
200
  });
201
201
  }
202
202
  /**
203
- * Parse a `ForwardableEmailMessage` into structured fields. postal-mime is
204
- * loaded lazily so workers that never call this don't bundle it.
205
- *
206
- * For proxy messages (built via `createMessageProxy`) the raw bytes are
207
- * cached on first read so subsequent `parseEmail`/`message.raw` accesses
208
- * still work. For real CF `ForwardableEmailMessage`s the raw stream is
209
- * one-shot.
203
+ * Parse a `ForwardableEmailMessage` into structured fields with postal-mime,
204
+ * loaded on first use. A native Cloudflare message's `raw` stream is
205
+ * one-shot, so parse it once.
210
206
  */
211
207
  declare function parseEmail(message: ForwardableEmailMessage): Promise<ParsedEmail>;
212
208
  /** Inbound message decoded from the authenticated gateway request. */
@@ -227,52 +223,23 @@ interface EmailEnvelope {
227
223
  viaDomain?: string;
228
224
  }
229
225
  /** Handler intents, validated and admitted by the gateway before delivery. */
230
- type EmailAction = {
231
- type: "reject";
232
- reason: string;
233
- } | {
234
- type: "forward";
235
- to: string;
236
- headers?: Record<string, string>;
237
- } | {
238
- type: "reply";
239
- from: string;
240
- to: string;
241
- raw: Uint8Array;
242
- };
226
+ type EmailAction = EmailWireAction;
243
227
  interface MessageProxy {
244
228
  message: ForwardableEmailMessage;
245
229
  getActions(): Array<EmailAction>;
246
230
  }
247
231
  interface CreateMessageProxyOptions {
248
232
  /**
249
- * Project slug stripped from the `<slug>+<tag>` recipient by the
250
- * dispatcher. When set, `message.to` is rewritten to the bare
251
- * `<tag>@<domain>` form so user handlers see clean addresses (the slug
252
- * is platform-internal). The original `<slug>+<tag>@<domain>` is
253
- * preserved on a non-enumerable `__voidPlatformTo` property for
254
- * diagnostics.
233
+ * Project slug the platform prefixes recipients with
234
+ * (`<slug>+<tag>@<domain>`). When set, `message.to` drops the `<slug>+`.
255
235
  */
256
236
  slug?: string;
257
237
  }
258
238
  /**
259
- * Build a proxy `ForwardableEmailMessage` from an envelope. The proxy's
260
- * `setReject` / `forward` / `reply` methods don't dispatch directly — they
261
- * record `EmailAction` entries that the router (which holds the real
262
- * message) enacts after the handler returns.
263
- *
264
- * `reply()` accepts a duck-typed `{ from, to, raw }` with `raw` a
265
- * `Uint8Array` or `ReadableStream` — what `replyEmail()` passes. It does NOT
266
- * accept a native `EmailMessage` from `cloudflare:email`: that class exposes
267
- * only `from` and `to` (workers-types declares nothing else, and the body
268
- * has no public accessor), so its bytes cannot be recorded here, and nothing
269
- * could encode them for the gateway. The reply MIME bytes are
270
- * buffered before being recorded so the action is fully self-contained.
271
- *
272
- * When `opts.slug` is provided, `message.to` is rewritten to remove the
273
- * platform-injected `<slug>+` prefix so handlers see `<tag>@<domain>`
274
- * instead of `<slug>+<tag>@<domain>`. The original wire-form recipient is
275
- * preserved on a non-enumerable `__voidPlatformTo` property.
239
+ * Build the message a handler sees from an envelope. `setReject`, `forward`
240
+ * and `reply` record `EmailAction`s instead of dispatching; the caller enacts
241
+ * them after the handler returns. `reply()` takes `{ from, to, raw }`, which
242
+ * `replyEmail()` passes: a native `EmailMessage` has no readable body.
276
243
  */
277
244
  declare function createMessageProxy(envelope: EmailEnvelope, opts?: CreateMessageProxyOptions): MessageProxy;
278
245
  interface ReplyEmailOptions {
@@ -334,15 +301,9 @@ declare function replyEmail(message: ForwardableEmailMessage, opts: ReplyEmailOp
334
301
  */
335
302
  declare function isForwardableEmailMessage(value: unknown): value is ForwardableEmailMessage;
336
303
  /**
337
- * Replay recorded `EmailAction`s on a real `ForwardableEmailMessage`, in
338
- * order. The proxy already made `setReject` terminal (earlier forward/reply
339
- * entries are purged, later ones dropped), so a reject is never followed by
340
- * anything. `reply` needs a genuine `EmailMessage` — Cloudflare rejects a
341
- * duck-typed object — so `cloudflare:email` is loaded here, and only when
342
- * a reply was recorded.
343
- *
344
- * The proxy already validated forward headers and normalized reject reasons.
345
- * Provider refusals still propagate to the native event caller.
304
+ * Replay recorded actions on a native message, in order. The proxy already
305
+ * made `setReject` terminal and validated the rest. `reply` needs a real
306
+ * `EmailMessage`, so `cloudflare:email` loads only when one was recorded.
346
307
  */
347
308
  declare function enactEmailActions(message: ForwardableEmailMessage, actions: ReadonlyArray<EmailAction>): Promise<void>;
348
309
  //#endregion
package/dist/index.d.mts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { n as HeadDescriptor } from "./head-C8K_iGe6.mjs";
2
2
  import { r as AuthUser } from "./auth-DkcFflXV.mjs";
3
- import { C as defer, E as ValidatorSlots, S as InferProps, T as HandlerInput, _ as defineQueue, a as CloudEnv, b as Deferred, c as QueueRetryOptions, d as TypedQueueHandler, f as VoidAssetRewriteError, g as defineMiddleware, h as defineHead, i as CloudContextVariables, l as RenderAssetTags, m as defineHandler, o as QueueBatch, p as basicAuth, r as CloudContext, s as QueueMessage, t as BasicAuthOptions, u as TypedHandler, v as defineRender, x as DeferredState, y as defineScheduled } from "./handler-CNAwjRcW.mjs";
3
+ import { C as defer, E as ValidatorSlots, S as InferProps, T as HandlerInput, _ as defineQueue, a as CloudEnv, b as Deferred, c as QueueRetryOptions, d as TypedQueueHandler, f as VoidAssetRewriteError, g as defineMiddleware, h as defineHead, i as CloudContextVariables, l as RenderAssetTags, m as defineHandler, o as QueueBatch, p as basicAuth, r as CloudContext, s as QueueMessage, t as BasicAuthOptions, u as TypedHandler, v as defineRender, x as DeferredState, y as defineScheduled } from "./handler-_PqY82xe.mjs";
4
4
  import { t as QueueMap } from "./queues-BWKt1Xo4.mjs";
5
5
  import { PluginConfig } from "@cloudflare/vite-plugin";
6
6
  import { Plugin } from "vite";
@@ -49,23 +49,7 @@ export declare function shouldBindWorkersAi(command: string, needsAI: boolean, r
49
49
  export declare function resolveWorkersAiBindingName(resolvedAi: unknown, configuredName?: string): string;
50
50
  //#endregion
51
51
  //#region src/index.d.ts
52
- /**
53
- * Void plugin — the main entry point.
54
- *
55
- * Composes:
56
- * 1. Routing plugin (file-based routing from routes/ and middleware/)
57
- * 2. Migration plugin (auto-apply .sql migrations on dev startup)
58
- * 3. @cloudflare/vite-plugin (workerd runtime, HMR, builds)
59
- *
60
- * Binding inference runs synchronously here so results are available
61
- * before the Cloudflare plugin initializes.
62
- *
63
- * The Cloudflare plugin reads Void's generated config and provides it to our
64
- * config function. Bindings already defined there (with real IDs for
65
- * production deployment) are preserved — we only add inferred bindings
66
- * that are missing. This allows `vite build && wrangler deploy` to work
67
- * for deploying directly to Cloudflare without the Void platform.
68
- */
52
+ /** Returns the Vite plugins that build and serve a Void app for its configured target. */
69
53
  export declare function voidPlugin(options?: {
70
54
  persistTo?: string;
71
55
  auxiliaryWorkers?: PluginConfig["auxiliaryWorkers"];