void 1.4.0 → 1.6.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.
- package/README.md +1 -1
- package/dist/{account-cmd-HP8bixYo.mjs → account-cmd-DRhmCWcm.mjs} +7 -8
- package/dist/{action-key-XZ9HkWAO.mjs → action-key-XtKKbbsi.mjs} +1 -2
- package/dist/{agents-CuNtT0D_.mjs → agents-DRo8gzni.mjs} +2 -3
- package/dist/{application-analysis-DDOQwiXk.mjs → application-analysis-HRFsZOv3.mjs} +18 -24
- package/dist/{application-routing-4719u_kf.mjs → application-routing-P4TggvWp.mjs} +2 -3
- package/dist/{ast-CsZ_q_gc.mjs → ast-Cv0JwXqb.mjs} +1 -2
- package/dist/{ast-bindings-C3yaPs1y.mjs → ast-bindings-BkivMJIo.mjs} +6 -11
- package/dist/{atomic-write-Dq6R0BPN.mjs → atomic-write-DA6eD1Kp.mjs} +1 -2
- package/dist/{auth-g2TQbDLD.d.mts → auth-CH4PLAX1.d.mts} +0 -2
- package/dist/{auth-Cbqi1iVX.mjs → auth-CL-p_rqV.mjs} +1 -1
- package/dist/{auth-B6iOCjKI.mjs → auth-Dy8svcqQ.mjs} +6 -7
- package/dist/{auth-3sGB0zJ1.mjs → auth-YVjBX5NY.mjs} +1 -2
- package/dist/{auth-client-Bawdj38n.d.mts → auth-client-6-Ft9i9T.d.mts} +0 -2
- package/dist/{auth-client-BWBT8HLp.mjs → auth-client-DwCdwKbw.mjs} +1 -2
- package/dist/{auth-client-react-CMLwT2xI.mjs → auth-client-react-CJdeErvM.mjs} +1 -2
- package/dist/{auth-client-react-7GFffu8R.d.mts → auth-client-react-DvQLe5Zb.d.mts} +0 -2
- package/dist/{auth-client-solid-UoreJWZG.mjs → auth-client-solid-BRvgvp6h.mjs} +1 -2
- package/dist/{auth-client-solid-DyTFL4cq.d.mts → auth-client-solid-P9pEtKGp.d.mts} +0 -2
- package/dist/{auth-client-svelte-zetW0KIH.d.mts → auth-client-svelte-B5j8irT6.d.mts} +0 -2
- package/dist/{auth-client-svelte-Cv_WvrRk.mjs → auth-client-svelte-BSqUCEed.mjs} +1 -2
- package/dist/{auth-client-vue-bChShbQP.d.mts → auth-client-vue-BEiAfavk.d.mts} +0 -2
- package/dist/{auth-client-vue-CFk7Xbv3.mjs → auth-client-vue-CPkbRtOO.mjs} +1 -2
- package/dist/{auth-link-CedYpDCy.mjs → auth-link-CVXP1G6G.mjs} +7 -8
- package/dist/{auth-migrations-BO27GDNr.mjs → auth-migrations-DDeifS3v.mjs} +1 -2
- package/dist/{auth-router-vafo7x8w.mjs → auth-router-D1pGdbvB.mjs} +6 -7
- package/dist/{base64-DVrOndmI.mjs → base64-ikl9yBy3.mjs} +1 -2
- package/dist/{better-auth-shared-BHB8kiTE.d.mts → better-auth-shared-BJyG2mH0.d.mts} +2 -6
- package/dist/{better-auth-shared-7FM3Uk2N.mjs → better-auth-shared-C958aM7W.mjs} +31 -7
- package/dist/{build-cmd-9vUAQ1_V.mjs → build-cmd-DmjbuT6d.mjs} +7 -8
- package/dist/{cache-jvwLNb0h.mjs → cache-2khBO1MR.mjs} +7 -8
- package/dist/{cancel-deploy-Dw0UmWKO.mjs → cancel-deploy-_itbbvY3.mjs} +6 -7
- package/dist/{cf-access-CWP4avfP.mjs → cf-access-BmBT2h8_.mjs} +3 -4
- package/dist/{cf-access-BM9G0lhO.mjs → cf-access-pejlJmuy.mjs} +1 -2
- package/dist/{cf-build-output-XpNR9zoh.mjs → cf-build-output-B1C8U83u.mjs} +41 -314
- package/dist/cf-build-output-CmDOcA7K.mjs +1 -0
- package/dist/{cf-command-values-ByHk0xg4.mjs → cf-command-values-Ccl-zRhl.mjs} +10 -7
- package/dist/cf-config-migrate-Dy8MrKgF.mjs +326 -0
- package/dist/{cf-worker-settings-Dg27RzyT.mjs → cf-worker-settings-CARs4Wy9.mjs} +3 -5
- package/dist/cli/cli.mjs +66 -76
- package/dist/cli/cloudflare-operation-process.mjs +14 -18
- package/dist/cli/env-schema-probe.d.mts +1 -5
- package/dist/cli/env-schema-probe.mjs +4 -5
- package/dist/client-CEtr5UOR.mjs +1 -0
- package/dist/{client-B3LnB_bE.mjs → client-CoxPEhJq.mjs} +15 -13
- package/dist/{cloudflare-auth-DyD_kVFr.mjs → cloudflare-auth-CEu-1Ps_.mjs} +2 -3
- package/dist/{cloudflare-cmd-D-b_u3T4.mjs → cloudflare-cmd-fZ6AMSWk.mjs} +7 -8
- package/dist/{cloudflare-config-CH1AylZT.mjs → cloudflare-config-eQunqX6A.mjs} +22 -17
- package/dist/{cloudflare-connect-zTJh8UnN.mjs → cloudflare-connect-9OZe4XVQ.mjs} +5 -6
- package/dist/{cloudflare-operations-Bc-7fN44.mjs → cloudflare-operations-CrskD4_O.mjs} +8 -9
- package/dist/{cloudflare-operations-BtulCNOg.mjs → cloudflare-operations-oLvAd9Nd.mjs} +1 -1
- package/dist/{cloudflare-process-8jEYIeim.mjs → cloudflare-process-DjJ638A-.mjs} +7 -9
- package/dist/{cloudflare-user-output-Q-k0QoNQ.mjs → cloudflare-user-output-zEwuGrEJ.mjs} +1 -2
- package/dist/collect-8i0wU63d.mjs +1 -0
- package/dist/{collect-Dew86qce.mjs → collect-C6Blu9yw.mjs} +2 -3
- package/dist/{config-tqMM6DwY.mjs → config-BBlVXZCU.mjs} +5 -6
- package/dist/{config-OFOAimzt.mjs → config-BITKQ3O6.mjs} +5 -5
- package/dist/{config-BV2ASlpn.mjs → config-BgysUhnm.mjs} +1 -1
- package/dist/{config-CAdZVTLN.d.mts → config-CPxJmt4M.d.mts} +4 -6
- package/dist/{config-D-6q7EBH.mjs → config-WlvEcL82.mjs} +3 -4
- package/dist/config-entry.d.mts +1 -3
- package/dist/config-entry.mjs +1 -2
- package/dist/{connect-BOM6zvFX.mjs → connect-CKvmkl2R.mjs} +10 -11
- package/dist/{create-project-C2K0DN2O.mjs → create-project-BiMmR5wA.mjs} +1 -1
- package/dist/{create-project-Bxd02EHN.mjs → create-project-Bq0M8MtO.mjs} +9 -11
- package/dist/{database-provider-Cx525bwX.mjs → database-provider-DkZo4VwN.mjs} +1 -2
- package/dist/database-provider.d.mts +1 -3
- package/dist/database-provider.mjs +1 -1
- package/dist/{db-Cdvr3zwG.mjs → db-cq5RW4Vy.mjs} +52 -54
- package/dist/{db-types-0eCiqYb1.mjs → db-types-C_8amnB0.mjs} +3 -4
- package/dist/{delete-lETE6Tpt.mjs → delete-CY4L8fi2.mjs} +7 -8
- package/dist/deploy-B029oHlE.mjs +2 -0
- package/dist/{deploy-CdM-LAxX.mjs → deploy-D_gEojD2.mjs} +144 -136
- package/dist/{deploy-managed-static-DjeBFG2c.mjs → deploy-managed-static-BHVbB_-A.mjs} +33 -40
- package/dist/{deploy-transport-DIq_gFTP.mjs → deploy-transport-DEyOUfac.mjs} +6 -7
- package/dist/deploy.d.mts +1 -3
- package/dist/deploy.mjs +11 -11
- package/dist/{dev-inbox-D0jxye_D.mjs → dev-inbox-CUUS6iUg.mjs} +3 -4
- package/dist/discover-D4mQthao.mjs +1 -0
- package/dist/{discover-LaV0tbIu.mjs → discover-Dhkzxgdt.mjs} +3 -4
- package/dist/{dispatch-CLa2LThw.mjs → dispatch-BNLB5_Gm.mjs} +12 -15
- package/dist/{dist-Cegxq8gs.mjs → dist-B6eN80gc.mjs} +199 -118
- package/dist/{dist-D15hFhP0.mjs → dist-BWNkVq50.mjs} +8 -15
- package/dist/{dist-Cor9XGoz.mjs → dist-D23AAMxT.mjs} +9 -16
- package/dist/{dist-ipQi0Q8y.mjs → dist-DMYe8CZJ.mjs} +1 -2
- package/dist/{dist-B1PLt4_8.mjs → dist-eV_Ep60B.mjs} +1 -1
- package/dist/{domain-DyhNtdYf.mjs → domain-BlH90Ods.mjs} +8 -9
- package/dist/{dotenv-CNazY3-w.mjs → dotenv-CEI8hapP.mjs} +1 -2
- package/dist/{drizzle-9TubSZvI.mjs → drizzle-C8MPqt5m.mjs} +1 -1
- package/dist/{drizzle-BQfyvQKX.mjs → drizzle-lFdzSEa9.mjs} +2 -3
- package/dist/{email-B9ayYQEG.mjs → email-BHY72ixO.mjs} +3 -4
- package/dist/{email-DM2wDcBN.mjs → email-Bkq8ZL1p.mjs} +14 -15
- package/dist/{email-cloudflare-PMbAev9Q.mjs → email-cloudflare-MvJIxrwx.mjs} +18 -123
- package/dist/{email-protocol-D9nTvhCp.mjs → email-protocol-DTs_TjCS.mjs} +1 -2
- package/dist/{entry-BEM8ZuGP.mjs → entry-CBZsCy3O.mjs} +5 -6
- package/dist/{env-78hbN-oI.mjs → env-AvuCSeCH.mjs} +10 -11
- package/dist/{env-BaMz0j7H.mjs → env-CuzZZyjB.mjs} +3 -4
- package/dist/{env-0jrMQJI_.mjs → env-DtKg5G26.mjs} +2 -3
- package/dist/{env-helpers--wFmQ_5Q.mjs → env-helpers-Dj_SIwPu.mjs} +1 -2
- package/dist/{env-helpers-CyKtOBpj.d.mts → env-helpers-U56xuFgL.d.mts} +1 -3
- package/dist/{env-public-6lqiSD2b.d.mts → env-public-CeNeO_AT.d.mts} +2 -4
- package/dist/{env-raw-D74P4ebM.mjs → env-raw-e8qgqAzQ.mjs} +1 -2
- package/dist/{env-types-BicfKBhV.mjs → env-types-DqzVBKnS.mjs} +4 -5
- package/dist/{env-validation-BUfFZ6bt.mjs → env-validation-C8Cmvas0.mjs} +1 -1
- package/dist/{env-validation-B3VobvXm.mjs → env-validation-GV1oD4EV.mjs} +9 -10
- package/dist/{error-pages-CLIJ7aYq.mjs → error-pages-COVBnzK7.mjs} +6 -12
- package/dist/{fetch-CUX0tB78.d.mts → fetch-B-gLGYVl.d.mts} +0 -4
- package/dist/{fetch-CtESUYWd.mjs → fetch-C8yhLoF3.mjs} +3 -4
- package/dist/{fetch-error-Bw0n-IY-.mjs → fetch-error-DmlRM6e4.mjs} +2 -4
- package/dist/{fetch-stream-BspOeTAI.mjs → fetch-stream-DafNtVJC.mjs} +4 -5
- package/dist/{fetch-stream-DfkAzZf-.d.mts → fetch-stream-DuwxWmBM.d.mts} +1 -3
- package/dist/{gen-CFmsUsW1.mjs → gen-BD-dfjxY.mjs} +12 -13
- package/dist/gen-CIHXh9I8.mjs +1 -0
- package/dist/{generate-DkEb9rL-.mjs → generate-BOp1g1H_.mjs} +1 -1
- package/dist/{generate-B1m4Cm4n.mjs → generate-CWb8aOsm.mjs} +4 -5
- package/dist/{generated-wrangler-config-DeWj5F9Y.mjs → generated-wrangler-config-CoDaaFsA.mjs} +1 -2
- package/dist/{git-metadata-D-gurjzG.mjs → git-metadata-Cukp5kV5.mjs} +1 -2
- package/dist/{github-cmd-De-_IWbM.mjs → github-cmd-CA-lBdkn.mjs} +8 -9
- package/dist/{handler-BHktmuTL.d.mts → handler-BR6Tvjkp.d.mts} +18 -26
- package/dist/{handler-BZ1t7-Rv.mjs → handler-CKeTtYID.mjs} +6 -17
- package/dist/{head-D2VF4ApL.mjs → head-5XPcnG-j.mjs} +1 -2
- package/dist/{head-C8K_iGe6.d.mts → head-MeF_5M_3.d.mts} +0 -2
- package/dist/headers-CuTEdP9C.mjs +445 -0
- package/dist/{help-CKbrhZha.mjs → help-1OCFDsRr.mjs} +28 -12
- package/dist/help-Ba8Dq5-r.mjs +1 -0
- package/dist/{inbound-Da7XsjH3.d.mts → inbound-BHt4dIlL.d.mts} +16 -9
- package/dist/{inbound-VrOLqwZY.mjs → inbound-CdO-qY0w.mjs} +6 -81
- package/dist/index.d.mts +23 -13
- package/dist/index.mjs +495 -223
- package/dist/{info-Yg0-V5Rs.mjs → info-CJxua_db.mjs} +6 -7
- package/dist/{init-CDiJQycf.mjs → init-B-4CluYx.mjs} +43 -59
- package/dist/{isr-config-fZaJJ8t7.mjs → isr-config-Czzb4mIq.mjs} +5 -55
- package/dist/{limits-D0vD1M9A.mjs → limits-CrHLm5Tk.mjs} +1 -2
- package/dist/{limits-CFsDKQvU.d.mts → limits-_xIf5z_P.d.mts} +0 -2
- package/dist/{link-Dllip08S.mjs → link-DAXOT-G_.mjs} +8 -9
- package/dist/{list-BYRP6am0.mjs → list-BYSOo9fm.mjs} +8 -9
- package/dist/{live-BllfDuzA.d.mts → live-0xrcVpyq.d.mts} +2 -4
- package/dist/{live-BcHoTDFe.mjs → live-DF4HUl2m.mjs} +5 -7
- package/dist/{load-user-env-DD5qveNU.mjs → load-user-env-CSwdofj0.mjs} +1 -2
- package/dist/{local-d1-CAwAs9GH.mjs → local-d1-BLgsNUj9.mjs} +4 -5
- package/dist/{log-BMwmN5Ae.mjs → log-D9hwSySP.mjs} +3 -4
- package/dist/login-BpbYeu-n.mjs +1 -0
- package/dist/{login-PcFy5mlC.mjs → login-CJopTWX4.mjs} +6 -7
- package/dist/{logs-DmJTBhed.mjs → logs-DE0weBsR.mjs} +19 -18
- package/dist/{migrate-B8S2xTcb.mjs → migrate-ChHHZBTi.mjs} +20 -16
- package/dist/migrate-HdA6Kh2p.mjs +1 -0
- package/dist/{migration-handler-CwlEQUoo.d.mts → migration-handler-D8mDx3Ew.d.mts} +0 -4
- package/dist/{migration-handler-Cg0Y4EPu.mjs → migration-handler-DCehTlWs.mjs} +1 -2
- package/dist/{mime-BAyHPskU.mjs → mime-CtP6-qAF.mjs} +145 -18
- package/dist/{mysql-migration-sql-BIS5vbNk.mjs → mysql-migration-sql-CI9VTwjt.mjs} +3 -5
- package/dist/{neon-DTZr7Bu7.mjs → neon-CJzQSycr.mjs} +2 -3
- package/dist/nitro.d.mts +0 -2
- package/dist/nitro.mjs +5 -6
- package/dist/{node-CDOPrGSl.mjs → node-CZ6lGNLn.mjs} +8 -9
- package/dist/{operator-args-BsJIYXaT.mjs → operator-args-D79WQP70.mjs} +2 -3
- package/dist/{operator-auth-Cr2zCc-J.mjs → operator-auth-CfDcmzpo.mjs} +2 -3
- package/dist/{operator-client-C-ROjk1I.mjs → operator-client-BIY4-N_6.mjs} +3 -4
- package/dist/{operator-cmd-DmkmS2wL.mjs → operator-cmd-BUqsdk2K.mjs} +32 -15
- package/dist/operator-cmd-wBYyp8iQ.mjs +1 -0
- package/dist/{output-BpgYODYx.mjs → output-BCdLioKP.mjs} +4 -5
- package/dist/output-E6gecbbV.mjs +1 -0
- package/dist/{package-json-BjYqR-So.mjs → package-json-DvS6IFRv.mjs} +2 -3
- package/dist/pages/client.d.mts +147 -31
- package/dist/pages/client.mjs +199 -43
- package/dist/pages/head.d.mts +1 -1
- package/dist/pages/head.mjs +1 -1
- package/dist/pages/index.d.mts +25 -18
- package/dist/pages/index.mjs +24 -12
- package/dist/pages/islands-plugin.d.mts +75 -13
- package/dist/pages/islands-plugin.mjs +92 -7
- package/dist/pages/prefetch.d.mts +2 -2
- package/dist/pages/prefetch.mjs +1 -1
- package/dist/pages/protocol.d.mts +2 -2
- package/dist/pages/protocol.mjs +2 -2
- package/dist/pages/serialize.d.mts +1 -1
- package/dist/pages/serialize.mjs +1 -1
- package/dist/{pg-J2HbZIkX.mjs → pg-DoyPxa_X.mjs} +1 -2
- package/dist/{picocolors-BsDfhxIw.mjs → picocolors-D1NxSLw-.mjs} +2 -3
- package/dist/{plan-BhLO2p4w.mjs → plan-BOD70XGS.mjs} +1 -2
- package/dist/plan-CQ-N4gws.mjs +1 -0
- package/dist/platform-args-C7XUw9mw.mjs +1 -0
- package/dist/{platform-args-BMD2gjc_.mjs → platform-args-Cx1M-7bq.mjs} +22 -11
- package/dist/{platform-auth-config-CImnfohz.mjs → platform-auth-config-K4m_LE8b.mjs} +10 -11
- package/dist/{platform-auth-protection-BogLhtHi.mjs → platform-auth-protection-KF5Vo-1I.mjs} +10 -11
- package/dist/{platform-auth-recovery-B-mEaWEi.mjs → platform-auth-recovery-BOdFrl7R.mjs} +9 -11
- package/dist/{platform-cmd-CV8NxIIn.mjs → platform-cmd-DpCHawGF.mjs} +1 -1
- package/dist/{platform-cmd-DZK2ixMl.mjs → platform-cmd-Ds3EAV5t.mjs} +13 -13
- package/dist/{platform-discovery-CHhNs8Nn.mjs → platform-discovery-B0eZjZ3B.mjs} +2 -3
- package/dist/{platform-domain-CRvelPGE.mjs → platform-domain-rWJshybd.mjs} +7 -8
- package/dist/{platform-lifecycle-DwXq7kZt.mjs → platform-lifecycle-BH34I0rh.mjs} +1 -1
- package/dist/{platform-lifecycle-CPYY7E9B.mjs → platform-lifecycle-D9RdGub1.mjs} +110 -110
- package/dist/{platform-management-BOnGbMSM.mjs → platform-management-BRefdHGD.mjs} +27 -11
- package/dist/{platform-management-lXdgGgAM.mjs → platform-management-BfLW0Zlo.mjs} +1 -1
- package/dist/{platform-plans-config-CeydDSj0.mjs → platform-plans-config-Dx1agneU.mjs} +5 -6
- package/dist/{platform-recovery-noaALXnE.mjs → platform-recovery-DZuZGJtt.mjs} +5 -6
- package/dist/{platform-registry-B9mWX9LO.mjs → platform-registry-DZ_2Xuqd.mjs} +4 -6
- package/dist/platform-runtime-logs-CdJGnk3f.mjs +68 -0
- package/dist/{platform-setup-Ca53gtt0.mjs → platform-setup-Vw1AaUN8.mjs} +19 -7
- package/dist/{plugin-inference-CeiB6BG5.mjs → plugin-inference-CdLbxZL_.mjs} +16 -24
- package/dist/{prefetch-Bsc_Pb6c.mjs → prefetch-Dx2jIbtg.mjs} +20 -3
- package/dist/{prefetch-Ce6la4EI.d.mts → prefetch-NdNeubbH.d.mts} +7 -3
- package/dist/{prepare-D604Yiyr.mjs → prepare-BJW-f1f1.mjs} +13 -14
- package/dist/{prepare-BuOS18AM.mjs → prepare-BMGeKL16.mjs} +4 -5
- package/dist/prepare-BdxJJCMv.mjs +1 -0
- package/dist/{prerender-render-CaShbHJ3.mjs → prerender-render-RlAj6hh8.mjs} +2 -3
- package/dist/prerender-render.d.mts +1 -3
- package/dist/prerender-render.mjs +1 -1
- package/dist/{project-rqDnVsJN.mjs → project-CLwxcEdq.mjs} +3 -4
- package/dist/{project-zdB3fs9G.mjs → project-DVsTAWFh.mjs} +1 -1
- package/dist/{project-cmd-DBYqAIbe.mjs → project-cmd-B_bUyZ3J.mjs} +21 -23
- package/dist/{project-paths-DGu_QZ_Q.mjs → project-paths-CdGv9Tmi.mjs} +3 -5
- package/dist/project-slug-BUy0lmyR.mjs +1 -0
- package/dist/{project-slug-23TpquG4.mjs → project-slug-CO6ci9XG.mjs} +0 -1
- package/dist/{project-team-BjCLgTRC.mjs → project-team-MjT5K4rQ.mjs} +7 -8
- package/dist/{project-token-BB6PwaA9.mjs → project-token-BKHGwY3k.mjs} +7 -8
- package/dist/{project-tsconfig-CVvk6Z_e.mjs → project-tsconfig-Cf2NFjlM.mjs} +4 -6
- package/dist/{project-zero-trust-CWDh1P_t.mjs → project-zero-trust-Bzdd05-h.mjs} +7 -8
- package/dist/{protocol-DimNxVRr.mjs → protocol-COyySMki.mjs} +135 -113
- package/dist/{protocol-D5XDySYu.d.mts → protocol-CkwjASep.d.mts} +4 -6
- package/dist/{providers-BNKRacMr.d.mts → providers-D5P8j_8D.d.mts} +0 -2
- package/dist/{providers-BUHwJlmM.mjs → providers-ZARwX2cL.mjs} +1 -2
- package/dist/{provision-DztLJ97X.mjs → provision-BbCzpbXs.mjs} +6 -7
- package/dist/{provision-DfxLCg-d.mjs → provision-DQF6Kw-6.mjs} +1 -1
- package/dist/{queues-BWKt1Xo4.d.mts → queues-DdM42xXW.d.mts} +0 -2
- package/dist/{r2-conditions-B8xUgJRc.mjs → r2-conditions-BqkQNt2n.mjs} +1 -2
- package/dist/{requests-D_pbzDyz.mjs → requests-daJmVpjk.mjs} +6 -7
- package/dist/resolve-project-CgfjtOwz.mjs +1 -0
- package/dist/{resolve-project-Xoi6eTWY.mjs → resolve-project-D0YNnJfm.mjs} +4 -5
- package/dist/{resource-name-C7LVpcRm.mjs → resource-name-DlJ9QXzg.mjs} +1 -2
- package/dist/{response-Tn7rU0MV.mjs → response-HmNjB30w.mjs} +1 -2
- package/dist/{rollback-CjfIYsJx.mjs → rollback-BgL0wY1J.mjs} +7 -8
- package/dist/{rolldown-runtime-3h0WiCiA.mjs → rolldown-runtime-uD8oG6U2.mjs} +1 -2
- package/dist/{route-types-DvEGmPif.mjs → route-types-CZc1YXjF.mjs} +80 -9
- package/dist/route-url-CRDF-I0I.mjs +57 -0
- package/dist/route-url-C_YIH_zO.d.mts +37 -0
- package/dist/routes-stub.d.mts +8 -3
- package/dist/routes-stub.mjs +1 -1
- package/dist/{routing-assets-DdSFxoLp.mjs → routing-assets-DJIVOrCh.mjs} +1 -2
- package/dist/{runner-3uGC-oLF.mjs → runner-5MCSimKx.mjs} +5 -6
- package/dist/{runner-WCdfeI0q.mjs → runner-QMeOpScZ.mjs} +1 -1
- package/dist/{runner-mysql-BcHnLUuM.mjs → runner-mysql-0zVmB1JW.mjs} +1 -1
- package/dist/{runner-mysql-BWmbk5IE.mjs → runner-mysql-Bdmsp_x4.mjs} +3 -4
- package/dist/{runner-pg-Cgp-cr_p.mjs → runner-pg-2pjltt0t.mjs} +1 -1
- package/dist/{runner-pg-Cr3qrqi4.mjs → runner-pg-mYc75KfH.mjs} +2 -3
- package/dist/runtime/ai.d.mts +0 -4
- package/dist/runtime/ai.mjs +6 -8
- package/dist/runtime/auth-client-react.d.mts +1 -1
- package/dist/runtime/auth-client-react.mjs +1 -1
- package/dist/runtime/auth-client-solid.d.mts +1 -1
- package/dist/runtime/auth-client-solid.mjs +1 -1
- package/dist/runtime/auth-client-svelte.d.mts +1 -1
- package/dist/runtime/auth-client-svelte.mjs +1 -1
- package/dist/runtime/auth-client-vue.d.mts +1 -1
- package/dist/runtime/auth-client-vue.mjs +1 -1
- package/dist/runtime/auth-client.d.mts +1 -1
- package/dist/runtime/auth-client.mjs +1 -1
- package/dist/runtime/auth.d.mts +1 -1
- package/dist/runtime/auth.mjs +1 -1
- package/dist/runtime/better-auth-mysql.d.mts +2 -4
- package/dist/runtime/better-auth-mysql.mjs +3 -4
- package/dist/runtime/better-auth-pg.d.mts +2 -4
- package/dist/runtime/better-auth-pg.mjs +4 -5
- package/dist/runtime/better-auth.d.mts +2 -4
- package/dist/runtime/better-auth.mjs +3 -4
- package/dist/runtime/client-react.d.mts +4 -4
- package/dist/runtime/client-react.mjs +4 -4
- package/dist/runtime/client-solid.d.mts +4 -4
- package/dist/runtime/client-solid.mjs +4 -4
- package/dist/runtime/client-svelte.d.mts +4 -4
- package/dist/runtime/client-svelte.mjs +4 -4
- package/dist/runtime/client-vue.d.mts +4 -4
- package/dist/runtime/client-vue.mjs +4 -4
- package/dist/runtime/client.d.mts +4 -4
- package/dist/runtime/client.mjs +4 -4
- package/dist/runtime/db.d.mts +0 -2
- package/dist/runtime/db.mjs +2 -3
- package/dist/runtime/durable.d.mts +0 -2
- package/dist/runtime/durable.mjs +3 -4
- package/dist/runtime/email/testing.d.mts +1 -5
- package/dist/runtime/email/testing.mjs +5 -6
- package/dist/runtime/email-protocol.d.mts +0 -2
- package/dist/runtime/email-protocol.mjs +1 -1
- package/dist/runtime/email.d.mts +1 -5
- package/dist/runtime/email.mjs +6 -7
- package/dist/runtime/env-public-client.d.mts +1 -3
- package/dist/runtime/env-public-client.mjs +2 -3
- package/dist/runtime/env-public.d.mts +2 -2
- package/dist/runtime/env-public.mjs +5 -7
- package/dist/runtime/env.d.mts +0 -4
- package/dist/runtime/env.mjs +1 -1
- package/dist/runtime/fetch-server.d.mts +1 -3
- package/dist/runtime/fetch-server.mjs +3 -4
- package/dist/runtime/fetch-stream.d.mts +2 -2
- package/dist/runtime/fetch-stream.mjs +2 -2
- package/dist/runtime/fetch.d.mts +1 -1
- package/dist/runtime/fetch.mjs +2 -2
- package/dist/runtime/handler.d.mts +1 -1
- package/dist/runtime/handler.mjs +2 -2
- package/dist/runtime/isr.d.mts +1 -3
- package/dist/runtime/isr.mjs +2 -3
- package/dist/runtime/kv.d.mts +1 -3
- package/dist/runtime/kv.mjs +2 -3
- package/dist/runtime/limits.d.mts +1 -1
- package/dist/runtime/limits.mjs +1 -1
- package/dist/runtime/live-client.d.mts +1 -3
- package/dist/runtime/live-client.mjs +1 -2
- package/dist/runtime/live-server.d.mts +0 -2
- package/dist/runtime/live-server.mjs +3 -4
- package/dist/runtime/live.d.mts +1 -1
- package/dist/runtime/live.mjs +1 -1
- package/dist/runtime/log.d.mts +3 -3
- package/dist/runtime/log.mjs +26 -18
- package/dist/runtime/migration-handler-mysql.d.mts +2 -4
- package/dist/runtime/migration-handler-mysql.mjs +2 -3
- package/dist/runtime/migration-handler-pg.d.mts +2 -4
- package/dist/runtime/migration-handler-pg.mjs +2 -3
- package/dist/runtime/migration-handler.d.mts +1 -1
- package/dist/runtime/migration-handler.mjs +1 -1
- package/dist/runtime/queues.d.mts +1 -1
- package/dist/runtime/queues.mjs +2 -3
- package/dist/runtime/remote/binding-handler.d.mts +1 -3
- package/dist/runtime/remote/binding-handler.mjs +3 -4
- package/dist/runtime/remote/index.d.mts +1 -3
- package/dist/runtime/remote/index.mjs +8 -13
- package/dist/runtime/response.d.mts +1 -3
- package/dist/runtime/response.mjs +1 -1
- package/dist/runtime/route-url.d.mts +2 -2
- package/dist/runtime/route-url.mjs +1 -1
- package/dist/runtime/routing.d.mts +8 -11
- package/dist/runtime/routing.mjs +52 -32
- package/dist/runtime/sandbox-container.d.mts +1 -1
- package/dist/runtime/sandbox-container.mjs +1 -1
- package/dist/runtime/sandbox.d.mts +2 -2
- package/dist/runtime/sandbox.mjs +5 -6
- package/dist/runtime/seed.d.mts +0 -2
- package/dist/runtime/seed.mjs +1 -2
- package/dist/runtime/sse-client.d.mts +1 -3
- package/dist/runtime/sse-client.mjs +1 -2
- package/dist/runtime/sse.d.mts +1 -3
- package/dist/runtime/sse.mjs +1 -1
- package/dist/runtime/storage.d.mts +1 -3
- package/dist/runtime/storage.mjs +2 -3
- package/dist/runtime/validator.d.mts +1 -1
- package/dist/runtime/validator.mjs +1 -1
- package/dist/runtime/ws-server.d.mts +3 -5
- package/dist/runtime/ws-server.mjs +3 -4
- package/dist/runtime/ws.d.mts +1 -1
- package/dist/runtime/ws.mjs +3 -4
- package/dist/{sandbox-q3waMc2T.d.mts → sandbox-DE1WsxuB.d.mts} +2 -4
- package/dist/{sandbox-container-a9LRUtii.mjs → sandbox-container-BuxhwCgt.mjs} +1 -2
- package/dist/{sandbox-container-ChQRum-j.d.mts → sandbox-container-CZFZdMso.d.mts} +0 -2
- package/dist/{scan-N9WzdcAl.mjs → scan-X2rDDRNa.mjs} +49 -35
- package/dist/{secret-3X0PxmuX.mjs → secret-CPq-B_vp.mjs} +17 -15
- package/dist/{serialize-YHvlcG3Q.mjs → serialize-DUuYuaY3.mjs} +2 -4
- package/dist/{serialize-DtR8Vwa_.d.mts → serialize-I4EmS-Wf.d.mts} +0 -2
- package/dist/{skills-CrUO3PJ0.mjs → skills-D393E4lB.mjs} +4 -5
- package/dist/{sqlite-validation-BzKMWnO4.mjs → sqlite-validation-CLJXXN93.mjs} +1 -2
- package/dist/{sse-CMvCgjNk.mjs → sse-CxR30yMF.mjs} +1 -2
- package/dist/{standard-schema-Fo_vCAZh.d.mts → standard-schema-CuDawHOC.d.mts} +0 -2
- package/dist/{static-asset-marker-Btf-6oCD.mjs → static-asset-marker-DsQKz6lt.mjs} +9 -3
- package/dist/{subcommand-prompt-D9OhhbGG.mjs → subcommand-prompt-CxJXporl.mjs} +3 -4
- package/dist/sveltekit.d.mts +0 -2
- package/dist/sveltekit.mjs +2 -3
- package/dist/{terminal-log-text-D9ACPOuG.mjs → terminal-log-text-DNsWJREL.mjs} +1 -2
- package/dist/{types-w72dljaA.d.mts → types-agfx0alu.d.mts} +0 -4
- package/dist/validate-DY1U9rET.mjs +1 -0
- package/dist/{validate-CnZPMq4q.mjs → validate-Ddzl-IwT.mjs} +4 -5
- package/dist/validation-error-uAAjlsiW.mjs +82 -0
- package/dist/{validator-BTOu0fB0.mjs → validator-CTfmzZYb.mjs} +2 -5
- package/dist/{version-metadata-D2vfMQzv.mjs → version-metadata-C8hLzQkv.mjs} +4 -6
- package/dist/{worker-conditions-AWFRcFxR.mjs → worker-conditions-CBZ0RYsZ.mjs} +1 -2
- package/dist/{wrangler-I-scB_1t.mjs → wrangler-DESSbN8L.mjs} +6 -8
- package/dist/wrangler-DUB3MGHV.mjs +1 -0
- package/dist/{wrapper-BBl1rC32.mjs → wrapper-C9SUxoj7.mjs} +17 -14
- package/dist/{ws-B3ClMVDh.d.mts → ws-Dmjg5NH2.d.mts} +3 -5
- package/dist/{yarn-pnp-DLbEFMT0.mjs → yarn-pnp-DgWbE7z5.mjs} +2 -3
- package/docs/guide/database.md +4 -4
- package/docs/guide/deployment.md +1 -1
- package/docs/guide/edge/headers.md +4 -6
- package/docs/guide/edge/redirects.md +4 -4
- package/docs/guide/edge/rewrites.md +1 -1
- package/docs/guide/edge/static-assets.md +0 -10
- package/docs/guide/email/domains.md +3 -1
- package/docs/guide/email/receiving.md +4 -4
- package/docs/guide/email/sending.md +43 -13
- package/docs/guide/pages-routing/actions-and-forms.md +26 -9
- package/docs/guide/pages-routing/islands.md +5 -5
- package/docs/guide/pages-routing/layouts.md +16 -2
- package/docs/guide/pages-routing/loaders.md +5 -5
- package/docs/guide/pages-routing/markdown.md +7 -7
- package/docs/guide/pages-routing/overview.md +137 -27
- package/docs/guide/platform/administration/connected-apps.md +4 -2
- package/docs/guide/platform/administration/email.md +6 -8
- package/docs/guide/platform/installation/credentials.md +12 -10
- package/docs/guide/platform/installation/maintenance.md +18 -21
- package/docs/guide/platform/installation/prerequisites.md +1 -1
- package/docs/guide/platform/installation/setup.md +23 -2
- package/docs/guide/platform/installation/uninstall.md +1 -1
- package/docs/guide/queues.md +4 -8
- package/docs/guide/self-hosted-platform.md +3 -3
- package/docs/guide/server-routing.md +7 -7
- package/docs/guide/ssg.md +3 -3
- package/docs/guide/type-safety.md +84 -1
- package/docs/guide/typed-fetch.md +1 -1
- package/docs/guide/websockets.md +1 -1
- package/docs/integrations/cloudflare.md +2 -2
- package/docs/integrations/frameworks/analog.md +1 -1
- package/docs/integrations/frameworks/astro.md +17 -12
- package/docs/integrations/frameworks/nuxt.md +1 -1
- package/docs/integrations/frameworks/overview.md +2 -2
- package/docs/integrations/frameworks/sveltekit.md +1 -1
- package/docs/integrations/frameworks/tanstack-start.md +1 -1
- package/docs/integrations/hono.md +5 -5
- package/docs/reference/api/auth.md +1 -1
- package/docs/reference/api/deploy.md +6 -6
- package/docs/reference/api/pages.md +109 -50
- package/docs/reference/api/plugin.md +4 -4
- package/docs/reference/api/resources.md +4 -1
- package/docs/reference/api/rewrites.md +24 -3
- package/docs/reference/api/types.md +45 -0
- package/docs/reference/api.md +2 -2
- package/docs/reference/cli/database.md +15 -9
- package/docs/reference/cli/email.md +4 -2
- package/docs/reference/cli/platform-installation.md +6 -3
- package/docs/reference/cli/project.md +2 -2
- package/docs/reference/cli/secrets.md +3 -1
- package/docs/reference/cli/setup.md +4 -4
- package/docs/reference/cli.md +1 -1
- package/docs/reference/config.md +12 -2
- package/package.json +36 -32
- package/sandbox.Dockerfile +1 -1
- package/schema.json +4 -0
- package/skills/void/SKILL.md +5 -0
- package/dist/cf-build-output-bd8Uwv1P.mjs +0 -1
- package/dist/client-BZb9j66F.mjs +0 -1
- package/dist/collect-BWhkgtAn.mjs +0 -1
- package/dist/deploy-CX94CmKa.mjs +0 -2
- package/dist/discover-D4TPKo57.mjs +0 -1
- package/dist/gen-BhWBT4iu.mjs +0 -1
- package/dist/headers--vaK_chu.mjs +0 -226
- package/dist/help-qOZr3wng.mjs +0 -1
- package/dist/login-BAPmYnb7.mjs +0 -1
- package/dist/migrate-BIYTPQE6.mjs +0 -1
- package/dist/operator-cmd-CjazwOyb.mjs +0 -1
- package/dist/output-BW9uK099.mjs +0 -1
- package/dist/plan-CKX_jWnD.mjs +0 -1
- package/dist/platform-args-BC8_hsDj.mjs +0 -1
- package/dist/prepare-DU-tOpS5.mjs +0 -1
- package/dist/project-slug-6cyz8E7k.mjs +0 -1
- package/dist/resolve-project-DD1vu8s9.mjs +0 -1
- package/dist/route-url-BgPja1GS.d.mts +0 -5
- package/dist/route-url-BjGv_KKY.mjs +0 -28
- package/dist/validate-D7Wn8PUX.mjs +0 -1
- package/dist/validation-error-Dg9Recn1.mjs +0 -49
- package/dist/wrangler-UnwdISay.mjs +0 -1
|
@@ -11,8 +11,8 @@ Use an action to change server data from a form or button. Define it in the page
|
|
|
11
11
|
Export `action` from a `.server.ts` file. Use `withValidator()` with a [schema-derived validator](../database.md#schema-derived-validators) to validate the request body:
|
|
12
12
|
|
|
13
13
|
```ts
|
|
14
|
-
import { users, insertUserSchema } from '@schema';
|
|
15
14
|
// pages/users/index.server.ts
|
|
15
|
+
import { users, insertUserSchema } from '@schema';
|
|
16
16
|
import { defineHandler } from 'void';
|
|
17
17
|
import { db } from 'void/db';
|
|
18
18
|
|
|
@@ -29,6 +29,8 @@ export const action = defineHandler.withValidator({
|
|
|
29
29
|
| Nothing (void) | Re-runs the loader, page re-renders with fresh props. |
|
|
30
30
|
| `c.redirect('/path')` | Navigates to another page. |
|
|
31
31
|
|
|
32
|
+
Middleware does not run again after the action. To change [shared data](./layouts.md#shared-data), update it in the action or redirect.
|
|
33
|
+
|
|
32
34
|
## Form
|
|
33
35
|
|
|
34
36
|
Pair `Form` with `useForm` to submit values and display validation and action errors. Inputs stay editable when a submission fails.
|
|
@@ -163,7 +165,7 @@ The types are inferred from your action's `withValidator()` schema in the compan
|
|
|
163
165
|
| `clearErrors(...fields)` | Clear validation errors. Field names autocomplete. |
|
|
164
166
|
| `clearError()` | Clear `error`. |
|
|
165
167
|
|
|
166
|
-
Use `setError()`
|
|
168
|
+
Use `setError()` for client-side validation. Editing a field clears its error automatically.
|
|
167
169
|
|
|
168
170
|
For a native React form, use `form.post`, `form.put`, `form.patch`, or `form.delete` as a native form action. For an awaitable mutation, use `action()`. In Vue, Svelte, and Solid, form submissions return `Promise<void>`; catch thrown errors or use your framework's error handling.
|
|
169
171
|
|
|
@@ -175,7 +177,7 @@ const form = useForm('/users/:id', { name: '' }, { params: { id: '42' } });
|
|
|
175
177
|
<Form form={form} method="put">{/* submits to /users/42 */}</Form>
|
|
176
178
|
```
|
|
177
179
|
|
|
178
|
-
|
|
180
|
+
To clear a create form after saving, pass `resetOnSuccess: true` in the third argument. Use `form.reset({ initial: true })` to restore the original values manually.
|
|
179
181
|
|
|
180
182
|
### React submission callbacks
|
|
181
183
|
|
|
@@ -188,26 +190,41 @@ const form = useForm(
|
|
|
188
190
|
{
|
|
189
191
|
onSuccess: () => setDialogOpen(false),
|
|
190
192
|
onError: (error) => {
|
|
191
|
-
// A field-error map or VoidActionError for a handled action failure.
|
|
192
193
|
console.error(error);
|
|
193
194
|
},
|
|
194
195
|
},
|
|
195
196
|
);
|
|
196
197
|
```
|
|
197
198
|
|
|
198
|
-
|
|
199
|
+
`onError` receives a field-error map or a `VoidActionError`. Callbacks can be async; `form.pending` stays true until they finish, and thrown errors reach the nearest React error boundary. Callbacks run before React commits the updated UI, so use an effect or ref callback to focus an element that appears after submission.
|
|
199
200
|
|
|
200
|
-
|
|
201
|
+
If a callback awaits `router.visit()` or `router.refresh()`, pass `{ resolveOn: 'data' }` so it can finish before React commits the navigation. See [React navigation completion](../../reference/api/pages.md#react-navigation-completion).
|
|
201
202
|
|
|
202
203
|
Vue, Svelte, and Solid submissions return a promise instead; use `await form.post()` to run work after a submission.
|
|
203
204
|
|
|
205
|
+
### Scroll after submission
|
|
206
|
+
|
|
207
|
+
Actions and forms keep the current scroll position when updating the page in place. Redirects and submissions that open another page scroll to the top, or to the destination's hash target.
|
|
208
|
+
|
|
209
|
+
Pass `preserveScroll: false` to reset scroll after an in-place update, or `true` to keep it even after a redirect:
|
|
210
|
+
|
|
211
|
+
```ts
|
|
212
|
+
await action('/users/:id?update', {
|
|
213
|
+
params: { id: '42' },
|
|
214
|
+
data: { name: 'Alice' },
|
|
215
|
+
preserveScroll: false,
|
|
216
|
+
});
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
In React, set `preserveScroll` in the third argument to `useForm()`. In Vue, Svelte, and Solid, pass it to the submit method, such as `form.post({ preserveScroll: false })`.
|
|
220
|
+
|
|
204
221
|
## Named Actions
|
|
205
222
|
|
|
206
223
|
When a page needs multiple mutations, such as updating and deleting a user on the same page, export `actions` (plural) instead of `action`:
|
|
207
224
|
|
|
208
225
|
```ts
|
|
209
|
-
import { users, updateUserSchema } from '@schema';
|
|
210
226
|
// pages/users/[id].server.ts
|
|
227
|
+
import { users, updateUserSchema } from '@schema';
|
|
211
228
|
import { defineHandler } from 'void';
|
|
212
229
|
import { db, eq } from 'void/db';
|
|
213
230
|
|
|
@@ -227,7 +244,7 @@ export const actions = {
|
|
|
227
244
|
};
|
|
228
245
|
```
|
|
229
246
|
|
|
230
|
-
Named actions
|
|
247
|
+
Named actions use a `?actionName` suffix, such as `/users/42?update`. `useForm` and `action()` handle this automatically. After a POST action renders the page or uses a default `c.redirect()`, the page URL keeps ordinary query parameters: `/users/42?update&tab=profile` becomes `/users/42?tab=profile`. See [redirect query parameters](../../reference/api/rewrites.md#c-rewrite-destination) for redirects that preserve the request method.
|
|
231
248
|
|
|
232
249
|
Use `action` or `actions` in a file, not both.
|
|
233
250
|
|
|
@@ -273,7 +290,7 @@ if (!result.ok) {
|
|
|
273
290
|
|
|
274
291
|
`action()` defaults to `POST`. Pass `data`, `params`, and `method` to set the body, route parameters, or HTTP method.
|
|
275
292
|
|
|
276
|
-
A successful call returns `{ ok: true, pageData }`. Expected errors, such as validation failures or conflicts, return `{ ok: false, error }`.
|
|
293
|
+
A successful call returns `{ ok: true, pageData }`. Expected errors, such as validation failures or conflicts, return `{ ok: false, error }`. `error.message` is the message of an [`HTTPException`](../../integrations/hono.md#utilities) with a `4xx` status, or the body of another plain-text `4xx` response. For other errors, it is a status summary such as `Action failed with 404 Not Found`.
|
|
277
294
|
|
|
278
295
|
## Validation Errors
|
|
279
296
|
|
|
@@ -96,11 +96,11 @@ export default function BlogIndex({ posts }) {
|
|
|
96
96
|
|
|
97
97
|
```vue [Vue]
|
|
98
98
|
<!-- pages/blog/index.island.vue -->
|
|
99
|
-
<script setup>
|
|
99
|
+
<script setup lang="ts">
|
|
100
100
|
import Counter from './_Counter.vue' with { island: 'load' };
|
|
101
101
|
import PostForm from './_PostForm.vue' with { island: 'visible' };
|
|
102
102
|
|
|
103
|
-
defineProps
|
|
103
|
+
const { posts } = defineProps<{ posts: { slug: string; title: string }[] }>();
|
|
104
104
|
</script>
|
|
105
105
|
|
|
106
106
|
<template>
|
|
@@ -135,8 +135,8 @@ let { posts } = $props();
|
|
|
135
135
|
```
|
|
136
136
|
|
|
137
137
|
```tsx [Solid]
|
|
138
|
-
import { For } from 'solid-js';
|
|
139
138
|
// pages/blog/index.island.tsx
|
|
139
|
+
import { For } from 'solid-js';
|
|
140
140
|
import Counter from './_Counter' with { island: 'load' };
|
|
141
141
|
import PostForm from './_PostForm' with { island: 'visible' };
|
|
142
142
|
|
|
@@ -209,7 +209,7 @@ After a successful action, an island page reloads or redirects through `window.l
|
|
|
209
209
|
|
|
210
210
|
## Forms
|
|
211
211
|
|
|
212
|
-
|
|
212
|
+
Use `useIslandForm` for forms in island components. It provides the same form state as `useForm`, and its submit helpers take the action URL:
|
|
213
213
|
|
|
214
214
|
::: code-group
|
|
215
215
|
|
|
@@ -249,7 +249,7 @@ export default function PostForm() {
|
|
|
249
249
|
```
|
|
250
250
|
|
|
251
251
|
```vue [Vue]
|
|
252
|
-
<script setup>
|
|
252
|
+
<script setup lang="ts">
|
|
253
253
|
import { useIslandForm } from '@void/vue';
|
|
254
254
|
|
|
255
255
|
const form = useIslandForm({ title: '', body: '' });
|
|
@@ -167,7 +167,7 @@ export default function Page() {
|
|
|
167
167
|
```
|
|
168
168
|
|
|
169
169
|
```vue [Vue]
|
|
170
|
-
<script>
|
|
170
|
+
<script lang="ts">
|
|
171
171
|
export const layout = 'landing';
|
|
172
172
|
</script>
|
|
173
173
|
|
|
@@ -238,4 +238,18 @@ export default defineMiddleware(async (c, next) => {
|
|
|
238
238
|
});
|
|
239
239
|
```
|
|
240
240
|
|
|
241
|
-
Call `useShared()` from your framework adapter, as in the layout examples above. Its return type is inferred from `CloudContextVariables`.
|
|
241
|
+
Call `useShared()` from your framework adapter, as in the layout examples above. Its return type is inferred from `CloudContextVariables`. See [Context variables](../type-safety.md#context-variables).
|
|
242
|
+
|
|
243
|
+
Middleware sets the starting value. A loader or action can update it before the page is sent:
|
|
244
|
+
|
|
245
|
+
```ts
|
|
246
|
+
// pages/profile.server.ts
|
|
247
|
+
import { defineHandler } from 'void';
|
|
248
|
+
|
|
249
|
+
export const action = defineHandler(async (c) => {
|
|
250
|
+
const user = await updateProfile(c);
|
|
251
|
+
c.set('shared', { ...c.get('shared'), auth: { user } });
|
|
252
|
+
});
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
Middleware runs before the action. If an action changes data that shared data is built from, update shared data in the action, or redirect with `c.redirect()` so middleware runs again on the next page load.
|
|
@@ -11,8 +11,8 @@ A loader fetches the data a page needs. Define it in a companion `.server.ts` fi
|
|
|
11
11
|
`loader` runs on GET requests and returns an object that becomes the page's props:
|
|
12
12
|
|
|
13
13
|
```ts
|
|
14
|
-
import { users } from '@schema';
|
|
15
14
|
// pages/users/index.server.ts
|
|
15
|
+
import { users } from '@schema';
|
|
16
16
|
import { defineHandler } from 'void';
|
|
17
17
|
import type { InferProps } from 'void';
|
|
18
18
|
import { db } from 'void/db';
|
|
@@ -51,7 +51,7 @@ export default function UsersPage({ users }: Props) {
|
|
|
51
51
|
<!-- pages/users/index.vue -->
|
|
52
52
|
<script setup lang="ts">
|
|
53
53
|
import type { Props } from './index.server';
|
|
54
|
-
defineProps<Props>();
|
|
54
|
+
const { users } = defineProps<Props>();
|
|
55
55
|
</script>
|
|
56
56
|
|
|
57
57
|
<template>
|
|
@@ -79,8 +79,8 @@ defineProps<Props>();
|
|
|
79
79
|
```
|
|
80
80
|
|
|
81
81
|
```tsx [Solid]
|
|
82
|
-
import { For } from 'solid-js';
|
|
83
82
|
// pages/users/index.tsx
|
|
83
|
+
import { For } from 'solid-js';
|
|
84
84
|
import type { Props } from './index.server';
|
|
85
85
|
|
|
86
86
|
export default function UsersPage(props: Props) {
|
|
@@ -102,8 +102,8 @@ export default function UsersPage(props: Props) {
|
|
|
102
102
|
Use `defer()` for slow data. The page renders immediately and receives the result when it is ready:
|
|
103
103
|
|
|
104
104
|
```ts
|
|
105
|
-
import { projects } from '@schema';
|
|
106
105
|
// pages/dashboard.server.ts
|
|
106
|
+
import { projects } from '@schema';
|
|
107
107
|
import { defineHandler, defer } from 'void';
|
|
108
108
|
import type { InferProps } from 'void';
|
|
109
109
|
import { db } from 'void/db';
|
|
@@ -177,7 +177,7 @@ Check `loading` first, then `error`. TypeScript narrows `value` to `T` in the re
|
|
|
177
177
|
```vue [Vue]
|
|
178
178
|
<script setup lang="ts">
|
|
179
179
|
import type { Props } from './dashboard.server';
|
|
180
|
-
defineProps<Props>();
|
|
180
|
+
const { projects, usage } = defineProps<Props>();
|
|
181
181
|
</script>
|
|
182
182
|
|
|
183
183
|
<template>
|
|
@@ -64,9 +64,9 @@ Add the plugin to your Vite config **after** the framework adapter:
|
|
|
64
64
|
::: code-group
|
|
65
65
|
|
|
66
66
|
```ts [React]
|
|
67
|
+
// vite.config.ts
|
|
67
68
|
import { voidMarkdown } from '@void/md/plugin';
|
|
68
69
|
import { voidReact } from '@void/react/plugin';
|
|
69
|
-
// vite.config.ts
|
|
70
70
|
import { defineConfig } from 'vite';
|
|
71
71
|
import { voidPlugin } from 'void';
|
|
72
72
|
|
|
@@ -76,9 +76,9 @@ export default defineConfig({
|
|
|
76
76
|
```
|
|
77
77
|
|
|
78
78
|
```ts [Vue]
|
|
79
|
+
// vite.config.ts
|
|
79
80
|
import { voidMarkdown } from '@void/md/plugin';
|
|
80
81
|
import { voidVue } from '@void/vue/plugin';
|
|
81
|
-
// vite.config.ts
|
|
82
82
|
import { defineConfig } from 'vite';
|
|
83
83
|
import { voidPlugin } from 'void';
|
|
84
84
|
|
|
@@ -88,9 +88,9 @@ export default defineConfig({
|
|
|
88
88
|
```
|
|
89
89
|
|
|
90
90
|
```ts [Svelte]
|
|
91
|
+
// vite.config.ts
|
|
91
92
|
import { voidMarkdown } from '@void/md/plugin';
|
|
92
93
|
import { voidSvelte } from '@void/svelte/plugin';
|
|
93
|
-
// vite.config.ts
|
|
94
94
|
import { defineConfig } from 'vite';
|
|
95
95
|
import { voidPlugin } from 'void';
|
|
96
96
|
|
|
@@ -100,9 +100,9 @@ export default defineConfig({
|
|
|
100
100
|
```
|
|
101
101
|
|
|
102
102
|
```ts [Solid]
|
|
103
|
+
// vite.config.ts
|
|
103
104
|
import { voidMarkdown } from '@void/md/plugin';
|
|
104
105
|
import { voidSolid } from '@void/solid/plugin';
|
|
105
|
-
// vite.config.ts
|
|
106
106
|
import { defineConfig } from 'vite';
|
|
107
107
|
import { voidPlugin } from 'void';
|
|
108
108
|
|
|
@@ -190,7 +190,7 @@ export default function DocsLayout({ children }) {
|
|
|
190
190
|
```
|
|
191
191
|
|
|
192
192
|
```vue [Vue]
|
|
193
|
-
<script setup>
|
|
193
|
+
<script setup lang="ts">
|
|
194
194
|
import { useFrontmatter } from '@void/md';
|
|
195
195
|
|
|
196
196
|
const fm = useFrontmatter();
|
|
@@ -230,7 +230,7 @@ export default function DocsLayout(props) {
|
|
|
230
230
|
|
|
231
231
|
:::
|
|
232
232
|
|
|
233
|
-
Island components
|
|
233
|
+
Island components can also call `useFrontmatter()`. Keep frontmatter on pages with islands safe to share with the browser.
|
|
234
234
|
|
|
235
235
|
## Pages Virtual Module
|
|
236
236
|
|
|
@@ -241,7 +241,7 @@ import pages from '@void/md/pages';
|
|
|
241
241
|
// [{ path: "/docs/getting-started", title: "Getting Started", frontmatter: {...}, headings: [...] }, ...]
|
|
242
242
|
```
|
|
243
243
|
|
|
244
|
-
The list
|
|
244
|
+
The list follows [page environment suffixes](./overview.md#environment-only-pages): `debug.dev.md` appears as `/debug` during development.
|
|
245
245
|
|
|
246
246
|
Each entry has this shape:
|
|
247
247
|
|
|
@@ -41,8 +41,8 @@ Add both plugins to your Vite config:
|
|
|
41
41
|
::: code-group
|
|
42
42
|
|
|
43
43
|
```ts [React]
|
|
44
|
-
import { voidReact } from '@void/react/plugin';
|
|
45
44
|
// vite.config.ts
|
|
45
|
+
import { voidReact } from '@void/react/plugin';
|
|
46
46
|
import { defineConfig } from 'vite';
|
|
47
47
|
import { voidPlugin } from 'void';
|
|
48
48
|
|
|
@@ -52,8 +52,8 @@ export default defineConfig({
|
|
|
52
52
|
```
|
|
53
53
|
|
|
54
54
|
```ts [Vue]
|
|
55
|
-
import { voidVue } from '@void/vue/plugin';
|
|
56
55
|
// vite.config.ts
|
|
56
|
+
import { voidVue } from '@void/vue/plugin';
|
|
57
57
|
import { defineConfig } from 'vite';
|
|
58
58
|
import { voidPlugin } from 'void';
|
|
59
59
|
|
|
@@ -63,8 +63,8 @@ export default defineConfig({
|
|
|
63
63
|
```
|
|
64
64
|
|
|
65
65
|
```ts [Svelte]
|
|
66
|
-
import { voidSvelte } from '@void/svelte/plugin';
|
|
67
66
|
// vite.config.ts
|
|
67
|
+
import { voidSvelte } from '@void/svelte/plugin';
|
|
68
68
|
import { defineConfig } from 'vite';
|
|
69
69
|
import { voidPlugin } from 'void';
|
|
70
70
|
|
|
@@ -74,8 +74,8 @@ export default defineConfig({
|
|
|
74
74
|
```
|
|
75
75
|
|
|
76
76
|
```ts [Solid]
|
|
77
|
-
import { voidSolid } from '@void/solid/plugin';
|
|
78
77
|
// vite.config.ts
|
|
78
|
+
import { voidSolid } from '@void/solid/plugin';
|
|
79
79
|
import { defineConfig } from 'vite';
|
|
80
80
|
import { voidPlugin } from 'void';
|
|
81
81
|
|
|
@@ -94,16 +94,9 @@ Pages can be flat files such as `about.vue` or directory-based routes such as `a
|
|
|
94
94
|
|
|
95
95
|
<PagesFileTree />
|
|
96
96
|
|
|
97
|
-
|
|
97
|
+
Use one page file per URL in each environment.
|
|
98
98
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
| File | Role |
|
|
102
|
-
| ---------------------- | ------------------------------ |
|
|
103
|
-
| `pages/foo.tsx` | Page component at `/foo` |
|
|
104
|
-
| `pages/foo.server.tsx` | Server companion for that page |
|
|
105
|
-
|
|
106
|
-
A companion can export:
|
|
99
|
+
Pair a page with a `.server.ts` file for server code, such as `about.server.ts` for `about.vue`. Companions also support `.js`, `.mts`, `.mjs`, and [JSX](../server-routing.md#jsx-handlers) with `.tsx` or `.jsx`. They can export:
|
|
107
100
|
|
|
108
101
|
- A [**loader**](./loaders), which runs on `GET` and returns the data that becomes the page component's props
|
|
109
102
|
- [**Actions**](./actions-and-forms), which handle mutations from forms and programmatic calls. Export a single `action` or multiple [named actions](./actions-and-forms#named-actions) when a page has several mutations
|
|
@@ -113,7 +106,7 @@ File-based routing rules are the same as [server routing](../server-routing.md):
|
|
|
113
106
|
|
|
114
107
|
### Environment-only pages
|
|
115
108
|
|
|
116
|
-
Add a `.dev` or `.prod` suffix before the extension to
|
|
109
|
+
Add a `.dev` or `.prod` suffix before the extension to choose when a page is available:
|
|
117
110
|
|
|
118
111
|
```
|
|
119
112
|
pages/
|
|
@@ -126,12 +119,9 @@ pages/
|
|
|
126
119
|
|
|
127
120
|
`.dev` pages run only on the dev server; `.prod` pages run in builds, deployments, and production previews.
|
|
128
121
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
- Suffixes apply to page files only. Layouts take no suffix.
|
|
133
|
-
- A resource used only by `.dev` pages and their companions is not provisioned for production.
|
|
134
|
-
- The dev server and builds generate types for their own environment. `void prepare` generates types for both.
|
|
122
|
+
Keep the suffix in companion filenames (`home.dev.server.ts`) and place it before `.island` for island pages (`chart.dev.island.tsx`). Layouts are shared across environments.
|
|
123
|
+
|
|
124
|
+
Production deploys exclude resources used only by `.dev` pages and their companions. Run `void prepare` to generate types for both environments.
|
|
135
125
|
|
|
136
126
|
## How Navigation Works
|
|
137
127
|
|
|
@@ -163,46 +153,54 @@ Render and prerender flags combine like this:
|
|
|
163
153
|
| Island page + `ssr = false` | Invalid. Island pages already use the island renderer. |
|
|
164
154
|
| `output: "static"` + `prerender` unset | Auto-prerender pages that have known paths, including client-only shells. |
|
|
165
155
|
|
|
166
|
-
|
|
156
|
+
### Typed navigation
|
|
157
|
+
|
|
158
|
+
Use the `Link` component for SPA navigation between pages. Build dynamic URLs with [`routeUrl()`](../type-safety.md#typed-urls-and-navigation) to check the route pattern and its parameters:
|
|
167
159
|
|
|
168
160
|
::: code-group
|
|
169
161
|
|
|
170
162
|
```tsx [React]
|
|
171
163
|
import { Link } from "@void/react";
|
|
164
|
+
import { routeUrl } from 'void/routes';
|
|
172
165
|
|
|
173
166
|
<Link href="/users">Users</Link>
|
|
174
|
-
<Link href={
|
|
167
|
+
<Link href={routeUrl('/users/:id', { params: { id } })}>View</Link>
|
|
175
168
|
```
|
|
176
169
|
|
|
177
170
|
```vue [Vue]
|
|
178
171
|
<script setup lang="ts">
|
|
179
172
|
import { Link } from '@void/vue';
|
|
173
|
+
import { routeUrl } from 'void/routes';
|
|
180
174
|
</script>
|
|
181
175
|
|
|
182
176
|
<template>
|
|
183
177
|
<Link href="/users">Users</Link>
|
|
184
|
-
<Link :href="
|
|
178
|
+
<Link :href="routeUrl('/users/:id', { params: { id } })">View</Link>
|
|
185
179
|
</template>
|
|
186
180
|
```
|
|
187
181
|
|
|
188
182
|
```svelte [Svelte]
|
|
189
183
|
<script>
|
|
190
184
|
import { Link } from "@void/svelte";
|
|
185
|
+
import { routeUrl } from 'void/routes';
|
|
191
186
|
</script>
|
|
192
187
|
|
|
193
188
|
<Link href="/users">Users</Link>
|
|
194
|
-
<Link href={
|
|
189
|
+
<Link href={routeUrl('/users/:id', { params: { id } })}>View</Link>
|
|
195
190
|
```
|
|
196
191
|
|
|
197
192
|
```tsx [Solid]
|
|
198
193
|
import { Link } from "@void/solid";
|
|
194
|
+
import { routeUrl } from 'void/routes';
|
|
199
195
|
|
|
200
196
|
<Link href="/users">Users</Link>
|
|
201
|
-
<Link href={
|
|
197
|
+
<Link href={routeUrl('/users/:id', { params: { id } })}>View</Link>
|
|
202
198
|
```
|
|
203
199
|
|
|
204
200
|
:::
|
|
205
201
|
|
|
202
|
+
With [`routing.typedRoutes`](../type-safety.md#checked-url-strings), which apps created with `void init` have on, `href` and the router methods below reject plain strings such as `"/user"` that don't match a route.
|
|
203
|
+
|
|
206
204
|
`Link` also supports query data, history replacement, full-page navigation, and cancellation:
|
|
207
205
|
|
|
208
206
|
```tsx
|
|
@@ -232,17 +230,28 @@ import { Link } from "@void/solid";
|
|
|
232
230
|
|
|
233
231
|
`prefetch` and `reloadDocument` work only with GET links. GET `data` becomes query parameters; use scalar values or arrays.
|
|
234
232
|
|
|
235
|
-
For programmatic navigation, use `useRouter()`:
|
|
233
|
+
For programmatic navigation, use `useRouter()`. Pass a typed destination object to `visit()`, `prefetch()`, or `flush()`:
|
|
236
234
|
|
|
237
235
|
```ts
|
|
238
236
|
import { useRouter } from '@void/vue'; // or "@void/react", "@void/svelte", "@void/solid"
|
|
237
|
+
import type { RouteDestination } from 'void/routes';
|
|
239
238
|
|
|
240
239
|
const router = useRouter();
|
|
241
|
-
|
|
240
|
+
const profile = {
|
|
241
|
+
pathname: '/users/:id',
|
|
242
|
+
params: { id: 42 },
|
|
243
|
+
query: { tab: 'activity' },
|
|
244
|
+
} satisfies RouteDestination;
|
|
245
|
+
|
|
246
|
+
await router.prefetch(profile);
|
|
247
|
+
await router.visit(profile);
|
|
248
|
+
router.flush(profile); // clear its prefetched data
|
|
242
249
|
router.refresh(); // re-fetch current page props, keeping the same history entry
|
|
243
250
|
router.visit('/logout', { method: 'POST' }); // non-GET navigation
|
|
244
251
|
```
|
|
245
252
|
|
|
253
|
+
You can also pass URL strings or `URL` instances to these router methods. See [Typed URLs and Navigation](../type-safety.md#typed-urls-and-navigation) for query values, fragments, and catch-all routes.
|
|
254
|
+
|
|
246
255
|
`router.visit()` updates the page in place for same-origin URLs. `http(s)` URLs on another origin get a full page load, and other schemes such as `javascript:` are rejected.
|
|
247
256
|
|
|
248
257
|
For dynamic route params, use `useParams()` from the same adapter package:
|
|
@@ -256,12 +265,113 @@ export default function PostPage() {
|
|
|
256
265
|
}
|
|
257
266
|
```
|
|
258
267
|
|
|
268
|
+
### Active links
|
|
269
|
+
|
|
270
|
+
`Link` marks the link to the current page with `aria-current="page"` and `data-void-active`. Use them to style navigation:
|
|
271
|
+
|
|
272
|
+
```css
|
|
273
|
+
nav a[data-void-active] {
|
|
274
|
+
font-weight: 600;
|
|
275
|
+
}
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
A link is active only on its own path by default. Set `activeMatch="prefix"` to keep it active on nested pages:
|
|
279
|
+
|
|
280
|
+
::: code-group
|
|
281
|
+
|
|
282
|
+
```tsx [React]
|
|
283
|
+
<nav>
|
|
284
|
+
<Link href="/">Home</Link>
|
|
285
|
+
<Link href="/users" activeMatch="prefix">
|
|
286
|
+
Users
|
|
287
|
+
</Link>
|
|
288
|
+
</nav>
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
```vue [Vue]
|
|
292
|
+
<nav>
|
|
293
|
+
<Link href="/">Home</Link>
|
|
294
|
+
<Link href="/users" active-match="prefix">Users</Link>
|
|
295
|
+
</nav>
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
```svelte [Svelte]
|
|
299
|
+
<nav>
|
|
300
|
+
<Link href="/">Home</Link>
|
|
301
|
+
<Link href="/users" activeMatch="prefix">Users</Link>
|
|
302
|
+
</nav>
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
```tsx [Solid]
|
|
306
|
+
<nav>
|
|
307
|
+
<Link href="/">Home</Link>
|
|
308
|
+
<Link href="/users" activeMatch="prefix">
|
|
309
|
+
Users
|
|
310
|
+
</Link>
|
|
311
|
+
</nav>
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
:::
|
|
315
|
+
|
|
316
|
+
| Current URL | `href="/users"` | `href="/users" activeMatch="prefix"` |
|
|
317
|
+
| --------------- | --------------- | ------------------------------------ |
|
|
318
|
+
| `/users` | both attributes | both attributes |
|
|
319
|
+
| `/users?page=2` | both attributes | both attributes |
|
|
320
|
+
| `/users/42` | none | `data-void-active` |
|
|
321
|
+
| `/users-admin` | none | none |
|
|
322
|
+
|
|
323
|
+
`aria-current="page"` marks only the exact page, so select `[aria-current="page"]` to style it differently from its section. A link to `/` is active only on the home page.
|
|
324
|
+
|
|
325
|
+
Paths match the way pages are routed: letter case and trailing slashes count, while the query string and hash are ignored. Links to other origins and non-GET links are never active. An `aria-current` or `data-void-active` you pass to `Link` replaces the computed value.
|
|
326
|
+
|
|
327
|
+
### Pending links
|
|
328
|
+
|
|
329
|
+
While a page loads, `Link` adds `data-void-pending` to every link to it. Use it to show that a click is being handled:
|
|
330
|
+
|
|
331
|
+
```css
|
|
332
|
+
a[data-void-pending] {
|
|
333
|
+
opacity: 0.6;
|
|
334
|
+
/* Skip visits that finish quickly, such as to a prefetched page */
|
|
335
|
+
transition: opacity 0.15s 0.1s;
|
|
336
|
+
}
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
A link is pending only while its exact destination loads. The path, query and hash must all match, so a link to `/users?page=2` isn't pending while `/users?page=3` loads. A non-GET link, which renders a `<button>`, is pending while a request with its method to its `href` runs. `router.refresh()` reloads the current page, so links to it are pending during a refresh.
|
|
340
|
+
|
|
341
|
+
A `data-void-pending` you pass to `Link` replaces the computed value. For a loading indicator that covers the whole page, use [`useNavigation()`](../../reference/api/pages.md).
|
|
342
|
+
|
|
343
|
+
### Prefetching
|
|
344
|
+
|
|
345
|
+
Add `prefetch` to a `Link` to load its page before the user clicks, so the visit doesn't wait for the server:
|
|
346
|
+
|
|
347
|
+
```tsx
|
|
348
|
+
<Link href="/dashboard" prefetch>
|
|
349
|
+
Dashboard
|
|
350
|
+
</Link>
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
`prefetch` on its own loads the page on hover, keyboard focus, or touch. A `Link` can also prefetch on click, as soon as it renders, or once it stays in view, and `cacheFor` sets how long a prefetched page is reused. See [Prefetching](../../reference/api/pages.md#prefetching) for every option.
|
|
354
|
+
|
|
355
|
+
To give every `Link` a prefetch strategy, set `prefetch.defaultStrategy` in the adapter plugin. A `Link` that sets its own `prefetch` keeps it:
|
|
356
|
+
|
|
357
|
+
```ts
|
|
358
|
+
// vite.config.ts
|
|
359
|
+
voidReact({ prefetch: { defaultStrategy: 'hover' } });
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
Prefer `'hover'` or `'click'` as the default. With `'mount'` or `'visible'`, every `Link` loads its page once it renders or stays in view, which adds up in long lists.
|
|
363
|
+
|
|
364
|
+
`Link` doesn't prefetch while the browser reports that data saver is on or the connection is 2G, which only Chromium-based browsers report.
|
|
365
|
+
|
|
366
|
+
Prefetching runs the destination's loader, so keep loaders free of side effects such as counting views.
|
|
367
|
+
|
|
259
368
|
## Scroll Restoration
|
|
260
369
|
|
|
261
370
|
Void manages scroll position for Pages automatically:
|
|
262
371
|
|
|
263
372
|
- **Back/forward navigation and reloads** restore the saved scroll position.
|
|
264
373
|
- **New navigation** scrolls to the top of the page.
|
|
374
|
+
- **Actions and forms** keep scroll when updating the current page. Redirects follow normal navigation behavior.
|
|
265
375
|
- **Hash links** (`/docs#api`) scroll to the target element. Same-page hash links (`#section`) skip the server fetch entirely.
|
|
266
376
|
|
|
267
377
|
To keep the current scroll position, pass `preserveScroll: true`:
|
|
@@ -16,7 +16,7 @@ Local development permits exact HTTP callbacks on localhost when the platform's
|
|
|
16
16
|
|
|
17
17
|
The app sends users to Void's authorization page, where Void displays its registered name, operator, callback origin, and requested permission. Sign-in permits reading the user's ID and username. It does not provide an account token or project management access.
|
|
18
18
|
|
|
19
|
-
Users can disconnect applications at `<platform API URL>/oauth/connections`.
|
|
19
|
+
Users can disconnect applications at `<platform API URL>/oauth/connections`. Access tokens expire after an hour, and apps renew them with a refresh token. Refreshing does not extend access past the Void sign-in the user approved the app from: access ends 30 days after that sign-in, or earlier if the sign-in is revoked or the account is suspended. Applications must then ask the user to sign in again.
|
|
20
20
|
|
|
21
21
|
## Private previews
|
|
22
22
|
|
|
@@ -48,6 +48,8 @@ Disabling the app or disconnecting its grant stops authorization for subsequent
|
|
|
48
48
|
|
|
49
49
|
Discover endpoints at `/.well-known/oauth-authorization-server` on the platform API origin. Use authorization code flow with `scope=profile`, a random `state`, and S256 PKCE. Authenticate token exchanges using HTTP Basic client authentication. Send access tokens as Bearer credentials to `/oauth/userinfo`; its response contains `sub`, `preferred_username`, and the consented `scope`.
|
|
50
50
|
|
|
51
|
+
The code exchange also returns a `refresh_token`. To renew access, POST `grant_type=refresh_token` and `refresh_token` to `/oauth/token` with client Basic authentication. The response has a new access token and a new `refresh_token`; store the new one and discard the old. Each refresh token works once: sending a used one again revokes the connection and the user must reconnect, so send one refresh at a time per connection. Store refresh tokens as securely as access tokens. An optional space-separated `scope` requests fewer permissions than the user approved; the connection keeps the narrower set, and later refreshes cannot widen it. `deploy:approve` publish tokens never come with a refresh token, so each publish still needs its own approval.
|
|
52
|
+
|
|
51
53
|
For publishing, package the built app with [`prepareDeployArtifact`](/reference/api/deploy). POST to `/oauth/deployment-requests` using the profile token:
|
|
52
54
|
|
|
53
55
|
```ts
|
|
@@ -66,6 +68,6 @@ Redirect the browser to the returned `authorization_url`. Exchange its code with
|
|
|
66
68
|
|
|
67
69
|
Use the token to request URLs from `POST /projects/:id/deploy/upload-urls`, upload the declared assets, and send the artifact to `POST /projects/:id/deploy`. Set `x-void-deploy-idempotency-key` to `approval_id`. Deployment uses Void's managed deployment protocol and requires the platform deployment Queue. The credential cannot read secrets, mint project tokens, delete projects, or deploy different bytes.
|
|
68
70
|
|
|
69
|
-
Revoke
|
|
71
|
+
Revoke a connection with `POST /oauth/revoke`, authenticated as the client, using either its access token or its refresh token. Void does not issue an OpenID Connect ID token.
|
|
70
72
|
|
|
71
73
|
If the API is protected by Cloudflare Access, the application operator must also configure a service identity permitted by that Access application's policy. Server OAuth endpoints and approved deployment requests still validate their own client, grant, and project authority; browser consent requires the user's company identity.
|
|
@@ -10,7 +10,7 @@ These commands apply to a platform that enables email. Every project can send fr
|
|
|
10
10
|
|
|
11
11
|
Shared inbound mail uses one exact routing rule per receiving project and enables Cloudflare’s per-zone plus addressing. Creating a project or deploying an app that only sends mail consumes no inbound rule. Existing rules and the apex catch-all remain in place. Cloudflare normally allows [200 routing rules per domain](https://developers.cloudflare.com/email-service/platform/limits/); remove unused rules or request a higher limit if the shared domain reaches capacity. An unrelated rule for a project’s base address or a plus address blocks its setup until that conflict is removed.
|
|
12
12
|
|
|
13
|
-
A project owner can
|
|
13
|
+
A project owner can set a permanent, shorter address with [`void email alias <name>`](../../../reference/cli/email.md#void-email-alias). Receiving mail at both the slug and alias uses two routing rules. Resolve conflicting rules and check the domain's rule limit before adding an alias.
|
|
14
14
|
|
|
15
15
|
If recipient creation is interrupted, inspect its retained intent:
|
|
16
16
|
|
|
@@ -31,7 +31,7 @@ for the recovery requirements.
|
|
|
31
31
|
|
|
32
32
|
### Mail that the platform sends {#platform-sender}
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
Platform invitations, welcome mail, and deployment alerts use `noreply@<mail domain>` with the platform's display name. Void configures this sender automatically.
|
|
35
35
|
|
|
36
36
|
Mail to an address that is not verified needs Cloudflare Email Sending onboarding and [Workers Paid](https://dash.cloudflare.com/?to=/:account/workers/plans).
|
|
37
37
|
|
|
@@ -161,10 +161,8 @@ If an apex already receives mail with another provider, such as Microsoft 365 or
|
|
|
161
161
|
void platform email domain-add brand.example --project hr-portal --outbound-only
|
|
162
162
|
```
|
|
163
163
|
|
|
164
|
-
The project can then send from any address on the apex, such as `support@brand.example`.
|
|
164
|
+
The project can then send from any address on the apex, such as `support@brand.example`. Incoming mail, MX records, and the apex SPF record stay with your current provider.
|
|
165
165
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
- `domain-rotate-secret` does not apply. `domain-remove` stops sending through the platform and leaves the MX records alone.
|
|
170
|
-
- To switch an outbound-only domain to platform-managed inbound mail, or back, remove it first and add it again.
|
|
166
|
+
This requires [Workers Paid](https://dash.cloudflare.com/?to=/:account/workers/plans) and Cloudflare Email Sending onboarding. Email Sending adds records at `cf-bounce.<domain>` and `_dmarc.<domain>`. Resolve any reported DNS conflicts, then run `domain-sync`.
|
|
167
|
+
|
|
168
|
+
Only administrators can register outbound-only domains. Choose a zone apex separate from the platform's shared mail zone. Use `domain-remove` to stop sending through the platform. To change between outbound-only and platform-managed inbound mail, remove the domain and add it again.
|