void 1.1.11 → 1.2.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/dist/{account-cmd-R35a4Oa8.mjs → account-cmd-CdUll_35.mjs} +5 -5
- package/dist/action-key-XZ9HkWAO.mjs +26 -0
- package/dist/{application-analysis-D7nNmNJb.mjs → application-analysis-fEqoSeMp.mjs} +11 -11
- package/dist/{application-routing-CZH66gXn.mjs → application-routing-DAhNP4u3.mjs} +1 -1
- package/dist/{ast-CPGPjb0V.mjs → ast-CsZ_q_gc.mjs} +6 -1
- package/dist/ast-bindings-C3yaPs1y.mjs +296 -0
- package/dist/{auth-link-VHmiKZmP.mjs → auth-link-C87vGXM-.mjs} +5 -5
- package/dist/{auth-router-O_Wrs5kg.mjs → auth-router-6I81r-ix.mjs} +3 -3
- package/dist/{better-auth-shared-Bv18bB-l.d.mts → better-auth-shared-DVk2DkTW.d.mts} +1 -1
- package/dist/{build-cmd-CMZiMn46.mjs → build-cmd-ex1g-j_e.mjs} +4 -4
- package/dist/{cache-TZ5Ab3d7.mjs → cache-oHzrnY3z.mjs} +4 -4
- package/dist/{cancel-deploy-DXoR6oC3.mjs → cancel-deploy-viAMD0Q_.mjs} +3 -3
- package/dist/cf-build-output-BJHuSsVN.mjs +1 -0
- package/dist/{cf-build-output-Bc8i3dzE.mjs → cf-build-output-BhVxldCw.mjs} +75 -10
- package/dist/{cf-user-agent-ChjQp2MU.mjs → cf-command-values-ByHk0xg4.mjs} +6 -16
- package/dist/cf-worker-settings-BECvvTVd.mjs +37 -0
- package/dist/cli/cli.mjs +139 -35
- package/dist/cli/cloudflare-operation-process.mjs +65 -18
- package/dist/cli/env-schema-probe.d.mts +1 -1
- package/dist/cli/env-schema-probe.mjs +3 -3
- package/dist/{client-GuSO3v_x.mjs → client-BEkdj1kx.mjs} +58 -13
- package/dist/client-BiRDZTSd.mjs +1 -0
- package/dist/{cloudflare-auth-DSvBc1Gu.mjs → cloudflare-auth-Byo_0_N9.mjs} +1 -1
- package/dist/{cloudflare-cmd-ZSErUl6Y.mjs → cloudflare-cmd-DMzCv12s.mjs} +5 -5
- package/dist/{cloudflare-config-rdFOys4X.mjs → cloudflare-config-DchHxPTo.mjs} +1 -1
- package/dist/{cloudflare-connect-BN-k2kD-.mjs → cloudflare-connect-CCRTVg-I.mjs} +3 -3
- package/dist/{cloudflare-operations-DH3GedbV.mjs → cloudflare-operations-Dh9dEHJj.mjs} +17 -7
- package/dist/{cloudflare-operations-Cm8lVx7W.mjs → cloudflare-operations-DsSaw2BT.mjs} +1 -1
- package/dist/{cloudflare-process-CZJ4viYl.mjs → cloudflare-process-8jEYIeim.mjs} +3 -2
- package/dist/{config-DC5llZaI.mjs → config-BIaXIkkv.mjs} +8 -3
- package/dist/{config-DYJV8aEH.mjs → config-BU6hMu1W.mjs} +1 -1
- package/dist/{config-D26zcdKy.mjs → config-DHgSEWT7.mjs} +39 -6
- package/dist/{config-7qoq2p9v.d.mts → config-DQfHOKh9.d.mts} +10 -1
- package/dist/config-entry.d.mts +1 -1
- package/dist/{connect-yQuLbuiJ.mjs → connect-k7R2rPVA.mjs} +6 -6
- package/dist/{create-project-CGOo_OL_.mjs → create-project-DTuy-l0z.mjs} +1 -1
- package/dist/{create-project-DEEWJX_M.mjs → create-project-DV71ol5d.mjs} +4 -4
- package/dist/{db-COI-yTJE.mjs → db-DVOkLH5X.mjs} +79 -23
- package/dist/{delete-PgN6L_9N.mjs → delete-BbP5eopu.mjs} +4 -4
- package/dist/{deploy-DsW-PrRQ.mjs → deploy-7H32EnUs.mjs} +220 -95
- package/dist/deploy-CE0Ev0Ob.mjs +2 -0
- package/dist/{deploy-managed-static-Dqz06S2u.mjs → deploy-managed-static-DlvcvnQT.mjs} +74 -28
- package/dist/{deploy-transport-nY3vLXPL.mjs → deploy-transport-BzGEj0Ge.mjs} +2 -2
- package/dist/deploy.d.mts +22 -1
- package/dist/deploy.mjs +49 -8
- package/dist/{dev-inbox-Rd6j_8vM.mjs → dev-inbox-D0jxye_D.mjs} +1 -1
- package/dist/{dispatch-BAbbn3jg.mjs → dispatch-DoUnxTNo.mjs} +15 -11
- package/dist/{dist-CfgIkieS.mjs → dist-B1PLt4_8.mjs} +1 -1
- package/dist/{dist-BVdsO7Py.mjs → dist-Cor9XGoz.mjs} +94 -200
- package/dist/{dist-Bn8Kodjp.mjs → dist-D15hFhP0.mjs} +1 -1
- package/dist/{domain-DKlNI0SR.mjs → domain-CA2wBgra.mjs} +5 -5
- package/dist/drizzle-9TubSZvI.mjs +1 -0
- package/dist/{email-BcjSyAL0.mjs → email-B9ayYQEG.mjs} +1 -1
- package/dist/{email-C0s3OvJk.mjs → email-DXpCc77w.mjs} +10 -10
- package/dist/{email-cloudflare-etpKiITL.mjs → email-cloudflare-D03g2TkS.mjs} +7 -7
- package/dist/{entry-B_0IhV64.mjs → entry-BEM8ZuGP.mjs} +40 -12
- package/dist/{env-BX2JFsgF.mjs → env-DgOQ9_8S.mjs} +6 -6
- package/dist/{env-public-CCdykygU.d.mts → env-public-6lqiSD2b.d.mts} +1 -0
- package/dist/{env-types-GRchm5dw.mjs → env-types-BicfKBhV.mjs} +1 -1
- package/dist/{env-validation-CuGfWRJd.mjs → env-validation-BmsdCZEk.mjs} +1 -1
- package/dist/{env-validation-D_KyMdab.mjs → env-validation-Dwq3PJzK.mjs} +3 -3
- package/dist/{fetch-DHLOuPyk.d.mts → fetch-CUX0tB78.d.mts} +14 -1
- package/dist/fetch-CtESUYWd.mjs +26 -0
- package/dist/{fetch-error-Dj3crt0e.mjs → fetch-error-Bw0n-IY-.mjs} +1 -1
- package/dist/{fetch-stream-PGgz4uGz.mjs → fetch-stream-BspOeTAI.mjs} +1 -1
- package/dist/{fetch-stream-CNxOrBdP.d.mts → fetch-stream-DfkAzZf-.d.mts} +1 -1
- package/dist/{gen-Bj6ZkOcI.mjs → gen-BfmcIi2g.mjs} +5 -5
- package/dist/gen-NrOlWZaG.mjs +1 -0
- package/dist/{github-cmd-DQDryS-5.mjs → github-cmd-CY9LUqLh.mjs} +4 -4
- package/dist/{handler-_PqY82xe.d.mts → handler-BbkSPzGF.d.mts} +91 -9
- package/dist/{headers-Bi4bOAwp.mjs → headers-D522zd0A.mjs} +2 -2
- package/dist/help-BeAFFE5C.mjs +1 -0
- package/dist/{help-D49SL_lN.mjs → help-CxSlPpzJ.mjs} +83 -12
- package/dist/{inbound-BuTfm11U.mjs → inbound-VrOLqwZY.mjs} +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +125 -124
- package/dist/{info-Bxunp14X.mjs → info-7VDlhtyy.mjs} +4 -4
- package/dist/{init-DyTEY04s.mjs → init-DxYyOs4-.mjs} +103 -43
- package/dist/{link-CgOVn9EC.mjs → link-Ddmod1dZ.mjs} +5 -5
- package/dist/{list-CUfD9RSb.mjs → list-MogaugiO.mjs} +5 -5
- package/dist/{live-DJONVlQK.d.mts → live-Bt8Y_0bg.d.mts} +1 -1
- package/dist/{local-d1-CpaPbd_L.mjs → local-d1-BHBnKWRb.mjs} +1 -1
- package/dist/{log-vqY3pqwI.mjs → log-BMwmN5Ae.mjs} +2 -2
- package/dist/{login-BJvGW5Eu.mjs → login-Cttnagmm.mjs} +4 -4
- package/dist/login-DgDwlKc_.mjs +1 -0
- package/dist/{logs-DeizBI4j.mjs → logs-CAszUWZI.mjs} +4 -4
- package/dist/{migrate-8rk56vV8.mjs → migrate-DyT2jJ8y.mjs} +5 -5
- package/dist/migrate-n49ZeS1X.mjs +1 -0
- package/dist/{mime-srOklVVv.mjs → mime-BAyHPskU.mjs} +1 -1
- package/dist/nitro.mjs +3 -3
- package/dist/{node-uN8_zxJr.mjs → node-WB7c2N4L.mjs} +2 -2
- package/dist/operator-cmd-d2MvJOrl.mjs +1 -0
- package/dist/{operator-cmd-CA5QQyvE.mjs → operator-cmd-skshjMGl.mjs} +4 -4
- package/dist/output-BW9uK099.mjs +1 -0
- package/dist/{output-Ba6ZbrzY.mjs → output-BpgYODYx.mjs} +16 -4
- package/dist/pages/client.d.mts +2 -2
- package/dist/pages/client.mjs +48 -25
- package/dist/pages/index.d.mts +2 -2
- package/dist/pages/index.mjs +4 -4
- package/dist/pages/islands-plugin.d.mts +43 -5
- package/dist/pages/islands-plugin.mjs +100 -28
- package/dist/pages/protocol.d.mts +2 -2
- package/dist/pages/protocol.mjs +1 -1
- package/dist/pages/serialize.d.mts +2 -2
- package/dist/pages/serialize.mjs +1 -1
- package/dist/{parse-filename-CUbj-1MP.mjs → parse-filename-DioPHiR9.mjs} +1 -35
- package/dist/{picocolors-BTps1_gs.mjs → picocolors-BsDfhxIw.mjs} +1 -1
- package/dist/{platform-args-B7ke06up.mjs → platform-args-DVbVClZl.mjs} +12 -4
- package/dist/platform-args-kQrgxScY.mjs +1 -0
- package/dist/{platform-auth-config-CZaY812e.mjs → platform-auth-config-C-pm5Qzx.mjs} +6 -6
- package/dist/{platform-auth-protection-U9HCqoXv.mjs → platform-auth-protection-SHhvim1L.mjs} +4 -4
- package/dist/{platform-auth-recovery-B0BV2hfV.mjs → platform-auth-recovery-DXVWs-wA.mjs} +4 -4
- package/dist/{platform-cmd-CXrjk4fb.mjs → platform-cmd-D5I1beUX.mjs} +7 -7
- package/dist/{platform-cmd-D9lwFpcl.mjs → platform-cmd-PiNRkopU.mjs} +1 -1
- package/dist/{platform-domain-CXyq-68_.mjs → platform-domain-jpmBfZeb.mjs} +4 -4
- package/dist/{platform-lifecycle-Dz2cJsLX.mjs → platform-lifecycle-DH3Yr1qQ.mjs} +1 -1
- package/dist/{platform-lifecycle-D0TdyXbN.mjs → platform-lifecycle-DyKmuNY6.mjs} +405 -44
- package/dist/{platform-management-CnXhgxTM.mjs → platform-management--vDwSn35.mjs} +49 -5
- package/dist/{platform-management-BvgbusqL.mjs → platform-management-7m-PLaPJ.mjs} +1 -1
- package/dist/{platform-plans-config-BWn1S2Rv.mjs → platform-plans-config-CeydDSj0.mjs} +2 -2
- package/dist/{platform-recovery-CH_fThW6.mjs → platform-recovery-BiNpZZab.mjs} +2 -2
- package/dist/{platform-setup-YvN9VQXV.mjs → platform-setup-Ca53gtt0.mjs} +3 -2
- package/dist/{plugin-inference-Bekzjuqw.mjs → plugin-inference-DUjCd55H.mjs} +145 -218
- package/dist/{prepare-2XD6kh77.mjs → prepare-BcAE5Sdj.mjs} +3 -3
- package/dist/prepare-C4I0f--h.mjs +1 -0
- package/dist/{prepare-DepAGBcV.mjs → prepare-DA-17DhO.mjs} +5 -5
- package/dist/{prerender-render-Bfsumdkv.mjs → prerender-render-Cijv7UFo.mjs} +11 -6
- package/dist/prerender-render.mjs +1 -1
- package/dist/{project-cmd-CpLYflCH.mjs → project-cmd-DA4K5faU.mjs} +18 -18
- package/dist/{project-team-CTSY7W7Q.mjs → project-team-CQBNveX3.mjs} +4 -4
- package/dist/{project-token-Cybtlfbl.mjs → project-token-CCalFyQf.mjs} +4 -4
- package/dist/{project-zero-trust-DKOtqyvu.mjs → project-zero-trust-DPnkiEuT.mjs} +4 -4
- package/dist/{protocol-B8sI8dRD.d.mts → protocol-BBDpJz3G.d.mts} +3 -1
- package/dist/{protocol-RNP0u7UY.mjs → protocol-DimNxVRr.mjs} +42 -17
- package/dist/{provision-UcYjpTRh.mjs → provision-BFLCrnUp.mjs} +1 -1
- package/dist/{provision-BuifYvLc.mjs → provision-DtROpNNI.mjs} +6 -5
- package/dist/{requests-Ryiazz9i.mjs → requests-BpH0kImL.mjs} +3 -3
- package/dist/resolve-project-DD1vu8s9.mjs +1 -0
- package/dist/{resolve-project-WpwkCB_c.mjs → resolve-project-Xoi6eTWY.mjs} +1 -1
- package/dist/{rollback-Or0EV3rP.mjs → rollback-CXS1tAa-.mjs} +10 -9
- package/dist/{rolldown-runtime-DXIUcv95.mjs → rolldown-runtime-3h0WiCiA.mjs} +1 -1
- package/dist/{routing-assets-VkrKIbxE.mjs → routing-assets-DdSFxoLp.mjs} +10 -4
- package/dist/runtime/better-auth-mysql.d.mts +1 -1
- package/dist/runtime/better-auth-pg.d.mts +1 -1
- package/dist/runtime/better-auth.d.mts +1 -1
- package/dist/runtime/client-react.d.mts +2 -2
- package/dist/runtime/client-react.mjs +3 -3
- package/dist/runtime/client-solid.d.mts +2 -2
- package/dist/runtime/client-solid.mjs +3 -3
- package/dist/runtime/client-svelte.d.mts +2 -2
- package/dist/runtime/client-svelte.mjs +3 -3
- package/dist/runtime/client-vue.d.mts +2 -2
- package/dist/runtime/client-vue.mjs +3 -3
- package/dist/runtime/client.d.mts +2 -2
- package/dist/runtime/client.mjs +3 -3
- package/dist/runtime/email/testing.mjs +4 -4
- package/dist/runtime/email.mjs +3 -3
- package/dist/runtime/env-public.d.mts +1 -1
- package/dist/runtime/fetch-server.d.mts +8 -0
- package/dist/runtime/fetch-server.mjs +30 -0
- package/dist/runtime/fetch-stream.d.mts +2 -2
- package/dist/runtime/fetch-stream.mjs +2 -2
- package/dist/runtime/fetch.d.mts +2 -2
- package/dist/runtime/fetch.mjs +3 -3
- package/dist/runtime/handler.d.mts +1 -1
- package/dist/runtime/live-client.d.mts +1 -1
- package/dist/runtime/live.d.mts +1 -1
- package/dist/runtime/routing.d.mts +17 -76
- package/dist/runtime/routing.mjs +277 -216
- package/dist/runtime/validator.d.mts +1 -1
- package/dist/runtime/ws-server.d.mts +2 -2
- package/dist/runtime/ws.d.mts +1 -1
- package/dist/{scan-D2-FcLHs.mjs → scan-8IzYXiU_.mjs} +12 -11
- package/dist/{secret-CClHaFxm.mjs → secret-BbXHfLAt.mjs} +6 -6
- package/dist/serialize-DtR8Vwa_.d.mts +18 -0
- package/dist/serialize-YHvlcG3Q.mjs +31 -0
- package/dist/{skills-C_yRTg0g.mjs → skills-CrUO3PJ0.mjs} +1 -1
- package/dist/{subcommand-prompt-Bm3ZlYgA.mjs → subcommand-prompt-D9OhhbGG.mjs} +2 -2
- package/dist/{version-metadata-B1Bm2wSq.mjs → version-metadata-tS39iW09.mjs} +1 -1
- package/dist/wrangler-BLb3_luP.mjs +1 -0
- package/dist/{wrangler-C9XSzrju.mjs → wrangler-F96NnLyb.mjs} +13 -5
- package/dist/{wrapper-BOigE1xJ.mjs → wrapper-D3sZyh2C.mjs} +5 -3
- package/dist/{ws-CsBNxv86.d.mts → ws-BH-im_tX.d.mts} +1 -1
- package/docs/guide/ai.md +1 -1
- package/docs/guide/database/postgresql.md +1 -1
- package/docs/guide/database.md +26 -0
- package/docs/guide/deployment.md +2 -0
- package/docs/guide/edge/headers.md +1 -1
- package/docs/guide/email/domains.md +1 -1
- package/docs/guide/email/receiving.md +1 -1
- package/docs/guide/email/sending.md +3 -3
- package/docs/guide/pages-routing/actions-and-forms.md +1 -1
- package/docs/guide/pages-routing/markdown.md +3 -1
- package/docs/guide/platform/administration/email.md +7 -1
- package/docs/guide/platform/installation/ci.md +2 -0
- package/docs/guide/platform/installation/credentials.md +24 -6
- package/docs/guide/platform/installation/domains.md +16 -0
- package/docs/guide/platform/installation/maintenance.md +32 -2
- package/docs/guide/platform/installation/setup.md +1 -1
- package/docs/guide/self-hosted-platform.md +1 -1
- package/docs/guide/server-routing.md +1 -1
- package/docs/guide/typed-fetch.md +1 -1
- package/docs/integrations/cloudflare.md +2 -1
- package/docs/integrations/frameworks/tanstack-start.md +25 -0
- package/docs/reference/api/deploy.md +35 -3
- package/docs/reference/api/env.md +1 -1
- package/docs/reference/api/rewrites.md +1 -1
- package/docs/reference/api/types.md +1 -0
- package/docs/reference/cli/database.md +15 -0
- package/docs/reference/cli/platform-installation.md +5 -2
- package/docs/reference/cli/project.md +4 -2
- package/docs/reference/cli/setup.md +17 -0
- package/docs/reference/cli.md +1 -0
- package/docs/reference/config.md +14 -1
- package/docs/reference/resource-inference.md +4 -0
- package/package.json +23 -22
- package/sandbox.Dockerfile +1 -1
- package/schema.json +23 -3
- package/dist/cf-build-output-BU3hqdHu.mjs +0 -1
- package/dist/client-DrdeJgHR.mjs +0 -1
- package/dist/deploy-CxNgEYr4.mjs +0 -2
- package/dist/fetch-sAcwjzLO.mjs +0 -18
- package/dist/gen-DsCukhuw.mjs +0 -1
- package/dist/help-DOFygYi4.mjs +0 -1
- package/dist/login-alAlxw4S.mjs +0 -1
- package/dist/migrate-D2odrAmh.mjs +0 -1
- package/dist/operator-cmd-D7toMPJ9.mjs +0 -1
- package/dist/platform-args-B_LrqEZB.mjs +0 -1
- package/dist/prepare-EVEbQ9n2.mjs +0 -1
- package/dist/resolve-project-PnhzMtY6.mjs +0 -1
- package/dist/serialize-BtQyaYoC.mjs +0 -20
- package/dist/serialize-CfSwWfF2.d.mts +0 -10
- package/dist/wrangler-DAdxHEzh.mjs +0 -1
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
//#region src/pages/script-json.ts
|
|
2
|
+
const UNSAFE_SCRIPT_CHARS = /[<>&\u2028\u2029]/g;
|
|
3
|
+
function escapeScriptJson(json) {
|
|
4
|
+
return json.replace(UNSAFE_SCRIPT_CHARS, (c) => {
|
|
5
|
+
return `\\u${c.charCodeAt(0).toString(16).padStart(4, "0")}`;
|
|
6
|
+
});
|
|
7
|
+
}
|
|
8
|
+
//#endregion
|
|
9
|
+
//#region src/pages/serialize.ts
|
|
10
|
+
/**
|
|
11
|
+
* Escape JSON for embedding inside an inline `<script type="application/json">`
|
|
12
|
+
* tag. Replaces `<`, `>`, `&`, U+2028, U+2029 with their `\uXXXX` JSON escape
|
|
13
|
+
* sequences so the script tag cannot be closed early and the payload survives
|
|
14
|
+
* `JSON.parse` on hydration.
|
|
15
|
+
*/
|
|
16
|
+
function serializePageData(pageObj) {
|
|
17
|
+
return escapeScriptJson(JSON.stringify(pageObj));
|
|
18
|
+
}
|
|
19
|
+
/** Element id of the Markdown page frontmatter that islands read when they hydrate. */
|
|
20
|
+
const ISLAND_FRONTMATTER_ID = "__void_frontmatter";
|
|
21
|
+
/**
|
|
22
|
+
* Script tag that carries a Markdown page's frontmatter to its islands, so
|
|
23
|
+
* `useFrontmatter()` returns the same value in the browser as on the server.
|
|
24
|
+
* Empty when the page has no frontmatter.
|
|
25
|
+
*/
|
|
26
|
+
function islandFrontmatterScript(frontmatter) {
|
|
27
|
+
if (!frontmatter || Object.keys(frontmatter).length === 0) return "";
|
|
28
|
+
return `<script type="application/json" id="${ISLAND_FRONTMATTER_ID}">${serializePageData(frontmatter)}<\/script>`;
|
|
29
|
+
}
|
|
30
|
+
//#endregion
|
|
31
|
+
export { escapeScriptJson as i, islandFrontmatterScript as n, serializePageData as r, ISLAND_FRONTMATTER_ID as t };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { a as join, s as relative } from "./dist-ipQi0Q8y.mjs";
|
|
2
|
-
import { L as log } from "./dist-
|
|
2
|
+
import { L as log } from "./dist-Cor9XGoz.mjs";
|
|
3
3
|
import { r as getPackageDir } from "./agents-CuNtT0D_.mjs";
|
|
4
4
|
import { existsSync, mkdirSync, readFileSync, readdirSync, readlinkSync, symlinkSync } from "node:fs";
|
|
5
5
|
//#region src/cli/skills.ts
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { $ as wrapTextWithPrefix, G as promptTitle, M as getGuide, V as optionText, b as S_RADIO_ACTIVE, d as S_CHECKBOX_SELECTED, i as S_BAR_END, it as wrapAnsi, j as formatInstructionFooter, n as SELECT_INSTRUCTIONS, r as S_BAR, t as MULTISELECT_INSTRUCTIONS, u as S_CHECKBOX_INACTIVE, w as S_STEP_SUBMIT } from "./dist-
|
|
2
|
-
import { f as import_picocolors } from "./output-
|
|
1
|
+
import { $ as wrapTextWithPrefix, G as promptTitle, M as getGuide, V as optionText, b as S_RADIO_ACTIVE, d as S_CHECKBOX_SELECTED, i as S_BAR_END, it as wrapAnsi, j as formatInstructionFooter, n as SELECT_INSTRUCTIONS, r as S_BAR, t as MULTISELECT_INSTRUCTIONS, u as S_CHECKBOX_INACTIVE, w as S_STEP_SUBMIT } from "./dist-Cor9XGoz.mjs";
|
|
2
|
+
import { f as import_picocolors } from "./output-BpgYODYx.mjs";
|
|
3
3
|
//#region src/cli/subcommand-prompt.ts
|
|
4
4
|
const isUpKey = (key) => key === "\x1B[A" || key === "\x1BOA";
|
|
5
5
|
const isDownKey = (key) => key === "\x1B[B" || key === "\x1BOB";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { a as join } from "./dist-ipQi0Q8y.mjs";
|
|
2
|
-
import { l as bindingNamesForField, p as findBindingNameOwner } from "./wrangler-
|
|
2
|
+
import { l as bindingNamesForField, p as findBindingNameOwner } from "./wrangler-F96NnLyb.mjs";
|
|
3
3
|
//#region src/shared/untrusted-env.ts
|
|
4
4
|
/** Authentication inputs that Wrangler may consume from the environment. */
|
|
5
5
|
const WRANGLER_AUTH_CREDENTIAL_ENV_VARS = [
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { b as readRootWranglerConfig } from "./wrangler-F96NnLyb.mjs";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { a as join, n as dirname, o as normalize, t as basename } from "./dist-ipQi0Q8y.mjs";
|
|
1
|
+
import { a as join, c as resolve, n as dirname, o as normalize, t as basename } from "./dist-ipQi0Q8y.mjs";
|
|
2
2
|
import "./project-paths-DGu_QZ_Q.mjs";
|
|
3
|
-
import {
|
|
4
|
-
import { i as persistCloudflareConfig, r as materializeCloudflareConfig } from "./cloudflare-config-
|
|
3
|
+
import { p as readConfig } from "./config-DHgSEWT7.mjs";
|
|
4
|
+
import { i as persistCloudflareConfig, r as materializeCloudflareConfig } from "./cloudflare-config-DchHxPTo.mjs";
|
|
5
5
|
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
6
6
|
import { appendSqliteClassMigration, isRecord } from "@void/deploy-core";
|
|
7
7
|
import { createHash } from "node:crypto";
|
|
@@ -640,7 +640,7 @@ function writeProvisionedWranglerConfig(root, patch, options) {
|
|
|
640
640
|
const existingDir = d1Entries[index].migrations_dir;
|
|
641
641
|
if (existingDir !== void 0 && typeof existingDir !== "string") throw new Error(`deploy: cannot update "${configPath}" — the D1 entry for binding ${JSON.stringify(patch.d1MigrationsDir.binding)} has a non-string "migrations_dir" value; expected a string. Fix the config and retry.`);
|
|
642
642
|
if (typeof existingDir === "string") {
|
|
643
|
-
if (
|
|
643
|
+
if (!sameMigrationsDir(configPath, existingDir, patch.d1MigrationsDir.dir)) throw new Error(`deploy: cannot update "${configPath}" — the D1 entry for binding ${JSON.stringify(patch.d1MigrationsDir.binding)} already sets "migrations_dir": ${JSON.stringify(existingDir)}, but Void keeps this database's migrations in ${JSON.stringify(patch.d1MigrationsDir.dir)}. Refusing to overwrite an explicit different migrations directory. Either remove "migrations_dir" from the entry (or set it to ${JSON.stringify(patch.d1MigrationsDir.dir)}) to let Void manage it, or move the migrations and keep your directory, then retry.`);
|
|
644
644
|
} else {
|
|
645
645
|
if (existingPattern !== void 0 && !migrationsPatternMatchesDir(existingPattern, patch.d1MigrationsDir.dir)) throw new Error(`deploy: cannot update "${configPath}" — the D1 entry for binding ${JSON.stringify(patch.d1MigrationsDir.binding)} has "migrations_pattern": ${JSON.stringify(existingPattern)}, which is not under the requested "migrations_dir": ${JSON.stringify(patch.d1MigrationsDir.dir)}. Wrangler requires the pattern to start with the migrations dir, so this change would break \`wrangler d1 migrations\`. Align "migrations_pattern" with the dir (or remove it) and retry.`);
|
|
646
646
|
set([
|
|
@@ -1379,6 +1379,14 @@ function strictBindingEntries(members, keyField, field) {
|
|
|
1379
1379
|
function bindingSetError(problem, hidden) {
|
|
1380
1380
|
return /* @__PURE__ */ new Error(`deploy: cannot verify binding-name uniqueness — ${problem}. Refusing to proceed on a partially-readable binding set (a ${hidden} could hide a real collision). Fix the wrangler config and retry.`);
|
|
1381
1381
|
}
|
|
1382
|
+
/**
|
|
1383
|
+
* Whether two `migrations_dir` values name the same folder. Wrangler resolves the value
|
|
1384
|
+
* against the config file's directory and accepts either slash.
|
|
1385
|
+
*/
|
|
1386
|
+
function sameMigrationsDir(configPath, a, b) {
|
|
1387
|
+
const base = dirname(configPath);
|
|
1388
|
+
return resolve(base, a.replaceAll("\\", "/")) === resolve(base, b.replaceAll("\\", "/"));
|
|
1389
|
+
}
|
|
1382
1390
|
/** Wrangler's rule: the normalized pattern starts with `<dir>/`, unless the dir is ".". */
|
|
1383
1391
|
function migrationsPatternMatchesDir(pattern, dir) {
|
|
1384
1392
|
const normalizedDir = normalizeMigrationsPath(dir);
|
|
@@ -1391,4 +1399,4 @@ function normalizeMigrationsPath(p) {
|
|
|
1391
1399
|
return normalized.endsWith("/") ? normalized.slice(0, -1) : normalized;
|
|
1392
1400
|
}
|
|
1393
1401
|
//#endregion
|
|
1394
|
-
export {
|
|
1402
|
+
export { syncWranglerWebSockets as A, readWranglerManagedQueueCleanupCandidates as C, sameMigrationsDir as D, resolveLiveBindingConfig as E, writeProvisionedWranglerConfig as M, writeWranglerPublishedTrafficSnapshot as N, syncWranglerBindings as O, readWranglerCustomDomains as S, readWranglerWebSocketTombstones as T, persistMaterializedWranglerConfig as _, LIVE_MIGRATION_TAG as a, readRootWranglerConfig as b, bindingEntriesForField as c, ensureWranglerCompatibilityDate as d, ensureWranglerNodejsAlsFlag as f, normalizeWranglerCompatibilityFlags as g, nextDurableObjectMigrationTag as h, LATEST_KNOWN_COMPAT_DATE as i, updateWranglerCustomDomain as j, syncWranglerDurableObjects as k, bindingNamesForField as l, hasDurableObjectSqliteMigration as m, DEFAULT_LIVE_CLASS as n, acknowledgeWranglerManagedQueueRemovals as o, findBindingNameOwner as p, FRIENDLY_BINDING_NAMES as r, assertNoDuplicateMembers as s, DEFAULT_LIVE_BINDING as t, ensureWranglerCompat as u, readExistingLiveBindingConfig as v, readWranglerPublishedTrafficSnapshot as w, readWranglerCompat as x, readProvisionedBindingEntry as y };
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { a as join, l as toSlash, n as dirname, r as extname } from "./dist-ipQi0Q8y.mjs";
|
|
2
2
|
import { n as readProjectPaths } from "./project-paths-DGu_QZ_Q.mjs";
|
|
3
|
-
import {
|
|
4
|
-
import { n as isIdentifier, r as isLiteral } from "./ast-
|
|
3
|
+
import { l as getDatabaseDialect, p as readConfig } from "./config-DHgSEWT7.mjs";
|
|
4
|
+
import { n as isIdentifier, r as isLiteral } from "./ast-CsZ_q_gc.mjs";
|
|
5
5
|
import { t as MagicString } from "./dist-Cegxq8gs.mjs";
|
|
6
|
-
import { r as voidDbBundlerPlugin, t as generateQueueResolverSource } from "./dispatch-
|
|
6
|
+
import { r as voidDbBundlerPlugin, t as generateQueueResolverSource } from "./dispatch-DoUnxTNo.mjs";
|
|
7
7
|
import { createRequire } from "node:module";
|
|
8
8
|
import { copyFileSync, existsSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
9
9
|
import { fileURLToPath } from "node:url";
|
|
@@ -459,6 +459,7 @@ function generateWrapperSource(renamedEntry, handlersModule, features, migration
|
|
|
459
459
|
const lines = [];
|
|
460
460
|
lines.push(WRAPPER_MARKER);
|
|
461
461
|
lines.push(`import original from "./${renamedEntry}";`);
|
|
462
|
+
lines.push(`export * from "./${renamedEntry}";`);
|
|
462
463
|
if (features.isr) {
|
|
463
464
|
lines.push("import { handleFrameworkIsr } from \"./__void_isr.mjs\";");
|
|
464
465
|
lines.push(`const __voidIsrDeploymentId = ${JSON.stringify(crypto.randomUUID())};`);
|
|
@@ -558,6 +559,7 @@ function generateWrapperSource(renamedEntry, handlersModule, features, migration
|
|
|
558
559
|
lines.push("");
|
|
559
560
|
}
|
|
560
561
|
lines.push("export default {");
|
|
562
|
+
lines.push(" ...original,");
|
|
561
563
|
if (needsFetchWrap) lines.push(" fetch: wrappedFetch,");
|
|
562
564
|
else lines.push(" fetch: original.fetch,");
|
|
563
565
|
if (features.crons.length > 0) lines.push(features.isr ? " scheduled(controller, env, ctx) { env.__VOID_ISR_DEPLOYMENT_ID ??= __voidIsrDeploymentId; return handleScheduled(controller, env, ctx); }," : " scheduled: handleScheduled,");
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { t as StandardSchemaV1 } from "./standard-schema-Fo_vCAZh.mjs";
|
|
2
2
|
import { r as AuthUser } from "./auth-DkcFflXV.mjs";
|
|
3
|
-
import { a as CloudEnv } from "./handler-
|
|
3
|
+
import { a as CloudEnv } from "./handler-BbkSPzGF.mjs";
|
|
4
4
|
import { WebSocketRouteMap } from "void/routes";
|
|
5
5
|
//#region src/runtime/ws.d.ts
|
|
6
6
|
type MaybePromise<T> = T | Promise<T>;
|
package/docs/guide/ai.md
CHANGED
package/docs/guide/database.md
CHANGED
|
@@ -114,6 +114,32 @@ export * from "./schema/users";
|
|
|
114
114
|
export * from "./schema/posts";
|
|
115
115
|
```
|
|
116
116
|
|
|
117
|
+
### Column casing
|
|
118
|
+
|
|
119
|
+
By default, a column declared without a name, such as `createdAt: timestamp()`, uses its key as the column name. Set `database.casing` to `'snake_case'` to store these columns as `created_at` instead. It applies to `void/db` queries and to `void db` commands such as `generate`, `push`, and `seed`. Columns with an explicit name, such as `text('created_at')`, keep that name.
|
|
120
|
+
|
|
121
|
+
```ts
|
|
122
|
+
// void.config.ts
|
|
123
|
+
import { defineConfig } from 'void/config';
|
|
124
|
+
|
|
125
|
+
export default defineConfig({
|
|
126
|
+
database: { dialect: 'pg', casing: 'snake_case' },
|
|
127
|
+
});
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
```ts
|
|
131
|
+
// db/schema.ts
|
|
132
|
+
import { pgTable, serial, text, timestamp } from 'void/schema-pg';
|
|
133
|
+
|
|
134
|
+
export const posts = pgTable('posts', {
|
|
135
|
+
id: serial().primaryKey(),
|
|
136
|
+
title: text().notNull(),
|
|
137
|
+
createdAt: timestamp().notNull().defaultNow(), // created_at
|
|
138
|
+
});
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Omit `dialect` for D1. If your database already has tables, run `void db generate` after you change `casing` and review the migration before you apply it.
|
|
142
|
+
|
|
117
143
|
## Querying
|
|
118
144
|
|
|
119
145
|
Void re-exports all common [Drizzle query operators](https://orm.drizzle.team/docs/select) from `void/db` so you don't need to install `drizzle-orm` separately. Import `db` from `void/db` and your tables from `@schema`:
|
package/docs/guide/deployment.md
CHANGED
|
@@ -35,6 +35,8 @@ void db generate
|
|
|
35
35
|
|
|
36
36
|
Review and commit the SQL, then deploy again. Rollback does not reverse database migrations. See [Database](./database.md) for the local workflow.
|
|
37
37
|
|
|
38
|
+
On your own Cloudflare account, deploy saves a D1 [Time Travel](https://developers.cloudflare.com/d1/reference/time-travel/) restore point before it applies pending migrations and prints the [`void db restore`](../reference/cli/database.md#void-db-restore) command for it. If no restore point can be saved, deploy stops before it migrates. If deploy fails after it applied the migrations, for example when the upload fails, it prints the command again. Usually you fix the error and deploy again; restore only if the live version cannot run against the new schema. To recover from a bad migration, roll back the code with `void project rollback` if the new version is live, restore the database, then fix or remove the migration before you deploy again. After a one-off `void deploy --platform cloudflare`, add `--platform cloudflare` to each of these commands. Restoring discards every write made after the restore point. Restore points expire after 7 days on Workers Free and 30 days on Workers Paid; after that, undo a migration with a new one.
|
|
39
|
+
|
|
38
40
|
### Environment variables
|
|
39
41
|
|
|
40
42
|
Declare values in `env.ts` and set production server secrets with `void secret put`. Deploy never uploads your local `.env`. Supply public `VITE_*` values through the build environment. See [Environment Variables](./env-vars.md).
|
|
@@ -43,7 +43,7 @@ On a [Void platform](../deployment.md#deploy-to-a-team-platform), apps usually s
|
|
|
43
43
|
|
|
44
44
|
This stops a header rule from setting or clearing cookies for other apps on the same domain. These limits apply only to header rules. Your app's own response can set cookies and send `Clear-Site-Data`, and on a shared domain those can affect other apps. See [Domains and Resources](../platform/installation/domains.md#adding-a-domain).
|
|
45
45
|
|
|
46
|
-
|
|
46
|
+
During local development, with `void deploy --platform cloudflare`, and on [other runtimes](../deployment.md#other-runtimes), header rules apply both headers as written.
|
|
47
47
|
|
|
48
48
|
## Framework `_headers` files
|
|
49
49
|
|
|
@@ -16,7 +16,7 @@ void email domain add acme.com
|
|
|
16
16
|
|
|
17
17
|
`add` opens a Cloudflare API-token template. Restrict the token to the selected account and mail zone before creating it; Workers Scripts permission applies across that account. The CLI accepts a masked paste or a newly copied token and asks you to confirm those restrictions. The platform encrypts the credential for the zone connection, so projects sharing that zone do not need separate ingress Workers.
|
|
18
18
|
|
|
19
|
-
Platform-managed custom inbound email requires the apex of a Cloudflare zone. Cloudflare’s catch-all only covers that apex, so a subdomain of the selected zone cannot receive arbitrary addresses.
|
|
19
|
+
Platform-managed custom inbound email requires the apex of a Cloudflare zone. Cloudflare’s catch-all only covers that apex, so a subdomain of the selected zone cannot receive arbitrary addresses. `add` refuses to register a new apex that already has MX records, or whose catch-all already routes elsewhere, so it never takes over mail hosted with another provider such as Microsoft 365 or Google Workspace. Use an apex that has no mail yet, or the platform’s shared mail address. Running `add` again for a registered apex, for example to renew its token, keeps working. Each custom apex belongs to one project; a project can register more than one apex.
|
|
20
20
|
|
|
21
21
|
If setup is interrupted, use `void email domain status <domain>` to inspect the saved operation before retrying.
|
|
22
22
|
|
|
@@ -96,7 +96,7 @@ to check current provider routing and any remaining setup steps.
|
|
|
96
96
|
|
|
97
97
|
For direct deployments, follow [Your own Cloudflare account](./domains.md#your-own-cloudflare-account) to configure inbound addresses.
|
|
98
98
|
|
|
99
|
-
|
|
99
|
+
The local dev server provides the outbound email inbox but has no inbound email trigger. Test inbound handlers with `createInboundTestHarness` below.
|
|
100
100
|
|
|
101
101
|
## Testing inbound handlers {#testing-inbound-handlers}
|
|
102
102
|
|
|
@@ -34,7 +34,7 @@ Check both failure shapes: `result.error` reports a request failure, while `resu
|
|
|
34
34
|
|
|
35
35
|
## Setup {#setup}
|
|
36
36
|
|
|
37
|
-
On a platform with email enabled, deploy without additional email configuration. Ask your administrator for its shared mail domain. Administrators [enable email during installation or upgrade](/guide/platform/installation/credentials#
|
|
37
|
+
On a platform with email enabled, deploy without additional email configuration. Ask your administrator for its shared mail domain. Administrators [enable email during installation or upgrade](/guide/platform/installation/credentials#enable-email).
|
|
38
38
|
|
|
39
39
|
Each project on an email-enabled platform has:
|
|
40
40
|
|
|
@@ -171,7 +171,7 @@ The default platform allowance is 200 recipient attempts per UTC month and 10 pe
|
|
|
171
171
|
|
|
172
172
|
## Local development {#local-development}
|
|
173
173
|
|
|
174
|
-
During
|
|
174
|
+
During local development, sends are captured to an in-memory inbox instead of going to Cloudflare. The dev server prints the inbox URL when it starts:
|
|
175
175
|
|
|
176
176
|
```
|
|
177
177
|
[void] Email inbox: http://localhost:5173/__void/inbox?token=<printed-token>
|
|
@@ -195,7 +195,7 @@ The inbox keeps the most recent 100 messages through HMR and clears on a full se
|
|
|
195
195
|
|
|
196
196
|
The dev inbox works in native Void apps, TanStack Start, and React Router. It is unavailable in SvelteKit, Nuxt, Analog, and Astro; sends from those apps return `BINDING_MISSING`. Use `createEmailTestHarness` from `void/email/testing` to capture sends in tests. If a configured inbox cannot be reached, `sendEmail` returns `UPSTREAM_ERROR` without sending.
|
|
197
197
|
|
|
198
|
-
`sendInDev` is deprecated. During
|
|
198
|
+
`sendInDev` is deprecated. During local development it skips the inbox and returns `BINDING_MISSING`, so it never delivers. Remove it, and deploy the app to test real delivery.
|
|
199
199
|
|
|
200
200
|
## Testing {#testing}
|
|
201
201
|
|
|
@@ -197,7 +197,7 @@ export const actions = {
|
|
|
197
197
|
};
|
|
198
198
|
```
|
|
199
199
|
|
|
200
|
-
Named actions are dispatched via a `?actionName` suffix on the URL (e.g. `/users/42?update`). The client primitives `useForm` and `action()` handle this automatically.
|
|
200
|
+
Named actions are dispatched via a `?actionName` suffix on the URL (e.g. `/users/42?update`). The client primitives `useForm` and `action()` handle this automatically. The action key stays out of the page URL. When `POST /users/42?update&tab=profile` renders the page again, `useForm` and `action()` leave the address bar at `/users/42?tab=profile`, and `c.redirect('/users/42')` goes to `/users/42?tab=profile`.
|
|
201
201
|
|
|
202
202
|
Use `action` or `actions` in a file, not both.
|
|
203
203
|
|
|
@@ -137,7 +137,7 @@ Welcome to Void. Here's an interactive demo:
|
|
|
137
137
|
```
|
|
138
138
|
|
|
139
139
|
- **`<script>` block:** extracted before markdown compilation. Island imports use `with { island: "..." }` syntax (see [islands](./islands)). Any other code in the block becomes a [client script](#client-scripts) that runs in the browser.
|
|
140
|
-
- **Frontmatter:** YAML metadata between `---` fences. Layouts can read it through [`useFrontmatter()`](#frontmatter-access).
|
|
140
|
+
- **Frontmatter:** YAML metadata between `---` fences. Layouts and islands can read it through [`useFrontmatter()`](#frontmatter-access).
|
|
141
141
|
- **Body:** standard markdown plus GFM. Uppercase tags such as `<Counter />` reference imported components and render as islands.
|
|
142
142
|
|
|
143
143
|
## Client Scripts
|
|
@@ -230,6 +230,8 @@ export default function DocsLayout(props) {
|
|
|
230
230
|
|
|
231
231
|
:::
|
|
232
232
|
|
|
233
|
+
Island components on a Markdown page can call `useFrontmatter()` too. A page with islands includes its frontmatter in the HTML for them to read in the browser. Keep private values out of the frontmatter of those pages.
|
|
234
|
+
|
|
233
235
|
## Pages Virtual Module
|
|
234
236
|
|
|
235
237
|
Import `@void/md/pages` to get metadata for all markdown pages at build time. Use it to build sidebars, navigation, or search indexes:
|
|
@@ -27,6 +27,12 @@ reconciliation verifies delivery afterward; a deleting project stays closed
|
|
|
27
27
|
and its deletion can be retried. See [operator email commands](../../../reference/cli/platform-email.md#operator-email)
|
|
28
28
|
for the recovery requirements.
|
|
29
29
|
|
|
30
|
+
### Mail that the platform sends {#platform-sender}
|
|
31
|
+
|
|
32
|
+
The platform sends its own mail, for example invitations, welcome mail, failed-deploy notices, and error alerts. This mail comes from `noreply@<mail domain>`, and the sender name is the platform's display name. Void sets this sender, so you do not need to configure one. Do not set a different sender on the platform Workers in the Cloudflare dashboard. That change stops the next `upgrade`, `repair`, `enable`, or `rollback` until you let Void replace it. See [Platform Workers changed outside Void](/guide/platform/installation/maintenance#workers-changed-outside-void).
|
|
33
|
+
|
|
34
|
+
Mail to an address that is not verified needs Cloudflare Email Sending onboarding and [Workers Paid](https://dash.cloudflare.com/?to=/:account/workers/plans).
|
|
35
|
+
|
|
30
36
|
### Deciding who mail may reach
|
|
31
37
|
|
|
32
38
|
By default, mail from the shared sender reaches only the recipients each project has verified. For a team whose applications mainly mail colleagues, widen that once for the whole installation:
|
|
@@ -114,7 +120,7 @@ Use the apex of the selected Cloudflare zone. Platform-managed custom inbound em
|
|
|
114
120
|
void platform email domain-add other.example --project hr-portal --token-stdin --yes < token.txt
|
|
115
121
|
```
|
|
116
122
|
|
|
117
|
-
Project owners see administrator-registered domains in `void email domain list` and `status`; `status` names the `void platform email` command for any step they cannot take themselves, and `sync` and `remove` point them at `domain-sync` and `domain-remove`. A domain an owner registered before you switched to `admin` stays theirs to renew, sync and remove. The runtime token needs the email permissions
|
|
123
|
+
Project owners see administrator-registered domains in `void email domain list` and `status`; `status` names the `void platform email` command for any step they cannot take themselves, and `sync` and `remove` point them at `domain-sync` and `domain-remove`. A domain an owner registered before you switched to `admin` stays theirs to renew, sync and remove. The runtime token needs the [email permissions](/guide/platform/installation/credentials#enable-email) for this to work.
|
|
118
124
|
|
|
119
125
|
A permission refusal leaves setup blocked. After correcting it, run `domain-sync`
|
|
120
126
|
to resume that same setup operation; repeat `domain-rotate-secret` to resume a
|
|
@@ -51,6 +51,8 @@ void platform install \
|
|
|
51
51
|
|
|
52
52
|
Mutations require `--yes` in CI; a read-only `--plan` does not. Custom runtimes also require `--runtime <directory>`. For a new installation, run `--plan` with the same account, name, and domain options as the unattended install. If you use `--auth-config`, pass the same file to both commands. Register `<platform-api-url>/auth/callback` when creating a login provider's OAuth or OIDC client manually; automatic Access setup manages its own application. A custom API hostname is optional.
|
|
53
53
|
|
|
54
|
+
In CI, `upgrade`, `repair`, `enable`, `rollback`, and `install --resume` stop before they change a platform Worker or pause traffic when a platform Worker was changed in the Cloudflare dashboard or with the Cloudflare API, or has an active version without a Void deployment record. See [Platform Workers changed outside Void](/guide/platform/installation/maintenance#workers-changed-outside-void).
|
|
55
|
+
|
|
54
56
|
:::
|
|
55
57
|
|
|
56
58
|
## Customize the Platform
|
|
@@ -60,7 +60,7 @@ Use the following permissions for the core platform. Cloudflare may label write
|
|
|
60
60
|
|
|
61
61
|
When Void configures Access in the installation account, the initial management-token link also selects **Account → Access: Apps and Policies → Edit** and **Account → Access: Organizations, Identity Providers, and Groups → Read**. Protection adds **Account → Access: Service Tokens → Edit**. When the authentication configuration or saved setup selects existing applications, the link requests Read access instead of Edit. These permissions belong to the management token; the runtime token does not need them.
|
|
62
62
|
|
|
63
|
-
The management token also needs **Zone Edit** with authority to create zones if you ask Void to create the zone. If it already exists, use the selected zone with Zone Read and DNS Edit. Nested application domains additionally need **SSL and Certificates: Read** on the management token.
|
|
63
|
+
The management token also needs **Zone Edit** with authority to create zones if you ask Void to create the zone. If it already exists, use the selected zone with Zone Read and DNS Edit. Nested application domains additionally need **SSL and Certificates: Read** on the management token. An installation with [project custom domains](/guide/platform/installation/domains#project-custom-domains) needs **SSL and Certificates: Edit** on the runtime token.
|
|
64
64
|
|
|
65
65
|
Void checks access before provisioning. If it reports a missing permission, update the token's permissions for the selected account or zone and retry.
|
|
66
66
|
|
|
@@ -68,7 +68,25 @@ Void checks access before provisioning. If it reports a missing permission, upda
|
|
|
68
68
|
|
|
69
69
|
## Enable Email {#enable-email}
|
|
70
70
|
|
|
71
|
-
Choose a shared sender domain and its Cloudflare zone ID. The mail zone may differ from the application zone, but it must belong to the platform's Cloudflare account.
|
|
71
|
+
Choose a shared sender domain and its Cloudflare zone ID. The mail zone may differ from the application zone, but it must belong to the platform's Cloudflare account.
|
|
72
|
+
|
|
73
|
+
Before you enable email, enable [Cloudflare Email Routing](https://developers.cloudflare.com/email-service/get-started/route-emails/) for the exact shared sender domain and confirm that its MX records point to Cloudflare. For a subdomain, add that name under the zone's **Email Routing → Settings → Subdomains**. Cloudflare adds the required MX and SPF records. The installer's shared-mail bootstrap verifies those records; it does not add them. Keep existing mail-provider records on other domain names in place.
|
|
74
|
+
|
|
75
|
+
Enabling email lets administrators [register email domains for projects](/guide/platform/administration/email#registering-email-domains-for-projects) and lets projects register destination addresses through the runtime token. The runtime token needs these permissions:
|
|
76
|
+
|
|
77
|
+
| Scope | Permission | Access |
|
|
78
|
+
| ------- | ----------------------- | ------ |
|
|
79
|
+
| Account | Email Routing Addresses | Edit |
|
|
80
|
+
| Account | Email Sending | Edit |
|
|
81
|
+
| Zone | Zone | Read |
|
|
82
|
+
| Zone | Zone Settings | Edit |
|
|
83
|
+
| Zone | Email Routing Rules | Edit |
|
|
84
|
+
|
|
85
|
+
The zone permissions must include each zone that will carry mail, including the mail zone. Email Sending onboarding for arbitrary recipients needs Workers Paid.
|
|
86
|
+
|
|
87
|
+
For a new installation, set `VOID_EMAIL_SENDER_DOMAIN` and `VOID_EMAIL_SHARED_ZONE_ID` before `void platform install`. The runtime-token link then preselects these permissions.
|
|
88
|
+
|
|
89
|
+
For an existing installation, add the permissions to its runtime token first. Edit the token in the Cloudflare dashboard. The token value stays the same. Or set `VOID_PLATFORM_RUNTIME_CLOUDFLARE_API_TOKEN` to a new token that has all runtime permissions. Then run:
|
|
72
90
|
|
|
73
91
|
```sh
|
|
74
92
|
VOID_EMAIL_SENDER_DOMAIN=mail.example.com \
|
|
@@ -76,13 +94,13 @@ VOID_EMAIL_SHARED_ZONE_ID=your-zone-id \
|
|
|
76
94
|
void platform upgrade your-installation-id
|
|
77
95
|
```
|
|
78
96
|
|
|
79
|
-
|
|
97
|
+
Void records the domain and zone for later upgrades; an ordinary upgrade cannot replace them.
|
|
80
98
|
|
|
81
|
-
Before
|
|
99
|
+
Before the CLI changes anything or pauses traffic, it checks that the runtime token can read the mail zone and its Email Routing settings, rules, and addresses. If Cloudflare denies a request, the command stops and names each missing permission. Void keeps a saved runtime token, so you can add the permission to the same token and run the command again. The check cannot confirm Edit access or Email Sending, so select those permissions as the table shows.
|
|
82
100
|
|
|
83
|
-
|
|
101
|
+
Without `VOID_PLATFORM_RUNTIME_CLOUDFLARE_API_TOKEN`, `upgrade`, `repair`, `enable`, and `rollback` check the runtime token saved on this machine. The platform can use a newer token, for example one set from another machine. If Cloudflare does not accept the saved token, the CLI shows a warning and continues without the check. To check the token that the platform uses, set `VOID_PLATFORM_RUNTIME_CLOUDFLARE_API_TOKEN` to it.
|
|
84
102
|
|
|
85
|
-
The installer deploys the email gateway, prepares the shared mail route, and verifies inbound readiness before opening platform traffic. If setup fails,
|
|
103
|
+
The installer deploys the email gateway, prepares the shared mail route, and verifies inbound readiness before opening platform traffic. If setup fails, fix the problem that the error names, for example a missing permission, the exact-domain MX records, or a routing conflict. Then run the same install or upgrade command again. A fresh install resumes with `void platform install --resume --name <installation-id>`; it continues the recorded email operation after the configuration is corrected.
|
|
86
104
|
|
|
87
105
|
## R2 Upload Credentials
|
|
88
106
|
|
|
@@ -53,6 +53,22 @@ The management token needs **SSL and Certificates: Read** (or Edit) on that zone
|
|
|
53
53
|
|
|
54
54
|
:::
|
|
55
55
|
|
|
56
|
+
## Project Custom Domains
|
|
57
|
+
|
|
58
|
+
Projects can serve their own domains, such as `www.example.com`, through Cloudflare for SaaS custom hostnames. This needs a dedicated application zone. Turn it on when installing, or later with an upgrade:
|
|
59
|
+
|
|
60
|
+
```sh
|
|
61
|
+
void platform install --application-domain example.app --zone example.app --dedicated-zone --custom-domains
|
|
62
|
+
void platform upgrade <installation-id> --custom-domains
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
The runtime token needs **SSL and Certificates: Edit** on the application zone. Void includes it in the runtime token's creation link and checks it before deploying; a token created before custom domains were on needs it added. Before adding the first domain, set up Cloudflare for SaaS on that zone once:
|
|
66
|
+
|
|
67
|
+
1. Create a proxied DNS record for `cname.<application domain>`, for example an `AAAA` record pointing to `100::`.
|
|
68
|
+
2. Open **SSL/TLS > Custom Hostnames**, enable Cloudflare for SaaS, and set `cname.<application domain>` as the fallback origin.
|
|
69
|
+
|
|
70
|
+
A project owner then runs `void domain add <hostname>`. Void prints the CNAME target, `cname.<application domain>`, and the TXT records that prove ownership. Once the records resolve and the certificate is issued, the dedicated zone's catch-all routes send the hostname to the project.
|
|
71
|
+
|
|
56
72
|
## Optional Dashboard
|
|
57
73
|
|
|
58
74
|
The API's `/admin/` pages are included in the core installation. You can deploy
|
|
@@ -113,9 +113,13 @@ An upgrade validates the runtime, applies supported pending migrations, deploys
|
|
|
113
113
|
|
|
114
114
|
Before starting, Void checks access to the installation's Cloudflare account, Workers, and existing R2 buckets. If credentials are rejected, set `CLOUDFLARE_API_TOKEN` to a management token scoped to that account and retry. This overrides the installation's saved management token.
|
|
115
115
|
|
|
116
|
-
|
|
116
|
+
Some upgrades pause application traffic during the cutover to the new version. Traffic resumes after the new version passes its health checks. If an upgrade or another lifecycle command fails after it paused traffic, traffic stays paused until a later run succeeds. To resume:
|
|
117
117
|
|
|
118
|
-
|
|
118
|
+
1. Run `void platform status <id>` to see the saved progress.
|
|
119
|
+
2. Fix the problem that the error names.
|
|
120
|
+
3. Run the resume command that the CLI printed. It is the same command, with the same runtime.
|
|
121
|
+
|
|
122
|
+
::: details Migration safety, credential rotation, and rollback
|
|
119
123
|
|
|
120
124
|
To update the runtime Cloudflare token, GitHub OAuth credentials when GitHub login is enabled, or R2 credentials,
|
|
121
125
|
provide their `VOID_PLATFORM_*` environment variables when running the upgrade.
|
|
@@ -141,6 +145,32 @@ Let running rotations finish before you roll back. If an older proxy runs next t
|
|
|
141
145
|
|
|
142
146
|
:::
|
|
143
147
|
|
|
148
|
+
### Platform Workers changed outside Void {#workers-changed-outside-void}
|
|
149
|
+
|
|
150
|
+
Void manages the platform's own Workers. Do not change them in the Cloudflare dashboard or with the Cloudflare API. To change the platform, use the Void commands on this page.
|
|
151
|
+
|
|
152
|
+
`upgrade`, `repair`, `enable`, `rollback`, and `install --resume` deploy the platform Workers again. Before they change a platform Worker or pause traffic, Void finds each platform Worker that:
|
|
153
|
+
|
|
154
|
+
- was changed in the Cloudflare dashboard or with the Cloudflare API.
|
|
155
|
+
- has an active version without a Void deployment record. This can occur when an earlier run replaced a change made outside Void, and then stopped or failed. If that run stopped during the cutover to the new version, the command first makes the earlier versions active again. Void checks those earlier versions too. A version that an older Void release deployed can also have no record.
|
|
156
|
+
|
|
157
|
+
The `--plan` preview of `upgrade`, `repair`, `enable`, and `rollback` shows the same list as a warning.
|
|
158
|
+
|
|
159
|
+
In a terminal, Void lists these Workers and asks **Replace the configuration of these Workers?** The default answer is No.
|
|
160
|
+
|
|
161
|
+
- If you answer No, the command stops. No platform Worker changed, and the command did not pause traffic.
|
|
162
|
+
- If you answer Yes, the command continues. First, Void prepares the platform resources and the database. Then, before it pauses traffic or deploys a Worker, the Cloudflare CLI asks you again for each Worker changed in the dashboard or with the API. For a dashboard change, it shows the differences. Void uploads a new version of each of these Workers and does not deploy it yet. For a Worker that has an active version without a Void deployment record, the Cloudflare CLI does not ask again.
|
|
163
|
+
|
|
164
|
+
If you refuse in the Cloudflare CLI, the command stops. Void does not undo the resource and database changes. No deployment changed, and the command did not pause traffic.
|
|
165
|
+
|
|
166
|
+
The replacement removes values that Void does not set, for example an `EMAIL_FROM` variable that you added. It also resets values that Void sets, for example `AUTH_REDIRECT_URI`.
|
|
167
|
+
|
|
168
|
+
Without a terminal, for example in CI, or with `--yes`, the command stops before it changes a platform Worker, and it does not pause traffic. Run the command that Void prints once in a terminal, and answer the questions there. After that run completes, the command works in CI again.
|
|
169
|
+
|
|
170
|
+
If Void cannot read a platform Worker, the command also stops before it changes a platform Worker or pauses traffic. Run the command again. If a platform Worker has no single version that gets 100% of traffic, for example after a gradual deployment, deploy one version of it to 100% of traffic in the Cloudflare dashboard. Then run the command once in a terminal, so that you can approve the dashboard change.
|
|
171
|
+
|
|
172
|
+
If an earlier run failed after it paused traffic, traffic stays paused after these stops. To resume traffic, see [Upgrade the platform](#upgrade-the-platform).
|
|
173
|
+
|
|
144
174
|
### Follow upgrade and rollback progress
|
|
145
175
|
|
|
146
176
|
Watching progress is optional: a running upgrade or rollback proceeds through
|
|
@@ -260,6 +260,6 @@ You can also rerun `void platform install` and choose **Continue setup** for an
|
|
|
260
260
|
|
|
261
261
|
Resume restores your selected Hyperdrive. If that selection is missing from the saved checkpoint, add `--hyperdrive <existing-id>` when resuming, using the same configuration you originally selected.
|
|
262
262
|
|
|
263
|
-
If Cloudflare rejects a saved runtime token during continued credential setup, Void opens the token page and asks for a replacement in the same run. Network or service failures do not discard saved tokens. Tokens supplied through the environment must be corrected there instead.
|
|
263
|
+
If Cloudflare rejects a saved runtime token during continued credential setup, Void opens the token page and asks for a replacement in the same run. A missing [email permission](/guide/platform/installation/credentials#enable-email) does not discard the saved token: add the permission to the same token, then resume. Network or service failures do not discard saved tokens. Tokens supplied through the environment must be corrected there instead.
|
|
264
264
|
|
|
265
265
|
:::
|
|
@@ -10,7 +10,7 @@ If you're deploying an app for yourself, [deploy directly to Cloudflare](/integr
|
|
|
10
10
|
|
|
11
11
|
The core platform supports GitHub, Google, generic OIDC, and Cloudflare Access login, CLI deploys, D1, KV, R2, Queues, cron jobs, Workers AI, WebSockets, SSE, ISR, routing, logs, and rollback.
|
|
12
12
|
|
|
13
|
-
The core installation includes managed Sandboxes and an email gateway; email is enabled when you configure a shared mail domain and zone. The user dashboard, GitHub builds and webhooks, build Containers
|
|
13
|
+
The core installation includes managed Sandboxes and an email gateway; email is enabled when you configure a shared mail domain and zone. The user dashboard, GitHub builds and webhooks, and build Containers aren't part of the core installation. [Project custom domains](/guide/platform/installation/domains#project-custom-domains) are opt-in with `--custom-domains`. Source-built platforms that add the optional GitHub services should follow the [isolated webhook ingress setup](/guide/platform/development/runtime#optional-github-webhook-ingress-for-access-protected-apis) when Access protects the API.
|
|
14
14
|
|
|
15
15
|
## Deployment features
|
|
16
16
|
|
|
@@ -12,7 +12,7 @@ Create route handlers in `routes/**/*.ts`. Each file maps to a URL path based on
|
|
|
12
12
|
|
|
13
13
|
<RoutesFileTree />
|
|
14
14
|
|
|
15
|
-
Dynamic segments use brackets: `[id]` becomes a route parameter and `[...slug]` becomes a catch-all. Files or directories starting with `_` are ignored
|
|
15
|
+
Dynamic segments use brackets: `[id]` becomes a route parameter and `[...slug]` becomes a catch-all. Files or directories starting with `_` are ignored, and so are those starting with `.`, except `.well-known`. Directories wrapped in parentheses like `(admin)` are route groups. They help organize files without changing the URL.
|
|
16
16
|
|
|
17
17
|
### Environment-only routes
|
|
18
18
|
|
|
@@ -106,4 +106,4 @@ export default defineRender(async (c, assetTags) => {
|
|
|
106
106
|
});
|
|
107
107
|
```
|
|
108
108
|
|
|
109
|
-
Server-side calls forward the incoming request's `cookie` and `authorization` headers. Explicit headers take precedence.
|
|
109
|
+
Server-side calls to your app forward the incoming request's `cookie` and `authorization` headers. Explicit headers take precedence. Calls to an external `baseURL` use HTTP and do not inherit these headers.
|
|
@@ -52,6 +52,7 @@ This provides binding types and Workers runtime types.
|
|
|
52
52
|
| `KV` | KV | `c.env.KV` or `void/kv` |
|
|
53
53
|
| `STORAGE` | R2 | `c.env.STORAGE` or `void/storage` |
|
|
54
54
|
| `AI` | Workers AI | `c.env.AI` or `void/ai` |
|
|
55
|
+
| `ASSETS` | Static assets | `c.env.ASSETS.fetch(request)` |
|
|
55
56
|
| `QUEUE_*` | Queues | `defineQueue()` or `void/queues` |
|
|
56
57
|
| Filename-derived | Durable Objects | A module in `durable-objects/` |
|
|
57
58
|
|
|
@@ -183,7 +184,7 @@ void project status
|
|
|
183
184
|
void project rollback [version]
|
|
184
185
|
```
|
|
185
186
|
|
|
186
|
-
Void restores recorded triggers along with the code. Versions without a complete trigger snapshot keep current routes and schedules. Rollback does not reverse database migrations.
|
|
187
|
+
Void restores recorded triggers along with the code. Versions without a complete trigger snapshot keep current routes and schedules. Rollback does not reverse database migrations. To undo D1 migrations, run [`void db restore`](../reference/cli/database.md#void-db-restore) with the restore point that deploy printed before it applied them, within 7 days on Workers Free or 30 days on Workers Paid.
|
|
187
188
|
|
|
188
189
|
#### Scope and limitations
|
|
189
190
|
|
|
@@ -71,6 +71,31 @@ Use [KV](../../guide/kv.md), [object storage](../../guide/storage.md), and [AI](
|
|
|
71
71
|
|
|
72
72
|
Declare variables in `env.ts` and read them with `import { env } from "void/env"`. See [Environment Variables](../../guide/env-vars.md) for local values, production secrets, and public `VITE_*` values.
|
|
73
73
|
|
|
74
|
+
## Custom Worker Entry
|
|
75
|
+
|
|
76
|
+
Set `cloudflare.main` in `void.config.ts` when your Worker needs its own entry module, for example to export a Durable Object class:
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
import { defineConfig } from 'void/config';
|
|
80
|
+
|
|
81
|
+
export default defineConfig({
|
|
82
|
+
cloudflare: { main: './server.ts' },
|
|
83
|
+
});
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
The path is relative to your app root. Default-export the TanStack request handler and add your named exports in that module:
|
|
87
|
+
|
|
88
|
+
```ts
|
|
89
|
+
import handler from '@tanstack/react-start/server-entry';
|
|
90
|
+
|
|
91
|
+
export { Counter } from './counter';
|
|
92
|
+
export default handler;
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Void preserves these named exports in development, production builds, and deploys. Without `cloudflare.main`, Void uses TanStack's default server entry. A package entry such as `@tanstack/react-start/server-entry` is resolved as a module.
|
|
96
|
+
|
|
97
|
+
Bind an exported Durable Object or Workflow class under `cloudflare` as well, for example in `cloudflare.durable_objects`. These settings apply when you deploy with `void deploy --platform cloudflare`. On a Void platform, use [Durable State](../../guide/durable-state.md) instead.
|
|
98
|
+
|
|
74
99
|
## Accessing Bindings Directly
|
|
75
100
|
|
|
76
101
|
You can also access Cloudflare bindings via the `cloudflare:workers` module:
|