void 0.26.1 → 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 (287) hide show
  1. package/README.md +3 -1
  2. package/dist/{account-cmd-CfUXh_nU.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-B5_tZLxT.mjs → auth-B6iOCjKI.mjs} +23 -56
  8. package/dist/{auth-link-D5RmKnzh.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-Bap-pvbn.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-B58c8iS8.mjs → build-cmd-Cr3FJxv0.mjs} +5 -5
  16. package/dist/{cache-Bo52trKF.mjs → cache-D0Tt28cn.mjs} +5 -5
  17. package/dist/{cancel-deploy-BZNz3Q26.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-ngGqZpHZ.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 +46 -14
  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-C2Prx_Bi.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-X0MUA1gk.mjs → connect-nukQSoEO.mjs} +8 -8
  45. package/dist/{create-project-DxiyW6iX.mjs → create-project-D4APeBwX.mjs} +7 -7
  46. package/dist/{create-project-iwkbqiBU.mjs → create-project-DL7YXpjj.mjs} +1 -1
  47. package/dist/{db-XnVMHzoV.mjs → db-27RztQLy.mjs} +173 -263
  48. package/dist/{delete-esYlMiSJ.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-CbbBWhWE.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-CpuT42g7.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-w9jOyGZn.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-D_FsOFxq.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-CVFBTmBx.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-Bw-fRKGp.mjs → init-ZWOJvc-Z.mjs} +179 -388
  91. package/dist/isr-config-DPjXM8J2.mjs +194 -0
  92. package/dist/{link-DlPG8iX3.mjs → link-UEc7bnF4.mjs} +8 -8
  93. package/dist/{list-2GN7_ueV.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-D-Q4xw3Q.mjs → login-CZ2Cqa-D.mjs} +11 -11
  99. package/dist/login-DhK7o1oJ.mjs +2 -0
  100. package/dist/{logs-rd8J-OFh.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-BNsW5gfp.mjs → operator-args-UnE8Y2eK.mjs} +27 -26
  108. package/dist/{operator-auth-AzVLbrr3.mjs → operator-auth-Cr2zCc-J.mjs} +2 -2
  109. package/dist/{operator-client-BQtzyG-g.mjs → operator-client-C-ROjk1I.mjs} +4 -4
  110. package/dist/{operator-cmd-B6f6Cg9Z.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-BoZkWQnJ.mjs → platform-args-C6Mb_I3a.mjs} +34 -58
  123. package/dist/platform-args-Cm7x-fot.mjs +2 -0
  124. package/dist/{platform-auth-config-n603OANg.mjs → platform-auth-config-CJmNkFT2.mjs} +10 -11
  125. package/dist/{platform-auth-protection-zxDr0hWW.mjs → platform-auth-protection-D5wvsI-Y.mjs} +36 -26
  126. package/dist/{platform-auth-recovery-tw9lgtgE.mjs → platform-auth-recovery-D_0I3n-1.mjs} +8 -9
  127. package/dist/{platform-cmd-C00YM14r.mjs → platform-cmd-Cuj4oUVo.mjs} +1 -1
  128. package/dist/{platform-cmd-B8-bCb7t.mjs → platform-cmd-DxxZO6e5.mjs} +17 -16
  129. package/dist/{platform-discovery-BC0HCKYt.mjs → platform-discovery-CHhNs8Nn.mjs} +1 -1
  130. package/dist/{platform-domain-p0kobLV8.mjs → platform-domain-zLXnW1G_.mjs} +5 -5
  131. package/dist/{platform-lifecycle-D_QEY32D.mjs → platform-lifecycle-DOW-wLfx.mjs} +1398 -2043
  132. package/dist/{platform-lifecycle-vFqtNPPa.mjs → platform-lifecycle-_gfnjUBr.mjs} +1 -1
  133. package/dist/{platform-management-oi-SvI3f.mjs → platform-management-CYrLvTGH.mjs} +1 -1
  134. package/dist/{platform-management-BdYblvvE.mjs → platform-management-t7HKy4-U.mjs} +632 -124
  135. package/dist/{platform-plans-config-CjiFv5J4.mjs → platform-plans-config-CNH6zbPX.mjs} +15 -11
  136. package/dist/{platform-recovery-PvNS9Nl2.mjs → platform-recovery-DeucI7A9.mjs} +6 -9
  137. package/dist/{platform-registry-P387v42A.mjs → platform-registry-B9mWX9LO.mjs} +18 -19
  138. package/dist/{platform-setup-DVe42Ws7.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-ti8_yTcA.mjs → project-cmd-Dq75AXzy.mjs} +19 -19
  148. package/dist/{project-paths-GgcMozYz.mjs → project-paths-DMvEeSau.mjs} +9 -14
  149. package/dist/{project-DQstYTxO.mjs → project-rqDnVsJN.mjs} +8 -4
  150. package/dist/{project-team-CDPE1Tsg.mjs → project-team-B3_QcStG.mjs} +6 -6
  151. package/dist/{project-token-CkZ1cN0Z.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-DdjLR61k.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-DFAqyYy8.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-BKYXBduI.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-BAt2KMmO.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/deployment.md +2 -2
  236. package/docs/guide/durable-state.md +24 -0
  237. package/docs/guide/platform/administration/access.md +5 -1
  238. package/docs/guide/platform/administration/connected-apps.md +55 -0
  239. package/docs/guide/platform/installation/credentials.md +3 -1
  240. package/docs/guide/platform/installation/first-deployment.md +1 -1
  241. package/docs/guide/project-collaboration.md +1 -1
  242. package/docs/guide/quickstart.md +2 -0
  243. package/docs/guide/sandboxes.md +2 -0
  244. package/docs/reference/api/deploy.md +23 -0
  245. package/docs/reference/api/pages.md +2 -0
  246. package/docs/reference/api.md +2 -1
  247. package/docs/reference/cli/auth.md +1 -1
  248. package/docs/reference/cli/database.md +9 -3
  249. package/docs/reference/cli/deploy.md +1 -1
  250. package/docs/reference/cli/platform-installation.md +1 -1
  251. package/docs/reference/cli/setup.md +2 -0
  252. package/package.json +14 -17
  253. package/skills/void/SKILL.md +4 -2
  254. package/dist/auth-BgX2qYSY.mjs +0 -2
  255. package/dist/cf-build-output-H9a97vME.mjs +0 -2
  256. package/dist/client-By4JjMw_.mjs +0 -2
  257. package/dist/collect-DLyFDiKW.mjs +0 -2
  258. package/dist/config-5r-YpMC-.mjs +0 -2
  259. package/dist/config-B_ggY-IO.mjs +0 -89
  260. package/dist/config-BtSFvXZx.mjs +0 -2
  261. package/dist/config-write-AHGesphx.mjs +0 -61
  262. package/dist/deploy-BsEvnlJl.mjs +0 -10455
  263. package/dist/deploy-C1d-YTfp.mjs +0 -2
  264. package/dist/dev-inbox-CK-UuPob.mjs +0 -297
  265. package/dist/discover-EDUf6JJw.mjs +0 -2
  266. package/dist/dist-_UUlL6bg.mjs +0 -2
  267. package/dist/env-validation-Dxdx_5wo.mjs +0 -951
  268. package/dist/gen-dA9hW7AV.mjs +0 -2
  269. package/dist/head-client-DzmJGN4C.mjs +0 -90
  270. package/dist/help-DzKUrQvk.mjs +0 -2
  271. package/dist/login-Dc-wuTDq.mjs +0 -2
  272. package/dist/migrate-BHp07yJE.mjs +0 -2
  273. package/dist/operator-cmd-Cwn50lOV.mjs +0 -2
  274. package/dist/pages/head-client.d.mts +0 -13
  275. package/dist/pages/head-client.mjs +0 -2
  276. package/dist/platform-args-DYgITk0D.mjs +0 -2
  277. package/dist/prepare-DRUV-g3X.mjs +0 -2
  278. package/dist/project-BiaPQ7ur.mjs +0 -2
  279. package/dist/provision-Wu9ZBk9L.mjs +0 -2
  280. package/dist/resolve-project-BIeYs9Cw.mjs +0 -2
  281. package/dist/resolve-project-CP8rZs_p.mjs +0 -28
  282. package/dist/runner-mysql-CkFqZ6CE.mjs +0 -2
  283. package/dist/runner-pg-BGYRFdRp.mjs +0 -2
  284. package/dist/runtime/env-helpers.d.mts +0 -2
  285. package/dist/runtime/env-helpers.mjs +0 -2
  286. package/dist/validate-BJr9LfXy.mjs +0 -2
  287. package/dist/yarn-pnp-CUX_iTPA.mjs +0 -188
@@ -1,3 +1,4 @@
1
+ import { n as bytesToBase64 } from "./base64-DVrOndmI.mjs";
1
2
  import { validate } from "email-validator";
2
3
  //#region src/runtime/email/mime.ts
3
4
  /**
@@ -10,29 +11,10 @@ import { validate } from "email-validator";
10
11
  /** Encoded outbound MIME ceiling, separate from the 10 MiB inbound limit. */
11
12
  const MAX_MESSAGE_BYTES = 5242880;
12
13
  /**
13
- * Upper bound on the TOTAL attachment bytes `normalizeEmail` will materialize.
14
- *
15
- * Base64 expands by `ceil(n / 3) * 4`, so an attachment set larger than three
16
- * quarters of `MAX_MESSAGE_BYTES` cannot fit in a message that passes the
17
- * check at the end of `buildMime` no matter how small everything else is.
18
- * `buildMime` remains the authority on the final size — this bound only stops
19
- * `normalizeEmail` from materializing, and then expanding, bytes already known
20
- * not to fit.
21
- *
22
- * It has to be charged here because that final check comes far too late to
23
- * help. Measured peak live memory is about 10x the attachment bytes (8 MiB in
24
- * gives 83 MiB live) once the normalized copy, the base64 binary string, the
25
- * 76-column slices, the joins, `rawText` and its `TextEncoder.encode` are all
26
- * resident at once. Against a 128 MB isolate ceiling, a set over roughly
27
- * 12 MiB terminates the isolate rather than returning the `MIME_ERROR` the
28
- * docs promise for an oversize payload.
29
- *
30
- * This is a developer-experience guardrail, NOT the security boundary.
31
- * Attachments come from the app's own code, never from a remote sender, and
32
- * the platform proxy already caps the base64 length before decoding and the
33
- * raw length after. What this buys is a precise, catchable failure at the call
34
- * that went wrong, instead of a dead isolate with nothing a caller could act
35
- * on.
14
+ * Total attachment bytes `normalizeEmail` will materialize: base64 of more
15
+ * than 3/4 of `MAX_MESSAGE_BYTES` cannot fit. Charged before each copy so an
16
+ * oversize set fails with `MIME_ERROR` instead of exhausting the isolate;
17
+ * `buildMime`'s final size check stays authoritative.
36
18
  */
37
19
  const MAX_ATTACHMENT_BYTES_TOTAL = Math.floor(MAX_MESSAGE_BYTES * 3 / 4);
38
20
  /** Maximum serialized size of app-defined top-level MIME fields. */
@@ -47,33 +29,24 @@ function rejectCRLF(field, value) {
47
29
  }
48
30
  }
