void 0.20.2 → 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-gniL2fNt.mjs → auth-cmd-MkBG2u1f.mjs} +5 -5
- package/dist/{auth-link-NZdjCmSc.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-sI18tX_O.mjs → build-cmd-DsBGwtfs.mjs} +6 -4
- package/dist/{cache-IHn5MwBC.mjs → cache-BMw8eMyF.mjs} +6 -4
- package/dist/{cancel-deploy-C5qTOdLi.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 +61 -38
- package/dist/cli/env-schema-probe.mjs +3 -3
- package/dist/client-DAAivdid.mjs +2 -0
- package/dist/{client-dHfSJvAN.mjs → client-PdAJ-F0t.mjs} +148 -89
- 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-Bfk31O_8.mjs → connect-BvC9kolB.mjs} +8 -6
- package/dist/{create-project-Bk9Z0-Jg.mjs → create-project-C9lQhRzj.mjs} +9 -25
- 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-BkRoptAt.mjs → db-R7IQgOv5.mjs} +48 -44
- package/dist/{delete-DouASY9P.mjs → delete-CghI_NXn.mjs} +6 -4
- package/dist/deploy-CYPymbtG.mjs +2 -0
- package/dist/{deploy-DTaWUS1S.mjs → deploy-H968Lo4T.mjs} +765 -197
- 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-1RhhOVrC.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-C-lGh51B.mjs → email-_8VmyX7V.mjs} +14 -12
- package/dist/{entry-DU3oDoQ3.mjs → entry-DdRFGK0y.mjs} +2 -2
- package/dist/{env-DJHsPE7Z.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-PW7ZnWTp.mjs → github-cmd-jYjha2LO.mjs} +18 -22
- 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-BWZ7q5Z4.mjs → init-CSXmvxKu.mjs} +49 -50
- package/dist/{link-Rmvu2Wl_.mjs → link-DxMOALXk.mjs} +7 -5
- package/dist/{list-DEE2S6mY.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-Uvferzmm.mjs → login-CKk5NX4d.mjs} +6 -11
- package/dist/login-Ch9cgWRF.mjs +2 -0
- package/dist/{logs-27FenuiC.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-CjOTmAYE.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-DrbQXXiW.mjs → platform-auth-config-Df6yVw-e.mjs} +6 -6
- package/dist/{platform-auth-protection-Bhtvp0B_.mjs → platform-auth-protection-Jb0yftay.mjs} +7 -5
- package/dist/{platform-auth-recovery-CeOKGVeJ.mjs → platform-auth-recovery-DmRyIfW0.mjs} +6 -5
- package/dist/platform-cmd-C9Vt7m-d.mjs +2 -0
- package/dist/{platform-cmd-BFhieCdV.mjs → platform-cmd-DRxCOTwy.mjs} +8 -5
- package/dist/{platform-domain-C74PULqV.mjs → platform-domain-IjiXgrXJ.mjs} +4 -3
- package/dist/{platform-lifecycle-BwAIgz-t.mjs → platform-lifecycle-BquAaU-5.mjs} +263 -56
- package/dist/platform-lifecycle-CuJIZNvA.mjs +2 -0
- package/dist/{platform-management-COogu_Se.mjs → platform-management-CCQKGsq4.mjs} +12 -7
- package/dist/platform-management-Cgyed0WY.mjs +2 -0
- package/dist/{platform-recovery-ewqLefp1.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-DmZK9Hxf.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-D8jOJMUJ.mjs → project-team-Dapn9HZn.mjs} +9 -5
- package/dist/{project-token-DA34bf-C.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-CUExwGQQ.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-CDNGU1gr.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/remote/index.mjs +49 -8
- package/dist/runtime/response.mjs +1 -29
- package/dist/runtime/sandbox.d.mts +4 -56
- package/dist/runtime/sandbox.mjs +82 -221
- 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-Bzzi2e9E.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 +7 -5
- 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 +16 -16
- 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 +27 -25
- 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 +171 -0
- package/skills/void/docs/guide/platform/administration/email.md +121 -0
- package/skills/void/docs/guide/platform/administration/operations.md +97 -0
- package/skills/void/docs/guide/platform/administration/projects.md +56 -0
- package/skills/void/docs/guide/platform/development/local.md +119 -0
- package/skills/void/docs/guide/platform/development/runtime.md +124 -0
- package/skills/void/docs/guide/platform/development/schema-ci.md +95 -0
- package/skills/void/docs/guide/platform/installation/ci.md +58 -0
- package/skills/void/docs/guide/platform/installation/credentials.md +90 -0
- package/skills/void/docs/guide/platform/installation/domains.md +68 -0
- package/skills/void/docs/guide/platform/installation/first-deployment.md +82 -0
- package/skills/void/docs/guide/platform/installation/maintenance.md +137 -0
- package/skills/void/docs/guide/platform/installation/prerequisites.md +88 -0
- package/skills/void/docs/guide/platform/installation/setup.md +169 -0
- package/skills/void/docs/guide/platform/installation/uninstall.md +54 -0
- package/skills/void/docs/guide/platform-administration.md +6 -414
- package/skills/void/docs/guide/platform-development.md +5 -316
- package/skills/void/docs/guide/project-collaboration.md +1 -1
- package/skills/void/docs/guide/remote-dev.md +2 -2
- package/skills/void/docs/guide/sandboxes.md +10 -25
- package/skills/void/docs/guide/self-hosted-platform.md +11 -694
- 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 +55 -38
- package/skills/void/docs/reference/cli.md +60 -34
- package/skills/void/docs/reference/config.md +57 -34
- package/skills/void/docs/reference/resource-inference.md +10 -10
- 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) {
|
|
@@ -2123,8 +2582,8 @@ function formatConnectionLostMessage(deploymentId, logPath) {
|
|
|
2123
2582
|
* Three cases:
|
|
2124
2583
|
* 1. `PlatformApiError` with 409 + a JSON body carrying `{error, deployment}`
|
|
2125
2584
|
* — surface the server-supplied error and prefer the body's deployment id.
|
|
2126
|
-
* 2. Any other `PlatformApiError` —
|
|
2127
|
-
*
|
|
2585
|
+
* 2. Any other `PlatformApiError` — retain the client's actionable message and
|
|
2586
|
+
* structured error fields; opaque provider failures use a trimmed body snippet.
|
|
2128
2587
|
* 3. Anything else — preserve the original message under a `Connection lost
|
|
2129
2588
|
* during deploy: <original>` prefix so the caller can still tell network,
|
|
2130
2589
|
* parse, and transport errors apart.
|
|
@@ -2132,13 +2591,19 @@ function formatConnectionLostMessage(deploymentId, logPath) {
|
|
|
2132
2591
|
function formatStreamDeployError(err, deploymentId, logPath) {
|
|
2133
2592
|
if (err instanceof PlatformApiError) {
|
|
2134
2593
|
const parsed = parsePlatformErrorBody(err.body);
|
|
2135
|
-
const parsedError = parsed
|
|
2594
|
+
const parsedError = platformErrorMessage(parsed) ?? parsed?.error ?? null;
|
|
2136
2595
|
const effectiveDeploymentId = parsed?.deployment ?? null ?? deploymentId;
|
|
2137
|
-
if (isCliOutdatedError(err) && parsed?.message)
|
|
2138
|
-
|
|
2596
|
+
if (isCliOutdatedError(err) && parsed?.message) {
|
|
2597
|
+
err.message = appendTrailingLines(err.message, effectiveDeploymentId, logPath);
|
|
2598
|
+
return err;
|
|
2599
|
+
}
|
|
2600
|
+
if (parsedError || err.status === 401 || err.status === 403 || parsed !== null) {
|
|
2601
|
+
err.message = appendTrailingLines(`deploy: ${err.message}`, effectiveDeploymentId, logPath);
|
|
2602
|
+
return err;
|
|
2603
|
+
}
|
|
2139
2604
|
const detail = parsedError ?? trimSnippet(err.body);
|
|
2140
|
-
|
|
2141
|
-
return
|
|
2605
|
+
err.message = appendTrailingLines(detail ? `deploy: Deploy failed (HTTP ${err.status}): ${detail}` : `deploy: Deploy failed (HTTP ${err.status}).`, effectiveDeploymentId, logPath);
|
|
2606
|
+
return err;
|
|
2142
2607
|
}
|
|
2143
2608
|
const original = err instanceof Error ? err.message : String(err);
|
|
2144
2609
|
return new Error(appendTrailingLines(`deploy: Connection lost during deploy: '${original}'.`, deploymentId, logPath));
|
|
@@ -3058,6 +3523,7 @@ function toWebSocketManifest(routes) {
|
|
|
3058
3523
|
}
|
|
3059
3524
|
function toSandboxManifest(sandbox) {
|
|
3060
3525
|
return {
|
|
3526
|
+
controllerProtocol: 1,
|
|
3061
3527
|
bindingName: sandbox.binding,
|
|
3062
3528
|
className: sandbox.className,
|
|
3063
3529
|
containerName: sandbox.containerName,
|
|
@@ -3365,7 +3831,7 @@ function selectBundledEntryFilename(outFiles) {
|
|
|
3365
3831
|
* Determine whether a wrapper is needed based on the features.
|
|
3366
3832
|
*/
|
|
3367
3833
|
function needsWrapper(features) {
|
|
3368
|
-
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;
|
|
3369
3835
|
}
|
|
3370
3836
|
/**
|
|
3371
3837
|
* Generate a wrapper entry in-place in the worker directory.
|
|
@@ -3417,8 +3883,8 @@ async function generateWrapper(workerDir, workerMain, root, features) {
|
|
|
3417
3883
|
let migrations;
|
|
3418
3884
|
let migrationPlanBundle;
|
|
3419
3885
|
if (features.hasMigrations) {
|
|
3420
|
-
const { collectMigrations } = await import("./
|
|
3421
|
-
const { buildMigrationPlanBundle } = await import("./
|
|
3886
|
+
const { collectMigrations } = await import("./collect-DAUItMDS.mjs");
|
|
3887
|
+
const { buildMigrationPlanBundle } = await import("./plan-DpuOr14e.mjs");
|
|
3422
3888
|
const migrationsDir = readProjectPaths(root).migrationsDir;
|
|
3423
3889
|
migrations = collectMigrations(migrationsDir);
|
|
3424
3890
|
migrationPlanBundle = features.migrationDialect === "sqlite" ? buildMigrationPlanBundle(migrations) : void 0;
|
|
@@ -3431,6 +3897,7 @@ async function generateWrapper(workerDir, workerMain, root, features) {
|
|
|
3431
3897
|
if (!existsSync(handlerPath)) throw new Error(`Migration handler not found: ${handlerFilename_}. Run "pnpm -C packages/void build" first.`);
|
|
3432
3898
|
await bundleMigrationHandler(root, workerDir, handlerPath, features.migrationDialect ?? "sqlite");
|
|
3433
3899
|
}
|
|
3900
|
+
if (features.isr) await bundleFrameworkIsr(root, workerDir);
|
|
3434
3901
|
const wrapperSource = generateWrapperSource(renamedName, handlerFilename, features, migrations, migrationPlanBundle);
|
|
3435
3902
|
const stagedPath = `${mainPath}.${crypto.randomUUID()}.tmp`;
|
|
3436
3903
|
try {
|
|
@@ -3441,6 +3908,33 @@ async function generateWrapper(workerDir, workerMain, root, features) {
|
|
|
3441
3908
|
rmSync(stagedPath, { force: true });
|
|
3442
3909
|
}
|
|
3443
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
|
+
}
|
|
3444
3938
|
async function bundleMigrationHandler(root, workerDir, handlerPath, dialect) {
|
|
3445
3939
|
const tmpDir = join(root, ".void", "migration-handler");
|
|
3446
3940
|
mkdirSync(tmpDir, { recursive: true });
|
|
@@ -3595,6 +4089,7 @@ function cleanupWrapper(root) {
|
|
|
3595
4089
|
for (const directory of [
|
|
3596
4090
|
"handlers",
|
|
3597
4091
|
"migration-handler",
|
|
4092
|
+
"isr",
|
|
3598
4093
|
"bundle"
|
|
3599
4094
|
]) rmSync(join(voidDir, directory), {
|
|
3600
4095
|
recursive: true,
|
|
@@ -3605,6 +4100,14 @@ function generateWrapperSource(renamedEntry, handlersModule, features, migration
|
|
|
3605
4100
|
const lines = [];
|
|
3606
4101
|
lines.push(WRAPPER_MARKER);
|
|
3607
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
|
+
}
|
|
3608
4111
|
if (features.crons.length > 0) lines.push(`import { handleScheduled } from "./${handlersModule}";`);
|
|
3609
4112
|
if (features.queues.length > 0) lines.push(`import { handleQueue, handleQueueRelay } from "./${handlersModule}";`);
|
|
3610
4113
|
if (migrations && migrations.length > 0) {
|
|
@@ -3614,10 +4117,14 @@ function generateWrapperSource(renamedEntry, handlersModule, features, migration
|
|
|
3614
4117
|
lines.push(`const __migrationDialect = ${JSON.stringify(features.migrationDialect ?? "sqlite")};`);
|
|
3615
4118
|
}
|
|
3616
4119
|
lines.push("");
|
|
3617
|
-
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;
|
|
3618
4121
|
if (needsFetchWrap) {
|
|
3619
4122
|
lines.push("async function wrappedFetch(request, env, ctx) {");
|
|
3620
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
|
+
}
|
|
3621
4128
|
if (features.readiness || features.crons.length > 0 || features.queues.length > 0 || features.hasMigrations) {
|
|
3622
4129
|
lines.push(" if (request.method === \"GET\" && url.pathname === \"/__void/ready\") {");
|
|
3623
4130
|
lines.push(" return Response.json({ ready: true });");
|
|
@@ -3679,6 +4186,12 @@ function generateWrapperSource(renamedEntry, handlersModule, features, migration
|
|
|
3679
4186
|
lines.push(" }");
|
|
3680
4187
|
lines.push(" }");
|
|
3681
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
|
+
}
|
|
3682
4195
|
lines.push(" return original.fetch(request, env, ctx);");
|
|
3683
4196
|
lines.push("}");
|
|
3684
4197
|
lines.push("");
|
|
@@ -3686,8 +4199,8 @@ function generateWrapperSource(renamedEntry, handlersModule, features, migration
|
|
|
3686
4199
|
lines.push("export default {");
|
|
3687
4200
|
if (needsFetchWrap) lines.push(" fetch: wrappedFetch,");
|
|
3688
4201
|
else lines.push(" fetch: original.fetch,");
|
|
3689
|
-
if (features.crons.length > 0) lines.push(" scheduled: handleScheduled,");
|
|
3690
|
-
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,");
|
|
3691
4204
|
lines.push("};");
|
|
3692
4205
|
return lines.join("\n");
|
|
3693
4206
|
}
|
|
@@ -3775,66 +4288,6 @@ export async function handleQueueRelay(payload, env, ctx) {
|
|
|
3775
4288
|
}
|
|
3776
4289
|
//#endregion
|
|
3777
4290
|
//#region src/cli/deploy.ts
|
|
3778
|
-
var deploy_exports = /* @__PURE__ */ __exportAll({
|
|
3779
|
-
CloudflareAuthSecretError: () => CloudflareAuthSecretError,
|
|
3780
|
-
DEPLOY_PASSTHROUGH_ASSERT_FIELDS: () => DEPLOY_PASSTHROUGH_ASSERT_FIELDS,
|
|
3781
|
-
DEPLOY_PASSTHROUGH_EXCLUDE_FIELDS: () => DEPLOY_PASSTHROUGH_EXCLUDE_FIELDS,
|
|
3782
|
-
DEPLOY_WHOLE_OBJECT_PINNED_FIELDS: () => DEPLOY_WHOLE_OBJECT_PINNED_FIELDS,
|
|
3783
|
-
applyDeployEvent: () => applyDeployEvent,
|
|
3784
|
-
assembleVoidManifest: () => assembleVoidManifest,
|
|
3785
|
-
assertManagedDurableStateSupported: () => assertManagedDurableStateSupported,
|
|
3786
|
-
assertMigrationsProduceAuthSchema: () => assertMigrationsProduceAuthSchema,
|
|
3787
|
-
assertNoConfigOverrideInProjectDotenv: () => assertNoConfigOverrideInProjectDotenv,
|
|
3788
|
-
assertRemoteMigrationsDeployable: () => assertRemoteMigrationsDeployable,
|
|
3789
|
-
assertWranglerUploaderUnchanged: () => assertWranglerUploaderUnchanged,
|
|
3790
|
-
checkWranglerMigrationApplySet: () => checkWranglerMigrationApplySet,
|
|
3791
|
-
compareWranglerMigrationPaths: () => compareWranglerMigrationPaths,
|
|
3792
|
-
computeDesiredCloudflareResources: () => computeDesiredCloudflareResources,
|
|
3793
|
-
createDeployWranglerRunner: () => createDeployWranglerRunner,
|
|
3794
|
-
deployChildEnv: () => deployChildEnv,
|
|
3795
|
-
deriveWorkerName: () => deriveWorkerName,
|
|
3796
|
-
discoverRootWranglerConfig: () => discoverRootWranglerConfig,
|
|
3797
|
-
ensureCloudflareAuthSecret: () => ensureCloudflareAuthSecret,
|
|
3798
|
-
ensurePreviouslyDeployedLiveBindingConfig: () => ensurePreviouslyDeployedLiveBindingConfig,
|
|
3799
|
-
formatCloudflareActivationError: () => formatCloudflareActivationError,
|
|
3800
|
-
formatCloudflareSandboxUnavailable: () => formatCloudflareSandboxUnavailable,
|
|
3801
|
-
generateDeployWrapperIfNeeded: () => generateDeployWrapperIfNeeded,
|
|
3802
|
-
hasDeploySchemaDrift: () => hasDeploySchemaDrift,
|
|
3803
|
-
hasNonPageBackend: () => hasNonPageBackend,
|
|
3804
|
-
hasPrerenderSources: () => hasPrerenderSources,
|
|
3805
|
-
hashWranglerUploader: () => hashWranglerUploader,
|
|
3806
|
-
isWranglerNonInteractiveOrCI: () => isWranglerNonInteractiveOrCI,
|
|
3807
|
-
loadProvisionModule: () => loadProvisionModule,
|
|
3808
|
-
parseRootWranglerConfig: () => parseRootWranglerConfig$1,
|
|
3809
|
-
prepareCloudflareFrameworkArtifact: () => prepareCloudflareFrameworkArtifact,
|
|
3810
|
-
promptDeployProjectConfig: () => promptDeployProjectConfig,
|
|
3811
|
-
reconstructExpectedContainers: () => reconstructExpectedContainers,
|
|
3812
|
-
resolveCloudflareVoidStaticPreset: () => resolveCloudflareVoidStaticPreset,
|
|
3813
|
-
resolveDeployLiveBindingConfig: () => resolveDeployLiveBindingConfig,
|
|
3814
|
-
resolveDeployTransport: () => resolveDeployTransport,
|
|
3815
|
-
resolveDeployWorkerMain: () => resolveDeployWorkerMain,
|
|
3816
|
-
resolveDeployWranglerCompat: () => resolveDeployWranglerCompat,
|
|
3817
|
-
resolveDeploymentPlatform: () => resolveDeploymentPlatform,
|
|
3818
|
-
resolveDistDir: () => resolveDistDir,
|
|
3819
|
-
resolveFullDeployBuildCommand: () => resolveFullDeployBuildCommand,
|
|
3820
|
-
resolveStaticBuildCommand: () => resolveStaticBuildCommand,
|
|
3821
|
-
resolveStaticDeployPreset: () => resolveStaticDeployPreset,
|
|
3822
|
-
resolveWorkerDirName: () => resolveWorkerDirName,
|
|
3823
|
-
resolveWranglerMigrationPattern: () => resolveWranglerMigrationPattern,
|
|
3824
|
-
runCloudflareDeploy: () => runCloudflareDeploy,
|
|
3825
|
-
runDeploy: () => runDeploy,
|
|
3826
|
-
runStaticDeploy: () => runStaticDeploy,
|
|
3827
|
-
runWranglerAuthToken: () => runWranglerAuthToken,
|
|
3828
|
-
snapshotBindingIdentities: () => snapshotBindingIdentities,
|
|
3829
|
-
snapshotPassthroughIdentities: () => snapshotPassthroughIdentities,
|
|
3830
|
-
snapshotPassthroughRawFields: () => snapshotPassthroughRawFields,
|
|
3831
|
-
streamDeployEvents: () => streamDeployEvents,
|
|
3832
|
-
validateAuthMigrationSchema: () => validateAuthMigrationSchema,
|
|
3833
|
-
verifyGeneratedDeployConfig: () => verifyGeneratedDeployConfig,
|
|
3834
|
-
warnIgnoredNotFoundForFramework: () => warnIgnoredNotFoundForFramework,
|
|
3835
|
-
warnRedundantForceOn3xx: () => warnRedundantForceOn3xx,
|
|
3836
|
-
warnUnpublishedRouting: () => warnUnpublishedRouting
|
|
3837
|
-
});
|
|
3838
4291
|
const drizzleKitBin = join(fileURLToPath(import.meta.resolve("drizzle-kit")), "..", "bin.cjs");
|
|
3839
4292
|
const deployDriftCheckDir = join(".void", "deploy-drift-check");
|
|
3840
4293
|
let loadedProvisionModule;
|
|
@@ -3844,7 +4297,7 @@ let loadedProvisionModule;
|
|
|
3844
4297
|
* so a managed deploy never imports it — and thus never loads `proper-lockfile`.
|
|
3845
4298
|
*/
|
|
3846
4299
|
async function loadProvisionModule() {
|
|
3847
|
-
loadedProvisionModule ??= await import("./provision-
|
|
4300
|
+
loadedProvisionModule ??= await import("./provision-CNgEBkVA.mjs");
|
|
3848
4301
|
return loadedProvisionModule;
|
|
3849
4302
|
}
|
|
3850
4303
|
/**
|
|
@@ -4431,6 +4884,34 @@ function hashWranglerUploader(root, resolveArgv = resolveWranglerArgv) {
|
|
|
4431
4884
|
if (typeof entry !== "string" || entry.length === 0 || !existsSync(entry)) return;
|
|
4432
4885
|
return hashDirectoryContents(dirname(entry));
|
|
4433
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
|
+
}
|
|
4434
4915
|
/**
|
|
4435
4916
|
* sha256 over every file under `dir`, walked in a STABLE (name-sorted, depth-first) order with
|
|
4436
4917
|
* each file's relative path folded into the digest, so the hash depends only on the directory's
|
|
@@ -4468,11 +4949,11 @@ function hashDirectoryContents(dir) {
|
|
|
4468
4949
|
function assertWranglerUploaderUnchanged(before, after) {
|
|
4469
4950
|
if (before === void 0 || after === void 0) return {
|
|
4470
4951
|
ok: false,
|
|
4471
|
-
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.`
|
|
4472
4953
|
};
|
|
4473
4954
|
if (before !== after) return {
|
|
4474
4955
|
ok: false,
|
|
4475
|
-
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.`
|
|
4476
4957
|
};
|
|
4477
4958
|
return { ok: true };
|
|
4478
4959
|
}
|
|
@@ -4725,14 +5206,12 @@ function resolveGeneratedDeployConfigPathDefault(root) {
|
|
|
4725
5206
|
function readGeneratedDeployConfig(root) {
|
|
4726
5207
|
const redirectedPath = resolveGeneratedDeployConfigPathDefault(root);
|
|
4727
5208
|
try {
|
|
4728
|
-
const config = JSON.parse(readFileSync(redirectedPath, "utf-8"));
|
|
4729
|
-
if (config === null || typeof config !== "object" || Array.isArray(config)) throw new Error("malformed config");
|
|
4730
5209
|
return {
|
|
4731
5210
|
path: redirectedPath,
|
|
4732
|
-
config
|
|
5211
|
+
config: readGeneratedWranglerConfigFile(redirectedPath)
|
|
4733
5212
|
};
|
|
4734
5213
|
} catch {
|
|
4735
|
-
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.`);
|
|
4736
5215
|
}
|
|
4737
5216
|
}
|
|
4738
5217
|
/** Older project plugins can repeat root flags; normalize only the generated artifact. */
|
|
@@ -4820,11 +5299,11 @@ function verifyGeneratedDeployConfig(root, expected) {
|
|
|
4820
5299
|
};
|
|
4821
5300
|
let generated;
|
|
4822
5301
|
try {
|
|
4823
|
-
generated =
|
|
5302
|
+
generated = readGeneratedWranglerConfigFile(redirectedPath);
|
|
4824
5303
|
} catch {
|
|
4825
5304
|
return {
|
|
4826
5305
|
ok: false,
|
|
4827
|
-
reason: `generated wrangler config ${redirectedPath} is not valid JSON.`
|
|
5306
|
+
reason: `generated wrangler config ${redirectedPath} is not valid JSON/JSONC.`
|
|
4828
5307
|
};
|
|
4829
5308
|
}
|
|
4830
5309
|
if (generated.account_id !== expected.accountId) return {
|
|
@@ -5641,16 +6120,12 @@ function createDeployWranglerRunner(root, accountId, apiBaseUrl) {
|
|
|
5641
6120
|
const [command, ...prefix] = resolveWranglerArgv(root);
|
|
5642
6121
|
return (args, opts) => {
|
|
5643
6122
|
const childEnv = deployChildEnv(accountId, apiBaseUrl);
|
|
5644
|
-
const
|
|
5645
|
-
if (!opts.capture ||
|
|
6123
|
+
const interactiveLogin = cloudflareAuthNeedsTerminal(args);
|
|
6124
|
+
if (!opts.capture || interactiveLogin) childEnv.WRANGLER_LOG = "none";
|
|
5646
6125
|
if (opts.env) Object.assign(childEnv, opts.env);
|
|
5647
6126
|
const result = spawnSync(command, [...prefix, ...args], {
|
|
5648
6127
|
cwd: root,
|
|
5649
|
-
stdio:
|
|
5650
|
-
"inherit",
|
|
5651
|
-
"inherit",
|
|
5652
|
-
"ignore"
|
|
5653
|
-
] : opts.input === void 0 ? opts.capture ? [
|
|
6128
|
+
stdio: interactiveLogin ? "inherit" : opts.input === void 0 ? opts.capture ? [
|
|
5654
6129
|
"ignore",
|
|
5655
6130
|
"pipe",
|
|
5656
6131
|
"pipe"
|
|
@@ -5784,7 +6259,7 @@ async function runCloudflareEmailStep(input) {
|
|
|
5784
6259
|
};
|
|
5785
6260
|
const from = input.voidConfig.email?.from;
|
|
5786
6261
|
if (!from) {
|
|
5787
|
-
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"));
|
|
5788
6263
|
return without;
|
|
5789
6264
|
}
|
|
5790
6265
|
const { rootConfig } = input;
|
|
@@ -5893,7 +6368,7 @@ async function runCloudflareEmailStep(input) {
|
|
|
5893
6368
|
};
|
|
5894
6369
|
};
|
|
5895
6370
|
if (pre.blockers.some((b) => b.scope === "all")) return leaveAccount(`email on ${pre.domain} cannot be set up from here.`);
|
|
5896
|
-
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"));
|
|
5897
6372
|
if (!await input.confirm(`Set up email on ${pre.domain}?`)) return leaveAccount("email setup skipped — run `void email setup --platform cloudflare` later.");
|
|
5898
6373
|
const out = await applyEmailSetup(pre, inputs);
|
|
5899
6374
|
if (out.lines.length > 0) log.message(out.lines.join("\n"));
|
|
@@ -5955,6 +6430,11 @@ async function ensureCloudflareAuthSecret(options) {
|
|
|
5955
6430
|
};
|
|
5956
6431
|
if ((await list(true)).includes(BETTER_AUTH_SECRET_NAME)) return { created: false };
|
|
5957
6432
|
const secret = randomBytes(32).toString("hex");
|
|
6433
|
+
if (workerWasMissing) return {
|
|
6434
|
+
created: true,
|
|
6435
|
+
workerWasMissing: true,
|
|
6436
|
+
candidateSecret: secret
|
|
6437
|
+
};
|
|
5958
6438
|
beforeRun();
|
|
5959
6439
|
let put;
|
|
5960
6440
|
try {
|
|
@@ -5972,8 +6452,8 @@ async function ensureCloudflareAuthSecret(options) {
|
|
|
5972
6452
|
} catch {
|
|
5973
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");
|
|
5974
6454
|
}
|
|
5975
|
-
if (!isCleanWranglerExit(put)) throw new CloudflareAuthSecretError(`deploy: could not create the remote ${BETTER_AUTH_SECRET_NAME} (
|
|
5976
|
-
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");
|
|
5977
6457
|
return {
|
|
5978
6458
|
created: true,
|
|
5979
6459
|
...workerWasMissing ? { workerWasMissing: true } : {}
|
|
@@ -6073,10 +6553,16 @@ async function runCloudflareDeploy(root, options, cliLog, deps = {}) {
|
|
|
6073
6553
|
}
|
|
6074
6554
|
const hashUploader = deps.hashWranglerUploader ?? hashWranglerUploader;
|
|
6075
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
|
+
};
|
|
6076
6562
|
const assertUploaderStillPinned = () => {
|
|
6077
6563
|
const check = assertWranglerUploaderUnchanged(wranglerUploaderHashBefore, hashUploader(root));
|
|
6078
6564
|
if (check.ok) return true;
|
|
6079
|
-
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"));
|
|
6080
6566
|
return false;
|
|
6081
6567
|
};
|
|
6082
6568
|
let accountId = readWranglerTopLevelString(rootConfig, "account_id") ?? (process.env.CLOUDFLARE_ACCOUNT_ID?.trim() || void 0);
|
|
@@ -6141,10 +6627,10 @@ async function runCloudflareDeploy(root, options, cliLog, deps = {}) {
|
|
|
6141
6627
|
const staleAddresses = Array.isArray(rootConfig.addresses) ? rootConfig.addresses.filter((a) => typeof a === "string") : [];
|
|
6142
6628
|
const staleBinding = Array.isArray(rootConfig.send_email) && rootConfig.send_email.some((e) => e?.name === "SEND_EMAIL");
|
|
6143
6629
|
if (staleAddresses.length > 0 || staleBinding) log.warn([
|
|
6144
|
-
"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:",
|
|
6145
6631
|
...staleAddresses.map((a) => ` • ${a} — still routed to worker "${workerName}", which no longer exports email(); inbound mail there will fail.`),
|
|
6146
6632
|
...staleBinding ? [` • send_email ${SEND_EMAIL_BINDING} binding`] : [],
|
|
6147
|
-
"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)."
|
|
6148
6634
|
].join("\n"));
|
|
6149
6635
|
}
|
|
6150
6636
|
const schemaProbeEnv = buildSchemaProbeEnv(accountId, apiBaseUrl);
|
|
@@ -6248,7 +6734,7 @@ async function runCloudflareDeploy(root, options, cliLog, deps = {}) {
|
|
|
6248
6734
|
const provisionAndVerify = async () => {
|
|
6249
6735
|
if (existingWorker) {
|
|
6250
6736
|
const { missing } = provisionModule.checkCloudflareProvisionDrift(configPath, desired);
|
|
6251
|
-
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.");
|
|
6252
6738
|
}
|
|
6253
6739
|
if (!assertUploaderStillPinned()) return exit(1);
|
|
6254
6740
|
const provision = deps.provision ?? provisionModule.provisionCloudflareResources;
|
|
@@ -6375,7 +6861,7 @@ async function runCloudflareDeploy(root, options, cliLog, deps = {}) {
|
|
|
6375
6861
|
return exit(getExitCode(err));
|
|
6376
6862
|
}
|
|
6377
6863
|
if (detectedFramework && frameworkPreset) try {
|
|
6378
|
-
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);
|
|
6379
6865
|
} catch (error) {
|
|
6380
6866
|
log.error(`deploy: could not prepare ${detectedFramework.name} for Cloudflare — ${getErrorMessage(error)}`);
|
|
6381
6867
|
return exit(1);
|
|
@@ -6534,7 +7020,22 @@ async function runCloudflareDeploy(root, options, cliLog, deps = {}) {
|
|
|
6534
7020
|
d1MigrateToken = migrateTarget.token;
|
|
6535
7021
|
}
|
|
6536
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
|
+
}
|
|
6537
7037
|
let workerWasMissingBeforeSecretProvisioning = false;
|
|
7038
|
+
let initialAuthSecret;
|
|
6538
7039
|
if (authEnabled) {
|
|
6539
7040
|
const inheritance = (deps.verifyDeployConfig ?? verifyGeneratedDeployConfig)(root, {
|
|
6540
7041
|
accountId,
|
|
@@ -6563,6 +7064,7 @@ async function runCloudflareDeploy(root, options, cliLog, deps = {}) {
|
|
|
6563
7064
|
beforeWranglerRun: assertUploaderStillPinned
|
|
6564
7065
|
});
|
|
6565
7066
|
workerWasMissingBeforeSecretProvisioning ||= authSecret.workerWasMissing === true;
|
|
7067
|
+
initialAuthSecret = authSecret.candidateSecret;
|
|
6566
7068
|
cliLog.info("cloudflare_auth_secret_ready", { created: authSecret.created });
|
|
6567
7069
|
} catch (error) {
|
|
6568
7070
|
if (error instanceof CloudflareAuthSecretError && error.reason === "uploader-changed") return exit(1);
|
|
@@ -6679,23 +7181,35 @@ async function runCloudflareDeploy(root, options, cliLog, deps = {}) {
|
|
|
6679
7181
|
].filter(Boolean).join("\n"));
|
|
6680
7182
|
return exit(1);
|
|
6681
7183
|
}
|
|
6682
|
-
const generatedConfigPath = (deps.resolveGeneratedConfigPath ?? resolveGeneratedDeployConfigPathDefault)(root);
|
|
6683
7184
|
const queueConsumerCleanup = readWranglerManagedQueueCleanupCandidates(configPath);
|
|
6684
7185
|
if (existingWorker) assertCloudflareLinkUnchanged(root, pinnedHandoffLink);
|
|
6685
7186
|
const candidateReceipt = pinnedHandoffLink?.candidateReceipt;
|
|
6686
|
-
|
|
6687
|
-
|
|
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({
|
|
6688
7194
|
accountId,
|
|
6689
7195
|
apiBaseUrl,
|
|
7196
|
+
env: deployChildEnv,
|
|
7197
|
+
verifyUploader: cfUploaderIsPinned
|
|
7198
|
+
}) : null;
|
|
7199
|
+
const activationRunner = cfOutput && cfCommand ? createCfVersionRunner({
|
|
7200
|
+
output: cfOutput,
|
|
6690
7201
|
workerName,
|
|
6691
|
-
|
|
6692
|
-
|
|
6693
|
-
|
|
6694
|
-
|
|
6695
|
-
|
|
7202
|
+
runCf: cfCommand,
|
|
7203
|
+
verifyResources: createCfResourceVerifier({
|
|
7204
|
+
configPath: generatedConfigPath,
|
|
7205
|
+
runCf: cfCommand,
|
|
7206
|
+
runWrangler,
|
|
7207
|
+
verifyCompatibilityRunner: assertUploaderStillPinned
|
|
7208
|
+
})
|
|
7209
|
+
}) : runWrangler;
|
|
6696
7210
|
const execution = await (deps.activateVersion ?? activateCloudflareVersion)({
|
|
6697
7211
|
runWrangler: activationRunner,
|
|
6698
|
-
verifyUploader: assertUploaderStillPinned,
|
|
7212
|
+
verifyUploader: cfOutput ? cfUploaderIsPinned : assertUploaderStillPinned,
|
|
6699
7213
|
workerName,
|
|
6700
7214
|
configPath: generatedConfigPath,
|
|
6701
7215
|
preserveTriggers: existingWorker !== null,
|
|
@@ -6727,10 +7241,18 @@ async function runCloudflareDeploy(root, options, cliLog, deps = {}) {
|
|
|
6727
7241
|
workerName,
|
|
6728
7242
|
runWrangler
|
|
6729
7243
|
}),
|
|
7244
|
+
publishEmptyCrons: createCloudflareEmptyCronPublisher({
|
|
7245
|
+
accountId,
|
|
7246
|
+
apiBaseUrl,
|
|
7247
|
+
configPath: generatedConfigPath,
|
|
7248
|
+
workerName,
|
|
7249
|
+
runWrangler
|
|
7250
|
+
}),
|
|
6730
7251
|
previousTrafficConfig: readWranglerPublishedTrafficSnapshot(configPath),
|
|
6731
7252
|
queueConsumerCleanup,
|
|
6732
|
-
verifyInheritedSecrets: true
|
|
6733
|
-
|
|
7253
|
+
verifyInheritedSecrets: true,
|
|
7254
|
+
...initialAuthSecret ? { candidateSecrets: { [BETTER_AUTH_SECRET_NAME]: initialAuthSecret } } : {}
|
|
7255
|
+
}).finally(() => cfOutput?.dispose());
|
|
6734
7256
|
if (!execution.ok) {
|
|
6735
7257
|
await reportCloudflareActivationFailure(cliLog, needsSandbox && execution.containersUnavailable ? formatCloudflareSandboxUnavailable() : formatCloudflareActivationError(execution));
|
|
6736
7258
|
return exit(1);
|
|
@@ -6758,11 +7280,7 @@ async function runCloudflareDeploy(root, options, cliLog, deps = {}) {
|
|
|
6758
7280
|
*/
|
|
6759
7281
|
function discoverRootWranglerConfig(root) {
|
|
6760
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.");
|
|
6761
|
-
|
|
6762
|
-
const candidate = join(root, name);
|
|
6763
|
-
if (existsSync(candidate)) return candidate;
|
|
6764
|
-
}
|
|
6765
|
-
return join(root, "wrangler.jsonc");
|
|
7283
|
+
return materializeCloudflareConfig(root);
|
|
6766
7284
|
}
|
|
6767
7285
|
/** Avoid making Wrangler open a config path that Void has not created yet. */
|
|
6768
7286
|
function existingWranglerConfigArgs(configPath) {
|
|
@@ -6812,6 +7330,7 @@ function formatCloudflareActivationError(result) {
|
|
|
6812
7330
|
"deploy: Cloudflare Access blocked the uploaded Worker Version readiness probe.",
|
|
6813
7331
|
"For CI, set CF_ACCESS_CLIENT_ID and CF_ACCESS_CLIENT_SECRET to an admitted service token.",
|
|
6814
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.",
|
|
6815
7334
|
`Then retry. ${formatCloudflareReadinessRestoration(result)}`
|
|
6816
7335
|
].join("\n");
|
|
6817
7336
|
case "bootstrap-failed": return `deploy: Cloudflare could not bootstrap the first Worker deployment${status}.${cloudflareCode}${diagnostic}`;
|
|
@@ -6825,6 +7344,7 @@ function formatCloudflareActivationError(result) {
|
|
|
6825
7344
|
"deploy: Cloudflare Access blocked the first Worker deployment readiness probe.",
|
|
6826
7345
|
"For CI, set CF_ACCESS_CLIENT_ID and CF_ACCESS_CLIENT_SECRET to an admitted service token;",
|
|
6827
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.",
|
|
6828
7348
|
"Then retry. Cloudflare requires the first deployment to be non-versioned, so the new",
|
|
6829
7349
|
"Worker is already active behind Access."
|
|
6830
7350
|
].join("\n");
|
|
@@ -6850,7 +7370,7 @@ function cloudflareWorkerReadinessHeaders() {
|
|
|
6850
7370
|
});
|
|
6851
7371
|
}
|
|
6852
7372
|
/** Build the trusted Wrangler pointer for a framework that emits Worker files directly. */
|
|
6853
|
-
async function prepareCloudflareFrameworkArtifact(root, configPath, accountId, workerName, voidConfig, framework, preset, requiredSecretNames = []) {
|
|
7373
|
+
async function prepareCloudflareFrameworkArtifact(root, configPath, accountId, workerName, voidConfig, framework, preset, requiredSecretNames = [], ai) {
|
|
6854
7374
|
const workerMain = join(root, preset.workerDir, preset.workerMain);
|
|
6855
7375
|
const assetsDirectory = join(root, preset.assetsDir);
|
|
6856
7376
|
if (!existsSync(workerMain)) throw new Error(`framework ${framework.name} did not emit its Worker entry at ${preset.workerDir}/${preset.workerMain}`);
|
|
@@ -6858,13 +7378,18 @@ async function prepareCloudflareFrameworkArtifact(root, configPath, accountId, w
|
|
|
6858
7378
|
const paths = resolveProjectPaths(root, voidConfig);
|
|
6859
7379
|
const crons = scanJobsSync(root, paths.cronsDir);
|
|
6860
7380
|
const queues = scanQueuesSync(root, paths.queuesDir);
|
|
7381
|
+
const revalidate = collectRevalidate(voidConfig, null);
|
|
6861
7382
|
await generateDeployWrapperIfNeeded(root, join(root, preset.workerDir), preset.workerMain, {
|
|
6862
7383
|
auth: null,
|
|
6863
7384
|
crons,
|
|
6864
7385
|
queues,
|
|
6865
7386
|
hasMigrations: false,
|
|
6866
7387
|
migrationDialect: getDatabaseDialect(voidConfig),
|
|
6867
|
-
readiness: true
|
|
7388
|
+
readiness: true,
|
|
7389
|
+
...hasRevalidate(revalidate) && { isr: {
|
|
7390
|
+
revalidate,
|
|
7391
|
+
queryAllowlist: voidConfig.routing?.revalidateQueryAllowlist
|
|
7392
|
+
} }
|
|
6868
7393
|
});
|
|
6869
7394
|
if (preset.cloudflareArtifact === "vite-plugin") return;
|
|
6870
7395
|
const rootConfig = parseRootWranglerConfig(configPath);
|
|
@@ -6879,12 +7404,17 @@ async function prepareCloudflareFrameworkArtifact(root, configPath, accountId, w
|
|
|
6879
7404
|
compatibilityFlags: preset.cloudflareCompatibilityFlags,
|
|
6880
7405
|
crons: [...new Set(crons.flatMap((job) => job.crons))],
|
|
6881
7406
|
requiredSecrets: requiredSecretNames,
|
|
7407
|
+
...ai ? { ai: {
|
|
7408
|
+
...ai,
|
|
7409
|
+
gateway: voidConfig.ai?.gateway
|
|
7410
|
+
} } : {},
|
|
6882
7411
|
...preset.workerDir === preset.assetsDir ? { assetsIgnore: [
|
|
6883
7412
|
preset.workerMain,
|
|
6884
7413
|
"_routes.json",
|
|
6885
7414
|
"__original.js",
|
|
6886
7415
|
"__original.mjs",
|
|
6887
7416
|
"__void_handlers.mjs",
|
|
7417
|
+
"__void_isr*.mjs",
|
|
6888
7418
|
"__void_migration_handler*.mjs"
|
|
6889
7419
|
] } : {}
|
|
6890
7420
|
});
|
|
@@ -6954,9 +7484,15 @@ async function runCloudflareStaticDeploy(root, options, voidConfig, preset, cliL
|
|
|
6954
7484
|
}
|
|
6955
7485
|
const hashUploader = deps.hashWranglerUploader ?? hashWranglerUploader;
|
|
6956
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
|
+
};
|
|
6957
7493
|
const uploaderIsPinned = () => {
|
|
6958
7494
|
const result = assertWranglerUploaderUnchanged(uploaderHash, hashUploader(root));
|
|
6959
|
-
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"));
|
|
6960
7496
|
return result.ok;
|
|
6961
7497
|
};
|
|
6962
7498
|
let accountId = readWranglerTopLevelString(rootConfig, "account_id") ?? (process.env.CLOUDFLARE_ACCOUNT_ID?.trim() || void 0);
|
|
@@ -7085,19 +7621,37 @@ async function runCloudflareStaticDeploy(root, options, voidConfig, preset, cliL
|
|
|
7085
7621
|
const queueConsumerCleanup = readWranglerManagedQueueCleanupCandidates(configPath);
|
|
7086
7622
|
if (existingWorker) assertCloudflareLinkUnchanged(root, pinnedHandoffLink);
|
|
7087
7623
|
const candidateReceipt = pinnedHandoffLink?.candidateReceipt;
|
|
7088
|
-
|
|
7089
|
-
|
|
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({
|
|
7090
7636
|
accountId,
|
|
7091
7637
|
apiBaseUrl,
|
|
7638
|
+
env: deployChildEnv,
|
|
7639
|
+
verifyUploader: cfUploaderIsPinned
|
|
7640
|
+
}) : null;
|
|
7641
|
+
const activationRunner = cfOutput && cfCommand ? createCfVersionRunner({
|
|
7642
|
+
output: cfOutput,
|
|
7092
7643
|
workerName,
|
|
7093
|
-
|
|
7094
|
-
|
|
7095
|
-
|
|
7096
|
-
|
|
7097
|
-
|
|
7644
|
+
runCf: cfCommand,
|
|
7645
|
+
verifyResources: createCfResourceVerifier({
|
|
7646
|
+
configPath: staticConfigPath,
|
|
7647
|
+
runCf: cfCommand,
|
|
7648
|
+
runWrangler,
|
|
7649
|
+
verifyCompatibilityRunner: uploaderIsPinned
|
|
7650
|
+
})
|
|
7651
|
+
}) : runWrangler;
|
|
7098
7652
|
const execution = await (deps.activateVersion ?? activateCloudflareVersion)({
|
|
7099
7653
|
runWrangler: activationRunner,
|
|
7100
|
-
verifyUploader: uploaderIsPinned,
|
|
7654
|
+
verifyUploader: cfOutput ? cfUploaderIsPinned : uploaderIsPinned,
|
|
7101
7655
|
configPath: staticConfigPath,
|
|
7102
7656
|
preserveTriggers: existingWorker !== null,
|
|
7103
7657
|
expectedPreviousVersionId: existingWorker?.versionId,
|
|
@@ -7129,9 +7683,16 @@ async function runCloudflareStaticDeploy(root, options, voidConfig, preset, cliL
|
|
|
7129
7683
|
workerName,
|
|
7130
7684
|
runWrangler
|
|
7131
7685
|
}),
|
|
7686
|
+
publishEmptyCrons: createCloudflareEmptyCronPublisher({
|
|
7687
|
+
accountId,
|
|
7688
|
+
apiBaseUrl,
|
|
7689
|
+
configPath: staticConfigPath,
|
|
7690
|
+
workerName,
|
|
7691
|
+
runWrangler
|
|
7692
|
+
}),
|
|
7132
7693
|
previousTrafficConfig: readWranglerPublishedTrafficSnapshot(configPath),
|
|
7133
7694
|
queueConsumerCleanup
|
|
7134
|
-
});
|
|
7695
|
+
}).finally(() => cfOutput?.dispose());
|
|
7135
7696
|
if (!execution.ok) {
|
|
7136
7697
|
await reportCloudflareActivationFailure(cliLog, formatCloudflareActivationError(execution));
|
|
7137
7698
|
return exit(1);
|
|
@@ -7182,6 +7743,8 @@ const deployTargets = {
|
|
|
7182
7743
|
},
|
|
7183
7744
|
async deploy(root, options, cliLog) {
|
|
7184
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.");
|
|
7185
7748
|
return runCloudflareDeploy(root, options, cliLog);
|
|
7186
7749
|
}
|
|
7187
7750
|
},
|
|
@@ -7232,7 +7795,11 @@ async function runDeployInner(root, options, cliLog) {
|
|
|
7232
7795
|
const targetLabel = platform === "cloudflare" ? "Cloudflare" : "Void";
|
|
7233
7796
|
log.info(`Deployment target: ${targetLabel}`);
|
|
7234
7797
|
cliLog.info("deploy_target", { target: platform });
|
|
7235
|
-
|
|
7798
|
+
try {
|
|
7799
|
+
return await deployTargets[platform].deploy(root, options ?? {}, cliLog);
|
|
7800
|
+
} finally {
|
|
7801
|
+
if (existsSync(join(root, "void.config.ts"))) stashCloudflareDeployPointer(root);
|
|
7802
|
+
}
|
|
7236
7803
|
}
|
|
7237
7804
|
async function runManagedDeploy(root, options, cliLog) {
|
|
7238
7805
|
let reauthenticated = false;
|
|
@@ -7294,6 +7861,7 @@ async function runManagedDeploy(root, options, cliLog) {
|
|
|
7294
7861
|
projectId: config.projectId,
|
|
7295
7862
|
slug: config.slug
|
|
7296
7863
|
});
|
|
7864
|
+
if (migrateLegacyVoidConfig(root)) log.success("Migrated project configuration to void.config.ts. Commit void.config.ts and void.lock.json.");
|
|
7297
7865
|
const voidConfig = readConfig(root);
|
|
7298
7866
|
cliLog.info("config_resolved", {
|
|
7299
7867
|
target: voidConfig.target,
|
|
@@ -7411,7 +7979,7 @@ function resolveFullDeployBuildCommand(root, buildOverride) {
|
|
|
7411
7979
|
* (`router/compile.ts`) emits a `paths.push(...)` for:
|
|
7412
7980
|
* 1. `scan.pages.pages` — static patterns + dynamic pages' `getPrerenderPaths()`
|
|
7413
7981
|
* 2. the custom SSR entry's top-level `getPrerenderPaths()` (`ssr` argument)
|
|
7414
|
-
* 3. `options.explicitPrerenderPaths` — void.
|
|
7982
|
+
* 3. `options.explicitPrerenderPaths` — void.config.ts `routing.prerender`
|
|
7415
7983
|
* With none of them present the collector is a generated function whose body
|
|
7416
7984
|
* returns `[...new Set([])]`, so skipping is result-identical.
|
|
7417
7985
|
*
|
|
@@ -7824,7 +8392,7 @@ function warnRedundantForceOn3xx(count) {
|
|
|
7824
8392
|
*/
|
|
7825
8393
|
function warnIgnoredNotFoundForFramework(notFound, frameworkName) {
|
|
7826
8394
|
if (notFound === void 0) return;
|
|
7827
|
-
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).`);
|
|
7828
8396
|
}
|
|
7829
8397
|
/**
|
|
7830
8398
|
* Class B/C framework deploy: build with framework CLI, package with preset output paths.
|
|
@@ -7904,7 +8472,7 @@ async function runFrameworkDeploy(root, config, client, detected, fwPreset, void
|
|
|
7904
8472
|
} catch {}
|
|
7905
8473
|
if (resources) {
|
|
7906
8474
|
if (!resources.some((resource) => resource.type === "hyperdrive")) {
|
|
7907
|
-
const { text: promptText, isCancel: isCancelPrompt } = await import("./
|
|
8475
|
+
const { text: promptText, isCancel: isCancelPrompt } = await import("./dist-C5fND3R0.mjs");
|
|
7908
8476
|
const connectionString = await promptText({
|
|
7909
8477
|
message: `Your project uses ${dialect === "mysql" ? "MySQL" : "PostgreSQL"}. Enter your connection string:`,
|
|
7910
8478
|
placeholder: dialect === "mysql" ? "mysql://user:pass@host:3306/dbname" : "postgresql://user:pass@host:5432/dbname",
|
|
@@ -7946,8 +8514,8 @@ async function runFrameworkDeploy(root, config, client, detected, fwPreset, void
|
|
|
7946
8514
|
log.info("Wrapper generated");
|
|
7947
8515
|
}
|
|
7948
8516
|
const wranglerCompat = resolveDeployWranglerCompat(root, voidConfig, workerDir, { dialect });
|
|
7949
|
-
const revalidate = voidConfig
|
|
7950
|
-
const prerender = voidConfig.routing?.prerender;
|
|
8517
|
+
const revalidate = collectRevalidate(voidConfig, null);
|
|
8518
|
+
const prerender = voidConfig.routing?.isr === false ? void 0 : voidConfig.routing?.prerender;
|
|
7951
8519
|
const schedules = rawJobs.flatMap((job) => job.crons.map((cron) => ({
|
|
7952
8520
|
name: job.name,
|
|
7953
8521
|
cron
|
|
@@ -8150,7 +8718,7 @@ async function runFullDeploy(root, config, client, voidConfig, fwPreset, skipBui
|
|
|
8150
8718
|
} catch {}
|
|
8151
8719
|
if (resources) {
|
|
8152
8720
|
if (!resources.some((resource) => resource.type === "hyperdrive")) {
|
|
8153
|
-
const { text: promptText, isCancel: isCancelPrompt } = await import("./
|
|
8721
|
+
const { text: promptText, isCancel: isCancelPrompt } = await import("./dist-C5fND3R0.mjs");
|
|
8154
8722
|
const connectionString = await promptText({
|
|
8155
8723
|
message: `Your project uses ${dialect === "mysql" ? "MySQL" : "PostgreSQL"}. Enter your connection string:`,
|
|
8156
8724
|
placeholder: dialect === "mysql" ? "mysql://user:pass@host:3306/dbname" : "postgresql://user:pass@host:5432/dbname",
|
|
@@ -8597,4 +9165,4 @@ function resolveWorkerDirName(distDir, fwPreset, buildCommand) {
|
|
|
8597
9165
|
throw new Error("deploy: Worker output not found. Expected dist/ssr/ or dist/rsc/.");
|
|
8598
9166
|
}
|
|
8599
9167
|
//#endregion
|
|
8600
|
-
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 };
|