void 0.27.0 → 1.0.3
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.
- package/README.md +3 -1
- package/dist/{account-cmd-l-FM7Ioq.mjs → account-cmd-BTcUzv9L.mjs} +6 -6
- package/dist/{agents-B_pX_HmQ.mjs → agents-CuNtT0D_.mjs} +5 -2
- package/dist/{application-analysis-DKy02UY0.mjs → application-analysis-AB_YYWgH.mjs} +118 -135
- package/dist/{application-routing-DQyUh_5S.mjs → application-routing-L7V-TFhZ.mjs} +1 -2
- package/dist/atomic-write-Dq6R0BPN.mjs +18 -0
- package/dist/{auth-Dn2vw-SG.mjs → auth-B6iOCjKI.mjs} +23 -56
- package/dist/auth-Cbqi1iVX.mjs +1 -0
- package/dist/{auth-link-vz9Z2kmG.mjs → auth-link-DUJuvRx5.mjs} +11 -11
- package/dist/{auth-migrations-BwHgeEsD.mjs → auth-migrations-Cgs0k6lS.mjs} +28 -5
- package/dist/{auth-router-DvsCUVw4.mjs → auth-router-CIxiMG7i.mjs} +5 -5
- package/dist/base64-DVrOndmI.mjs +16 -0
- package/dist/{better-auth-shared-CPvWD3nG.d.mts → better-auth-shared-B74NJIus.d.mts} +8 -13
- package/dist/{better-auth-shared-DPpj8zxc.mjs → better-auth-shared-CMXlZG7W.mjs} +56 -68
- package/dist/{build-cmd-D6we0VjO.mjs → build-cmd-BkIv25PA.mjs} +6 -6
- package/dist/{cache-CZRdzKx1.mjs → cache-Ctzfig-W.mjs} +6 -6
- package/dist/{cancel-deploy-CQ3NnMvf.mjs → cancel-deploy-CD9o-SsC.mjs} +5 -5
- package/dist/{cf-access-TWNzXltp.mjs → cf-access-BM9G0lhO.mjs} +4 -3
- package/dist/{cf-access-BcIBSKqG.mjs → cf-access-CWP4avfP.mjs} +3 -7
- package/dist/cf-build-output-BU3hqdHu.mjs +1 -0
- package/dist/{cf-build-output-DjvB_872.mjs → cf-build-output-Bc8i3dzE.mjs} +2 -2
- package/dist/cf-user-agent-ChjQp2MU.mjs +33 -0
- package/dist/cli/cli.mjs +199 -312
- package/dist/cli/cloudflare-operation-process.mjs +41 -15
- package/dist/cli/env-schema-probe.d.mts +7 -44
- package/dist/cli/env-schema-probe.mjs +14 -80
- package/dist/client-B60PwCC4.mjs +1 -0
- package/dist/{client-DlDJuY0s.mjs → client-DM9Kcf4e.mjs} +161 -415
- package/dist/{cloudflare-auth-CuxfF6OA.mjs → cloudflare-auth-CqFBDo52.mjs} +12 -39
- package/dist/{cloudflare-cmd-lHqNlJGW.mjs → cloudflare-cmd-BIAF_BIY.mjs} +7 -6
- package/dist/{cloudflare-config-BmhBv3HV.mjs → cloudflare-config-DV60XFFK.mjs} +16 -28
- package/dist/{cloudflare-connect-2G3rL2rP.mjs → cloudflare-connect-WjwnVOJA.mjs} +4 -4
- package/dist/{cloudflare-operations-CwI1bChl.mjs → cloudflare-operations-B42EZeJy.mjs} +26 -34
- package/dist/cloudflare-operations-CrSUFRzJ.mjs +1 -0
- package/dist/{cloudflare-process-2-TfIEzB.mjs → cloudflare-process-CeDWJRhj.mjs} +12 -7
- package/dist/collect-Cae8A7Zr.mjs +1 -0
- package/dist/{collect-DiTn9yr6.mjs → collect-xjffdCdk.mjs} +1 -1
- package/dist/{config-CSa15FvD.d.mts → config-7qoq2p9v.d.mts} +2 -2
- package/dist/{config-CLYAosnQ.mjs → config-BEm9vRvS.mjs} +11 -5
- package/dist/{config-DiowPT80.mjs → config-Bx_1SpnO.mjs} +87 -177
- package/dist/{config-DPByhVck.mjs → config-D0GY5ItR.mjs} +1 -1
- package/dist/config-QrJWu0IX.mjs +1 -0
- package/dist/config-entry.d.mts +1 -1
- package/dist/{connect-BfPBHHm-.mjs → connect-CKtk-EZe.mjs} +9 -9
- package/dist/create-project-B-ewF_Af.mjs +1 -0
- package/dist/{create-project-BdXEFKal.mjs → create-project-yInGo72M.mjs} +8 -8
- package/dist/database-provider.mjs +1 -2
- package/dist/{db-Xs80hcaA.mjs → db-7I_gfdVq.mjs} +177 -268
- package/dist/db-types-Bb4WBWIs.mjs +49 -0
- package/dist/{delete-d2vuou3j.mjs → delete-Cy-M1u-r.mjs} +6 -6
- package/dist/deploy-9lgfhrXS.mjs +2 -0
- package/dist/deploy-BYYlnsiy.mjs +6164 -0
- package/dist/deploy-managed-static-Ca4TFdmx.mjs +1595 -0
- package/dist/deploy-transport-DWlWBe6M.mjs +180 -0
- package/dist/deploy.d.mts +10 -0
- package/dist/deploy.mjs +82 -0
- package/dist/dev-inbox-Rd6j_8vM.mjs +217 -0
- package/dist/discover-ClzFSwns.mjs +1 -0
- package/dist/{discover-CkCYv9T_.mjs → discover-D2PGT63u.mjs} +2 -2
- package/dist/dispatch-DrTTk8Xg.mjs +431 -0
- package/dist/{dist-D3m88sjf.mjs → dist-BVdsO7Py.mjs} +5 -6
- package/dist/dist-CfgIkieS.mjs +1 -0
- package/dist/{dist-BVqXeR_h.mjs → dist-ipQi0Q8y.mjs} +2 -3
- package/dist/{domain-BsDUBAvt.mjs → domain-CZGxPv9u.mjs} +8 -23
- package/dist/{dotenv-BfU6eqFt.mjs → dotenv-CNazY3-w.mjs} +4 -16
- package/dist/edge.mjs +1 -2
- package/dist/{email-d_Aux1vM.mjs → email-BcjSyAL0.mjs} +4 -20
- package/dist/{email-_lGAHOhp.mjs → email-DzyNVuoU.mjs} +100 -192
- package/dist/email-cloudflare-DfG6UEMm.mjs +1096 -0
- package/dist/email-protocol-D9nTvhCp.mjs +82 -0
- package/dist/{entry-CMAkqBmU.mjs → entry-ehmBvs5w.mjs} +2 -2
- package/dist/{env-DMA3cXZt.mjs → env-0jrMQJI_.mjs} +6 -14
- package/dist/{env-BxocywBB.mjs → env-BJjULvL0.mjs} +2 -2
- package/dist/{env-C74QepDE.mjs → env-Nx3yf50r.mjs} +9 -9
- package/dist/{env-public-DR7ZM6d-.d.mts → env-public-CCdykygU.d.mts} +6 -23
- package/dist/{env-raw-jZpP5n47.mjs → env-raw-D74P4ebM.mjs} +15 -21
- package/dist/{env-types-CwXgeMgL.mjs → env-types-DS2_y4X8.mjs} +2 -2
- package/dist/env-validation-BT7z-qpQ.mjs +1 -0
- package/dist/env-validation-DYxjz_Wo.mjs +488 -0
- package/dist/{gen-DtkQhvQg.mjs → gen-CufHEf42.mjs} +132 -254
- package/dist/gen-sXyp5DFO.mjs +1 -0
- package/dist/generate-ClI89brV.mjs +1 -0
- package/dist/{generate-GDbL7sUr.mjs → generate-Dat0UTry.mjs} +38 -4
- package/dist/generated-wrangler-config-DeWj5F9Y.mjs +18 -0
- package/dist/{github-cmd-DaDdBbSS.mjs → github-cmd-FU8EjFyU.mjs} +28 -72
- package/dist/{handler-BHAn2fZJ.mjs → handler-BZ1t7-Rv.mjs} +2 -2
- package/dist/{handler-CNAwjRcW.d.mts → handler-_PqY82xe.d.mts} +1 -1
- package/dist/{headers-DlfR78Nu.mjs → headers-Di1FsD3e.mjs} +26 -81
- package/dist/{help-0bTe_lID.mjs → help-BT2hovNI.mjs} +26 -14
- package/dist/help-i2YGGnTH.mjs +1 -0
- package/dist/{inbound-PfQDLXc5.mjs → inbound-BuTfm11U.mjs} +71 -222
- package/dist/{inbound-CH5Mksyy.d.mts → inbound-brj2-TM5.d.mts} +19 -58
- package/dist/index.d.mts +2 -18
- package/dist/index.mjs +714 -762
- package/dist/{info-PYWwkWyt.mjs → info-l249eUdH.mjs} +5 -5
- package/dist/{init-DaBGmaXC.mjs → init-D0A6M64Q.mjs} +229 -392
- package/dist/isr-config-fZaJJ8t7.mjs +165 -0
- package/dist/{link-C6fjafep.mjs → link-WMoJFf4i.mjs} +9 -9
- package/dist/{list-BTFBlqKl.mjs → list-CQ2EQEHL.mjs} +7 -18
- package/dist/{live-CgQuTpqD.mjs → live-BcHoTDFe.mjs} +19 -17
- package/dist/{live-Du8jXwOW.d.mts → live-DJONVlQK.d.mts} +1 -1
- package/dist/load-user-env-DD5qveNU.mjs +49 -0
- package/dist/{local-d1-ga5O_idV.mjs → local-d1-BxvQYEFi.mjs} +6 -6
- package/dist/{login-GKcNUmtI.mjs → login-C2T1oVG-.mjs} +12 -12
- package/dist/login-XD844Xs-.mjs +1 -0
- package/dist/{logs-BiMSULmc.mjs → logs-DnC1d7xB.mjs} +6 -6
- package/dist/{migrate-NLsjBbuM.mjs → migrate-BDIprOYd.mjs} +70 -22
- package/dist/migrate-BRwU-blY.mjs +1 -0
- package/dist/migration-handler-Cg0Y4EPu.mjs +470 -0
- package/dist/{migration-handler-DM4clYj5.d.mts → migration-handler-CwlEQUoo.d.mts} +17 -26
- package/dist/{mime-DxCznlJq.mjs → mime-srOklVVv.mjs} +92 -395
- package/dist/mysql-migration-sql-BIS5vbNk.mjs +241 -0
- package/dist/nitro.d.mts +30 -0
- package/dist/nitro.mjs +88 -0
- package/dist/{node-DJicPvPj.mjs → node-cPadMgUO.mjs} +9 -25
- package/dist/{operator-args-DOBhIaIg.mjs → operator-args-UnE8Y2eK.mjs} +27 -26
- package/dist/{operator-auth-BEZ_u0Cz.mjs → operator-auth-Cr2zCc-J.mjs} +2 -2
- package/dist/{operator-client-DbDv4vtE.mjs → operator-client-C-ROjk1I.mjs} +4 -4
- package/dist/operator-cmd-D6gnZsnK.mjs +1 -0
- package/dist/{operator-cmd-BT4hgavL.mjs → operator-cmd-DHieWtFp.mjs} +8 -8
- package/dist/{output-C50ag2r3.mjs → output-Ba6ZbrzY.mjs} +37 -6
- package/dist/{package-json-DXfiT1jV.mjs → package-json-BjYqR-So.mjs} +1 -1
- package/dist/pages/client.d.mts +1 -1
- package/dist/pages/client.mjs +91 -5
- package/dist/pages/head.mjs +1 -2
- package/dist/pages/index.d.mts +1 -2
- package/dist/pages/index.mjs +6 -6
- package/dist/pages/islands-plugin.mjs +5 -83
- package/dist/pages/prefetch.mjs +1 -2
- package/dist/pages/protocol.d.mts +2 -2
- package/dist/pages/protocol.mjs +1 -1
- package/dist/pages/serialize.mjs +1 -2
- package/dist/plan-CKX_jWnD.mjs +1 -0
- package/dist/platform-args-B0HeTh0C.mjs +1 -0
- package/dist/{platform-args-DUeXY9Om.mjs → platform-args-CaCL_1Ch.mjs} +43 -60
- package/dist/{platform-auth-config-CkSx3usH.mjs → platform-auth-config-Z16-I8nT.mjs} +11 -12
- package/dist/{platform-auth-protection-BJimB_p9.mjs → platform-auth-protection-BXwZiJSF.mjs} +37 -27
- package/dist/{platform-auth-recovery-BU6izFAU.mjs → platform-auth-recovery-CXjfqyOv.mjs} +9 -10
- package/dist/{platform-cmd-BbY1dWiM.mjs → platform-cmd-DaAOiWTl.mjs} +16 -16
- package/dist/platform-cmd-PT4YwMLM.mjs +1 -0
- package/dist/{platform-discovery-DIYz8V63.mjs → platform-discovery-CHhNs8Nn.mjs} +1 -1
- package/dist/{platform-domain-CHVS6cV0.mjs → platform-domain-CxpvUeo0.mjs} +6 -6
- package/dist/{platform-lifecycle-DzCwqhFq.mjs → platform-lifecycle-DBiS0cJd.mjs} +1693 -2120
- package/dist/platform-lifecycle-u9pMOvxC.mjs +1 -0
- package/dist/{platform-management-CuuVDhyt.mjs → platform-management-DhEFdQAf.mjs} +696 -130
- package/dist/platform-management-DvBS83rC.mjs +1 -0
- package/dist/{platform-plans-config-CN-heS4q.mjs → platform-plans-config-BWn1S2Rv.mjs} +16 -12
- package/dist/{platform-recovery-CskSJgLh.mjs → platform-recovery-BUGOB4RC.mjs} +6 -9
- package/dist/{platform-registry-Cjv2Qf0r.mjs → platform-registry-B9mWX9LO.mjs} +13 -18
- package/dist/{platform-setup-BBxRxmFC.mjs → platform-setup-YvN9VQXV.mjs} +21 -28
- package/dist/{plugin-inference-BlQbOL0P.mjs → plugin-inference-DsARdQKE.mjs} +18 -33
- package/dist/prepare-CYT6tAzD.mjs +1 -0
- package/dist/{prepare-Do96654b.mjs → prepare-DEB5SeVJ.mjs} +12 -13
- package/dist/{prepare-Dq9hTIbo.mjs → prepare-PQCgsny0.mjs} +4 -4
- package/dist/{prerender-render-Ct20jftc.mjs → prerender-render-Bfsumdkv.mjs} +8 -2
- package/dist/prerender-render.d.mts +2 -0
- package/dist/prerender-render.mjs +1 -2
- package/dist/{project-cmd-DaoRrn-8.mjs → project-cmd-DVatD8Ev.mjs} +20 -20
- package/dist/{project-paths-GgcMozYz.mjs → project-paths-DMvEeSau.mjs} +9 -14
- package/dist/{project-BAm2aB6Q.mjs → project-rqDnVsJN.mjs} +8 -4
- package/dist/project-slug-6cyz8E7k.mjs +1 -0
- package/dist/{project-team-Q_lCA7Io.mjs → project-team-DJrWEAG1.mjs} +7 -7
- package/dist/{project-token-BArgK9o1.mjs → project-token-CBgLBuL6.mjs} +6 -6
- package/dist/{project-tsconfig-CVJhNMxs.mjs → project-tsconfig-bveqhlYA.mjs} +3 -5
- package/dist/project-zdB3fs9G.mjs +1 -0
- package/dist/{project-zero-trust-KO9Hu2Pq.mjs → project-zero-trust-92gLtZ25.mjs} +6 -6
- package/dist/{protocol-BPZaNqBo.d.mts → protocol-4H7V_3Os.d.mts} +1 -1
- package/dist/{protocol-CfaUwNs8.mjs → protocol-RNP0u7UY.mjs} +9 -3
- package/dist/{provision-BfaLiWbj.mjs → provision-BnSSkiED.mjs} +119 -866
- package/dist/{requests-C7Oeoh5u.mjs → requests-7W1Pygt2.mjs} +5 -5
- package/dist/resolve-project-PnhzMtY6.mjs +1 -0
- package/dist/resolve-project-WpwkCB_c.mjs +48 -0
- package/dist/{rollback-DVAtrLAl.mjs → rollback-BcASVnwP.mjs} +8 -18
- package/dist/{route-types-CbtsIeFn.mjs → route-types-BZi26DVS.mjs} +9 -91
- package/dist/routing-assets-VkrKIbxE.mjs +139 -0
- package/dist/{runner-DMBKSrRk.mjs → runner-CabsQ-iM.mjs} +22 -34
- package/dist/runner-So9mYfcm.mjs +1 -0
- package/dist/runner-mysql-BhRaONkO.mjs +146 -0
- package/dist/runner-mysql-DWwE8jKi.mjs +1 -0
- package/dist/{runner-pg-DV8p_zjA.mjs → runner-pg-BRemq_GX.mjs} +3 -3
- package/dist/runner-pg-_Xncr3H5.mjs +1 -0
- package/dist/runtime/ai.mjs +23 -25
- package/dist/runtime/auth-client-react.mjs +1 -2
- package/dist/runtime/auth-client-solid.mjs +1 -2
- package/dist/runtime/auth-client-svelte.mjs +1 -2
- package/dist/runtime/auth-client-vue.mjs +1 -2
- package/dist/runtime/auth-client.mjs +1 -2
- package/dist/runtime/auth.mjs +1 -2
- package/dist/runtime/better-auth-mysql.d.mts +2 -5
- package/dist/runtime/better-auth-mysql.mjs +9 -31
- package/dist/runtime/better-auth-pg.d.mts +2 -5
- package/dist/runtime/better-auth-pg.mjs +6 -32
- package/dist/runtime/better-auth.d.mts +2 -4
- package/dist/runtime/better-auth.mjs +9 -19
- package/dist/runtime/db.mjs +6 -2
- package/dist/runtime/durable.d.mts +18 -1
- package/dist/runtime/durable.mjs +26 -2
- package/dist/runtime/email/testing.d.mts +1 -1
- package/dist/runtime/email/testing.mjs +9 -23
- package/dist/runtime/email-protocol.d.mts +12 -0
- package/dist/runtime/email-protocol.mjs +1 -70
- package/dist/runtime/email.d.mts +1 -1
- package/dist/runtime/email.mjs +79 -221
- package/dist/runtime/env-public.d.mts +1 -1
- package/dist/runtime/env-public.mjs +12 -38
- package/dist/runtime/env.d.mts +1 -12
- package/dist/runtime/env.mjs +1 -2
- package/dist/runtime/handler.d.mts +1 -1
- package/dist/runtime/handler.mjs +1 -1
- package/dist/runtime/isr.mjs +1 -1
- package/dist/runtime/kv.mjs +1 -1
- package/dist/runtime/limits.mjs +1 -2
- package/dist/runtime/live-client.d.mts +3 -2
- package/dist/runtime/live-server.d.mts +2 -1
- package/dist/runtime/live-server.mjs +1 -16
- package/dist/runtime/live.d.mts +1 -1
- package/dist/runtime/live.mjs +1 -2
- package/dist/runtime/log.d.mts +2 -1
- package/dist/runtime/migration-handler-mysql.d.mts +2 -2
- package/dist/runtime/migration-handler-mysql.mjs +39 -8
- package/dist/runtime/migration-handler-pg.d.mts +2 -2
- package/dist/runtime/migration-handler-pg.mjs +1 -1
- package/dist/runtime/migration-handler.d.mts +2 -2
- package/dist/runtime/migration-handler.mjs +1 -470
- package/dist/runtime/queues.mjs +1 -1
- package/dist/runtime/remote/binding-handler.mjs +62 -62
- package/dist/runtime/remote/index.mjs +16 -77
- package/dist/runtime/response.mjs +1 -2
- package/dist/runtime/route-url.mjs +1 -2
- package/dist/runtime/routing.d.mts +3 -5
- package/dist/runtime/routing.mjs +82 -218
- package/dist/runtime/sandbox-container.d.mts +2 -2
- package/dist/runtime/sandbox-container.mjs +1 -2
- package/dist/runtime/sandbox.d.mts +2 -2
- package/dist/runtime/sandbox.mjs +13 -6
- package/dist/runtime/seed.d.mts +2 -1
- package/dist/runtime/sse.mjs +1 -2
- package/dist/runtime/storage.mjs +1 -1
- package/dist/runtime/validator.d.mts +1 -1
- package/dist/runtime/validator.mjs +1 -2
- package/dist/runtime/ws-server.d.mts +4 -4
- package/dist/runtime/ws-server.mjs +6 -28
- package/dist/runtime/ws.d.mts +1 -1
- package/dist/{sandbox-container-Bo0eiFKz.d.mts → sandbox-container-ChQRum-j.d.mts} +3 -1
- package/dist/{sandbox-container-C6ItmVuN.mjs → sandbox-container-a9LRUtii.mjs} +13 -2
- package/dist/{sandbox-C5LFoJMf.d.mts → sandbox-q3waMc2T.d.mts} +1 -1
- package/dist/{scan-C3uDzz6J.mjs → scan-C0BMdmEd.mjs} +84 -7
- package/dist/{secret-BvtB7IjY.mjs → secret-bg73f1Ge.mjs} +63 -81
- package/dist/{serialize-BPvnNQuA.mjs → serialize-BtQyaYoC.mjs} +10 -4
- package/dist/{skills-BgVMvQdy.mjs → skills-C_yRTg0g.mjs} +3 -3
- package/dist/{subcommand-prompt-BSlnD1fI.mjs → subcommand-prompt-Bm3ZlYgA.mjs} +39 -44
- package/dist/sveltekit.d.mts +2 -1
- package/dist/sveltekit.mjs +1 -1
- package/dist/validate-BQFdf0Pi.mjs +1 -0
- package/dist/{validate-C9qJArv7.mjs → validate-CheZGRE7.mjs} +4 -8
- package/dist/version-metadata-DIrqEHQo.mjs +73 -0
- package/dist/{wrangler-D9KTuqnv.mjs → wrangler-BYs07Rxy.mjs} +119 -378
- package/dist/wrapper-CwhpNWtH.mjs +663 -0
- package/dist/{ws-CChrrAU-.d.mts → ws-aKVYB-fA.d.mts} +1 -1
- package/dist/yarn-pnp-DLbEFMT0.mjs +92 -0
- package/docs/guide/ai.md +8 -2
- package/docs/guide/auth.md +2 -0
- package/docs/guide/database/mysql.md +14 -3
- package/docs/guide/database/postgresql.md +2 -0
- package/docs/guide/database.md +3 -5
- package/docs/guide/durable-state.md +32 -4
- package/docs/guide/platform/administration/access.md +4 -0
- package/docs/guide/platform/administration/connected-apps.md +55 -0
- package/docs/guide/platform/installation/credentials.md +21 -3
- package/docs/guide/platform/installation/domains.md +1 -1
- package/docs/guide/platform/installation/maintenance.md +38 -1
- package/docs/guide/platform/installation/prerequisites.md +6 -2
- package/docs/guide/platform/installation/setup.md +23 -1
- package/docs/guide/platform/installation/uninstall.md +6 -1
- package/docs/guide/quickstart.md +2 -0
- package/docs/guide/sandboxes.md +3 -1
- package/docs/guide/self-hosted-platform.md +1 -1
- package/docs/integrations/cloudflare.md +2 -2
- package/docs/integrations/frameworks/analog.md +3 -11
- package/docs/integrations/frameworks/nuxt.md +7 -10
- package/docs/integrations/nodejs-bun-deno.md +2 -0
- package/docs/reference/api/deploy.md +23 -0
- package/docs/reference/api/pages.md +2 -0
- package/docs/reference/api.md +3 -1
- package/docs/reference/cli/database.md +9 -3
- package/docs/reference/cli/platform-installation.md +19 -7
- package/docs/reference/cli/setup.md +2 -0
- package/docs/reference/config.md +2 -0
- package/package.json +39 -36
- package/sandbox.Dockerfile +1 -1
- package/skills/void/SKILL.md +2 -1
- package/dist/auth-LMJcNESe.mjs +0 -2
- package/dist/cf-build-output-H9a97vME.mjs +0 -2
- package/dist/cf-user-agent-lKblH3zU.mjs +0 -17
- package/dist/client-tso2OfcG.mjs +0 -2
- package/dist/cloudflare-operations-BlYLlowZ.mjs +0 -2
- package/dist/collect-DLyFDiKW.mjs +0 -2
- package/dist/config-5r-YpMC-.mjs +0 -2
- package/dist/config-B_ggY-IO.mjs +0 -89
- package/dist/config-BtSFvXZx.mjs +0 -2
- package/dist/config-write-AHGesphx.mjs +0 -61
- package/dist/create-project-qFDC45zg.mjs +0 -2
- package/dist/deploy-Bqe1PYBw.mjs +0 -10458
- package/dist/deploy-VsWsVQkw.mjs +0 -2
- package/dist/dev-inbox-CK-UuPob.mjs +0 -297
- package/dist/discover-EDUf6JJw.mjs +0 -2
- package/dist/dist-Bx1z6Eva.mjs +0 -2
- package/dist/dist-_UUlL6bg.mjs +0 -2
- package/dist/env-validation-CrVNjsPm.mjs +0 -2
- package/dist/env-validation-Dxdx_5wo.mjs +0 -951
- package/dist/gen-dA9hW7AV.mjs +0 -2
- package/dist/head-client-DzmJGN4C.mjs +0 -90
- package/dist/help-DfQYVfGY.mjs +0 -2
- package/dist/login-mx_ydhmp.mjs +0 -2
- package/dist/migrate-BHp07yJE.mjs +0 -2
- package/dist/operator-cmd-CwBB-1yb.mjs +0 -2
- package/dist/pages/head-client.d.mts +0 -13
- package/dist/pages/head-client.mjs +0 -2
- package/dist/plan-CH2G51je.mjs +0 -2
- package/dist/platform-args-D4E1PjVw.mjs +0 -2
- package/dist/platform-cmd-BbmJiq5O.mjs +0 -2
- package/dist/platform-lifecycle-ByAlpkhV.mjs +0 -2
- package/dist/platform-management-CBOT4BSM.mjs +0 -2
- package/dist/prepare-DRUV-g3X.mjs +0 -2
- package/dist/project-DedqCp59.mjs +0 -2
- package/dist/project-slug-DofjTFd-.mjs +0 -2
- package/dist/provision-Wu9ZBk9L.mjs +0 -2
- package/dist/resolve-project-BIeYs9Cw.mjs +0 -2
- package/dist/resolve-project-CP8rZs_p.mjs +0 -28
- package/dist/runner-9wjsSZx-.mjs +0 -2
- package/dist/runner-mysql-CEzKtmFb.mjs +0 -54
- package/dist/runner-mysql-CkFqZ6CE.mjs +0 -2
- package/dist/runner-pg-BGYRFdRp.mjs +0 -2
- package/dist/runtime/env-helpers.d.mts +0 -2
- package/dist/runtime/env-helpers.mjs +0 -2
- package/dist/validate-BJr9LfXy.mjs +0 -2
- package/dist/yarn-pnp-CUX_iTPA.mjs +0 -188
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
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-D74P4ebM.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
|
-
|
|
29
|
-
|
|
30
|
+
/** The raw env, or `undefined` outside a worker or SSR request. */
|
|
31
|
+
function tryGetRawRuntimeEnv() {
|
|
30
32
|
try {
|
|
31
|
-
|
|
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
|
-
|
|
38
|
-
|
|
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
|
|
75
|
-
* loaded
|
|
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
|
|
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
|
|
130
|
-
*
|
|
131
|
-
*
|
|
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
|
|
150
|
-
*
|
|
151
|
-
*
|
|
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
|
|
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
|
|
218
|
-
*
|
|
219
|
-
*
|
|
220
|
-
*
|
|
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 >
|
|
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 >
|
|
340
|
-
if (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`
|
|
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
|
-
*
|
|
433
|
-
*
|
|
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 (
|
|
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
|
|
480
|
-
*
|
|
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
|
|
507
|
-
*
|
|
508
|
-
*
|
|
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
|
|
532
|
-
*
|
|
533
|
-
*
|
|
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
|
|
556
|
-
*
|
|
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" ?
|
|
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
|
-
*
|
|
612
|
-
*
|
|
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 =
|
|
496
|
+
const slug = readProjectSlug();
|
|
629
497
|
if (slug) {
|
|
630
|
-
const domain =
|
|
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 (
|
|
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) &&
|
|
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
|
|
709
|
-
*
|
|
710
|
-
*
|
|
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
|
|
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
|
|
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
|
|
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,
|
|
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
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
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
|
|
204
|
-
* loaded
|
|
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
|
|
250
|
-
*
|
|
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
|
|
260
|
-
*
|
|
261
|
-
*
|
|
262
|
-
*
|
|
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
|
|
338
|
-
*
|
|
339
|
-
*
|
|
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-
|
|
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"];
|