49
31
  /**
50
- * Refuse any other C0 control or DEL in a value that is rendered VERBATIM
51
- * into a header — an attachment's filename, media type and Content-ID.
52
- * `rejectCRLF` is enough for a value `encodeWord` renders (the subject, a
53
- * custom header value, a display name): anything outside printable ASCII
54
- * sends the whole value into base64, so a control never reaches the wire.
55
- * These three go through `quoteParam` or straight into the line, so a
56
- * control would reach the wire for the receiving MTA to refuse.
57
- *
58
- * RFC 5322 §3.2.4 `qtext` is printable US-ASCII less `"` and `\`; a
59
- * control inside a quoted-string is `obs-qtext`, which §4 says MUST NOT be
60
- * generated. HTAB is deliberately NOT refused: `quoted-string` is
61
- * `DQUOTE *([FWS] qcontent) [FWS] DQUOTE` and `FWS` is built from `WSP`
62
- * (SP / HTAB), so a tab between characters is folding white space exactly
63
- * as a space is — and `obs-NO-WS-CTL`, the RFC's own list of the controls
64
- * that used to be `qtext`, leaves %d9 out. The same set is illegal in an
65
- * RFC 2045 §5.1 `token` (no CTLs) and an RFC 5322 §3.6.4 `msg-id`
66
- * (`dot-atom-text`), so one rule serves the media type and the Content-ID.
67
- *
68
- * The message names the code point and never echoes the value, as
69
- * `validateAddressParts` does. Runs AFTER the filename's length bound, so
70
- * the scan is over a value already known to fit a line.
32
+ * Index of the first C0 control other than HTAB, or DEL; -1 when there is
33
+ * none. HTAB is folding whitespace (RFC 5322 §3.2.2).
71
34
  */
