void 0.20.3 → 0.21.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 +2 -2
- package/dist/agents-gni4eqBu.mjs +111 -0
- package/dist/auth-3sGB0zJ1.mjs +22 -0
- package/dist/{auth-DPl6kck4.mjs → auth-B9_D6ygs.mjs} +6 -241
- package/dist/auth-CAw7zHqj.mjs +2 -0
- package/dist/auth-client-BWBT8HLp.mjs +6 -0
- package/dist/auth-client-Bawdj38n.d.mts +7 -0
- package/dist/auth-client-react-7GFffu8R.d.mts +7 -0
- package/dist/auth-client-react-CMLwT2xI.mjs +6 -0
- package/dist/auth-client-solid-DyTFL4cq.d.mts +7 -0
- package/dist/auth-client-solid-UoreJWZG.mjs +6 -0
- package/dist/auth-client-svelte-Cv_WvrRk.mjs +6 -0
- package/dist/auth-client-svelte-zetW0KIH.d.mts +7 -0
- package/dist/auth-client-vue-CFk7Xbv3.mjs +6 -0
- package/dist/auth-client-vue-bChShbQP.d.mts +7 -0
- package/dist/{auth-cmd-CzwquNiP.mjs → auth-cmd-MkBG2u1f.mjs} +5 -5
- package/dist/{auth-link-ElDTgF7j.mjs → auth-link-Devmv96E.mjs} +5 -5
- package/dist/{better-auth-shared-DSCeohOK.d.mts → better-auth-shared-BoVwA5Vm.d.mts} +1 -6
- package/dist/{better-auth-shared-CYw1T3k4.mjs → better-auth-shared-syGYYmnY.mjs} +1 -1
- package/dist/{build-cmd-BpJe6boP.mjs → build-cmd-DsBGwtfs.mjs} +6 -4
- package/dist/{cache-D98YTqeE.mjs → cache-BMw8eMyF.mjs} +6 -4
- package/dist/{cancel-deploy-CPbEQLMG.mjs → cancel-deploy-B3_s9NIN.mjs} +5 -3
- package/dist/cf-access-rAZxzMkL.mjs +181 -0
- package/dist/cf-build-output-CTdlo6Rt.mjs +520 -0
- package/dist/cli/cf-compat.d.mts +1 -0
- package/dist/cli/cf-compat.mjs +934 -0
- package/dist/cli/cli.mjs +60 -38
- package/dist/cli/env-schema-probe.mjs +3 -3
- package/dist/client-DAAivdid.mjs +2 -0
- package/dist/{client-BQBrZoCX.mjs → client-PdAJ-F0t.mjs} +6 -12
- package/dist/{cloudflare-auth-6M5llVPC.mjs → cloudflare-auth-BCmTc1X_.mjs} +13 -44
- package/dist/{cloudflare-cmd-4RPGN3KB.mjs → cloudflare-cmd-D6PrKn7o.mjs} +4 -7
- package/dist/{cloudflare-connect-t1UU5svD.mjs → cloudflare-connect-DloREDlc.mjs} +6 -6
- package/dist/cloudflare-operations-BHNJVDbN.mjs +2 -0
- package/dist/{cloudflare-operations-BzWnlC1_.mjs → cloudflare-operations-CPEdHYhM.mjs} +37 -39
- package/dist/cloudflare-user-output-Q-k0QoNQ.mjs +20 -0
- package/dist/collect-DAUItMDS.mjs +2 -0
- package/dist/collect-DXHNWHcT.mjs +48 -0
- package/dist/config--T87TD8T.mjs +2 -0
- package/dist/{config-NOG_U1aK.mjs → config-BSe70f4T.mjs} +4 -6
- package/dist/config-DDIFxQYx.mjs +2 -0
- package/dist/{config-uNGuFsI2.mjs → config-Dxr6cTXn.mjs} +22 -37
- package/dist/config-DywxBLQC.d.mts +185 -0
- package/dist/config-entry.d.mts +6 -0
- package/dist/config-entry.mjs +7 -0
- package/dist/config-uP7ZDtVZ.mjs +21 -0
- package/dist/config-write-y3CBI_ux.mjs +60 -0
- package/dist/{connect-WCQZ_u3m.mjs → connect-BvC9kolB.mjs} +8 -6
- package/dist/{create-project-D0oXA090.mjs → create-project-C9lQhRzj.mjs} +8 -23
- package/dist/create-project-CI-17RVJ.mjs +2 -0
- package/dist/database-provider-Cx525bwX.mjs +6 -0
- package/dist/database-provider.mjs +1 -5
- package/dist/{db-DJ-9qs3S.mjs → db-R7IQgOv5.mjs} +48 -44
- package/dist/{delete-BZ4-WaGm.mjs → delete-CghI_NXn.mjs} +6 -4
- package/dist/deploy-CYPymbtG.mjs +2 -0
- package/dist/{deploy-BAhhcg5q.mjs → deploy-H968Lo4T.mjs} +751 -190
- package/dist/discover-BBzDZe_o.mjs +2 -0
- package/dist/{discover-xvfrgJeo.mjs → discover-C4O6YxVS.mjs} +3 -8
- package/dist/{dist-BrsS7cai.mjs → dist-4WkAWhWx.mjs} +1 -15
- package/dist/{dist-m40_XgNh.mjs → dist-Bn8Kodjp.mjs} +1 -1
- package/dist/dist-C5fND3R0.mjs +2 -0
- package/dist/dist-D7-nEOXi.mjs +2 -0
- package/dist/{output-B0cfNSx5.mjs → dist-Dn6nn2IU.mjs} +3 -926
- package/dist/{domain-BxAyhxXN.mjs → domain-CITt8lC-.mjs} +7 -5
- package/dist/{route-types-Da-DpyUp.mjs → drizzle-Beb2Am5S.mjs} +1 -280
- package/dist/{email-Ce6SQq-i.mjs → email-C5kaZXzJ.mjs} +2 -2
- package/dist/{email-Bj7Cvdwp.mjs → email-_8VmyX7V.mjs} +14 -12
- package/dist/{entry-DU3oDoQ3.mjs → entry-DdRFGK0y.mjs} +2 -2
- package/dist/{env-DP_EErve.mjs → env-DV4r3nHz.mjs} +9 -7
- package/dist/{env-DBKmK4vc.mjs → env-DX_v-Q-v.mjs} +1 -1
- package/dist/env-Yz4HcvHs.mjs +78 -0
- package/dist/env-helpers--wFmQ_5Q.mjs +136 -0
- package/dist/{env-types-BNPhro-M.mjs → env-types-CWDtqHgw.mjs} +6 -2
- package/dist/{env-validation-CF6KvTRf.mjs → env-validation-BsFEXps5.mjs} +19 -28
- package/dist/env-validation-DIDGM7h4.mjs +2 -0
- package/dist/fetch-CXDChK7B.mjs +18 -0
- package/dist/fetch-_SeGZao9.d.mts +57 -0
- package/dist/fetch-stream-AOByI7Ki.mjs +81 -0
- package/dist/fetch-stream-Bjf0hoZb.d.mts +49 -0
- package/dist/gen-BBiIZw6g.mjs +2 -0
- package/dist/{gen-B_wPnVTK.mjs → gen-CFOEEc-t.mjs} +13 -11
- package/dist/{generate-RTK8_kK1.mjs → generate-C0VY6RVf.mjs} +2 -2
- package/dist/{github-cmd-C-z_xRrQ.mjs → github-cmd-jYjha2LO.mjs} +6 -4
- package/dist/{handler-D1hLsObx.d.mts → handler-BXJTXd02.d.mts} +6 -1
- package/dist/handler-DghKr6dU.mjs +150 -0
- package/dist/head-D_QRR5Yd.mjs +112 -0
- package/dist/head-client-DzmJGN4C.mjs +90 -0
- package/dist/{headers-BAHwgHdW.mjs → headers-B_HBMgi0.mjs} +2 -2
- package/dist/{help-CwOX-zmI.mjs → help-C46mnlUS.mjs} +17 -12
- package/dist/help-CS_nAsWu.mjs +2 -0
- package/dist/index.d.mts +2 -20
- package/dist/index.mjs +116 -60
- package/dist/{init-BGktCXgA.mjs → init-CSXmvxKu.mjs} +49 -50
- package/dist/{link-D2kbqhWb.mjs → link-DxMOALXk.mjs} +7 -5
- package/dist/{list-CvkK_G7k.mjs → list-0wQs0oYg.mjs} +7 -5
- package/dist/live-CB1y5IuC.mjs +411 -0
- package/dist/live-CKiJilLr.d.mts +105 -0
- package/dist/local-d1-DzykTWY8.mjs +104 -0
- package/dist/{login-WIjNc77c.mjs → login-CKk5NX4d.mjs} +6 -11
- package/dist/login-Ch9cgWRF.mjs +2 -0
- package/dist/{logs-dLUFCapG.mjs → logs-hxWBSoej.mjs} +6 -4
- package/dist/migrate-CLty4mZR.mjs +2 -0
- package/dist/migrate-DcW8F2W8.mjs +285 -0
- package/dist/migration-handler-DM4clYj5.d.mts +51 -0
- package/dist/{neon-DHwd2zvC.mjs → neon-n74ta1Pr.mjs} +1 -1
- package/dist/{node-Ez5KW5rn.mjs → node-Cupyf7-s.mjs} +6 -6
- package/dist/{operator-auth-B3e08unv.mjs → operator-auth-BkVgJqv-.mjs} +2 -2
- package/dist/{operator-client-LUZnlnYk.mjs → operator-client-A0iex2yi.mjs} +2 -1
- package/dist/{operator-cmd-CKJ7xIRs.mjs → operator-cmd-BEUYhaHB.mjs} +6 -6
- package/dist/output-urU86XeT.mjs +146 -0
- package/dist/{package-json-CPoWX79C.mjs → package-json-iCbMg5XF.mjs} +1 -1
- package/dist/pages/client.d.mts +5 -2
- package/dist/pages/client.mjs +5 -3
- package/dist/pages/head-client.mjs +1 -89
- package/dist/pages/head.mjs +1 -111
- package/dist/pages/index.d.mts +2 -3
- package/dist/pages/index.mjs +7 -7
- package/dist/pages/islands-plugin.mjs +2 -2
- package/dist/pages/prefetch.d.mts +2 -30
- package/dist/pages/prefetch.mjs +1 -89
- package/dist/pages/protocol.d.mts +2 -2
- package/dist/pages/protocol.mjs +3 -3
- package/dist/pages/serialize.d.mts +2 -9
- package/dist/pages/serialize.mjs +1 -13
- package/dist/plan-BEZ8VJW0.mjs +256 -0
- package/dist/plan-DpuOr14e.mjs +2 -0
- package/dist/{platform-auth-config-CdVWRRJr.mjs → platform-auth-config-Df6yVw-e.mjs} +6 -6
- package/dist/{platform-auth-protection-Drl0qhrn.mjs → platform-auth-protection-Jb0yftay.mjs} +7 -5
- package/dist/{platform-auth-recovery-CmKEWpDo.mjs → platform-auth-recovery-DmRyIfW0.mjs} +6 -5
- package/dist/platform-cmd-C9Vt7m-d.mjs +2 -0
- package/dist/{platform-cmd-5q_k56xS.mjs → platform-cmd-DRxCOTwy.mjs} +8 -5
- package/dist/{platform-domain-4GiDlcqx.mjs → platform-domain-IjiXgrXJ.mjs} +4 -3
- package/dist/{platform-lifecycle-R9xAxvtG.mjs → platform-lifecycle-BquAaU-5.mjs} +208 -37
- package/dist/platform-lifecycle-CuJIZNvA.mjs +2 -0
- package/dist/{platform-management-BfWsXHEW.mjs → platform-management-CCQKGsq4.mjs} +8 -5
- package/dist/platform-management-Cgyed0WY.mjs +2 -0
- package/dist/{platform-recovery-CbK-I1FB.mjs → platform-recovery-DS8ih1SW.mjs} +3 -3
- package/dist/platform-registry-BJbgZLS1.mjs +431 -0
- package/dist/{plugin-inference-BDRfZngg.mjs → plugin-inference-DsvtJLll.mjs} +4 -4
- package/dist/prefetch-Bsc_Pb6c.mjs +90 -0
- package/dist/prefetch-Ce6la4EI.d.mts +31 -0
- package/dist/{prepare-blNRQvQl.mjs → prepare-CaUxODOU.mjs} +3 -2
- package/dist/prepare-D4CkM3_v.mjs +2 -0
- package/dist/{prepare-CtDJjoOj.mjs → prepare-pcWcxSCh.mjs} +13 -11
- package/dist/prerender-render-Cf_WDE9W.mjs +111 -0
- package/dist/prerender-render.mjs +1 -110
- package/dist/{preset-lAy0B0BQ.mjs → preset-Dowh9tTt.mjs} +16 -118
- package/dist/project-BEBFDFLz.mjs +2 -0
- package/dist/project-CWNIPoXc.mjs +209 -0
- package/dist/{project-cmd-CTdmnzvc.mjs → project-cmd-2lN--YAX.mjs} +18 -16
- package/dist/{project-paths-SK8nMHPp.mjs → project-paths-CKQ-Q5JS.mjs} +47 -14
- package/dist/project-slug-23TpquG4.mjs +8 -0
- package/dist/project-slug-DofjTFd-.mjs +2 -0
- package/dist/{project-team-CGxsQe3_.mjs → project-team-Dapn9HZn.mjs} +6 -4
- package/dist/{project-token-Cirx7uwZ.mjs → project-token-C90v9SJK.mjs} +6 -4
- package/dist/{project-tsconfig-Ql2XsSQp.mjs → project-tsconfig-CwfqUnVp.mjs} +2 -2
- package/dist/{protocol-C-pqYJjE.d.mts → protocol-ZH3jP4a7.d.mts} +1 -1
- package/dist/providers-BNKRacMr.d.mts +7 -0
- package/dist/provision-CNgEBkVA.mjs +3 -0
- package/dist/{provision-CSJOjjQk.mjs → provision-Cck2m3jJ.mjs} +11 -25
- package/dist/queues-BWKt1Xo4.d.mts +7 -0
- package/dist/{requests-4Nq59hOr.mjs → requests-CzX46I0i.mjs} +5 -3
- package/dist/resolve-project-BTotl8Nn.mjs +2 -0
- package/dist/{resolve-project--Vxawf7z.mjs → resolve-project-Xvis70DG.mjs} +2 -8
- package/dist/response-Tn7rU0MV.mjs +30 -0
- package/dist/{rollback-Dr7u0Ljx.mjs → rollback-BEeyc73H.mjs} +6 -4
- package/dist/{rolldown-runtime-rQ84J-ij.mjs → rolldown-runtime-DXIUcv95.mjs} +1 -10
- package/dist/route-types-Id82-veQ.mjs +280 -0
- package/dist/{local-d1-D2I6Ox5F.mjs → runner-BGVsGgkb.mjs} +6 -114
- package/dist/runner-CQs_cDSG.mjs +2 -0
- package/dist/runner-mysql-1o47achK.mjs +2 -0
- package/dist/{runner-mysql-7BPUNGmL.mjs → runner-mysql-BhwMk2Bm.mjs} +2 -9
- package/dist/{runner-pg-BkEza-dX.mjs → runner-pg-CJ_JeGF6.mjs} +2 -9
- package/dist/runner-pg-D7z01mQS.mjs +2 -0
- package/dist/runtime/ai.mjs +1 -1
- package/dist/runtime/auth-client-react.d.mts +2 -6
- package/dist/runtime/auth-client-react.mjs +1 -5
- package/dist/runtime/auth-client-solid.d.mts +2 -6
- package/dist/runtime/auth-client-solid.mjs +1 -5
- package/dist/runtime/auth-client-svelte.d.mts +2 -6
- package/dist/runtime/auth-client-svelte.mjs +1 -5
- package/dist/runtime/auth-client-vue.d.mts +2 -6
- package/dist/runtime/auth-client-vue.mjs +1 -5
- package/dist/runtime/auth-client.d.mts +2 -6
- package/dist/runtime/auth-client.mjs +1 -5
- package/dist/runtime/auth.mjs +1 -21
- package/dist/runtime/better-auth-mysql.d.mts +1 -1
- package/dist/runtime/better-auth-mysql.mjs +1 -1
- package/dist/runtime/better-auth-pg.d.mts +1 -1
- package/dist/runtime/better-auth-pg.mjs +1 -1
- package/dist/runtime/better-auth.d.mts +1 -1
- package/dist/runtime/better-auth.mjs +1 -1
- package/dist/runtime/client-react.d.mts +3 -3
- package/dist/runtime/client-react.mjs +3 -3
- package/dist/runtime/client-solid.d.mts +3 -3
- package/dist/runtime/client-solid.mjs +3 -3
- package/dist/runtime/client-svelte.d.mts +3 -3
- package/dist/runtime/client-svelte.mjs +3 -3
- package/dist/runtime/client-vue.d.mts +3 -3
- package/dist/runtime/client-vue.mjs +3 -3
- package/dist/runtime/client.d.mts +3 -3
- package/dist/runtime/client.mjs +3 -3
- package/dist/runtime/db.mjs +1 -1
- package/dist/runtime/durable.mjs +1 -1
- package/dist/runtime/email/testing.mjs +1 -1
- package/dist/runtime/env-helpers.mjs +1 -135
- package/dist/runtime/env-public-client.mjs +1 -1
- package/dist/runtime/env-public.mjs +2 -2
- package/dist/runtime/env.mjs +1 -77
- package/dist/runtime/fetch-stream.d.mts +2 -49
- package/dist/runtime/fetch-stream.mjs +2 -80
- package/dist/runtime/fetch.d.mts +2 -57
- package/dist/runtime/fetch.mjs +2 -17
- package/dist/runtime/handler.d.mts +1 -1
- package/dist/runtime/handler.mjs +1 -149
- package/dist/runtime/kv.mjs +1 -1
- package/dist/runtime/live-client.d.mts +1 -1
- package/dist/runtime/live-server.mjs +2 -2
- package/dist/runtime/live.d.mts +2 -104
- package/dist/runtime/live.mjs +1 -410
- package/dist/runtime/migration-handler-mysql.d.mts +1 -1
- package/dist/runtime/migration-handler-pg.d.mts +1 -1
- package/dist/runtime/migration-handler.d.mts +2 -50
- package/dist/runtime/queues.d.mts +2 -6
- package/dist/runtime/queues.mjs +1 -1
- package/dist/runtime/response.mjs +1 -29
- package/dist/runtime/sandbox.mjs +1 -1
- package/dist/runtime/sse.mjs +1 -171
- package/dist/runtime/storage.mjs +1 -1
- package/dist/runtime/validator.d.mts +1 -1
- package/dist/runtime/validator.mjs +1 -71
- package/dist/runtime/ws-server.d.mts +2 -2
- package/dist/runtime/ws-server.mjs +2 -2
- package/dist/runtime/ws.d.mts +2 -121
- package/dist/{scan-CpK-57ug.mjs → scan-DJbooZm2.mjs} +3 -3
- package/dist/{scan-BMH4rzlv.mjs → scan-DdDvRCU1.mjs} +8 -26
- package/dist/{secret-AcPi-FoA.mjs → secret-wnTel5Yw.mjs} +8 -6
- package/dist/serialize-BPvnNQuA.mjs +14 -0
- package/dist/serialize-CfSwWfF2.d.mts +10 -0
- package/dist/{skills-C0RvGjeE.mjs → skills-B-690E7h.mjs} +3 -2
- package/dist/sse-BaC1jXko.mjs +172 -0
- package/dist/{subcommand-prompt-Bmyn5Rlc.mjs → subcommand-prompt-Gj3VzLIh.mjs} +2 -1
- package/dist/sveltekit.d.mts +2 -1
- package/dist/sveltekit.mjs +3 -2
- package/dist/validate-DqJ33oHj.mjs +2 -0
- package/dist/validate-qNhV00PD.mjs +180 -0
- package/dist/validator-BTOu0fB0.mjs +72 -0
- package/dist/{wrangler--imS8n0d.mjs → wrangler-D01qs6VB.mjs} +259 -71
- package/dist/ws-BwcqizuH.d.mts +122 -0
- package/dist/{yarn-pnp-DxSInkzL.mjs → yarn-pnp-CVEc3gE7.mjs} +1 -1
- package/package.json +19 -8
- package/skills/void/SKILL.md +6 -4
- package/skills/void/docs/guide/ai.md +3 -3
- package/skills/void/docs/guide/app-types.md +12 -11
- package/skills/void/docs/guide/auth.md +2 -2
- package/skills/void/docs/guide/database/d1.md +1 -1
- package/skills/void/docs/guide/database/mysql.md +1 -1
- package/skills/void/docs/guide/database/postgresql.md +3 -3
- package/skills/void/docs/guide/deployment.md +2 -2
- package/skills/void/docs/guide/durable-state.md +2 -2
- package/skills/void/docs/guide/edge/headers.md +3 -3
- package/skills/void/docs/guide/edge/prerendering.md +1 -1
- package/skills/void/docs/guide/edge/redirects.md +4 -4
- package/skills/void/docs/guide/edge/revalidation.md +6 -6
- package/skills/void/docs/guide/edge/rewrites.md +28 -27
- package/skills/void/docs/guide/edge/static-assets.md +1 -1
- package/skills/void/docs/guide/email.md +15 -15
- package/skills/void/docs/guide/env-migration.md +1 -1
- package/skills/void/docs/guide/index.md +1 -1
- package/skills/void/docs/guide/pages-routing/head.md +1 -1
- package/skills/void/docs/guide/platform/administration/access.md +13 -5
- package/skills/void/docs/guide/platform/administration/projects.md +3 -1
- package/skills/void/docs/guide/platform/installation/ci.md +3 -0
- package/skills/void/docs/guide/platform/installation/credentials.md +15 -5
- package/skills/void/docs/guide/platform/installation/prerequisites.md +2 -0
- package/skills/void/docs/guide/platform/installation/setup.md +1 -1
- package/skills/void/docs/guide/remote-dev.md +2 -2
- package/skills/void/docs/guide/sandboxes.md +1 -1
- package/skills/void/docs/guide/ssg.md +1 -1
- package/skills/void/docs/guide/websockets.md +1 -1
- package/skills/void/docs/integrations/cloudflare.md +86 -84
- package/skills/void/docs/integrations/frameworks/analog.md +14 -9
- package/skills/void/docs/integrations/frameworks/astro.md +14 -10
- package/skills/void/docs/integrations/frameworks/nuxt.md +14 -9
- package/skills/void/docs/integrations/frameworks/overview.md +35 -29
- package/skills/void/docs/integrations/frameworks/react-router.md +1 -1
- package/skills/void/docs/integrations/frameworks/sveltekit.md +33 -30
- package/skills/void/docs/integrations/frameworks/tanstack-start.md +1 -1
- package/skills/void/docs/integrations/nodejs-bun-deno.md +5 -5
- package/skills/void/docs/reference/api.md +21 -4
- package/skills/void/docs/reference/cli.md +32 -23
- package/skills/void/docs/reference/config.md +56 -33
- package/skills/void/docs/reference/structure.md +2 -2
- package/dist/validate-tBBN_dXH.mjs +0 -505
|
@@ -1,51 +1,63 @@
|
|
|
1
|
-
import { n as
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { i as resolveProjectPaths, n as readProjectPaths, t as assertNoRootSourceConventionConflicts } from "./project-paths-
|
|
5
|
-
import {
|
|
1
|
+
import { n as __toESM, t as __commonJSMin } from "./rolldown-runtime-DXIUcv95.mjs";
|
|
2
|
+
import { a as join, l as relative, n as dirname, o as normalize, r as extname, t as basename, u as resolve } from "./dist-4WkAWhWx.mjs";
|
|
3
|
+
import { c as import_picocolors$1, d as require_picocolors, i as createSpinner, r as cliTitle } from "./output-urU86XeT.mjs";
|
|
4
|
+
import { i as resolveProjectPaths, n as readProjectPaths, t as assertNoRootSourceConventionConflicts } from "./project-paths-CKQ-Q5JS.mjs";
|
|
5
|
+
import { t as findVoidAuthConfig } from "./config-uP7ZDtVZ.mjs";
|
|
6
6
|
import { i as trustedCloudflareWorkerAccessHeaders, r as scopedAccessCredentials, t as cfAccessHeaders } from "./cf-access-DRsQRe6k.mjs";
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
7
|
+
import { a as getApiUrl, c as getToken, l as getTokenSource, o as getProxyUrl, u as isStagingMode } from "./auth-B9_D6ygs.mjs";
|
|
8
|
+
import { r as ensurePlatformProxyAccess, t as ensureCloudflaredToken } from "./cf-access-rAZxzMkL.mjs";
|
|
9
|
+
import { d as writeProjectConfig, i as readDeploymentPlatform, l as writeDeploymentPlatform, o as readProjectConfig, t as attachSelectedPlatform } from "./project-CWNIPoXc.mjs";
|
|
10
|
+
import { d as isNodeTarget, h as resolveBindingNames, m as readConfig, u as getDatabaseDialect } from "./config-Dxr6cTXn.mjs";
|
|
11
|
+
import { A as writeWranglerPublishedTrafficSnapshot, D as syncWranglerWebSockets, E as syncWranglerDurableObjects, L as materializeCloudflareConfig, M as isSandboxEnabled, N as requiresSandboxPlatformImage, P as resolveSandboxConfig, R as persistCloudflareConfig, S as readWranglerPublishedTrafficSnapshot, T as syncWranglerBindings, V as stashCloudflareDeployPointer, a as LIVE_MIGRATION_TAG, c as bindingEntriesForField, f as findBindingNameOwner, g as readExistingLiveBindingConfig, h as normalizeWranglerCompatibilityFlags, k as writeProvisionedWranglerConfig, l as ensureWranglerCompat, o as acknowledgeWranglerManagedQueueRemovals, r as FRIENDLY_BINDING_NAMES, w as resolveLiveBindingConfig, x as readWranglerManagedQueueCleanupCandidates } from "./wrangler-D01qs6VB.mjs";
|
|
10
12
|
import { i as voidWarn, r as voidLog } from "./log-ChfPKsVd.mjs";
|
|
11
|
-
import { n as lintDuplicateSources, r as mergeRoutingRules, t as lintDestinationSplats } from "./headers-
|
|
12
|
-
import { i as
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
13
|
+
import { n as lintDuplicateSources, r as mergeRoutingRules, t as lintDestinationSplats } from "./headers-B_HBMgi0.mjs";
|
|
14
|
+
import { a as scanQueuesSync, i as scanWebSocketRoutesSync, o as scanJobsSync, r as scanRoutes } from "./scan-DdDvRCU1.mjs";
|
|
15
|
+
import { i as inferProjectBindings, n as FRAMEWORK_SCAN_DIRS, r as detectFramework } from "./plugin-inference-DsvtJLll.mjs";
|
|
16
|
+
import { o as validateSsrEntry } from "./entry-DdRFGK0y.mjs";
|
|
17
|
+
import { t as collectMigrations } from "./collect-DXHNWHcT.mjs";
|
|
18
|
+
import { r as buildMigrationPlanBundle } from "./plan-BEZ8VJW0.mjs";
|
|
15
19
|
import { r as scanWranglerDotenvKeys } from "./dotenv-VQxupEUv.mjs";
|
|
16
|
-
import { t as discoverSchema } from "./discover-
|
|
17
|
-
import { t as findEnvFile } from "./env-types-
|
|
18
|
-
import {
|
|
19
|
-
import { n as CLOUDFLARE_DEPLOY_BUILD_ENV, o as resolveRemoteMode, s as stripInternalEnvKeys } from "./env-
|
|
20
|
-
import {
|
|
21
|
-
import { t as
|
|
22
|
-
import {
|
|
20
|
+
import { t as discoverSchema } from "./discover-C4O6YxVS.mjs";
|
|
21
|
+
import { t as findEnvFile } from "./env-types-CWDtqHgw.mjs";
|
|
22
|
+
import { d as formatEnvReport, f as listSelfHostSecretNames, g as validateProdEnv, h as selfHostSchemaFailureMessage, i as SelfHostSecretListError, l as dischargeSelfHostEnvContext, n as SelfHostFirstDeployError, p as readEmittedWorkerVars, r as SelfHostSchemaError, s as deriveSelfHostEnvContextFromVars, t as SelfHostEnvValidationError, u as fetchRemoteSecretNames, v as readGeneratedWranglerConfigFile } from "./env-validation-BsFEXps5.mjs";
|
|
23
|
+
import { n as CLOUDFLARE_DEPLOY_BUILD_ENV, o as resolveRemoteMode, s as stripInternalEnvKeys } from "./env-DX_v-Q-v.mjs";
|
|
24
|
+
import { E as confirm, I as select, N as note, O as intro, P as outro, W as isCancel, j as log$1 } from "./dist-Dn6nn2IU.mjs";
|
|
25
|
+
import { t as writeDrizzleConfig } from "./config-BSe70f4T.mjs";
|
|
26
|
+
import { i as runMySqlMigrations } from "./runner-mysql-BhwMk2Bm.mjs";
|
|
27
|
+
import { i as runPgMigrations } from "./runner-pg-CJ_JeGF6.mjs";
|
|
23
28
|
import { n as openMigrationValidationDatabase, t as SqliteMigrationError } from "./sqlite-validation-BzKMWnO4.mjs";
|
|
24
|
-
import { t as
|
|
25
|
-
import {
|
|
26
|
-
import {
|
|
27
|
-
import { a as
|
|
28
|
-
import {
|
|
29
|
-
import {
|
|
30
|
-
import { n as
|
|
31
|
-
import { i as
|
|
32
|
-
import { r as
|
|
29
|
+
import { i as validateMigrations, t as assertJournalCoherence } from "./validate-qNhV00PD.mjs";
|
|
30
|
+
import { t as scanPages } from "./scan-DJbooZm2.mjs";
|
|
31
|
+
import { t as renderPrerenderPaths } from "./prerender-render-Cf_WDE9W.mjs";
|
|
32
|
+
import { a as scanEmailHandlersSync, r as hasEmailHandlers } from "./email-C5kaZXzJ.mjs";
|
|
33
|
+
import { i as migrateBuiltWranglerConfig, n as prepareCfFrameworkBuildOutput, r as prepareCfStaticBuildOutput, t as prepareCfBuildOutput } from "./cf-build-output-CTdlo6Rt.mjs";
|
|
34
|
+
import { n as getPackageDir } from "./agents-gni4eqBu.mjs";
|
|
35
|
+
import { i as isExpiredTokenError, n as PlatformClient, o as parsePlatformErrorBody, r as isCliOutdatedError, s as platformErrorMessage, t as PlatformApiError } from "./client-PdAJ-F0t.mjs";
|
|
36
|
+
import { a as resolveProjectCommand, i as hasBackendFiles, n as detectPreset, o as resolveWranglerArgv, r as formatProjectCommand, t as FRAMEWORK_PRESETS } from "./preset-Dowh9tTt.mjs";
|
|
37
|
+
import { o as ensureCloudflareAuthentication, r as cloudflareAuthNeedsTerminal, t as CloudflareAuthenticationError } from "./cloudflare-auth-BCmTc1X_.mjs";
|
|
38
|
+
import { n as writeVoidProjectConfig } from "./config-write-y3CBI_ux.mjs";
|
|
39
|
+
import { r as discoverFrameworkWranglerFiles, t as migrateLegacyVoidConfig } from "./migrate-DcW8F2W8.mjs";
|
|
40
|
+
import { a as createCloudflareEmptyDomainPublisher, i as createCloudflareEmptyCronPublisher } from "./cloudflare-operations-CPEdHYhM.mjs";
|
|
41
|
+
import { t as formatCloudflareUserMessage } from "./cloudflare-user-output-Q-k0QoNQ.mjs";
|
|
42
|
+
import { a as promptProjectSetupAction, i as promptProjectSelection, r as promptAndCreateProject } from "./create-project-C9lQhRzj.mjs";
|
|
43
|
+
import { r as resolveProjectBySlug, t as getRequestedProjectSlug } from "./resolve-project-Xvis70DG.mjs";
|
|
33
44
|
import { t as collectGitDeployMetadata } from "./git-metadata-D-gurjzG.mjs";
|
|
34
|
-
import {
|
|
45
|
+
import { t as promptForLoginToken } from "./login-CKk5NX4d.mjs";
|
|
35
46
|
import { createRequire } from "node:module";
|
|
36
|
-
import { copyFileSync, cpSync, createWriteStream, existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, renameSync, rmSync, unlinkSync, writeFileSync } from "node:fs";
|
|
37
|
-
import { fileURLToPath
|
|
47
|
+
import { copyFileSync, cpSync, createWriteStream, existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, unlinkSync, writeFileSync } from "node:fs";
|
|
48
|
+
import { fileURLToPath } from "node:url";
|
|
38
49
|
import { createDeployArtifact, createDeployUploadPayload } from "@void/deploy-core";
|
|
39
50
|
import { createHash, randomBytes } from "node:crypto";
|
|
40
|
-
import { homedir } from "node:os";
|
|
51
|
+
import { homedir, tmpdir } from "node:os";
|
|
41
52
|
import { execFile, execSync, spawnSync } from "node:child_process";
|
|
42
53
|
import { applyEdits, modify, parse } from "jsonc-parser";
|
|
54
|
+
import { isDeepStrictEqual } from "node:util";
|
|
43
55
|
import { build } from "vite";
|
|
44
56
|
import { Minimatch } from "minimatch";
|
|
45
|
-
import {
|
|
46
|
-
import {
|
|
47
|
-
import { hash } from "blake3-jit";
|
|
57
|
+
import { activateCloudflareVersion, assertCloudflareBindingsPreserved, assertCloudflareDurableObjectLifecycleSupported, assertExistingCloudflareConfig, encodeCloudflareVersionMessage, extractWorkersDevSubdomain, normalizeWorkersDevSubdomain, parseRootWranglerConfig, parseRootWranglerConfig as parseRootWranglerConfig$1, readBindingFieldPresence, readCloudflareTriggerConfig, readConfigEntryString, readExistingCloudflareWorker, readStoredResourceName, readWranglerTopLevelString, renderCloudflareStaticEntry, resolveD1MigrateTarget, stageCloudflareStaticAssets, writeCloudflareFrameworkDeployConfig, writeCloudflareStaticDeployConfig } from "@void/deploy-cloudflare";
|
|
58
|
+
import { getWorkerConfigPath, readBuildOutput } from "@cloudflare/build-output-utils";
|
|
48
59
|
import ignore from "ignore";
|
|
60
|
+
import { hash } from "blake3-jit";
|
|
49
61
|
//#region src/asset-routing.ts
|
|
50
62
|
function isApiRoutePattern(pattern) {
|
|
51
63
|
return pattern === "/api" || pattern.startsWith("/api/");
|
|
@@ -96,7 +108,7 @@ function resolveAssetRoutingPolicy(inputs) {
|
|
|
96
108
|
//#region src/cli/email-cloudflare.ts
|
|
97
109
|
/** The `send_email` binding name Void provisions and the runtime reads. */
|
|
98
110
|
const SEND_EMAIL_BINDING = "SEND_EMAIL";
|
|
99
|
-
/** The root-config `vars` key carrying `void.
|
|
111
|
+
/** The root-config `vars` key carrying `void.config.ts` `email.from` into the worker. */
|
|
100
112
|
const EMAIL_FROM_VAR = "__VOID_EMAIL_FROM";
|
|
101
113
|
/** Cloudflare's public API base — the same one `wrangler` targets by default. */
|
|
102
114
|
const CLOUDFLARE_API_BASE_URL = "https://api.cloudflare.com/client/v4";
|
|
@@ -133,17 +145,17 @@ function findEmailConfigConflicts(config) {
|
|
|
133
145
|
try {
|
|
134
146
|
owner = findBindingNameOwner(config, field, name);
|
|
135
147
|
} catch (err) {
|
|
136
|
-
conflicts.add(`
|
|
148
|
+
conflicts.add(`Cloudflare config: ${err instanceof Error ? err.message : String(err)}`);
|
|
137
149
|
return;
|
|
138
150
|
}
|
|
139
|
-
if (owner !== void 0) conflicts.add(`
|
|
151
|
+
if (owner !== void 0) conflicts.add(`Cloudflare config already uses ${name} as a ${owner} binding; rename it in void.config.ts (Void writes ${name} into ${field})`);
|
|
140
152
|
};
|
|
141
153
|
check("send_email", SEND_EMAIL_BINDING);
|
|
142
154
|
check("vars", EMAIL_FROM_VAR);
|
|
143
155
|
return [...conflicts];
|
|
144
156
|
}
|
|
145
157
|
/**
|
|
146
|
-
* Host part of `email.from`, lowercased; `null` when it is not `local@host`. `void.
|
|
158
|
+
* Host part of `email.from`, lowercased; `null` when it is not `local@host`. `void.config.ts`
|
|
147
159
|
* also accepts the display-name form (`Acme <noreply@mail.acme.com>`, see `config.ts`),
|
|
148
160
|
* so the address inside `<…>` is read when present.
|
|
149
161
|
*
|
|
@@ -663,7 +675,7 @@ async function preflightEmail(inputs) {
|
|
|
663
675
|
state: "foreign",
|
|
664
676
|
foreignName: names[0]
|
|
665
677
|
};
|
|
666
|
-
block("all", `
|
|
678
|
+
block("all", `Cloudflare config already has a send_email binding named ${JSON.stringify(names[0])}; rename it to ${SEND_EMAIL_BINDING} in void.config.ts (a second binding would be silent)`);
|
|
667
679
|
}
|
|
668
680
|
if (inputs.existingAddresses !== void 0 && inputs.existingAddresses !== null) {
|
|
669
681
|
const existing = Array.isArray(inputs.existingAddresses) ? inputs.existingAddresses.map((a) => typeof a === "string" ? a.toLowerCase() : String(a)) : ["(not an array)"];
|
|
@@ -674,7 +686,7 @@ async function preflightEmail(inputs) {
|
|
|
674
686
|
state: "foreign",
|
|
675
687
|
foreign: unknown
|
|
676
688
|
};
|
|
677
|
-
block("all", `
|
|
689
|
+
block("all", `Cloudflare addresses holds entries Void did not derive (${unknown.join(", ")}); remove ${unknown.map((a) => JSON.stringify(a)).join(", ")} from cloudflare.addresses in void.config.ts, or manage addresses by hand and unset email.from — skipping email setup this deploy`);
|
|
678
690
|
} else {
|
|
679
691
|
pre.addressesOwnership = {
|
|
680
692
|
state: "mine",
|
|
@@ -710,7 +722,7 @@ function renderEmailChecklist(pre) {
|
|
|
710
722
|
const row = (label, value, note = "") => {
|
|
711
723
|
lines.push(` ${pad(label, 10)}${note ? `${pad(value, 23)}${note}` : value}`);
|
|
712
724
|
};
|
|
713
|
-
row("domain", pre.domain, "(void.
|
|
725
|
+
row("domain", pre.domain, "(void.config.ts email.from)");
|
|
714
726
|
const session = [pre.session.accountName ? `account ${pre.session.accountName} (${shortId(pre.accountId)})` : `account ${shortId(pre.accountId)}`, pre.session.authType && pre.session.authType !== "OAuth Token" ? `session ${pre.session.email ? `${pre.session.email} ` : ""}(${pre.session.authType})` : pre.session.email ? `session ${pre.session.email}` : null].filter(Boolean).join(" · ");
|
|
715
727
|
row("zone", pre.zone.state === "found" ? apex : `${apex} ${pre.zone.state}`, session);
|
|
716
728
|
if (pre.mode === "subdomain") row("apex MX", pre.apexMx.exchanges[0] ?? (pre.apexMx.state === "unknown" ? "unknown" : "none"), "left alone — mail lives on the subdomain");
|
|
@@ -745,7 +757,7 @@ function renderEmailChecklist(pre) {
|
|
|
745
757
|
if (pre.binding.state !== "present") parts.push(`send_email: [{ name: "${SEND_EMAIL_BINDING}" }]`);
|
|
746
758
|
if (pre.addressesStale) parts.push(pre.addresses.length > 0 ? `addresses: ${JSON.stringify(pre.addresses)}` : "addresses: (removed)");
|
|
747
759
|
if (pre.sender.state !== "ready") parts.push(`vars.${EMAIL_FROM_VAR}: ${JSON.stringify(pre.from)}`);
|
|
748
|
-
if (parts.length > 0) change("
|
|
760
|
+
if (parts.length > 0) change("Cloudflare config", parts.join(", "));
|
|
749
761
|
for (const address of pre.rules.absent) change("routing rule (created on deploy)", `${address} → ${pre.workerName}`);
|
|
750
762
|
for (const foreign of pre.rules.foreign) warn(foreign.address, `already routed to ${foreign.owner}; left alone, not in addresses`);
|
|
751
763
|
for (const refused of pre.derived.refused) warn(refused.handler, refused.reason);
|
|
@@ -930,7 +942,7 @@ async function applyEmailSetup(pre, inputs) {
|
|
|
930
942
|
result.patch.addresses = null;
|
|
931
943
|
if (result.addressesWithheld && pre.addresses.length > 0) lines.push(` ! config addresses withheld this run (${bearerFailed ? "session-bearer step failed" : "routing not ready"}); no routing rule is created for ${pre.addresses.join(", ")}`);
|
|
932
944
|
}
|
|
933
|
-
if (result.patch.sendEmail || result.patch.addresses !== void 0) lines.push(" ✔ config
|
|
945
|
+
if (result.patch.sendEmail || result.patch.addresses !== void 0) lines.push(" ✔ config void.lock.json updated");
|
|
934
946
|
result.inboundReady = result.routingReady && result.subaddressingReady && !result.addressesWithheld;
|
|
935
947
|
return result;
|
|
936
948
|
}
|
|
@@ -1643,9 +1655,7 @@ async function createCloudflarePrerenderRunner(options) {
|
|
|
1643
1655
|
voidStaging,
|
|
1644
1656
|
remoteMode
|
|
1645
1657
|
});
|
|
1646
|
-
const
|
|
1647
|
-
const miniflarePath = createRequire(wranglerUrl).resolve("miniflare");
|
|
1648
|
-
const { Miniflare, convertV4MiniflareOptions } = await import(pathToFileURL(miniflarePath).href);
|
|
1658
|
+
const { Miniflare, convertV4MiniflareOptions } = await import("miniflare");
|
|
1649
1659
|
const mfOptions = {
|
|
1650
1660
|
modules: collectPrerenderWorkerModules(workerDir, workerMain),
|
|
1651
1661
|
modulesRoot: workerDir,
|
|
@@ -1845,6 +1855,405 @@ async function prerenderPagesNode(options) {
|
|
|
1845
1855
|
return result;
|
|
1846
1856
|
}
|
|
1847
1857
|
//#endregion
|
|
1858
|
+
//#region src/cli/cf-version-runner.ts
|
|
1859
|
+
function failed(message) {
|
|
1860
|
+
return {
|
|
1861
|
+
status: 1,
|
|
1862
|
+
stdout: "",
|
|
1863
|
+
stderr: message
|
|
1864
|
+
};
|
|
1865
|
+
}
|
|
1866
|
+
function flag(args, name) {
|
|
1867
|
+
const index = args.indexOf(name);
|
|
1868
|
+
return index < 0 ? void 0 : args[index + 1];
|
|
1869
|
+
}
|
|
1870
|
+
function parseJson(value) {
|
|
1871
|
+
try {
|
|
1872
|
+
return JSON.parse(value);
|
|
1873
|
+
} catch {
|
|
1874
|
+
return null;
|
|
1875
|
+
}
|
|
1876
|
+
}
|
|
1877
|
+
function record(value) {
|
|
1878
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
1879
|
+
}
|
|
1880
|
+
function safePositional(value) {
|
|
1881
|
+
return typeof value === "string" && value.length > 0 && !value.startsWith("-") && ![...value].some((character) => {
|
|
1882
|
+
const code = character.charCodeAt(0);
|
|
1883
|
+
return code < 32 || code === 127;
|
|
1884
|
+
});
|
|
1885
|
+
}
|
|
1886
|
+
/** Prevent cf's prebuilt uploader from creating a resource as a side effect. */
|
|
1887
|
+
function createCfResourceVerifier(options) {
|
|
1888
|
+
return async (directory) => {
|
|
1889
|
+
const worker = parseJson(readFileSync(getWorkerConfigPath(directory), "utf8"));
|
|
1890
|
+
if (!record(worker) || worker.env !== void 0 && !record(worker.env)) return failed("The Cloudflare Worker bindings were not readable.");
|
|
1891
|
+
for (const [bindingName, value] of Object.entries(worker.env ?? {})) {
|
|
1892
|
+
if (!record(value)) return failed(`Cloudflare binding ${bindingName} was not readable.`);
|
|
1893
|
+
const identifier = (field) => safePositional(value[field]) ? value[field] : null;
|
|
1894
|
+
if (value.type === "kv" || value.type === "d1" || value.type === "flagship") {
|
|
1895
|
+
if (!identifier("id")) return failed(`Cloudflare binding ${bindingName} has no ID; refusing automatic provisioning.`);
|
|
1896
|
+
continue;
|
|
1897
|
+
}
|
|
1898
|
+
if (value.type === "queue") {
|
|
1899
|
+
const name = identifier("name");
|
|
1900
|
+
if (!name) return failed(`Cloudflare Queue binding ${bindingName} has no name.`);
|
|
1901
|
+
if (!options.verifyCompatibilityRunner()) return failed("The Cloudflare resource verifier changed during deployment.");
|
|
1902
|
+
const found = await Promise.resolve(options.runWrangler([
|
|
1903
|
+
"queues",
|
|
1904
|
+
"info",
|
|
1905
|
+
name,
|
|
1906
|
+
"-c",
|
|
1907
|
+
options.configPath,
|
|
1908
|
+
"--env="
|
|
1909
|
+
], { capture: true }));
|
|
1910
|
+
if (found.status !== 0 || found.signal || found.error || found.stdout.trim() !== `Queue Name: ${name}`) return failed(`Cloudflare Queue ${name} is unavailable; refusing automatic provisioning.`);
|
|
1911
|
+
continue;
|
|
1912
|
+
}
|
|
1913
|
+
const resource = value.type === "r2" ? {
|
|
1914
|
+
kind: "R2 bucket",
|
|
1915
|
+
field: "name",
|
|
1916
|
+
command: [
|
|
1917
|
+
"r2",
|
|
1918
|
+
"buckets",
|
|
1919
|
+
"get"
|
|
1920
|
+
],
|
|
1921
|
+
response: "name"
|
|
1922
|
+
} : value.type === "dispatch-namespace" ? {
|
|
1923
|
+
kind: "dispatch namespace",
|
|
1924
|
+
field: "namespace",
|
|
1925
|
+
command: [
|
|
1926
|
+
"workers-for-platforms",
|
|
1927
|
+
"dispatch-namespaces",
|
|
1928
|
+
"get"
|
|
1929
|
+
],
|
|
1930
|
+
response: "namespace_name"
|
|
1931
|
+
} : value.type === "ai-search-namespace" ? {
|
|
1932
|
+
kind: "AI Search namespace",
|
|
1933
|
+
field: "namespace",
|
|
1934
|
+
command: [
|
|
1935
|
+
"ai-search",
|
|
1936
|
+
"namespace",
|
|
1937
|
+
"get"
|
|
1938
|
+
],
|
|
1939
|
+
response: "name"
|
|
1940
|
+
} : value.type === "agent-memory" ? {
|
|
1941
|
+
kind: "Agent Memory namespace",
|
|
1942
|
+
field: "namespace",
|
|
1943
|
+
command: ["agent-memory", "get-namespace"],
|
|
1944
|
+
response: "name"
|
|
1945
|
+
} : null;
|
|
1946
|
+
if (!resource) continue;
|
|
1947
|
+
const name = identifier(resource.field);
|
|
1948
|
+
if (!name) return failed(`Cloudflare ${resource.kind} binding ${bindingName} has no name.`);
|
|
1949
|
+
const jurisdiction = value.type === "r2" ? value.jurisdiction : void 0;
|
|
1950
|
+
if (jurisdiction !== void 0 && !safePositional(jurisdiction)) return failed(`Cloudflare R2 binding ${bindingName} has an invalid jurisdiction.`);
|
|
1951
|
+
const result = options.runCf([
|
|
1952
|
+
...resource.command,
|
|
1953
|
+
name,
|
|
1954
|
+
...jurisdiction ? ["--cf-r2-jurisdiction", jurisdiction] : []
|
|
1955
|
+
], {
|
|
1956
|
+
cwd: directory,
|
|
1957
|
+
capture: true
|
|
1958
|
+
});
|
|
1959
|
+
const body = parseJson(result.stdout);
|
|
1960
|
+
if (result.status !== 0 || result.signal || result.error || !record(body) || body[resource.response] !== name) return failed(`Cloudflare ${resource.kind} ${name} is unavailable; refusing automatic provisioning.`);
|
|
1961
|
+
}
|
|
1962
|
+
return {
|
|
1963
|
+
status: 0,
|
|
1964
|
+
stdout: "",
|
|
1965
|
+
stderr: ""
|
|
1966
|
+
};
|
|
1967
|
+
};
|
|
1968
|
+
}
|
|
1969
|
+
/** Run the pinned package-local cf binary with Void's existing Cloudflare session. */
|
|
1970
|
+
function createCfCommand(options) {
|
|
1971
|
+
const cf = join(dirname(fileURLToPath(import.meta.resolve("cf/package.json"))), "bin", "cf");
|
|
1972
|
+
return (args, run) => {
|
|
1973
|
+
if (!options.verifyUploader()) return failed("The Cloudflare uploader changed during deployment.");
|
|
1974
|
+
const env = {
|
|
1975
|
+
...options.env(options.accountId, options.apiBaseUrl),
|
|
1976
|
+
CF_DELEGATION: "1"
|
|
1977
|
+
};
|
|
1978
|
+
if (env.HTTP_PROXY || env.HTTPS_PROXY || env.http_proxy || env.https_proxy) env.NODE_USE_ENV_PROXY = "1";
|
|
1979
|
+
if (options.token) env.CLOUDFLARE_API_TOKEN = options.token;
|
|
1980
|
+
const result = spawnSync(process.execPath, [cf, ...args], {
|
|
1981
|
+
cwd: run.cwd,
|
|
1982
|
+
env,
|
|
1983
|
+
shell: false,
|
|
1984
|
+
windowsHide: true,
|
|
1985
|
+
encoding: "utf8",
|
|
1986
|
+
maxBuffer: 268435456,
|
|
1987
|
+
stdio: run.capture ? [
|
|
1988
|
+
"ignore",
|
|
1989
|
+
"pipe",
|
|
1990
|
+
"pipe"
|
|
1991
|
+
] : "inherit"
|
|
1992
|
+
});
|
|
1993
|
+
return {
|
|
1994
|
+
status: typeof result.status === "number" ? result.status : 1,
|
|
1995
|
+
stdout: result.stdout ?? "",
|
|
1996
|
+
stderr: (result.stderr ?? "").replace(/\[(\d{4,})\]/g, "[code: $1]"),
|
|
1997
|
+
signal: result.signal ?? null,
|
|
1998
|
+
error: result.error?.message ?? null
|
|
1999
|
+
};
|
|
2000
|
+
};
|
|
2001
|
+
}
|
|
2002
|
+
/**
|
|
2003
|
+
* Adapt the stable activation protocol to cf's prebuilt and API commands.
|
|
2004
|
+
* The protocol keeps the existing preview, inheritance, traffic and rollback checks.
|
|
2005
|
+
*/
|
|
2006
|
+
function createCfVersionRunner(options) {
|
|
2007
|
+
const { output, workerName, runCf } = options;
|
|
2008
|
+
const run = (args, capture, cwd = output.directory) => runCf(args, {
|
|
2009
|
+
cwd,
|
|
2010
|
+
capture
|
|
2011
|
+
});
|
|
2012
|
+
const verifyResources = async (directory) => {
|
|
2013
|
+
try {
|
|
2014
|
+
return await options.verifyResources(directory);
|
|
2015
|
+
} catch {
|
|
2016
|
+
return failed("Cloudflare resources could not be verified before upload.");
|
|
2017
|
+
}
|
|
2018
|
+
};
|
|
2019
|
+
return async (args, command) => {
|
|
2020
|
+
if (args[0] === "deployments" && args[1] === "status") {
|
|
2021
|
+
const result = run([
|
|
2022
|
+
"workers",
|
|
2023
|
+
"deployments",
|
|
2024
|
+
"list",
|
|
2025
|
+
"--worker",
|
|
2026
|
+
workerName
|
|
2027
|
+
], true);
|
|
2028
|
+
if (result.status !== 0) return result;
|
|
2029
|
+
const body = parseJson(result.stdout);
|
|
2030
|
+
const deployments = record(body) ? body.deployments : void 0;
|
|
2031
|
+
if (Array.isArray(deployments) && deployments.length === 0) return failed("The Cloudflare Worker has no deployments.");
|
|
2032
|
+
if (!Array.isArray(deployments) || !record(deployments[0])) return failed("The Cloudflare Worker deployment was not readable.");
|
|
2033
|
+
return {
|
|
2034
|
+
...result,
|
|
2035
|
+
stdout: JSON.stringify(deployments[0])
|
|
2036
|
+
};
|
|
2037
|
+
}
|
|
2038
|
+
if (args[0] === "versions" && args[1] === "list") {
|
|
2039
|
+
const pageSize = 10;
|
|
2040
|
+
const readPage = (page) => {
|
|
2041
|
+
const result = run([
|
|
2042
|
+
"workers",
|
|
2043
|
+
"versions",
|
|
2044
|
+
"list",
|
|
2045
|
+
"--worker-id",
|
|
2046
|
+
workerName,
|
|
2047
|
+
"--per-page",
|
|
2048
|
+
String(pageSize),
|
|
2049
|
+
"--page",
|
|
2050
|
+
String(page)
|
|
2051
|
+
], true);
|
|
2052
|
+
const body = parseJson(result.stdout);
|
|
2053
|
+
return {
|
|
2054
|
+
result,
|
|
2055
|
+
versions: Array.isArray(body) && body.length <= pageSize && body.every((item) => record(item) && typeof item.id === "string" && Number.isSafeInteger(item.number)) && new Set(body.map((item) => item.number)).size === body.length ? body : null
|
|
2056
|
+
};
|
|
2057
|
+
};
|
|
2058
|
+
const first = readPage(1);
|
|
2059
|
+
if (first.result.status !== 0) return first.result;
|
|
2060
|
+
if (!first.versions) return failed("The Cloudflare Worker version list was not readable.");
|
|
2061
|
+
const versions = [...first.versions];
|
|
2062
|
+
if (versions.length === pageSize) {
|
|
2063
|
+
const second = readPage(2);
|
|
2064
|
+
if (second.result.status !== 0 || !second.versions) return failed("The Cloudflare Worker version history was not readable.");
|
|
2065
|
+
if (second.versions.length > 0) {
|
|
2066
|
+
const firstNumbers = versions.map((item) => item.number);
|
|
2067
|
+
const secondNumbers = second.versions.map((item) => item.number);
|
|
2068
|
+
if (Math.min(...secondNumbers) > Math.max(...firstNumbers)) {
|
|
2069
|
+
versions.push(...second.versions);
|
|
2070
|
+
let last = Math.max(...secondNumbers);
|
|
2071
|
+
for (let page = 3; page <= 1e3 && second.versions.length === pageSize; page++) {
|
|
2072
|
+
const next = readPage(page);
|
|
2073
|
+
if (next.result.status !== 0 || !next.versions) return failed("The Cloudflare Worker version history was not readable.");
|
|
2074
|
+
if (next.versions.length === 0) break;
|
|
2075
|
+
const numbers = next.versions.map((item) => item.number);
|
|
2076
|
+
if (Math.min(...numbers) <= last) return failed("The Cloudflare Worker version history changed during inspection.");
|
|
2077
|
+
versions.push(...next.versions);
|
|
2078
|
+
last = Math.max(...numbers);
|
|
2079
|
+
if (next.versions.length < pageSize) break;
|
|
2080
|
+
if (page === 1e3) return failed("The Cloudflare Worker version history is too large to verify.");
|
|
2081
|
+
}
|
|
2082
|
+
} else if (Math.max(...secondNumbers) >= Math.min(...firstNumbers)) return failed("The Cloudflare Worker version history changed during inspection.");
|
|
2083
|
+
}
|
|
2084
|
+
}
|
|
2085
|
+
return {
|
|
2086
|
+
...first.result,
|
|
2087
|
+
stdout: JSON.stringify(versions.sort((a, b) => a.number - b.number).slice(-10))
|
|
2088
|
+
};
|
|
2089
|
+
}
|
|
2090
|
+
if (args[0] === "versions" && args[1] === "view" && args[2]) {
|
|
2091
|
+
const result = run([
|
|
2092
|
+
"workers",
|
|
2093
|
+
"versions",
|
|
2094
|
+
"get",
|
|
2095
|
+
args[2],
|
|
2096
|
+
"--worker-id",
|
|
2097
|
+
workerName
|
|
2098
|
+
], true);
|
|
2099
|
+
if (result.status !== 0) return result;
|
|
2100
|
+
const version = parseJson(result.stdout);
|
|
2101
|
+
if (!record(version) || version.id !== args[2] || !Array.isArray(version.bindings)) return failed("The Cloudflare Worker version was not readable.");
|
|
2102
|
+
return {
|
|
2103
|
+
...result,
|
|
2104
|
+
stdout: JSON.stringify({
|
|
2105
|
+
...version,
|
|
2106
|
+
resources: { bindings: version.bindings }
|
|
2107
|
+
})
|
|
2108
|
+
};
|
|
2109
|
+
}
|
|
2110
|
+
if (args[0] === "versions" && args[1] === "upload") {
|
|
2111
|
+
if (flag(args, "--name") !== workerName || args.includes("--assets") && flag(args, "--assets") !== output.assetsDirectory) return failed("The Cloudflare version upload target changed.");
|
|
2112
|
+
const verified = await verifyResources(output.directory);
|
|
2113
|
+
if (verified.status !== 0 || verified.signal || verified.error) return verified;
|
|
2114
|
+
return run([
|
|
2115
|
+
"workers",
|
|
2116
|
+
"versions",
|
|
2117
|
+
"create",
|
|
2118
|
+
"--prebuilt",
|
|
2119
|
+
...flag(args, "--message") ? ["--message", flag(args, "--message")] : [],
|
|
2120
|
+
...flag(args, "--secrets-file") ? ["--secrets-file", flag(args, "--secrets-file")] : [],
|
|
2121
|
+
...flag(args, "--preview-alias") ? ["--preview-alias", flag(args, "--preview-alias")] : []
|
|
2122
|
+
], command.capture);
|
|
2123
|
+
}
|
|
2124
|
+
if (args[0] === "versions" && args[1] === "deploy") {
|
|
2125
|
+
if (flag(args, "--name") !== workerName) return failed("The Cloudflare deployment target changed.");
|
|
2126
|
+
const flagsStart = args.findIndex((item, index) => index >= 2 && item.startsWith("-"));
|
|
2127
|
+
const versions = args.slice(2, flagsStart < 0 ? void 0 : flagsStart);
|
|
2128
|
+
if (!versions.every((item) => /^[0-9a-f-]{36}@\d+(?:\.\d+)?$/i.test(item))) return failed("The Cloudflare deployment versions were invalid.");
|
|
2129
|
+
const parsed = versions.map((item) => {
|
|
2130
|
+
const [version_id, percentage] = item.split("@");
|
|
2131
|
+
return {
|
|
2132
|
+
version_id,
|
|
2133
|
+
percentage: Number(percentage)
|
|
2134
|
+
};
|
|
2135
|
+
});
|
|
2136
|
+
if (parsed.length === 0 || new Set(parsed.map((item) => item.version_id)).size !== parsed.length || parsed.some((item) => item.percentage < 0 || item.percentage > 100) || Math.abs(parsed.reduce((sum, item) => sum + item.percentage, 0) - 100) > .001) return failed("The Cloudflare deployment percentages were invalid.");
|
|
2137
|
+
return run([
|
|
2138
|
+
"workers",
|
|
2139
|
+
"deployments",
|
|
2140
|
+
"create",
|
|
2141
|
+
"--worker",
|
|
2142
|
+
workerName,
|
|
2143
|
+
"--strategy",
|
|
2144
|
+
"percentage",
|
|
2145
|
+
"--versions",
|
|
2146
|
+
JSON.stringify(parsed),
|
|
2147
|
+
...flag(args, "--message") ? ["--body", JSON.stringify({
|
|
2148
|
+
strategy: "percentage",
|
|
2149
|
+
versions: parsed,
|
|
2150
|
+
annotations: { "workers/message": flag(args, "--message") }
|
|
2151
|
+
})] : []
|
|
2152
|
+
], command.capture);
|
|
2153
|
+
}
|
|
2154
|
+
if (args[0] === "deploy") {
|
|
2155
|
+
if (flag(args, "--name") !== workerName || args.includes("--assets") && flag(args, "--assets") !== output.assetsDirectory) return failed("The Cloudflare bootstrap target changed.");
|
|
2156
|
+
const verified = await verifyResources(output.directory);
|
|
2157
|
+
if (verified.status !== 0 || verified.signal || verified.error) return verified;
|
|
2158
|
+
return run([
|
|
2159
|
+
"deploy",
|
|
2160
|
+
"--prebuilt",
|
|
2161
|
+
...flag(args, "--message") ? ["--message", flag(args, "--message")] : [],
|
|
2162
|
+
...flag(args, "--secrets-file") ? ["--secrets-file", flag(args, "--secrets-file")] : []
|
|
2163
|
+
], command.capture);
|
|
2164
|
+
}
|
|
2165
|
+
if (args[0] === "triggers" && args[1] === "deploy") {
|
|
2166
|
+
const configPath = flag(args, "-c");
|
|
2167
|
+
if (!configPath || flag(args, "--name") !== workerName) return failed("The Cloudflare trigger target changed.");
|
|
2168
|
+
const raw = parseJson(readFileSync(configPath, "utf8"));
|
|
2169
|
+
if (!record(raw) || raw.name !== workerName) return failed("The Cloudflare trigger snapshot was not readable.");
|
|
2170
|
+
const directory = mkdtempSync(join(tmpdir(), "void-cf-triggers-"));
|
|
2171
|
+
try {
|
|
2172
|
+
cpSync(join(output.directory, ".cloudflare"), join(directory, ".cloudflare"), { recursive: true });
|
|
2173
|
+
const workerPath = getWorkerConfigPath(directory);
|
|
2174
|
+
const worker = parseJson(readFileSync(workerPath, "utf8"));
|
|
2175
|
+
if (!record(worker)) return failed("The private Cloudflare Worker config was not readable.");
|
|
2176
|
+
const migrated = migrateBuiltWranglerConfig({
|
|
2177
|
+
...raw,
|
|
2178
|
+
compatibility_date: worker.compatibilityDate
|
|
2179
|
+
}).worker;
|
|
2180
|
+
if (!migrated) return failed("The Cloudflare trigger snapshot was not convertible.");
|
|
2181
|
+
const next = migrated.triggers ?? [];
|
|
2182
|
+
const previous = Array.isArray(worker.triggers) ? worker.triggers : [];
|
|
2183
|
+
const preserveRoutes = raw.routes === void 0 && raw.route === void 0;
|
|
2184
|
+
const preserveEmail = raw.addresses === void 0;
|
|
2185
|
+
worker.triggers = [
|
|
2186
|
+
...next,
|
|
2187
|
+
...preserveRoutes ? previous.filter((trigger) => record(trigger) && trigger.type === "fetch") : [],
|
|
2188
|
+
...preserveEmail ? previous.filter((trigger) => record(trigger) && trigger.type === "email") : []
|
|
2189
|
+
];
|
|
2190
|
+
for (const field of ["env", "exports"]) {
|
|
2191
|
+
const previous = record(worker[field]) ? worker[field] : {};
|
|
2192
|
+
worker[field] = {
|
|
2193
|
+
...Object.fromEntries(Object.entries(previous).filter(([, value]) => !record(value) || value.type !== "workflow")),
|
|
2194
|
+
...migrated[field]
|
|
2195
|
+
};
|
|
2196
|
+
}
|
|
2197
|
+
if (!preserveRoutes) worker.domains = migrated.domains ?? [];
|
|
2198
|
+
if (typeof raw.workers_dev === "boolean") worker.workersDev = raw.workers_dev;
|
|
2199
|
+
if (typeof raw.preview_urls === "boolean") worker.previewUrls = raw.preview_urls;
|
|
2200
|
+
writeFileSync(workerPath, JSON.stringify(worker), { mode: 384 });
|
|
2201
|
+
await readBuildOutput(directory);
|
|
2202
|
+
const verified = await verifyResources(directory);
|
|
2203
|
+
if (verified.status !== 0 || verified.signal || verified.error) return verified;
|
|
2204
|
+
return run([
|
|
2205
|
+
"workers",
|
|
2206
|
+
"triggers",
|
|
2207
|
+
"deploy",
|
|
2208
|
+
"--prebuilt"
|
|
2209
|
+
], command.capture, directory);
|
|
2210
|
+
} finally {
|
|
2211
|
+
rmSync(directory, {
|
|
2212
|
+
recursive: true,
|
|
2213
|
+
force: true
|
|
2214
|
+
});
|
|
2215
|
+
}
|
|
2216
|
+
}
|
|
2217
|
+
if (args[0] === "queues" && args[1] === "consumer" && args[2] === "remove") {
|
|
2218
|
+
const queueName = args[3];
|
|
2219
|
+
if (!queueName || args[4] !== workerName) return failed("The Cloudflare Queue consumer target changed.");
|
|
2220
|
+
const queues = run(["queues", "list"], true);
|
|
2221
|
+
if (queues.status !== 0) return queues;
|
|
2222
|
+
const allQueues = parseJson(queues.stdout);
|
|
2223
|
+
if (!Array.isArray(allQueues)) return failed("The Cloudflare Queue list was not readable.");
|
|
2224
|
+
const queue = allQueues.find((item) => record(item) && item.queue_name === queueName);
|
|
2225
|
+
if (!record(queue) || typeof queue.queue_id !== "string") return failed(`Cloudflare Queue ${queueName} was not found.`);
|
|
2226
|
+
const consumers = run([
|
|
2227
|
+
"queues",
|
|
2228
|
+
"consumers",
|
|
2229
|
+
"list",
|
|
2230
|
+
"--queue-id",
|
|
2231
|
+
queue.queue_id
|
|
2232
|
+
], true);
|
|
2233
|
+
if (consumers.status !== 0) return consumers;
|
|
2234
|
+
const allConsumers = parseJson(consumers.stdout);
|
|
2235
|
+
if (!Array.isArray(allConsumers)) return failed("The Cloudflare Queue consumers were not readable.");
|
|
2236
|
+
const matching = allConsumers.filter((item) => record(item) && item.script === workerName);
|
|
2237
|
+
if (matching.length === 0) return {
|
|
2238
|
+
status: 0,
|
|
2239
|
+
stdout: "",
|
|
2240
|
+
stderr: ""
|
|
2241
|
+
};
|
|
2242
|
+
if (matching.length !== 1 || !record(matching[0]) || typeof matching[0].consumer_id !== "string") return failed("The Cloudflare Queue consumer identity was ambiguous.");
|
|
2243
|
+
return run([
|
|
2244
|
+
"queues",
|
|
2245
|
+
"consumers",
|
|
2246
|
+
"delete",
|
|
2247
|
+
matching[0].consumer_id,
|
|
2248
|
+
"--queue-id",
|
|
2249
|
+
queue.queue_id,
|
|
2250
|
+
"--force"
|
|
2251
|
+
], command.capture);
|
|
2252
|
+
}
|
|
2253
|
+
return failed(`Unsupported Cloudflare activation operation: ${args[0] ?? ""} ${args[1] ?? ""}`);
|
|
2254
|
+
};
|
|
2255
|
+
}
|
|
2256
|
+
//#endregion
|
|
1848
2257
|
//#region src/cli/cloudflare-deploy/classify.ts
|
|
1849
2258
|
/**
|
|
1850
2259
|
* Narrow native Cloudflare deploys to app shapes whose emitted Worker artifact
|
|
@@ -1860,14 +2269,14 @@ function classifyCloudflareDeployApp(root, voidConfig, options) {
|
|
|
1860
2269
|
if (framework) {
|
|
1861
2270
|
if (!FRAMEWORK_PRESETS[framework.name]) return unsupported(`deploy: --platform cloudflare has no deployment preset for framework ${framework.name}.`);
|
|
1862
2271
|
}
|
|
1863
|
-
const staticPreset = detectPreset(root, {
|
|
2272
|
+
const staticPreset = framework ? null : detectPreset(root, {
|
|
1864
2273
|
dir: options.dir,
|
|
1865
2274
|
spa: options.spa
|
|
1866
2275
|
});
|
|
1867
2276
|
const configuredStatic = voidConfig.inference?.appType === "static" || voidConfig.inference?.appType === "spa";
|
|
1868
2277
|
if (staticPreset || configuredStatic || options.dir || options.spa) return unsupported([
|
|
1869
2278
|
`deploy: --platform cloudflare could not resolve the ${staticPreset?.appType ?? (options.spa ? "spa" : "static")} output to deploy.`,
|
|
1870
|
-
"Set inference.outputDir in void.
|
|
2279
|
+
"Set inference.outputDir in void.config.ts, pass --dir with an existing build directory,",
|
|
1871
2280
|
"or add a supported build tool so Void can locate the generated static assets."
|
|
1872
2281
|
].join("\n"));
|
|
1873
2282
|
if (!framework && !hasBackendFiles(root)) return unsupported([
|
|
@@ -1910,7 +2319,7 @@ function approvedCloudflareIsrBinding(config, rootConfig) {
|
|
|
1910
2319
|
/** Persist the migration decision in source configuration, not a temporary link marker. */
|
|
1911
2320
|
async function chooseCloudflareIsr(root, config, options) {
|
|
1912
2321
|
if (config.routing?.isr !== void 0) return config.routing.isr;
|
|
1913
|
-
if (!options.interactive) throw new Error("This migration needs an ISR caching choice. Set routing.isr to true in void.
|
|
2322
|
+
if (!options.interactive) throw new Error("This migration needs an ISR caching choice. Set routing.isr to true in void.config.ts to provision the KV cache, or false to keep rendering on each request, then rerun `void deploy`.");
|
|
1914
2323
|
const enabled = await (options.confirm ?? (async (message) => {
|
|
1915
2324
|
const answer = await confirm({
|
|
1916
2325
|
message,
|
|
@@ -1918,18 +2327,27 @@ async function chooseCloudflareIsr(root, config, options) {
|
|
|
1918
2327
|
});
|
|
1919
2328
|
if (isCancel(answer)) throw new Error("ISR setup cancelled. Rerun `void deploy` to finish linking.");
|
|
1920
2329
|
return answer === true;
|
|
1921
|
-
}))("Enable ISR caching for this app? Yes provisions a Cloudflare KV cache; No keeps caching disabled until you change void.
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
2330
|
+
}))("Enable ISR caching for this app? Yes provisions a Cloudflare KV cache; No keeps caching disabled until you change void.config.ts.");
|
|
2331
|
+
if (existsSync(join(root, "void.config.ts"))) writeVoidProjectConfig(root, {
|
|
2332
|
+
...config,
|
|
2333
|
+
routing: {
|
|
2334
|
+
...config.routing,
|
|
2335
|
+
isr: enabled
|
|
2336
|
+
}
|
|
2337
|
+
});
|
|
2338
|
+
else {
|
|
2339
|
+
const path = join(root, "void.json");
|
|
2340
|
+
const source = existsSync(path) ? readFileSync(path, "utf8") : "{}\n";
|
|
2341
|
+
writeFileSync(path, applyEdits(source, modify(source, ["routing", "isr"], enabled, { formattingOptions: {
|
|
2342
|
+
insertSpaces: true,
|
|
2343
|
+
tabSize: 2
|
|
2344
|
+
} })));
|
|
2345
|
+
}
|
|
1928
2346
|
config.routing = {
|
|
1929
2347
|
...config.routing,
|
|
1930
2348
|
isr: enabled
|
|
1931
2349
|
};
|
|
1932
|
-
log$1.info(`Saved routing.isr: ${String(enabled)} in void.
|
|
2350
|
+
log$1.info(`Saved routing.isr: ${String(enabled)} in void.config.ts. ISR caching ${enabled ? "will be enabled in this deployment" : "stays disabled until you change this setting"}.`);
|
|
1933
2351
|
return enabled;
|
|
1934
2352
|
}
|
|
1935
2353
|
//#endregion
|
|
@@ -2014,22 +2432,25 @@ async function prepareExistingCloudflareDeploy(options) {
|
|
|
2014
2432
|
workerName: config.name
|
|
2015
2433
|
});
|
|
2016
2434
|
writeFileSync(options.configPath, updated);
|
|
2435
|
+
persistCloudflareConfig(options.root);
|
|
2017
2436
|
return existing;
|
|
2018
2437
|
}
|
|
2019
2438
|
/** Offer the existing destination before the legacy hosted-platform fallback. */
|
|
2020
2439
|
async function maybeLinkCloudflareDeploy(root, options = {}, deps = {}) {
|
|
2021
2440
|
if (options.platform || options.backend || options.projectSlug || process.env.VOID_PROJECT || readDeploymentPlatform(root) !== null) return null;
|
|
2022
|
-
const files = [
|
|
2441
|
+
const files = [.../* @__PURE__ */ new Set([...[
|
|
2023
2442
|
"wrangler.jsonc",
|
|
2024
2443
|
"wrangler.json",
|
|
2025
2444
|
"wrangler.toml"
|
|
2026
|
-
].filter((name) => existsSync(join(root, name)));
|
|
2027
|
-
if (!files.length) return null;
|
|
2445
|
+
].filter((name) => existsSync(join(root, name))), ...discoverFrameworkWranglerFiles(root)])];
|
|
2446
|
+
if (!files.length && !existsSync(join(root, "void.config.ts"))) return null;
|
|
2028
2447
|
if (files.length > 1) throw new Error("Multiple Wrangler config files were found. Keep one root configuration before linking to Cloudflare.");
|
|
2029
|
-
const name = files[0];
|
|
2448
|
+
const name = files[0] ?? ".void-wrangler.jsonc";
|
|
2030
2449
|
if (name.endsWith(".toml")) throw new Error("Found wrangler.toml. Direct Cloudflare deployment currently needs a root wrangler.jsonc or wrangler.json with the same settings. Convert the config before linking.");
|
|
2031
2450
|
const errors = [];
|
|
2032
|
-
const
|
|
2451
|
+
const configPath = files.length ? join(root, name) : materializeCloudflareConfig(root);
|
|
2452
|
+
const config = parse(readFileSync(configPath, "utf8"), errors, { allowTrailingComma: true });
|
|
2453
|
+
if (!files.length && (!config || typeof config.name !== "string" || !config.name.trim())) return null;
|
|
2033
2454
|
if (errors.length || !config || typeof config !== "object" || Array.isArray(config) || typeof config.name !== "string" || !config.name.trim()) throw new Error(`Set the existing Worker's name in a valid ${name} before linking to Cloudflare.`);
|
|
2034
2455
|
if (!(deps.interactive ?? Boolean(process.stdin.isTTY && process.stdout.isTTY))) throw new Error(`Found ${name} without a deployment destination. Run void deploy interactively to link the existing Worker, or use void deploy --platform cloudflare with Cloudflare credentials in CI.`);
|
|
2035
2456
|
log$1.info(`Found ${basename(name)} for Worker "${config.name}".`);
|
|
@@ -2084,6 +2505,44 @@ function readCloudflareLocalState(root) {
|
|
|
2084
2505
|
}
|
|
2085
2506
|
}
|
|
2086
2507
|
//#endregion
|
|
2508
|
+
//#region src/cli/installed-void.ts
|
|
2509
|
+
/** A global CLI still builds with the project's installed Vite plugin. */
|
|
2510
|
+
function assertInstalledVoidMatchesCli(root) {
|
|
2511
|
+
const projectManifest = join(root, "package.json");
|
|
2512
|
+
if (!existsSync(projectManifest)) return;
|
|
2513
|
+
const project = JSON.parse(readFileSync(projectManifest, "utf8"));
|
|
2514
|
+
if (![
|
|
2515
|
+
"dependencies",
|
|
2516
|
+
"devDependencies",
|
|
2517
|
+
"optionalDependencies"
|
|
2518
|
+
].some((key) => {
|
|
2519
|
+
const dependencies = project[key];
|
|
2520
|
+
return typeof dependencies === "object" && dependencies !== null && "void" in dependencies;
|
|
2521
|
+
})) return;
|
|
2522
|
+
const cliPackageDir = getPackageDir();
|
|
2523
|
+
const cli = JSON.parse(readFileSync(join(cliPackageDir, "package.json"), "utf8"));
|
|
2524
|
+
let installedVersion;
|
|
2525
|
+
let installedPackageDir;
|
|
2526
|
+
try {
|
|
2527
|
+
const entry = createRequire(projectManifest).resolve("void");
|
|
2528
|
+
let directory = dirname(entry);
|
|
2529
|
+
for (let depth = 0; depth < 8; depth++) {
|
|
2530
|
+
const manifest = join(directory, "package.json");
|
|
2531
|
+
if (existsSync(manifest)) {
|
|
2532
|
+
const installed = JSON.parse(readFileSync(manifest, "utf8"));
|
|
2533
|
+
if (installed.name === "void") {
|
|
2534
|
+
installedVersion = installed.version;
|
|
2535
|
+
installedPackageDir = directory;
|
|
2536
|
+
break;
|
|
2537
|
+
}
|
|
2538
|
+
}
|
|
2539
|
+
directory = dirname(directory);
|
|
2540
|
+
}
|
|
2541
|
+
} catch {}
|
|
2542
|
+
if (installedVersion !== cli.version) throw new Error(`deploy: this CLI is void@${cli.version}, but the project's installed Vite plugin is ${installedVersion ? `void@${installedVersion}` : "missing"}. Install the same Void version in the project (or link this development checkout) before deploying. The build imports the project package; mixing versions can rewrite legacy config and produce an unsafe Cloudflare deploy target.`);
|
|
2543
|
+
if (installedPackageDir && existsSync(join(cliPackageDir, "src", "index.ts")) && realpathSync(installedPackageDir) !== realpathSync(cliPackageDir)) throw new Error("deploy: this development CLI and the project Vite plugin come from different Void builds, even though their package versions match. Link the same development checkout into the project before deploying.");
|
|
2544
|
+
}
|
|
2545
|
+
//#endregion
|
|
2087
2546
|
//#region src/cli/deploy-errors.ts
|
|
2088
2547
|
const BODY_SNIPPET_MAX = 200;
|
|
2089
2548
|
function trimSnippet(body) {
|
|
@@ -3372,7 +3831,7 @@ function selectBundledEntryFilename(outFiles) {
|
|
|
3372
3831
|
* Determine whether a wrapper is needed based on the features.
|
|
3373
3832
|
*/
|
|
3374
3833
|
function needsWrapper(features) {
|
|
3375
|
-
return features.crons.length > 0 || features.queues.length > 0 || !!features.hasMigrations || !!features.readiness;
|
|
3834
|
+
return features.crons.length > 0 || features.queues.length > 0 || !!features.hasMigrations || !!features.readiness || !!features.isr;
|
|
3376
3835
|
}
|
|
3377
3836
|
/**
|
|
3378
3837
|
* Generate a wrapper entry in-place in the worker directory.
|
|
@@ -3424,8 +3883,8 @@ async function generateWrapper(workerDir, workerMain, root, features) {
|
|
|
3424
3883
|
let migrations;
|
|
3425
3884
|
let migrationPlanBundle;
|
|
3426
3885
|
if (features.hasMigrations) {
|
|
3427
|
-
const { collectMigrations } = await import("./
|
|
3428
|
-
const { buildMigrationPlanBundle } = await import("./
|
|
3886
|
+
const { collectMigrations } = await import("./collect-DAUItMDS.mjs");
|
|
3887
|
+
const { buildMigrationPlanBundle } = await import("./plan-DpuOr14e.mjs");
|
|
3429
3888
|
const migrationsDir = readProjectPaths(root).migrationsDir;
|
|
3430
3889
|
migrations = collectMigrations(migrationsDir);
|
|
3431
3890
|
migrationPlanBundle = features.migrationDialect === "sqlite" ? buildMigrationPlanBundle(migrations) : void 0;
|
|
@@ -3438,6 +3897,7 @@ async function generateWrapper(workerDir, workerMain, root, features) {
|
|
|
3438
3897
|
if (!existsSync(handlerPath)) throw new Error(`Migration handler not found: ${handlerFilename_}. Run "pnpm -C packages/void build" first.`);
|
|
3439
3898
|
await bundleMigrationHandler(root, workerDir, handlerPath, features.migrationDialect ?? "sqlite");
|
|
3440
3899
|
}
|
|
3900
|
+
if (features.isr) await bundleFrameworkIsr(root, workerDir);
|
|
3441
3901
|
const wrapperSource = generateWrapperSource(renamedName, handlerFilename, features, migrations, migrationPlanBundle);
|
|
3442
3902
|
const stagedPath = `${mainPath}.${crypto.randomUUID()}.tmp`;
|
|
3443
3903
|
try {
|
|
@@ -3448,6 +3908,33 @@ async function generateWrapper(workerDir, workerMain, root, features) {
|
|
|
3448
3908
|
rmSync(stagedPath, { force: true });
|
|
3449
3909
|
}
|
|
3450
3910
|
}
|
|
3911
|
+
async function bundleFrameworkIsr(root, workerDir) {
|
|
3912
|
+
const entry = fileURLToPath(import.meta.resolve("@void/isr/runtime"));
|
|
3913
|
+
const tmpDir = join(root, ".void", "isr");
|
|
3914
|
+
const outDir = join(tmpDir, "out");
|
|
3915
|
+
mkdirSync(tmpDir, { recursive: true });
|
|
3916
|
+
await build({
|
|
3917
|
+
root: tmpDir,
|
|
3918
|
+
logLevel: "silent",
|
|
3919
|
+
ssr: { noExternal: true },
|
|
3920
|
+
build: {
|
|
3921
|
+
outDir,
|
|
3922
|
+
emptyOutDir: true,
|
|
3923
|
+
minify: false,
|
|
3924
|
+
ssr: entry,
|
|
3925
|
+
target: "esnext",
|
|
3926
|
+
rollupOptions: {
|
|
3927
|
+
input: entry,
|
|
3928
|
+
external: [/^cloudflare:/, /^node:/],
|
|
3929
|
+
output: {
|
|
3930
|
+
entryFileNames: "__void_isr.mjs",
|
|
3931
|
+
chunkFileNames: "__void_isr-[hash].mjs"
|
|
3932
|
+
}
|
|
3933
|
+
}
|
|
3934
|
+
}
|
|
3935
|
+
});
|
|
3936
|
+
for (const file of readdirSync(outDir)) copyFileSync(join(outDir, file), join(workerDir, file));
|
|
3937
|
+
}
|
|
3451
3938
|
async function bundleMigrationHandler(root, workerDir, handlerPath, dialect) {
|
|
3452
3939
|
const tmpDir = join(root, ".void", "migration-handler");
|
|
3453
3940
|
mkdirSync(tmpDir, { recursive: true });
|
|
@@ -3602,6 +4089,7 @@ function cleanupWrapper(root) {
|
|
|
3602
4089
|
for (const directory of [
|
|
3603
4090
|
"handlers",
|
|
3604
4091
|
"migration-handler",
|
|
4092
|
+
"isr",
|
|
3605
4093
|
"bundle"
|
|
3606
4094
|
]) rmSync(join(voidDir, directory), {
|
|
3607
4095
|
recursive: true,
|
|
@@ -3612,6 +4100,14 @@ function generateWrapperSource(renamedEntry, handlersModule, features, migration
|
|
|
3612
4100
|
const lines = [];
|
|
3613
4101
|
lines.push(WRAPPER_MARKER);
|
|
3614
4102
|
lines.push(`import original from "./${renamedEntry}";`);
|
|
4103
|
+
if (features.isr) {
|
|
4104
|
+
lines.push("import { handleFrameworkIsr } from \"./__void_isr.mjs\";");
|
|
4105
|
+
lines.push(`const __voidIsrDeploymentId = ${JSON.stringify(crypto.randomUUID())};`);
|
|
4106
|
+
lines.push(`const __voidIsrPolicy = ${JSON.stringify({
|
|
4107
|
+
revalidate: features.isr.revalidate,
|
|
4108
|
+
queryAllowlist: features.isr.queryAllowlist
|
|
4109
|
+
})};`);
|
|
4110
|
+
}
|
|
3615
4111
|
if (features.crons.length > 0) lines.push(`import { handleScheduled } from "./${handlersModule}";`);
|
|
3616
4112
|
if (features.queues.length > 0) lines.push(`import { handleQueue, handleQueueRelay } from "./${handlersModule}";`);
|
|
3617
4113
|
if (migrations && migrations.length > 0) {
|
|
@@ -3621,10 +4117,14 @@ function generateWrapperSource(renamedEntry, handlersModule, features, migration
|
|
|
3621
4117
|
lines.push(`const __migrationDialect = ${JSON.stringify(features.migrationDialect ?? "sqlite")};`);
|
|
3622
4118
|
}
|
|
3623
4119
|
lines.push("");
|
|
3624
|
-
const needsFetchWrap = features.readiness || features.crons.length > 0 || features.queues.length > 0 || migrations && migrations.length > 0;
|
|
4120
|
+
const needsFetchWrap = features.readiness || features.crons.length > 0 || features.queues.length > 0 || migrations && migrations.length > 0 || !!features.isr;
|
|
3625
4121
|
if (needsFetchWrap) {
|
|
3626
4122
|
lines.push("async function wrappedFetch(request, env, ctx) {");
|
|
3627
4123
|
lines.push(" const url = new URL(request.url);");
|
|
4124
|
+
if (features.isr) {
|
|
4125
|
+
lines.push(" env.__VOID_ISR_DEPLOYMENT_ID ??= __voidIsrDeploymentId;");
|
|
4126
|
+
lines.push(" env.__VOID_ISR_HOST = url.hostname;");
|
|
4127
|
+
}
|
|
3628
4128
|
if (features.readiness || features.crons.length > 0 || features.queues.length > 0 || features.hasMigrations) {
|
|
3629
4129
|
lines.push(" if (request.method === \"GET\" && url.pathname === \"/__void/ready\") {");
|
|
3630
4130
|
lines.push(" return Response.json({ ready: true });");
|
|
@@ -3686,6 +4186,12 @@ function generateWrapperSource(renamedEntry, handlersModule, features, migration
|
|
|
3686
4186
|
lines.push(" }");
|
|
3687
4187
|
lines.push(" }");
|
|
3688
4188
|
}
|
|
4189
|
+
if (features.isr) {
|
|
4190
|
+
lines.push(" if (env.ISR_CACHE && request.headers.get(\"upgrade\")?.toLowerCase() !== \"websocket\") {");
|
|
4191
|
+
lines.push(" const cached = await handleFrameworkIsr(request, env, ctx, { ...__voidIsrPolicy, deploymentId: __voidIsrDeploymentId }, (req) => original.fetch(req, env, ctx));");
|
|
4192
|
+
lines.push(" if (cached) return cached;");
|
|
4193
|
+
lines.push(" }");
|
|
4194
|
+
}
|
|
3689
4195
|
lines.push(" return original.fetch(request, env, ctx);");
|
|
3690
4196
|
lines.push("}");
|
|
3691
4197
|
lines.push("");
|
|
@@ -3693,8 +4199,8 @@ function generateWrapperSource(renamedEntry, handlersModule, features, migration
|
|
|
3693
4199
|
lines.push("export default {");
|
|
3694
4200
|
if (needsFetchWrap) lines.push(" fetch: wrappedFetch,");
|
|
3695
4201
|
else lines.push(" fetch: original.fetch,");
|
|
3696
|
-
if (features.crons.length > 0) lines.push(" scheduled: handleScheduled,");
|
|
3697
|
-
if (features.queues.length > 0) lines.push(" queue: handleQueue,");
|
|
4202
|
+
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,");
|
|
4203
|
+
if (features.queues.length > 0) lines.push(features.isr ? " queue(batch, env, ctx) { env.__VOID_ISR_DEPLOYMENT_ID ??= __voidIsrDeploymentId; return handleQueue(batch, env, ctx); }," : " queue: handleQueue,");
|
|
3698
4204
|
lines.push("};");
|
|
3699
4205
|
return lines.join("\n");
|
|
3700
4206
|
}
|
|
@@ -3782,66 +4288,6 @@ export async function handleQueueRelay(payload, env, ctx) {
|
|
|
3782
4288
|
}
|
|
3783
4289
|
//#endregion
|
|
3784
4290
|
//#region src/cli/deploy.ts
|
|
3785
|
-
var deploy_exports = /* @__PURE__ */ __exportAll({
|
|
3786
|
-
CloudflareAuthSecretError: () => CloudflareAuthSecretError,
|
|
3787
|
-
DEPLOY_PASSTHROUGH_ASSERT_FIELDS: () => DEPLOY_PASSTHROUGH_ASSERT_FIELDS,
|
|
3788
|
-
DEPLOY_PASSTHROUGH_EXCLUDE_FIELDS: () => DEPLOY_PASSTHROUGH_EXCLUDE_FIELDS,
|
|
3789
|
-
DEPLOY_WHOLE_OBJECT_PINNED_FIELDS: () => DEPLOY_WHOLE_OBJECT_PINNED_FIELDS,
|
|
3790
|
-
applyDeployEvent: () => applyDeployEvent,
|
|
3791
|
-
assembleVoidManifest: () => assembleVoidManifest,
|
|
3792
|
-
assertManagedDurableStateSupported: () => assertManagedDurableStateSupported,
|
|
3793
|
-
assertMigrationsProduceAuthSchema: () => assertMigrationsProduceAuthSchema,
|
|
3794
|
-
assertNoConfigOverrideInProjectDotenv: () => assertNoConfigOverrideInProjectDotenv,
|
|
3795
|
-
assertRemoteMigrationsDeployable: () => assertRemoteMigrationsDeployable,
|
|
3796
|
-
assertWranglerUploaderUnchanged: () => assertWranglerUploaderUnchanged,
|
|
3797
|
-
checkWranglerMigrationApplySet: () => checkWranglerMigrationApplySet,
|
|
3798
|
-
compareWranglerMigrationPaths: () => compareWranglerMigrationPaths,
|
|
3799
|
-
computeDesiredCloudflareResources: () => computeDesiredCloudflareResources,
|
|
3800
|
-
createDeployWranglerRunner: () => createDeployWranglerRunner,
|
|
3801
|
-
deployChildEnv: () => deployChildEnv,
|
|
3802
|
-
deriveWorkerName: () => deriveWorkerName,
|
|
3803
|
-
discoverRootWranglerConfig: () => discoverRootWranglerConfig,
|
|
3804
|
-
ensureCloudflareAuthSecret: () => ensureCloudflareAuthSecret,
|
|
3805
|
-
ensurePreviouslyDeployedLiveBindingConfig: () => ensurePreviouslyDeployedLiveBindingConfig,
|
|
3806
|
-
formatCloudflareActivationError: () => formatCloudflareActivationError,
|
|
3807
|
-
formatCloudflareSandboxUnavailable: () => formatCloudflareSandboxUnavailable,
|
|
3808
|
-
generateDeployWrapperIfNeeded: () => generateDeployWrapperIfNeeded,
|
|
3809
|
-
hasDeploySchemaDrift: () => hasDeploySchemaDrift,
|
|
3810
|
-
hasNonPageBackend: () => hasNonPageBackend,
|
|
3811
|
-
hasPrerenderSources: () => hasPrerenderSources,
|
|
3812
|
-
hashWranglerUploader: () => hashWranglerUploader,
|
|
3813
|
-
isWranglerNonInteractiveOrCI: () => isWranglerNonInteractiveOrCI,
|
|
3814
|
-
loadProvisionModule: () => loadProvisionModule,
|
|
3815
|
-
parseRootWranglerConfig: () => parseRootWranglerConfig$1,
|
|
3816
|
-
prepareCloudflareFrameworkArtifact: () => prepareCloudflareFrameworkArtifact,
|
|
3817
|
-
promptDeployProjectConfig: () => promptDeployProjectConfig,
|
|
3818
|
-
reconstructExpectedContainers: () => reconstructExpectedContainers,
|
|
3819
|
-
resolveCloudflareVoidStaticPreset: () => resolveCloudflareVoidStaticPreset,
|
|
3820
|
-
resolveDeployLiveBindingConfig: () => resolveDeployLiveBindingConfig,
|
|
3821
|
-
resolveDeployTransport: () => resolveDeployTransport,
|
|
3822
|
-
resolveDeployWorkerMain: () => resolveDeployWorkerMain,
|
|
3823
|
-
resolveDeployWranglerCompat: () => resolveDeployWranglerCompat,
|
|
3824
|
-
resolveDeploymentPlatform: () => resolveDeploymentPlatform,
|
|
3825
|
-
resolveDistDir: () => resolveDistDir,
|
|
3826
|
-
resolveFullDeployBuildCommand: () => resolveFullDeployBuildCommand,
|
|
3827
|
-
resolveStaticBuildCommand: () => resolveStaticBuildCommand,
|
|
3828
|
-
resolveStaticDeployPreset: () => resolveStaticDeployPreset,
|
|
3829
|
-
resolveWorkerDirName: () => resolveWorkerDirName,
|
|
3830
|
-
resolveWranglerMigrationPattern: () => resolveWranglerMigrationPattern,
|
|
3831
|
-
runCloudflareDeploy: () => runCloudflareDeploy,
|
|
3832
|
-
runDeploy: () => runDeploy,
|
|
3833
|
-
runStaticDeploy: () => runStaticDeploy,
|
|
3834
|
-
runWranglerAuthToken: () => runWranglerAuthToken,
|
|
3835
|
-
snapshotBindingIdentities: () => snapshotBindingIdentities,
|
|
3836
|
-
snapshotPassthroughIdentities: () => snapshotPassthroughIdentities,
|
|
3837
|
-
snapshotPassthroughRawFields: () => snapshotPassthroughRawFields,
|
|
3838
|
-
streamDeployEvents: () => streamDeployEvents,
|
|
3839
|
-
validateAuthMigrationSchema: () => validateAuthMigrationSchema,
|
|
3840
|
-
verifyGeneratedDeployConfig: () => verifyGeneratedDeployConfig,
|
|
3841
|
-
warnIgnoredNotFoundForFramework: () => warnIgnoredNotFoundForFramework,
|
|
3842
|
-
warnRedundantForceOn3xx: () => warnRedundantForceOn3xx,
|
|
3843
|
-
warnUnpublishedRouting: () => warnUnpublishedRouting
|
|
3844
|
-
});
|
|
3845
4291
|
const drizzleKitBin = join(fileURLToPath(import.meta.resolve("drizzle-kit")), "..", "bin.cjs");
|
|
3846
4292
|
const deployDriftCheckDir = join(".void", "deploy-drift-check");
|
|
3847
4293
|
let loadedProvisionModule;
|
|
@@ -3851,7 +4297,7 @@ let loadedProvisionModule;
|
|
|
3851
4297
|
* so a managed deploy never imports it — and thus never loads `proper-lockfile`.
|
|
3852
4298
|
*/
|
|
3853
4299
|
async function loadProvisionModule() {
|
|
3854
|
-
loadedProvisionModule ??= await import("./provision-
|
|
4300
|
+
loadedProvisionModule ??= await import("./provision-CNgEBkVA.mjs");
|
|
3855
4301
|
return loadedProvisionModule;
|
|
3856
4302
|
}
|
|
3857
4303
|
/**
|
|
@@ -4438,6 +4884,34 @@ function hashWranglerUploader(root, resolveArgv = resolveWranglerArgv) {
|
|
|
4438
4884
|
if (typeof entry !== "string" || entry.length === 0 || !existsSync(entry)) return;
|
|
4439
4885
|
return hashDirectoryContents(dirname(entry));
|
|
4440
4886
|
}
|
|
4887
|
+
/** Pin the cf uploader and prebuilt-artifact builders before project code runs. */
|
|
4888
|
+
function hashCfUploader() {
|
|
4889
|
+
try {
|
|
4890
|
+
const hash = createHash("sha256");
|
|
4891
|
+
for (const name of [
|
|
4892
|
+
"cf",
|
|
4893
|
+
"@cloudflare/config",
|
|
4894
|
+
"@cloudflare/build-output-utils",
|
|
4895
|
+
"vite"
|
|
4896
|
+
]) {
|
|
4897
|
+
let path = dirname(fileURLToPath(import.meta.resolve(name)));
|
|
4898
|
+
while (!existsSync(join(path, "package.json"))) {
|
|
4899
|
+
const parent = dirname(path);
|
|
4900
|
+
if (parent === path) return;
|
|
4901
|
+
path = parent;
|
|
4902
|
+
}
|
|
4903
|
+
const contents = hashDirectoryContents(path);
|
|
4904
|
+
if (!contents) return;
|
|
4905
|
+
hash.update(name);
|
|
4906
|
+
hash.update("\0");
|
|
4907
|
+
hash.update(contents);
|
|
4908
|
+
hash.update("\0");
|
|
4909
|
+
}
|
|
4910
|
+
return hash.digest("hex");
|
|
4911
|
+
} catch {
|
|
4912
|
+
return;
|
|
4913
|
+
}
|
|
4914
|
+
}
|
|
4441
4915
|
/**
|
|
4442
4916
|
* sha256 over every file under `dir`, walked in a STABLE (name-sorted, depth-first) order with
|
|
4443
4917
|
* each file's relative path folded into the digest, so the hash depends only on the directory's
|
|
@@ -4475,11 +4949,11 @@ function hashDirectoryContents(dir) {
|
|
|
4475
4949
|
function assertWranglerUploaderUnchanged(before, after) {
|
|
4476
4950
|
if (before === void 0 || after === void 0) return {
|
|
4477
4951
|
ok: false,
|
|
4478
|
-
reason: `could not resolve or hash the
|
|
4952
|
+
reason: `could not resolve or hash the Cloudflare uploader to verify it across the build — refusing to run a deploy binary that cannot be verified.`
|
|
4479
4953
|
};
|
|
4480
4954
|
if (before !== after) return {
|
|
4481
4955
|
ok: false,
|
|
4482
|
-
reason: `the build modified the
|
|
4956
|
+
reason: `the build modified the Cloudflare uploader (its bundle hash changed across the build) — refusing to run it with your Cloudflare credentials.`
|
|
4483
4957
|
};
|
|
4484
4958
|
return { ok: true };
|
|
4485
4959
|
}
|
|
@@ -4732,14 +5206,12 @@ function resolveGeneratedDeployConfigPathDefault(root) {
|
|
|
4732
5206
|
function readGeneratedDeployConfig(root) {
|
|
4733
5207
|
const redirectedPath = resolveGeneratedDeployConfigPathDefault(root);
|
|
4734
5208
|
try {
|
|
4735
|
-
const config = JSON.parse(readFileSync(redirectedPath, "utf-8"));
|
|
4736
|
-
if (config === null || typeof config !== "object" || Array.isArray(config)) throw new Error("malformed config");
|
|
4737
5209
|
return {
|
|
4738
5210
|
path: redirectedPath,
|
|
4739
|
-
config
|
|
5211
|
+
config: readGeneratedWranglerConfigFile(redirectedPath)
|
|
4740
5212
|
};
|
|
4741
5213
|
} catch {
|
|
4742
|
-
throw new Error(`Generated Cloudflare deploy config ${redirectedPath} is missing or invalid JSON.`);
|
|
5214
|
+
throw new Error(`Generated Cloudflare deploy config ${redirectedPath} is missing or invalid JSON/JSONC.`);
|
|
4743
5215
|
}
|
|
4744
5216
|
}
|
|
4745
5217
|
/** Older project plugins can repeat root flags; normalize only the generated artifact. */
|
|
@@ -4827,11 +5299,11 @@ function verifyGeneratedDeployConfig(root, expected) {
|
|
|
4827
5299
|
};
|
|
4828
5300
|
let generated;
|
|
4829
5301
|
try {
|
|
4830
|
-
generated =
|
|
5302
|
+
generated = readGeneratedWranglerConfigFile(redirectedPath);
|
|
4831
5303
|
} catch {
|
|
4832
5304
|
return {
|
|
4833
5305
|
ok: false,
|
|
4834
|
-
reason: `generated wrangler config ${redirectedPath} is not valid JSON.`
|
|
5306
|
+
reason: `generated wrangler config ${redirectedPath} is not valid JSON/JSONC.`
|
|
4835
5307
|
};
|
|
4836
5308
|
}
|
|
4837
5309
|
if (generated.account_id !== expected.accountId) return {
|
|
@@ -5648,16 +6120,12 @@ function createDeployWranglerRunner(root, accountId, apiBaseUrl) {
|
|
|
5648
6120
|
const [command, ...prefix] = resolveWranglerArgv(root);
|
|
5649
6121
|
return (args, opts) => {
|
|
5650
6122
|
const childEnv = deployChildEnv(accountId, apiBaseUrl);
|
|
5651
|
-
const
|
|
5652
|
-
if (!opts.capture ||
|
|
6123
|
+
const interactiveLogin = cloudflareAuthNeedsTerminal(args);
|
|
6124
|
+
if (!opts.capture || interactiveLogin) childEnv.WRANGLER_LOG = "none";
|
|
5653
6125
|
if (opts.env) Object.assign(childEnv, opts.env);
|
|
5654
6126
|
const result = spawnSync(command, [...prefix, ...args], {
|
|
5655
6127
|
cwd: root,
|
|
5656
|
-
stdio:
|
|
5657
|
-
"inherit",
|
|
5658
|
-
"inherit",
|
|
5659
|
-
"ignore"
|
|
5660
|
-
] : opts.input === void 0 ? opts.capture ? [
|
|
6128
|
+
stdio: interactiveLogin ? "inherit" : opts.input === void 0 ? opts.capture ? [
|
|
5661
6129
|
"ignore",
|
|
5662
6130
|
"pipe",
|
|
5663
6131
|
"pipe"
|
|
@@ -5791,7 +6259,7 @@ async function runCloudflareEmailStep(input) {
|
|
|
5791
6259
|
};
|
|
5792
6260
|
const from = input.voidConfig.email?.from;
|
|
5793
6261
|
if (!from) {
|
|
5794
|
-
log.warn(["deploy: this app uses email, but void.
|
|
6262
|
+
log.warn(["deploy: this app uses email, but void.config.ts names no sender.", "Set email.from to \"you@mail.acme.com\" in void.config.ts — deploying without email."].join("\n"));
|
|
5795
6263
|
return without;
|
|
5796
6264
|
}
|
|
5797
6265
|
const { rootConfig } = input;
|
|
@@ -5900,7 +6368,7 @@ async function runCloudflareEmailStep(input) {
|
|
|
5900
6368
|
};
|
|
5901
6369
|
};
|
|
5902
6370
|
if (pre.blockers.some((b) => b.scope === "all")) return leaveAccount(`email on ${pre.domain} cannot be set up from here.`);
|
|
5903
|
-
if (input.nonInteractive) return leaveAccount([`email on ${pre.domain} is not ${shipsBinding ? "fully " : ""}set up, and this shell cannot ask.`, "Run `void email setup --platform cloudflare` once locally, commit
|
|
6371
|
+
if (input.nonInteractive) return leaveAccount([`email on ${pre.domain} is not ${shipsBinding ? "fully " : ""}set up, and this shell cannot ask.`, "Run `void email setup --platform cloudflare` once locally, commit void.lock.json, then redeploy."].join("\n"));
|
|
5904
6372
|
if (!await input.confirm(`Set up email on ${pre.domain}?`)) return leaveAccount("email setup skipped — run `void email setup --platform cloudflare` later.");
|
|
5905
6373
|
const out = await applyEmailSetup(pre, inputs);
|
|
5906
6374
|
if (out.lines.length > 0) log.message(out.lines.join("\n"));
|
|
@@ -5962,6 +6430,11 @@ async function ensureCloudflareAuthSecret(options) {
|
|
|
5962
6430
|
};
|
|
5963
6431
|
if ((await list(true)).includes(BETTER_AUTH_SECRET_NAME)) return { created: false };
|
|
5964
6432
|
const secret = randomBytes(32).toString("hex");
|
|
6433
|
+
if (workerWasMissing) return {
|
|
6434
|
+
created: true,
|
|
6435
|
+
workerWasMissing: true,
|
|
6436
|
+
candidateSecret: secret
|
|
6437
|
+
};
|
|
5965
6438
|
beforeRun();
|
|
5966
6439
|
let put;
|
|
5967
6440
|
try {
|
|
@@ -5979,8 +6452,8 @@ async function ensureCloudflareAuthSecret(options) {
|
|
|
5979
6452
|
} catch {
|
|
5980
6453
|
throw new CloudflareAuthSecretError(`deploy: could not create the remote ${BETTER_AUTH_SECRET_NAME}. No worker was uploaded. Run \`void secret put ${BETTER_AUTH_SECRET_NAME}\` and retry.`, "put-failed");
|
|
5981
6454
|
}
|
|
5982
|
-
if (!isCleanWranglerExit(put)) throw new CloudflareAuthSecretError(`deploy: could not create the remote ${BETTER_AUTH_SECRET_NAME} (
|
|
5983
|
-
if (!(await list(false)).includes(BETTER_AUTH_SECRET_NAME)) throw new CloudflareAuthSecretError(`deploy:
|
|
6455
|
+
if (!isCleanWranglerExit(put)) throw new CloudflareAuthSecretError(`deploy: could not create the remote ${BETTER_AUTH_SECRET_NAME} (Cloudflare command exit ${String(put.status)}). No worker was uploaded. Run \`void secret put ${BETTER_AUTH_SECRET_NAME}\` and retry.`, "put-failed");
|
|
6456
|
+
if (!(await list(false)).includes(BETTER_AUTH_SECRET_NAME)) throw new CloudflareAuthSecretError(`deploy: Cloudflare reported success but ${BETTER_AUTH_SECRET_NAME} was not present afterward. No worker was uploaded; retry once Cloudflare secret storage is available.`, "verification-failed");
|
|
5984
6457
|
return {
|
|
5985
6458
|
created: true,
|
|
5986
6459
|
...workerWasMissing ? { workerWasMissing: true } : {}
|
|
@@ -6080,10 +6553,16 @@ async function runCloudflareDeploy(root, options, cliLog, deps = {}) {
|
|
|
6080
6553
|
}
|
|
6081
6554
|
const hashUploader = deps.hashWranglerUploader ?? hashWranglerUploader;
|
|
6082
6555
|
const wranglerUploaderHashBefore = hashUploader(root);
|
|
6556
|
+
const cfUploaderHashBefore = deps.activateVersion || deps.runWrangler ? void 0 : hashCfUploader();
|
|
6557
|
+
const cfUploaderIsPinned = () => {
|
|
6558
|
+
const matched = cfUploaderHashBefore !== void 0 && cfUploaderHashBefore === hashCfUploader();
|
|
6559
|
+
if (!matched) log.error("deploy: refusing to run a changed cf uploader with Cloudflare credentials.");
|
|
6560
|
+
return matched;
|
|
6561
|
+
};
|
|
6083
6562
|
const assertUploaderStillPinned = () => {
|
|
6084
6563
|
const check = assertWranglerUploaderUnchanged(wranglerUploaderHashBefore, hashUploader(root));
|
|
6085
6564
|
if (check.ok) return true;
|
|
6086
|
-
log.error(["deploy: refusing to run the
|
|
6565
|
+
log.error(["deploy: refusing to run the Cloudflare uploader with your Cloudflare credentials.", check.reason].filter(Boolean).join("\n"));
|
|
6087
6566
|
return false;
|
|
6088
6567
|
};
|
|
6089
6568
|
let accountId = readWranglerTopLevelString(rootConfig, "account_id") ?? (process.env.CLOUDFLARE_ACCOUNT_ID?.trim() || void 0);
|
|
@@ -6148,10 +6627,10 @@ async function runCloudflareDeploy(root, options, cliLog, deps = {}) {
|
|
|
6148
6627
|
const staleAddresses = Array.isArray(rootConfig.addresses) ? rootConfig.addresses.filter((a) => typeof a === "string") : [];
|
|
6149
6628
|
const staleBinding = Array.isArray(rootConfig.send_email) && rootConfig.send_email.some((e) => e?.name === "SEND_EMAIL");
|
|
6150
6629
|
if (staleAddresses.length > 0 || staleBinding) log.warn([
|
|
6151
|
-
"deploy: this app no longer declares email handlers or imports void/email, but
|
|
6630
|
+
"deploy: this app no longer declares email handlers or imports void/email, but the Cloudflare config still carries the email setup Void wrote:",
|
|
6152
6631
|
...staleAddresses.map((a) => ` • ${a} — still routed to worker "${workerName}", which no longer exports email(); inbound mail there will fail.`),
|
|
6153
6632
|
...staleBinding ? [` • send_email ${SEND_EMAIL_BINDING} binding`] : [],
|
|
6154
|
-
"Deploying as-is. To detach: remove `addresses`, `send_email
|
|
6633
|
+
"Deploying as-is. To detach: remove `addresses`, `send_email`, and `vars.__VOID_EMAIL_FROM` from `resolved` in void.lock.json (and any authored overrides in void.config.ts), then delete the rules in the Cloudflare dashboard (Email → Email Routing → Routing rules)."
|
|
6155
6634
|
].join("\n"));
|
|
6156
6635
|
}
|
|
6157
6636
|
const schemaProbeEnv = buildSchemaProbeEnv(accountId, apiBaseUrl);
|
|
@@ -6255,7 +6734,7 @@ async function runCloudflareDeploy(root, options, cliLog, deps = {}) {
|
|
|
6255
6734
|
const provisionAndVerify = async () => {
|
|
6256
6735
|
if (existingWorker) {
|
|
6257
6736
|
const { missing } = provisionModule.checkCloudflareProvisionDrift(configPath, desired);
|
|
6258
|
-
throw new Error(missing.length > 0 ? formatCloudflareDriftMessage(missing, reasons, "Linking cannot provision these inferred resources:", `Check the existing Worker's binding names and resource IDs in
|
|
6737
|
+
throw new Error(missing.length > 0 ? formatCloudflareDriftMessage(missing, reasons, "Linking cannot provision these inferred resources:", `Check the existing Worker's binding names and resource IDs in void.config.ts and inference.bindings there, then rerun \`void deploy\`. Keep new resources for a later deployment.`) : "Linking cannot provision resources. Remove --provision and rerun `void deploy` to reuse the existing Worker.");
|
|
6259
6738
|
}
|
|
6260
6739
|
if (!assertUploaderStillPinned()) return exit(1);
|
|
6261
6740
|
const provision = deps.provision ?? provisionModule.provisionCloudflareResources;
|
|
@@ -6382,7 +6861,7 @@ async function runCloudflareDeploy(root, options, cliLog, deps = {}) {
|
|
|
6382
6861
|
return exit(getExitCode(err));
|
|
6383
6862
|
}
|
|
6384
6863
|
if (detectedFramework && frameworkPreset) try {
|
|
6385
|
-
await (deps.prepareFrameworkArtifact ?? prepareCloudflareFrameworkArtifact)(root, configPath, accountId, workerName, voidConfig, detectedFramework, frameworkPreset, schemaFacts.requiredKeys);
|
|
6864
|
+
await (deps.prepareFrameworkArtifact ?? prepareCloudflareFrameworkArtifact)(root, configPath, accountId, workerName, voidConfig, detectedFramework, frameworkPreset, schemaFacts.requiredKeys, needsAI ? { binding: aiBindingName } : void 0);
|
|
6386
6865
|
} catch (error) {
|
|
6387
6866
|
log.error(`deploy: could not prepare ${detectedFramework.name} for Cloudflare — ${getErrorMessage(error)}`);
|
|
6388
6867
|
return exit(1);
|
|
@@ -6541,7 +7020,22 @@ async function runCloudflareDeploy(root, options, cliLog, deps = {}) {
|
|
|
6541
7020
|
d1MigrateToken = migrateTarget.token;
|
|
6542
7021
|
}
|
|
6543
7022
|
}
|
|
7023
|
+
const generatedConfigPath = (deps.resolveGeneratedConfigPath ?? resolveGeneratedDeployConfigPathDefault)(root);
|
|
7024
|
+
const prepareBuildOutput = () => frameworkPreset?.cloudflareArtifact === "worker-output" ? prepareCfFrameworkBuildOutput({
|
|
7025
|
+
projectRoot: root,
|
|
7026
|
+
configPath: generatedConfigPath,
|
|
7027
|
+
accountId
|
|
7028
|
+
}) : prepareCfBuildOutput(dirname(generatedConfigPath), accountId);
|
|
7029
|
+
if (!deps.activateVersion && !deps.runWrangler) {
|
|
7030
|
+
const preflight = await prepareBuildOutput();
|
|
7031
|
+
if (!preflight) {
|
|
7032
|
+
log.error("deploy: cf could not prepare the built Worker for deployment.");
|
|
7033
|
+
return exit(1);
|
|
7034
|
+
}
|
|
7035
|
+
preflight.dispose();
|
|
7036
|
+
}
|
|
6544
7037
|
let workerWasMissingBeforeSecretProvisioning = false;
|
|
7038
|
+
let initialAuthSecret;
|
|
6545
7039
|
if (authEnabled) {
|
|
6546
7040
|
const inheritance = (deps.verifyDeployConfig ?? verifyGeneratedDeployConfig)(root, {
|
|
6547
7041
|
accountId,
|
|
@@ -6570,6 +7064,7 @@ async function runCloudflareDeploy(root, options, cliLog, deps = {}) {
|
|
|
6570
7064
|
beforeWranglerRun: assertUploaderStillPinned
|
|
6571
7065
|
});
|
|
6572
7066
|
workerWasMissingBeforeSecretProvisioning ||= authSecret.workerWasMissing === true;
|
|
7067
|
+
initialAuthSecret = authSecret.candidateSecret;
|
|
6573
7068
|
cliLog.info("cloudflare_auth_secret_ready", { created: authSecret.created });
|
|
6574
7069
|
} catch (error) {
|
|
6575
7070
|
if (error instanceof CloudflareAuthSecretError && error.reason === "uploader-changed") return exit(1);
|
|
@@ -6686,23 +7181,35 @@ async function runCloudflareDeploy(root, options, cliLog, deps = {}) {
|
|
|
6686
7181
|
].filter(Boolean).join("\n"));
|
|
6687
7182
|
return exit(1);
|
|
6688
7183
|
}
|
|
6689
|
-
const generatedConfigPath = (deps.resolveGeneratedConfigPath ?? resolveGeneratedDeployConfigPathDefault)(root);
|
|
6690
7184
|
const queueConsumerCleanup = readWranglerManagedQueueCleanupCandidates(configPath);
|
|
6691
7185
|
if (existingWorker) assertCloudflareLinkUnchanged(root, pinnedHandoffLink);
|
|
6692
7186
|
const candidateReceipt = pinnedHandoffLink?.candidateReceipt;
|
|
6693
|
-
|
|
6694
|
-
|
|
7187
|
+
if (!deps.activateVersion && !deps.runWrangler && !cfUploaderIsPinned()) return exit(1);
|
|
7188
|
+
const cfOutput = deps.activateVersion || deps.runWrangler ? null : await prepareBuildOutput();
|
|
7189
|
+
if (!cfOutput && !deps.activateVersion && !deps.runWrangler) {
|
|
7190
|
+
log.error("deploy: cf could not prepare the built Worker for deployment.");
|
|
7191
|
+
return exit(1);
|
|
7192
|
+
}
|
|
7193
|
+
const cfCommand = cfOutput ? createCfCommand({
|
|
6695
7194
|
accountId,
|
|
6696
7195
|
apiBaseUrl,
|
|
7196
|
+
env: deployChildEnv,
|
|
7197
|
+
verifyUploader: cfUploaderIsPinned
|
|
7198
|
+
}) : null;
|
|
7199
|
+
const activationRunner = cfOutput && cfCommand ? createCfVersionRunner({
|
|
7200
|
+
output: cfOutput,
|
|
6697
7201
|
workerName,
|
|
6698
|
-
|
|
6699
|
-
|
|
6700
|
-
|
|
6701
|
-
|
|
6702
|
-
|
|
7202
|
+
runCf: cfCommand,
|
|
7203
|
+
verifyResources: createCfResourceVerifier({
|
|
7204
|
+
configPath: generatedConfigPath,
|
|
7205
|
+
runCf: cfCommand,
|
|
7206
|
+
runWrangler,
|
|
7207
|
+
verifyCompatibilityRunner: assertUploaderStillPinned
|
|
7208
|
+
})
|
|
7209
|
+
}) : runWrangler;
|
|
6703
7210
|
const execution = await (deps.activateVersion ?? activateCloudflareVersion)({
|
|
6704
7211
|
runWrangler: activationRunner,
|
|
6705
|
-
verifyUploader: assertUploaderStillPinned,
|
|
7212
|
+
verifyUploader: cfOutput ? cfUploaderIsPinned : assertUploaderStillPinned,
|
|
6706
7213
|
workerName,
|
|
6707
7214
|
configPath: generatedConfigPath,
|
|
6708
7215
|
preserveTriggers: existingWorker !== null,
|
|
@@ -6734,10 +7241,18 @@ async function runCloudflareDeploy(root, options, cliLog, deps = {}) {
|
|
|
6734
7241
|
workerName,
|
|
6735
7242
|
runWrangler
|
|
6736
7243
|
}),
|
|
7244
|
+
publishEmptyCrons: createCloudflareEmptyCronPublisher({
|
|
7245
|
+
accountId,
|
|
7246
|
+
apiBaseUrl,
|
|
7247
|
+
configPath: generatedConfigPath,
|
|
7248
|
+
workerName,
|
|
7249
|
+
runWrangler
|
|
7250
|
+
}),
|
|
6737
7251
|
previousTrafficConfig: readWranglerPublishedTrafficSnapshot(configPath),
|
|
6738
7252
|
queueConsumerCleanup,
|
|
6739
|
-
verifyInheritedSecrets: true
|
|
6740
|
-
|
|
7253
|
+
verifyInheritedSecrets: true,
|
|
7254
|
+
...initialAuthSecret ? { candidateSecrets: { [BETTER_AUTH_SECRET_NAME]: initialAuthSecret } } : {}
|
|
7255
|
+
}).finally(() => cfOutput?.dispose());
|
|
6741
7256
|
if (!execution.ok) {
|
|
6742
7257
|
await reportCloudflareActivationFailure(cliLog, needsSandbox && execution.containersUnavailable ? formatCloudflareSandboxUnavailable() : formatCloudflareActivationError(execution));
|
|
6743
7258
|
return exit(1);
|
|
@@ -6765,11 +7280,7 @@ async function runCloudflareDeploy(root, options, cliLog, deps = {}) {
|
|
|
6765
7280
|
*/
|
|
6766
7281
|
function discoverRootWranglerConfig(root) {
|
|
6767
7282
|
if (existsSync(join(root, "wrangler.toml"))) throw new Error("Found wrangler.toml. Direct Cloudflare deployment needs one root wrangler.jsonc or wrangler.json with the same settings. Convert the config before deploying.");
|
|
6768
|
-
|
|
6769
|
-
const candidate = join(root, name);
|
|
6770
|
-
if (existsSync(candidate)) return candidate;
|
|
6771
|
-
}
|
|
6772
|
-
return join(root, "wrangler.jsonc");
|
|
7283
|
+
return materializeCloudflareConfig(root);
|
|
6773
7284
|
}
|
|
6774
7285
|
/** Avoid making Wrangler open a config path that Void has not created yet. */
|
|
6775
7286
|
function existingWranglerConfigArgs(configPath) {
|
|
@@ -6819,6 +7330,7 @@ function formatCloudflareActivationError(result) {
|
|
|
6819
7330
|
"deploy: Cloudflare Access blocked the uploaded Worker Version readiness probe.",
|
|
6820
7331
|
"For CI, set CF_ACCESS_CLIENT_ID and CF_ACCESS_CLIENT_SECRET to an admitted service token.",
|
|
6821
7332
|
"For a local deploy, set CF_ACCESS_TOKEN to a short-lived user JWT from cloudflared.",
|
|
7333
|
+
"If the response is error 1050, create an Access application for this hostname; a token alone cannot bypass account default-deny.",
|
|
6822
7334
|
`Then retry. ${formatCloudflareReadinessRestoration(result)}`
|
|
6823
7335
|
].join("\n");
|
|
6824
7336
|
case "bootstrap-failed": return `deploy: Cloudflare could not bootstrap the first Worker deployment${status}.${cloudflareCode}${diagnostic}`;
|
|
@@ -6832,6 +7344,7 @@ function formatCloudflareActivationError(result) {
|
|
|
6832
7344
|
"deploy: Cloudflare Access blocked the first Worker deployment readiness probe.",
|
|
6833
7345
|
"For CI, set CF_ACCESS_CLIENT_ID and CF_ACCESS_CLIENT_SECRET to an admitted service token;",
|
|
6834
7346
|
"for a local deploy, set CF_ACCESS_TOKEN to a short-lived user JWT from cloudflared.",
|
|
7347
|
+
"If the response is error 1050, create an Access application for this hostname; a token alone cannot bypass account default-deny.",
|
|
6835
7348
|
"Then retry. Cloudflare requires the first deployment to be non-versioned, so the new",
|
|
6836
7349
|
"Worker is already active behind Access."
|
|
6837
7350
|
].join("\n");
|
|
@@ -6857,7 +7370,7 @@ function cloudflareWorkerReadinessHeaders() {
|
|
|
6857
7370
|
});
|
|
6858
7371
|
}
|
|
6859
7372
|
/** Build the trusted Wrangler pointer for a framework that emits Worker files directly. */
|
|
6860
|
-
async function prepareCloudflareFrameworkArtifact(root, configPath, accountId, workerName, voidConfig, framework, preset, requiredSecretNames = []) {
|
|
7373
|
+
async function prepareCloudflareFrameworkArtifact(root, configPath, accountId, workerName, voidConfig, framework, preset, requiredSecretNames = [], ai) {
|
|
6861
7374
|
const workerMain = join(root, preset.workerDir, preset.workerMain);
|
|
6862
7375
|
const assetsDirectory = join(root, preset.assetsDir);
|
|
6863
7376
|
if (!existsSync(workerMain)) throw new Error(`framework ${framework.name} did not emit its Worker entry at ${preset.workerDir}/${preset.workerMain}`);
|
|
@@ -6865,13 +7378,18 @@ async function prepareCloudflareFrameworkArtifact(root, configPath, accountId, w
|
|
|
6865
7378
|
const paths = resolveProjectPaths(root, voidConfig);
|
|
6866
7379
|
const crons = scanJobsSync(root, paths.cronsDir);
|
|
6867
7380
|
const queues = scanQueuesSync(root, paths.queuesDir);
|
|
7381
|
+
const revalidate = collectRevalidate(voidConfig, null);
|
|
6868
7382
|
await generateDeployWrapperIfNeeded(root, join(root, preset.workerDir), preset.workerMain, {
|
|
6869
7383
|
auth: null,
|
|
6870
7384
|
crons,
|
|
6871
7385
|
queues,
|
|
6872
7386
|
hasMigrations: false,
|
|
6873
7387
|
migrationDialect: getDatabaseDialect(voidConfig),
|
|
6874
|
-
readiness: true
|
|
7388
|
+
readiness: true,
|
|
7389
|
+
...hasRevalidate(revalidate) && { isr: {
|
|
7390
|
+
revalidate,
|
|
7391
|
+
queryAllowlist: voidConfig.routing?.revalidateQueryAllowlist
|
|
7392
|
+
} }
|
|
6875
7393
|
});
|
|
6876
7394
|
if (preset.cloudflareArtifact === "vite-plugin") return;
|
|
6877
7395
|
const rootConfig = parseRootWranglerConfig(configPath);
|
|
@@ -6886,12 +7404,17 @@ async function prepareCloudflareFrameworkArtifact(root, configPath, accountId, w
|
|
|
6886
7404
|
compatibilityFlags: preset.cloudflareCompatibilityFlags,
|
|
6887
7405
|
crons: [...new Set(crons.flatMap((job) => job.crons))],
|
|
6888
7406
|
requiredSecrets: requiredSecretNames,
|
|
7407
|
+
...ai ? { ai: {
|
|
7408
|
+
...ai,
|
|
7409
|
+
gateway: voidConfig.ai?.gateway
|
|
7410
|
+
} } : {},
|
|
6889
7411
|
...preset.workerDir === preset.assetsDir ? { assetsIgnore: [
|
|
6890
7412
|
preset.workerMain,
|
|
6891
7413
|
"_routes.json",
|
|
6892
7414
|
"__original.js",
|
|
6893
7415
|
"__original.mjs",
|
|
6894
7416
|
"__void_handlers.mjs",
|
|
7417
|
+
"__void_isr*.mjs",
|
|
6895
7418
|
"__void_migration_handler*.mjs"
|
|
6896
7419
|
] } : {}
|
|
6897
7420
|
});
|
|
@@ -6961,9 +7484,15 @@ async function runCloudflareStaticDeploy(root, options, voidConfig, preset, cliL
|
|
|
6961
7484
|
}
|
|
6962
7485
|
const hashUploader = deps.hashWranglerUploader ?? hashWranglerUploader;
|
|
6963
7486
|
const uploaderHash = hashUploader(root);
|
|
7487
|
+
const cfUploaderHashBefore = deps.activateVersion || deps.runWrangler ? void 0 : hashCfUploader();
|
|
7488
|
+
const cfUploaderIsPinned = () => {
|
|
7489
|
+
const matched = cfUploaderHashBefore !== void 0 && cfUploaderHashBefore === hashCfUploader();
|
|
7490
|
+
if (!matched) log.error("deploy: refusing to run a changed cf uploader with Cloudflare credentials.");
|
|
7491
|
+
return matched;
|
|
7492
|
+
};
|
|
6964
7493
|
const uploaderIsPinned = () => {
|
|
6965
7494
|
const result = assertWranglerUploaderUnchanged(uploaderHash, hashUploader(root));
|
|
6966
|
-
if (!result.ok) log.error(["deploy: refusing to run the
|
|
7495
|
+
if (!result.ok) log.error(["deploy: refusing to run the Cloudflare uploader with your Cloudflare credentials.", result.reason].filter(Boolean).join("\n"));
|
|
6967
7496
|
return result.ok;
|
|
6968
7497
|
};
|
|
6969
7498
|
let accountId = readWranglerTopLevelString(rootConfig, "account_id") ?? (process.env.CLOUDFLARE_ACCOUNT_ID?.trim() || void 0);
|
|
@@ -7092,19 +7621,37 @@ async function runCloudflareStaticDeploy(root, options, voidConfig, preset, cliL
|
|
|
7092
7621
|
const queueConsumerCleanup = readWranglerManagedQueueCleanupCandidates(configPath);
|
|
7093
7622
|
if (existingWorker) assertCloudflareLinkUnchanged(root, pinnedHandoffLink);
|
|
7094
7623
|
const candidateReceipt = pinnedHandoffLink?.candidateReceipt;
|
|
7095
|
-
|
|
7096
|
-
|
|
7624
|
+
if (!deps.activateVersion && !deps.runWrangler && !cfUploaderIsPinned()) return exit(1);
|
|
7625
|
+
const cfOutput = deps.activateVersion || deps.runWrangler ? null : await prepareCfStaticBuildOutput({
|
|
7626
|
+
projectRoot: root,
|
|
7627
|
+
configPath: staticConfigPath,
|
|
7628
|
+
assetsDirectory: stagedAssetsDirectory,
|
|
7629
|
+
accountId
|
|
7630
|
+
});
|
|
7631
|
+
if (!cfOutput && !deps.activateVersion && !deps.runWrangler) {
|
|
7632
|
+
log.error("deploy: cf could not prepare the static Worker for deployment.");
|
|
7633
|
+
return exit(1);
|
|
7634
|
+
}
|
|
7635
|
+
const cfCommand = cfOutput ? createCfCommand({
|
|
7097
7636
|
accountId,
|
|
7098
7637
|
apiBaseUrl,
|
|
7638
|
+
env: deployChildEnv,
|
|
7639
|
+
verifyUploader: cfUploaderIsPinned
|
|
7640
|
+
}) : null;
|
|
7641
|
+
const activationRunner = cfOutput && cfCommand ? createCfVersionRunner({
|
|
7642
|
+
output: cfOutput,
|
|
7099
7643
|
workerName,
|
|
7100
|
-
|
|
7101
|
-
|
|
7102
|
-
|
|
7103
|
-
|
|
7104
|
-
|
|
7644
|
+
runCf: cfCommand,
|
|
7645
|
+
verifyResources: createCfResourceVerifier({
|
|
7646
|
+
configPath: staticConfigPath,
|
|
7647
|
+
runCf: cfCommand,
|
|
7648
|
+
runWrangler,
|
|
7649
|
+
verifyCompatibilityRunner: uploaderIsPinned
|
|
7650
|
+
})
|
|
7651
|
+
}) : runWrangler;
|
|
7105
7652
|
const execution = await (deps.activateVersion ?? activateCloudflareVersion)({
|
|
7106
7653
|
runWrangler: activationRunner,
|
|
7107
|
-
verifyUploader: uploaderIsPinned,
|
|
7654
|
+
verifyUploader: cfOutput ? cfUploaderIsPinned : uploaderIsPinned,
|
|
7108
7655
|
configPath: staticConfigPath,
|
|
7109
7656
|
preserveTriggers: existingWorker !== null,
|
|
7110
7657
|
expectedPreviousVersionId: existingWorker?.versionId,
|
|
@@ -7136,9 +7683,16 @@ async function runCloudflareStaticDeploy(root, options, voidConfig, preset, cliL
|
|
|
7136
7683
|
workerName,
|
|
7137
7684
|
runWrangler
|
|
7138
7685
|
}),
|
|
7686
|
+
publishEmptyCrons: createCloudflareEmptyCronPublisher({
|
|
7687
|
+
accountId,
|
|
7688
|
+
apiBaseUrl,
|
|
7689
|
+
configPath: staticConfigPath,
|
|
7690
|
+
workerName,
|
|
7691
|
+
runWrangler
|
|
7692
|
+
}),
|
|
7139
7693
|
previousTrafficConfig: readWranglerPublishedTrafficSnapshot(configPath),
|
|
7140
7694
|
queueConsumerCleanup
|
|
7141
|
-
});
|
|
7695
|
+
}).finally(() => cfOutput?.dispose());
|
|
7142
7696
|
if (!execution.ok) {
|
|
7143
7697
|
await reportCloudflareActivationFailure(cliLog, formatCloudflareActivationError(execution));
|
|
7144
7698
|
return exit(1);
|
|
@@ -7189,6 +7743,8 @@ const deployTargets = {
|
|
|
7189
7743
|
},
|
|
7190
7744
|
async deploy(root, options, cliLog) {
|
|
7191
7745
|
if (options.projectSlug !== void 0) throw new Error("deploy: --project is not supported with platform cloudflare — this platform deploys to your own Cloudflare account and no Void project is involved.");
|
|
7746
|
+
assertInstalledVoidMatchesCli(root);
|
|
7747
|
+
if (migrateLegacyVoidConfig(root)) log.success("Migrated project configuration to void.config.ts. Commit void.config.ts and void.lock.json.");
|
|
7192
7748
|
return runCloudflareDeploy(root, options, cliLog);
|
|
7193
7749
|
}
|
|
7194
7750
|
},
|
|
@@ -7239,7 +7795,11 @@ async function runDeployInner(root, options, cliLog) {
|
|
|
7239
7795
|
const targetLabel = platform === "cloudflare" ? "Cloudflare" : "Void";
|
|
7240
7796
|
log.info(`Deployment target: ${targetLabel}`);
|
|
7241
7797
|
cliLog.info("deploy_target", { target: platform });
|
|
7242
|
-
|
|
7798
|
+
try {
|
|
7799
|
+
return await deployTargets[platform].deploy(root, options ?? {}, cliLog);
|
|
7800
|
+
} finally {
|
|
7801
|
+
if (existsSync(join(root, "void.config.ts"))) stashCloudflareDeployPointer(root);
|
|
7802
|
+
}
|
|
7243
7803
|
}
|
|
7244
7804
|
async function runManagedDeploy(root, options, cliLog) {
|
|
7245
7805
|
let reauthenticated = false;
|
|
@@ -7301,6 +7861,7 @@ async function runManagedDeploy(root, options, cliLog) {
|
|
|
7301
7861
|
projectId: config.projectId,
|
|
7302
7862
|
slug: config.slug
|
|
7303
7863
|
});
|
|
7864
|
+
if (migrateLegacyVoidConfig(root)) log.success("Migrated project configuration to void.config.ts. Commit void.config.ts and void.lock.json.");
|
|
7304
7865
|
const voidConfig = readConfig(root);
|
|
7305
7866
|
cliLog.info("config_resolved", {
|
|
7306
7867
|
target: voidConfig.target,
|
|
@@ -7418,7 +7979,7 @@ function resolveFullDeployBuildCommand(root, buildOverride) {
|
|
|
7418
7979
|
* (`router/compile.ts`) emits a `paths.push(...)` for:
|
|
7419
7980
|
* 1. `scan.pages.pages` — static patterns + dynamic pages' `getPrerenderPaths()`
|
|
7420
7981
|
* 2. the custom SSR entry's top-level `getPrerenderPaths()` (`ssr` argument)
|
|
7421
|
-
* 3. `options.explicitPrerenderPaths` — void.
|
|
7982
|
+
* 3. `options.explicitPrerenderPaths` — void.config.ts `routing.prerender`
|
|
7422
7983
|
* With none of them present the collector is a generated function whose body
|
|
7423
7984
|
* returns `[...new Set([])]`, so skipping is result-identical.
|
|
7424
7985
|
*
|
|
@@ -7831,7 +8392,7 @@ function warnRedundantForceOn3xx(count) {
|
|
|
7831
8392
|
*/
|
|
7832
8393
|
function warnIgnoredNotFoundForFramework(notFound, frameworkName) {
|
|
7833
8394
|
if (notFound === void 0) return;
|
|
7834
|
-
log.warn(`"routing.notFound" in void.
|
|
8395
|
+
log.warn(`"routing.notFound" in void.config.ts is ignored for ${frameworkName} deploys (not_found_handling is pinned to "none" — the framework's own worker owns unmatched HTML).`);
|
|
7835
8396
|
}
|
|
7836
8397
|
/**
|
|
7837
8398
|
* Class B/C framework deploy: build with framework CLI, package with preset output paths.
|
|
@@ -7911,7 +8472,7 @@ async function runFrameworkDeploy(root, config, client, detected, fwPreset, void
|
|
|
7911
8472
|
} catch {}
|
|
7912
8473
|
if (resources) {
|
|
7913
8474
|
if (!resources.some((resource) => resource.type === "hyperdrive")) {
|
|
7914
|
-
const { text: promptText, isCancel: isCancelPrompt } = await import("./
|
|
8475
|
+
const { text: promptText, isCancel: isCancelPrompt } = await import("./dist-C5fND3R0.mjs");
|
|
7915
8476
|
const connectionString = await promptText({
|
|
7916
8477
|
message: `Your project uses ${dialect === "mysql" ? "MySQL" : "PostgreSQL"}. Enter your connection string:`,
|
|
7917
8478
|
placeholder: dialect === "mysql" ? "mysql://user:pass@host:3306/dbname" : "postgresql://user:pass@host:5432/dbname",
|
|
@@ -7953,8 +8514,8 @@ async function runFrameworkDeploy(root, config, client, detected, fwPreset, void
|
|
|
7953
8514
|
log.info("Wrapper generated");
|
|
7954
8515
|
}
|
|
7955
8516
|
const wranglerCompat = resolveDeployWranglerCompat(root, voidConfig, workerDir, { dialect });
|
|
7956
|
-
const revalidate = voidConfig
|
|
7957
|
-
const prerender = voidConfig.routing?.prerender;
|
|
8517
|
+
const revalidate = collectRevalidate(voidConfig, null);
|
|
8518
|
+
const prerender = voidConfig.routing?.isr === false ? void 0 : voidConfig.routing?.prerender;
|
|
7958
8519
|
const schedules = rawJobs.flatMap((job) => job.crons.map((cron) => ({
|
|
7959
8520
|
name: job.name,
|
|
7960
8521
|
cron
|
|
@@ -8157,7 +8718,7 @@ async function runFullDeploy(root, config, client, voidConfig, fwPreset, skipBui
|
|
|
8157
8718
|
} catch {}
|
|
8158
8719
|
if (resources) {
|
|
8159
8720
|
if (!resources.some((resource) => resource.type === "hyperdrive")) {
|
|
8160
|
-
const { text: promptText, isCancel: isCancelPrompt } = await import("./
|
|
8721
|
+
const { text: promptText, isCancel: isCancelPrompt } = await import("./dist-C5fND3R0.mjs");
|
|
8161
8722
|
const connectionString = await promptText({
|
|
8162
8723
|
message: `Your project uses ${dialect === "mysql" ? "MySQL" : "PostgreSQL"}. Enter your connection string:`,
|
|
8163
8724
|
placeholder: dialect === "mysql" ? "mysql://user:pass@host:3306/dbname" : "postgresql://user:pass@host:5432/dbname",
|
|
@@ -8604,4 +9165,4 @@ function resolveWorkerDirName(distDir, fwPreset, buildCommand) {
|
|
|
8604
9165
|
throw new Error("deploy: Worker output not found. Expected dist/ssr/ or dist/rsc/.");
|
|
8605
9166
|
}
|
|
8606
9167
|
//#endregion
|
|
8607
|
-
export {
|
|
9168
|
+
export { streamDeployEvents as $, parseRootWranglerConfig$1 as A, resolveDistDir as B, generateDeployWrapperIfNeeded as C, resolveAssetRoutingPolicy as Ct, hashWranglerUploader as D, hasPrerenderSources as E, resolveDeployLiveBindingConfig as F, resolveWranglerMigrationPattern as G, resolveStaticBuildCommand as H, resolveDeployTransport as I, runStaticDeploy as J, runCloudflareDeploy as K, resolveDeployWorkerMain as L, promptDeployProjectConfig as M, reconstructExpectedContainers as N, isWranglerNonInteractiveOrCI as O, resolveCloudflareVoidStaticPreset as P, snapshotPassthroughRawFields as Q, resolveDeployWranglerCompat as R, formatCloudflareSandboxUnavailable as S, resolveAssetConfig as St, hasNonPageBackend as T, resolveStaticDeployPreset as U, resolveFullDeployBuildCommand as V, resolveWorkerDirName as W, snapshotBindingIdentities as X, runWranglerAuthToken as Y, snapshotPassthroughIdentities as Z, deriveWorkerName as _, preflightEmail as _t, applyDeployEvent as a, generateQueueResolverSource as at, ensurePreviouslyDeployedLiveBindingConfig as b, hasApiRoutes as bt, assertMigrationsProduceAuthSchema as c, buildEnv as ct, assertWranglerUploaderUnchanged as d, hasRevalidate as dt, validateAuthMigrationSchema as et, checkWranglerMigrationApplySet as f, scanDurableObjectModules as ft, deployChildEnv as g, findEmailConfigConflicts as gt, createDeployWranglerRunner as h, createNodeEmailDns as ht, DEPLOY_WHOLE_OBJECT_PINNED_FIELDS as i, warnUnpublishedRouting as it, prepareCloudflareFrameworkArtifact as j, loadProvisionModule as k, assertNoConfigOverrideInProjectDotenv as l, collectPages as lt, computeDesiredCloudflareResources as m, applyEmailSetup as mt, DEPLOY_PASSTHROUGH_ASSERT_FIELDS as n, warnIgnoredNotFoundForFramework as nt, assembleVoidManifest as o, prerenderPages as ot, compareWranglerMigrationPaths as p, SEND_EMAIL_BINDING as pt, runDeploy as q, DEPLOY_PASSTHROUGH_EXCLUDE_FIELDS as r, warnRedundantForceOn3xx as rt, assertManagedDurableStateSupported as s, prerenderPagesNode as st, CloudflareAuthSecretError as t, verifyGeneratedDeployConfig as tt, assertRemoteMigrationsDeployable as u, collectRevalidate as ut, discoverRootWranglerConfig as v, renderAddressMap as vt, hasDeploySchemaDrift as w, formatCloudflareActivationError as x, hasDocumentRoutes as xt, ensureCloudflareAuthSecret as y, renderEmailChecklist as yt, resolveDeploymentPlatform as z };
|