72
- function rejectControls(field, value) {
35
+ function indexOfControl(value) {
73
36
  for (let i = 0; i < value.length; i++) {
74
37
  const c = value.charCodeAt(i);
75
- if (c < 32 && c !== 9 || c === 127) throw new MimeError("MIME_ERROR", `${field} contains a control character (U+${c.toString(16).toUpperCase().padStart(4, "0")}).`);
38
+ if (c < 32 && c !== 9 || c === 127) return i;
76
39
  }
40
+ return -1;
41
+ }
42
+ /**
43
+ * Refuse a control in a value rendered verbatim into a header (an
44
+ * attachment's filename, media type and Content-ID). Names the code point,
45
+ * never the value.
46
+ */
47
+ function rejectControls(field, value) {
48
+ const i = indexOfControl(value);
49
+ if (i !== -1) throw new MimeError("MIME_ERROR", `${field} contains a control character (U+${value.charCodeAt(i).toString(16).toUpperCase().padStart(4, "0")}).`);
77
50
  }
78
51
  /** RFC 2045 §5.1 `tspecials`: what a `token` may not contain besides SPACE and CTLs. */
79
52
  const TSPECIALS = "()<>@,;:\\\"/[]?=";
@@ -82,33 +55,10 @@ function isTokenChar(c) {
82
55
  return c > 32 && c < 127 && !TSPECIALS.includes(String.fromCharCode(c));
83
56
  }
84
57
  /**
85
- * Refuse an attachment media type that does not parse as RFC 2045 §5.1
86
- * `type "/" subtype *(";" parameter)`.
87
- *
88
- * `rejectControls` answers only for CTLs, and `buildAttachmentPart` writes
89
- * the value verbatim ahead of its own `; name="…"`, so an unterminated
90
- * quote such as `text/plain; x="` would swallow the builder's `name`
91
- * parameter as the value of `x`.
92
- *
93
- * The grammar is the RFC's, read as a generator: a `token` is printable
94
- * US-ASCII less SPACE and `tspecials`; a `value` is a `token` or a
95
- * quoted-string, whose content is anything but a bare `"` or `\` (the same
96
- * rule `quoteParam` renders `name="…"` by, so a caller's quoted value may
97
- * carry what the builder's own already does). Optional WSP is admitted on
98
- * either side of `;` — the RFC 822 implicit LWSP every parser accepts and
99
- * the form HTTP's `Content-Type` writes — and nowhere else: `text/ plain`,
100
- * a trailing `;`, and an RFC 822 comment are refused rather than repaired.
101
- * Two parameters are also refused on their meaning: a `name`, because the
102
- * builder appends `name="<filename>"` and RFC 6838 §4.3 makes it "an error
103
- * for a specific parameter to be specified more than once"; and by that
104
- * same sentence any attribute given twice, compared case-insensitively as
105
- * §5.1 says attributes match. Type and subtype are kept as given — matching
106
- * is case-insensitive, so `TEXT/PLAIN` is legal and renders unchanged.
107
- *
108
- * One pass, no backtracking, and the only allocation is one lower-cased
109
- * attribute per parameter for the duplicate check, which is why this runs
110
- * AFTER the value's length bound. The message names the rule and never
111
- * echoes the value.
58
+ * Refuse a media type that is not RFC 2045 §5.1 `type "/" subtype *(";"
59
+ * parameter)`: it is written verbatim before the builder's `name=`, so an
60
+ * unterminated quote would swallow it. WSP is allowed only around `;`. A
61
+ * `name` parameter or a repeated attribute is refused (RFC 6838 §4.3).
112
62
  */
113
63
  function validateMediaType(field, value) {
114
64
  const syntax = () => new MimeError("MIME_ERROR", `${field} is not a valid media type (RFC 2045 §5.1: type/subtype, then ; attribute=value parameters).`);
@@ -160,34 +110,9 @@ function isAtext(c) {
160
110
  return c >= 48 && c <= 57 || c >= 65 && c <= 90 || c >= 97 && c <= 122 || ATEXT_SYMBOLS.includes(String.fromCharCode(c));
161
111
  }
162
112
  /**
163
- * Refuse an attachment Content-ID that would not render as one RFC 5322
164
- * §3.6.4 `msg-id`.
165
- *
166
- * `rejectControls` answers only for CTLs, and `buildAttachmentPart` writes
167
- * the value verbatim — adding `<` and `>` unless the value already starts
168
- * with `<` — so a malformed id would reach the receiver and break the
169
- * `cid:` reference.
170
- *
171
- * The grammar is the RFC's, read as a generator, with two deliberate
172
- * differences. An `msg-id` is `"<" id-left "@" id-right ">"`, each side a
173
- * `dot-atom-text` (§3.2.3: `1*atext *("." 1*atext)`, so no leading,
174
- * trailing or doubled dot — the strict form; `obs-id-left`/`obs-id-right`
175
- * are §4 obsolete syntax, which MUST NOT be generated); `no-fold-literal`
176
- * (`[…]` for `id-right`) is left out. First difference: the `@` and its
177
- * right side are OPTIONAL. RFC 2392 §2 resolves a `cid:` URL by wrapping
178
- * its body in `<` `>` and matching that against `Content-ID`, so an id
179
- * without `@` — the documented `contentId: 'logo'` + `cid:logo` — is what
180
- * every client already resolves, and the domain that would make it a
181
- * proper `msg-id` adds nothing a reference could use. Second: the angle
182
- * brackets are optional too, because the builder has always added them
183
- * around a bare id; given, they must be one pair around the whole value.
184
- *
185
- * Refused, then: whitespace of any kind, a second `@`, `<` or `>` anywhere
186
- * but as that one pair, `"`, `(`, `)`, `,`, `;`, `:`, `\`, `[`, `]`,
187
- * anything non-ASCII, and the empty string.
188
- *
189
- * One pass, no allocation, which is why this runs AFTER the value's length
190
- * bound. The message names the rule and never echoes the value.
113
+ * Refuse a Content-ID that would not render as an RFC 5322 §3.6.4 `msg-id`
114
+ * of strict `dot-atom-text`. Unlike `msg-id`, the `@` part and the angle
115
+ * brackets are optional: `cid:logo` resolves against `<logo>` (RFC 2392).
191
116
  */
192
117
  function validateContentId(field, value) {
193
118
  const syntax = () => new MimeError("MIME_ERROR", `${field} is not a valid Content-ID (RFC 5322 §3.6.4 msg-id: an identifier of atext, "." and "@", optionally in one pair of angle brackets).`);
@@ -255,37 +180,10 @@ function fieldErrorCode(field) {
255
180
  return "MIME_ERROR";
256
181
  }
257
182
  /**
258
- * Validate one parsed address (and its display name, when there is one),
259
- * throwing a `MimeError` for `field` on anything undeliverable. Exported so
260
- * the inbound proxy's `forward(to)` and hand-built `reply()` refuse a bare
261
- * address by the same rule `sendEmail` applies to its `to`.
262
- *
263
- * The address rule is `email-validator`, and nothing else. It is also the
264
- * platform router's rule (`isValidEmailAddress` in the proxy's
265
- * `email-router.ts`), so there is exactly ONE address syntax in the tree:
266
- * an action the framework records is never dropped by the router for its
267
- * shape, and a test harness never captures as a success what the managed
268
- * deployment would lose.
269
- *
270
- * What it enforces: at most 254 characters in total; an ASCII dot-atom
271
- * local part of at most 64 characters (RFC 5322 §3.2.3 `atext`, dots only
272
- * between atoms — no quoted local part, no whitespace, no control, no
273
- * special); a dotted domain of ASCII labels of at most 63 characters each,
274
- * with a TLD that starts with a letter and has at least two characters; so
275
- * `user@localhost`, `x@y` and a raw IDN or SMTPUTF8 address are refused
276
- * (an IDN domain is accepted as punycode, `xn--…`). ASCII-only makes
277
- * octets and characters the same thing, so the RFC 5321 §4.5.3.1 octet
278
- * limits are the package's length checks; the 64 is also what caps the
279
- * default `<slug>+noreply@` sender (`VALID_SLUG` in `runtime/email.ts`,
280
- * `MAX_SLUG_LENGTH` = `64 - 8` in `cli/project-slug.ts` and the API). One
281
- * known quirk, pinned in the tests rather than worked around: the FIRST
282
- * character of the local part may not be a backtick, while any later one
283
- * may.
284
- *
285
- * `MAX_ADDRESS_LENGTH` still runs first, on the raw string, so the scan is
286
- * bounded before anything reads the address; the package's own 254 check
287
- * runs before its regex for the same reason. The message never echoes the
288
- * address: it may hold a control character, and naming the rule is enough.
183
+ * Validate one parsed address and optional display name, throwing a
184
+ * `MimeError` for `field`. The address rule is `email-validator`, the one
185
+ * the platform router applies, so a recorded action is never dropped for its
186
+ * shape. The message never echoes the address.
289
187
  */
290
188
  function validateAddressParts(field, email, name) {
291
189
  if (email.length > 320) throw new MimeError(fieldErrorCode(field), `${field}: address is ${email.length} characters, over the 320-character limit.`);
@@ -297,25 +195,9 @@ function validateAddressParts(field, email, name) {
297
195
  }
298
196
  }
299
197
  /**
300
- * Undo the quoted-pairs in the content of a quoted display name: `\x` →
301
- * `x` for any `x` (RFC 5322 §3.2.4 — `qtext` excludes `"` and `\`, so a
302
- * quoted-string carries either only as a quoted-pair). The parsed name is
303
- * the RAW text `formatAddress` will quote and escape again, so leaving the
304
- * pairs in place would escape them twice. Only the quoted branch
305
- * of `parseAddress` calls this; a backslash in an unquoted name is a
306
- * character like any other, as it is in the object form.
307
- *
308
- * NOT `text.replace(/\\(.)/g, '$1')`: a global-regex replacement holds one
309
- * part per match before it builds the result, about 60 bytes each, and
310
- * nothing bounds this name before it runs — the quoted-string line guard
311
- * in `validateAddressParts` needs the DECODED name, and a non-ASCII name is
312
- * never bounded at all. Measured, 10 MiB of `\"` pairs peaked at 307 MB of
313
- * heap that way and terminated a 128 MB isolate; this shape peaks at 49 MB.
314
- * Same discipline as `to7bitBody`: one counting pass, a buffer of exactly
315
- * the output size, one fill, and one chunked `codeUnitsToString`.
316
- * The common case — no backslash at all — is one scan and no allocation.
317
- * The regex that admits the text guarantees every backslash is followed by
318
- * a character, so the fill never reads past the end.
198
+ * Undo quoted-pairs (`\x` → `x`) in a quoted display name so `formatAddress`
199
+ * escapes it once. A counting pass and an exact buffer, not a global-regex
200
+ * replace, which allocates per match on an unbounded name.
319
201
  */
320
202
  function unquotePairs(text) {
321
203
  const first = text.indexOf("\\");
@@ -372,22 +254,14 @@ function countRecipients(value) {
372
254
  if (!value) return 0;
373
255
  return Array.isArray(value) ? value.length : 1;
374
256
  }
375
- /**
376
- * Keeps the `exceeds Cloudflare limit of <N> bytes` tail that `buildMime`'s
377
- * own size error already uses, so the documented shape — and any caller
378
- * matching on it — holds for both paths.
379
- */
257
+ /** Same `exceeds Cloudflare limit of <N> bytes` tail as `buildMime`'s size error. */
380
258
  function attachmentsTooLargeError(bytes) {
381
259
  return new MimeError("MIME_ERROR", `email: attachment size ${bytes} bytes exceeds Cloudflare limit of ${MAX_ATTACHMENT_BYTES_TOTAL} bytes.`);
382
260
  }
383
261
  /**
384
- * Size of `content` WITHOUT materializing it.
385
- *
386
- * A string reports its UTF-16 `length`, which is a sound LOWER bound on its
387
- * UTF-8 byte length — every code unit encodes to at least one byte — so this
388
- * can never reject a string that would have fit; the exact length is charged
389
- * after the encode. Anything else reports 0 and is left to `toBytes` to reject
390
- * by type.
262
+ * Size of `content` without materializing it. A string's `length` is a lower
263
+ * bound on its UTF-8 size; an unsupported type reports 0 for `toBytes` to
264
+ * reject.
391
265
  */
392
266
  function declaredSize(content) {
393
267
  if (content instanceof Uint8Array) return content.byteLength;
@@ -493,22 +367,13 @@ async function normalizeEmail(opts) {
493
367
  };
494
368
  }
495
369
  /**
496
- * RFC 2047 §2 caps an encoded-word at 75 characters *including* the
497
- * `=?UTF-8?B?` prefix (10) and the `?=` suffix (2). That leaves 63
498
- * characters of base64, and base64 spends 4 characters per 3 input
499
- * bytes, so 45 source bytes is the largest payload that fits — 48 would
500
- * need 64.
370
+ * RFC 2047 §2: a 75-character encoded-word less `=?UTF-8?B?` and `?=` leaves
371
+ * 63 characters of base64, so 45 source bytes.
501
372
  */
502
373
  const ENCODED_WORD_PAYLOAD_BYTES = 45;
503
374
  /**
504
- * RFC 2047 encoded-word for non-ASCII text in headers (UTF-8, base64).
505
- *
506
- * Text longer than one word's payload becomes several encoded-words
507
- * separated by a space, which `foldHeader` turns into CRLF + SPACE
508
- * wherever a line would otherwise overrun (RFC 2047 §6.2: whitespace
509
- * between adjacent encoded-words is dropped on decode either way). This
510
- * keeps each word under §2's 75-character ceiling and a long subject or
511
- * display name under RFC 5322 §2.1.1's 998-octet line limit.
375
+ * RFC 2047 B encoded-words for non-ASCII header text, space-separated so
376
+ * `foldHeader` can fold between them.
512
377
  */
513
378
  function encodeWord(text) {
514
379
  if (ASCII_PRINTABLE.test(text)) return text;
@@ -518,7 +383,7 @@ function encodeWord(text) {
518
383
  const words = [];
519
384
  const flush = () => {
520
385
  if (length > 0) {
521
- words.push(`=?UTF-8?B?${base64(pending.subarray(0, length))}?=`);
386
+ words.push(`=?UTF-8?B?${bytesToBase64(pending.subarray(0, length))}?=`);
522
387
  length = 0;
523
388
  }
524
389
  };
@@ -532,17 +397,8 @@ function encodeWord(text) {
532
397
  return words.join(" ");
533
398
  }
534
399
  /**
535
- * RFC 5322 §3.2.3, verbatim:
536
- *
537
- * specials = "(" / ")" / "<" / ">" / "[" / "]" / ":" / ";" / "@" /
538
- * "\" / "," / "." / DQUOTE
539
- *
540
- * A display name is a §3.2.5 `phrase = 1*word`, `word = atom /
541
- * quoted-string`, and `atext` is everything printable EXCEPT these, so an
542
- * ASCII name containing any of them must be rendered as one quoted-string.
543
- * The class below lists the thirteen in the RFC's order so it can be checked
544
- * against the production by eye. `.` matters: an unquoted `Dr. Smith` is
545
- * `obs-phrase` (§4.1), which §4 says MUST NOT be generated.
400
+ * RFC 5322 §3.2.3 `specials`, in the RFC's order: an ASCII display name with
401
+ * any of them must be quoted (an unquoted `Dr. Smith` is obsolete syntax).
546
402
  */
547
403
  const RFC5322_SPECIALS = /[()<>[\]:;@\\,."]/;
548
404
  function formatAddress(addr) {
@@ -555,25 +411,10 @@ function formatAddressList(addrs) {
555
411
  return addrs.map(formatAddress).join(", ");
556
412
  }
557
413
  /**
558
- * Soft-fold a long header line. Fold points, strongest first: address-list
559
- * separators (a `, ` outside any double-quoted string), then any remaining
560
- * unquoted whitespace inside a part. A naive `split(/, /)` would split
561
- * inside `"Smith, John"`, corrupting quoted display names, and folding only
562
- * between whole parts is not enough — one recipient carrying a long encoded
563
- * display name, or a `References:` run of message IDs, is a single part
564
- * that can blow past RFC 5322 §2.1.1's 998-octet hard limit on its own.
565
- *
566
- * RFC 2047 §2 limits any header line carrying an encoded-word to 76
567
- * characters; RFC 5322 §2.1.1 makes 78 a SHOULD and 998 a MUST. Folding at
568
- * 76 satisfies all three. A comma always stays on the line it terminates.
569
- * A token longer than the budget still gets its own line, which is the
570
- * best a WSP-only fold rule allows (§3.2.2 permits folding only at WSP).
571
- *
572
- * One pass, and the only thing kept per input character is the folded
573
- * output itself: each finished line is one flat string in `lines`. Any
574
- * per-token allocation (a slice array, token objects, `out +=`) costs about
575
- * 130 bytes of heap per token, so a legal 3 MB subject of one-letter words
576
- * would terminate a 128 MB isolate even though the message fits.
414
+ * Soft-fold a header at 76 columns (RFC 2047 §2): at `, ` outside quotes
415
+ * first, then at unquoted whitespace. A token longer than a line keeps its
416
+ * own line, since RFC 5322 folds only at WSP. One pass that keeps only the
417
+ * output; per-token allocation would exhaust the isolate on a large subject.
577
418
  */
578
419
  function foldHeader(name, value) {
579
420
  const line = `${name}: ${value}`;
@@ -653,40 +494,20 @@ const MAX_LINE_OCTETS = 998;
653
494
  /** ` filename="` + `"`: the shortest line a quoted filename parameter can fold onto. */
654
495
  const QUOTED_FILENAME_LINE_OVERHEAD = 12;
655
496
  /**
656
- * ` ` + `;`: the shortest line an attachment's media type can fold onto,
657
- * the whole value taken as one token. `foldHeader` would split a value
658
- * of several parameters at their spaces, so this bound is exact for the
659
- * one-token media type every attachment carries in practice and
660
- * conservative for a run of parameters that together pass the line
661
- * limit; that is accepted, because the alternative — find the fold points
662
- * first — is the scan this bound exists to run ahead of.
497
+ * ` ` + `;`: the shortest line the media type can fold onto as one token
498
+ * (conservative for several parameters).
663
499
  */
664
500
  const CONTENT_TYPE_LINE_OVERHEAD = 2;
665
- /**
666
- * `Content-ID: `: the only line an attachment's Content-ID can sit on. The
667
- * value is one token — `<id>` — so `foldHeader` cannot fold it onto a
668
- * continuation line the way it can a media type, and the field name is
669
- * part of what the id must fit beside. Exact, not conservative: the `<`
670
- * and `>` the builder adds around a bare id are charged at the call.
671
- */
501
+ /** `Content-ID: `: the id is one token and cannot fold off this line. */
672
502
  const CONTENT_ID_LINE_OVERHEAD = 12;
673
503
  /** ` "` + `"`: the shortest line a quoted display name can fold onto. */
674
504
  const QUOTED_NAME_LINE_OVERHEAD = 3;
675
505
  /** `:` alone: the shortest line a header name can sit on, its value folded onto the next. */
676
506
  const HEADER_NAME_LINE_OVERHEAD = 1;
677
507
  /**
678
- * First line of `text` that exceeds the octet limit, if any.
679
- *
680
- * Every line is scanned, not just the top header block: a multipart part's
681
- * own headers (`Content-Disposition: …; filename="…"`) live inside the body
682
- * and are just as unfoldable. Body content cannot trip this — text is
683
- * quoted-printable re-encoded above 990 octets and base64 is emitted at a
684
- * fixed width — so a hit is always a header.
685
- *
686
- * One pass over the string, counting UTF-8 octets per CRLF-delimited line,
687
- * with NO allocation: a `split(CRLF)` would hold one substring per line, and
688
- * a legal body of pasted logs is millions of lines. Only a CRLF pair ends a
689
- * line; a bare CR or LF is content.
508
+ * First CRLF-delimited line over the octet limit, counted in UTF-8 without
509
+ * allocating. Every line is scanned because part headers live in the body;
510
+ * encoded body content never trips it.
690
511
  */
691
512
  function findOverlongLine(text) {
692
513
  let index = 0;
@@ -716,24 +537,20 @@ function findOverlongLine(text) {
716
537
  octets
717
538
  } : void 0;
718
539
  }
719
- /**
720
- * Escape a value for a quoted-string parameter (RFC 2045 §5.1 value, whose
721
- * quoted-string comes from RFC 5322 §3.2.4).
722
- *
723
- * `qtext` excludes both `\\` and `"`, so each may appear only as a
724
- * quoted-pair: a raw trailing backslash would escape the closing quote, and
725
- * a conformant parser drops every other raw backslash.
726
- *
727
- * Backslash first, then quote — the other order would double-escape.
728
- */
540
+ /** Escape `\` and `"` as quoted-pairs (RFC 5322 §3.2.4), backslash first. */
729
541
  function quoteParam(value) {
730
542
  return value.replace(/\\/g, "\\\\").replace(/"/g, "\\\"");
731
543
  }
732
- function base64(bytes) {
733
- return btoa(codeUnitsToString(bytes));
544
+ /** `<prefix>_<base36 time><16 random hex>`. */
545
+ function newId(prefix) {
546
+ const bytes = /* @__PURE__ */ new Uint8Array(8);
547
+ crypto.getRandomValues(bytes);
548
+ let hex = "";
549
+ for (const b of bytes) hex += b.toString(16).padStart(2, "0");
550
+ return `${prefix}_${Date.now().toString(36)}${hex}`;
734
551
  }
735
552
  function base64Wrapped(bytes) {
736
- const encoded = base64(bytes);
553
+ const encoded = bytesToBase64(bytes);
737
554
  const lines = [];
738
555
  for (let i = 0; i < encoded.length; i += 76) lines.push(encoded.slice(i, i + 76));
739
556
  return lines.join(CRLF);
@@ -797,14 +614,9 @@ function codeUnitsToString(units) {
797
614
  return s;
798
615
  }
799
616
  /**
800
- * Whether a body must be quoted-printable encoded: anything outside
801
- * printable ASCII, or any line longer than 990 characters (RFC 5322 §2.1.1
802
- * makes 998 octets the hard limit). Only LF and CRLF end a line; a bare CR
803
- * is a control character like any other and forces the encoding.
804
- *
805
- * One pass over the string with NO allocation: a `replace`/`split` shape
806
- * holds a copy of the body plus one substring per line, and a legal 6 MB
807
- * body of millions of two-character lines needed about 100 MB that way.
617
+ * Whether a body needs quoted-printable: anything outside printable ASCII
618
+ * (a bare CR included) or a line over 990 characters. One pass without
619
+ * allocation.
808
620
  */
809
621
  function needsQuotedPrintable(text) {
810
622
  let lineLen = 0;
@@ -825,18 +637,9 @@ function needsQuotedPrintable(text) {
825
637
  return false;
826
638
  }
827
639
  /**
828
- * The 7bit body: `text` with every bare LF widened to CRLF, and every CRLF
829
- * kept. Only called once `needsQuotedPrintable` has returned false, so every
830
- * character is printable ASCII, LF, or the CR of a CRLF — one byte each —
831
- * and a byte buffer is exact.
832
- *
833
- * NOT `text.replace(/\r?\n/g, CRLF)`: V8 builds a global-regex replacement
834
- * from a parts array that holds two or three slots per match, grown by
835
- * doubling, so that one line cost 144 MB of heap on a legal 6 MB body of
836
- * 3M lines and terminated a 128 MB isolate — the largest single allocation
837
- * in the whole build, for a body that renders to 9 MB. The buffer here is
838
- * the output size, known up front from one counting pass. A body that is
839
- * already CRLF-only (or has no line breaks) is returned as-is.
640
+ * `text` with each bare LF widened to CRLF. Called only when every character
641
+ * is one byte, so a counting pass sizes the buffer exactly; a global-regex
642
+ * replace would allocate per line.
840
643
  */
841
644
  function to7bitBody(text) {
842
645
  let bare = 0;
@@ -852,16 +655,8 @@ function to7bitBody(text) {
852
655
  return codeUnitsToString(out);
853
656
  }
854
657
  /**
855
- * Lower bound on the octets `text` will occupy in the rendered message, in
856
- * one pass over the string and with NO allocation. Every UTF-8 byte yields at
857
- * least one octet on either body path — the 7bit path copies bytes and only
858
- * ever widens a bare LF to CRLF; the quoted-printable path emits each
859
- * non-ASCII byte as `=XX` (3 octets) and every other byte as itself, and its
860
- * soft breaks only add. So `ascii + 3 * nonAscii` can never overshoot the
861
- * real size, which keeps a false rejection impossible; `buildMime`'s final
862
- * check remains the authority. `TextEncoder.encode` would give the same count
863
- * but at the price of a full copy, which is exactly the allocation this
864
- * bound exists to avoid.
658
+ * Lower bound on `text`'s rendered octets, without allocating: ASCII is at
659
+ * least 1 octet and each non-ASCII UTF-8 byte is `=XX`.
865
660
  */
866
661
  function minBodyOctets(text) {
867
662
  let octets = 0;
@@ -913,7 +708,7 @@ function buildAttachmentPart(att) {
913
708
  function makeBoundary(prefix) {
914
709
  const bytes = /* @__PURE__ */ new Uint8Array(16);
915
710
  crypto.getRandomValues(bytes);
916
- return `=_void_${prefix}_${base64(bytes).replace(/[+/=]/g, "")}`;
711
+ return `=_void_${prefix}_${bytesToBase64(bytes).replace(/[+/=]/g, "")}`;
917
712
  }
918
713
  function wrapMultipart(type, parts) {
919
714
  const boundary = makeBoundary(type);
@@ -939,29 +734,10 @@ const RESERVED_HEADERS = /* @__PURE__ */ new Set([
939
734
  "content-disposition"
940
735
  ]);
941
736
  /**
942
- * Lower bound on the octets one header VALUE occupies once `encodeWord` (or
943
- * `formatAddress`, for a display name) and `foldHeader` have rendered it, in
944
- * one pass over the string and with NO allocation.
945
- *
946
- * `encodeWord` leaves a value alone when every character is printable ASCII
947
- * and otherwise B-encodes ALL of it, so the two paths need different terms:
948
- *
949
- * - Plain: every character is at least one octet, EXCEPT whitespace.
950
- * `foldHeader` re-joins a long value from its non-WSP tokens, so a run of
951
- * spaces or tabs collapses to one, and a bound that charged them could
952
- * reject a message that fits. Only the non-WSP characters count.
953
- * - Encoded: each RFC 2047 word carries at most `ENCODED_WORD_PAYLOAD_BYTES`
954
- * (45) UTF-8 bytes as base64 — `ceil(n / 3) * 4 >= 4n / 3` octets — inside
955
- * 12 octets of `=?UTF-8?B?` and `?=`, so there are at least `floor(n / 45)`
956
- * words' worth of framing. Whitespace inside the value is base64 like any
957
- * other byte; only the single separators between words fold.
958
- *
959
- * Folding (`foldHeader`) can only ADD octets beyond that — a `CRLF SP` per
960
- * line — and quoting a display name (`formatAddress`) adds the quotes and
961
- * escapes, so neither path can render fewer octets than this returns.
962
- * Measured, the encoded bound is 96% of the rendered size for CJK, where the
963
- * real cost is 5 octets per character; a UTF-16 `length` would have counted
964
- * 1 and let the isolate die on a header five times over the limit.
737
+ * Lower bound on one rendered header value, without allocating. Printable
738
+ * ASCII counts its non-WSP characters (folding may collapse WSP runs);
739
+ * anything else is B-encoded whole, at least 4/3 of its UTF-8 bytes plus 12
740
+ * octets of framing per 45-byte word.
965
741
  */
966
742
  function minHeaderValueOctets(value) {
967
743
  let utf8 = 0;
@@ -996,18 +772,9 @@ function minAddressOctets(addr) {
996
772
  return addr.email.length + (addr.name ? minHeaderValueOctets(addr.name) : 0);
997
773
  }
998
774
  /**
999
- * Lower bound on the octets of a value rendered VERBATIM — never through
1000
- * `encodeWord` — into a header `foldHeader` may still fold: `In-Reply-To`,
1001
- * `References`, and an attachment part's `Content-Type` media type and
1002
- * `Content-ID`. Every non-WSP UTF-16 code unit is at least one octet of
1003
- * UTF-8; a WSP run may collapse to a single space when the line folds, so
1004
- * none is charged. The `<>` around a Content-ID and the fold's `CRLF SP`
1005
- * only add.
1006
- *
1007
- * `minHeaderValueOctets` cannot stand in here: a non-ASCII value sends it
1008
- * down the encoded-word formula (4.8 octets per CJK character) while these
1009
- * values render as raw UTF-8 (3), so it would overshoot and could reject a
1010
- * message that fits.
775
+ * Lower bound on a value rendered verbatim (threading ids, media type,
776
+ * Content-ID): one octet per non-WSP code unit. `minHeaderValueOctets` would
777
+ * overshoot, since these are raw UTF-8, not encoded-words.
1011
778
  */
1012
779
  function minVerbatimOctets(value) {
1013
780
  let octets = 0;
@@ -1018,94 +785,24 @@ function minVerbatimOctets(value) {
1018
785
  return octets;
1019
786
  }
1020
787
  /**
1021
- * Octets every attachment part costs before any of its values: what
1022
- * `wrapMultipart`, `renderPart` and `buildAttachmentPart` emit for a part
1023
- * whose filename, media type, disposition and content are all empty. Each
1024
- * term is emitted verbatim on every path — `foldHeader` returns a short
1025
- * line as-is and re-joins a long one from its tokens with at least one
1026
- * space between them, so the space after `Name:` and the one after `;` are
1027
- * floors, not counts — and a fold's `CRLF SP` only adds. The boundary's
1028
- * random suffix is left out: `makeBoundary` strips `+`, `/` and `=`, so it
1029
- * has no provable minimum, and `mixed` is the shortest prefix an attachment
1030
- * part can sit under.
788
+ * Framing every attachment part costs with empty values. The random boundary
789
+ * suffix has no provable minimum, so it is not counted.
1031
790
  */
1032
791
  const ATTACHMENT_PART_MIN_OCTETS = 117;
1033
792
  /**
1034
- * Cap on the attachment COUNT, checked against the raw list in
1035
- * `normalizeEmail` before a single entry is normalized.
1036
- *
1037
- * Every part costs at least `ATTACHMENT_PART_MIN_OCTETS` of framing plus
1038
- * its filename twice, and `normalizeAttachment` refuses an empty filename,
1039
- * so the size projection in `buildMime` charges a part at least 119 octets
1040
- * and refuses one more part than this whatever else the message holds.
1041
- * That projection runs only after `normalizeEmail` has normalized EVERY
1042
- * entry, and `MAX_ATTACHMENT_BYTES_TOTAL` cannot bound that loop for a
1043
- * zero-byte attachment — its running total never advances — while the
1044
- * normalized copy (the object, a fresh `Uint8Array`, the `TextEncoder`
1045
- * that made it) costs about 275 bytes of live heap per entry. Measured, 2M
1046
- * empty attachments terminated a 128 MB isolate in 0.3 s instead of
1047
- * returning `MIME_ERROR`; this many normalize in 24 MB and are then refused
1048
- * by the post-render size check under the same ceiling.
1049
- *
1050
- * Derived, not chosen: it is exactly the largest count the projection can
1051
- * admit, so this cannot reject a message that would have been accepted, and
1052
- * `buildMime` remains the authority on the final size. Same class as
1053
- * `MAX_ATTACHMENT_BYTES_TOTAL` — a developer-experience guardrail on the
1054
- * app's own input, not the security boundary.
793
+ * Cap on the attachment count, checked before any entry is normalized:
794
+ * zero-byte entries never advance the byte total. It is the most parts
795
+ * `buildMime`'s size projection can admit, so it refuses nothing that fits.
1055
796
  */
1056
797
  const MAX_ATTACHMENTS = Math.floor(MAX_MESSAGE_BYTES / 119);
1057
- /**
1058
- * Octets every custom header costs around its value: the `: ` after the
1059
- * name and the CRLF that ends its line. Exact, not a floor, once the name
1060
- * is counted: `buildMime` renders each non-reserved custom header through
1061
- * `foldHeader`, which emits the name verbatim, then `: ` — or, when the
1062
- * value's first token does not fit beside the name, `:` CRLF SP, which is
1063
- * more — and `join(CRLF)` ends every header line, a custom header never
1064
- * being the last of the block (the body part's own headers follow it).
1065
- */
798
+ /** `: ` and the CRLF around a custom header value; exact once the name is counted. */
1066
799
  const CUSTOM_HEADER_FRAMING_OCTETS = 4;
1067
800
  /**
1068
- * Lower bound on the octets of every header `buildMime` renders from
1069
- * caller-supplied values: `Subject`, the custom headers, the addresses in
1070
- * `From`, `To`, `Cc` and `Reply-To`, the `In-Reply-To` / `References` pair
1071
- * `replyEmail` threads through (remote-sender controlled, up to the whole
1072
- * inbound message), and each attachment part's `Content-Type`, `Content-ID`
1073
- * and — twice, once per header it is rendered into — filename. `Bcc` is
1074
- * never rendered and a reserved custom header is dropped, so neither is
1075
- * counted — charging either could reject a message that fits. The fixed
1076
- * `Name: ` and `CRLF` of the headers `buildMime` itself names — `Subject`,
1077
- * the address lists, the threading pair — are omitted for the same reason
1078
- * a lower bound may omit any term. They are NOT omitted where the caller
1079
- * controls the name or the count, because there they can be the whole
1080
- * message:
1081
- *
1082
- * - A custom header's name is rendered verbatim, and `normalizeEmail`
1083
- * bounds ONE name at under a kilobyte, not the sum, nor the count. With
1084
- * empty values the names and the `: ` CRLF around each are the entire
1085
- * size, and the framing is exact once the name is counted (see
1086
- * `CUSTOM_HEADER_FRAMING_OCTETS`), so charging both cannot reject a
1087
- * message that fits. Uncharged, 60k empty headers with 500-character
1088
- * names (a 30 MB message) would project to zero.
1089
- * - An attachment part: `normalizeAttachment` bounds ONE filename at under
1090
- * a kilobyte, not the sum, and a message is free to carry any number of
1091
- * parts, so the filename and the framing every part is wrapped in are
1092
- * the whole size of a message of empty attachments. Measured, 50k
1093
- * zero-byte attachments with legal 986-character filenames rendered to
1094
- * 106 MB — held three to four times over between the parts, their join,
1095
- * `rawText` and `raw` — and terminated a 128 MB isolate before the final
1096
- * size check could return `MIME_ERROR`.
1097
- *
1098
- * The header COUNT is deliberately not bounded here. Each header costs
1099
- * at least five octets (a one-character name, `: `, CRLF), so the count
1100
- * the projection can admit is finite, and past a few hundred thousand keys
1101
- * the caller's own object — measured at about 74 bytes per key, before
1102
- * `sendEmail` is called — is the dominant cost, which no check inside this
1103
- * module can pre-empt. Rendering does add live heap per header (about
1104
- * 150 bytes: two `Object.entries`, the `topHeaders` pair, the folded line),
1105
- * so a legal message of 500k four-character headers still does not fit a
1106
- * 128 MB isolate while one of 400k does; a bound on that would be the
1107
- * framework's own number — the platform proxy bounds bytes, not headers —
1108
- * and is left as a product decision rather than invented here.
801
+ * Lower bound on every header rendered from caller values. Bcc and reserved
802
+ * custom headers never render, and the fixed framing of Void's own headers
803
+ * is omitted. A custom header's name and framing, and each attachment part's
804
+ * framing and filename (twice), are charged: a message of many empty headers
805
+ * or attachments is all framing.
1109
806
  */
1110
807
  function minHeaderOctets(email) {
1111
808
  let octets = minHeaderValueOctets(email.subject);
@@ -1127,7 +824,7 @@ function generateMessageId(fromEmail) {
1127
824
  const domain = fromEmail.split("@")[1] ?? "localhost";
1128
825
  const bytes = /* @__PURE__ */ new Uint8Array(12);
1129
826
  crypto.getRandomValues(bytes);
1130
- return `<${base64(bytes).replace(/[+/=]/g, "")}@${domain}>`;
827
+ return `<${bytesToBase64(bytes).replace(/[+/=]/g, "")}@${domain}>`;
1131
828
  }
1132
829
  /**
1133
830
  * Build the raw RFC 5322 message body. Returns the message bytes plus the
@@ -1177,4 +874,4 @@ function buildMime(email) {
1177
874
  };
1178
875
  }
1179
876
  //#endregion
1180
- export { parseAddress as a, normalizeEmail as i, MimeError as n, validateAddressParts as o, buildMime as r, MAX_MESSAGE_BYTES as t };
877
+ export { newId as a, validateAddressParts as c, indexOfControl as i, MimeError as n, normalizeEmail as o, buildMime as r, parseAddress as s, MAX_MESSAGE_BYTES as t };