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,11 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { n as __toESM } from "./rolldown-runtime-DXIUcv95.mjs";
|
|
2
|
+
import { a as join } from "./dist-4WkAWhWx.mjs";
|
|
3
|
+
import { c as import_picocolors$1, d as require_picocolors, i as createSpinner, n as cliCommandName, r as cliTitle } from "./output-urU86XeT.mjs";
|
|
4
4
|
import { t as cfAccessHeaders } from "./cf-access-DRsQRe6k.mjs";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
5
|
+
import { d as openBrowser } from "./auth-B9_D6ygs.mjs";
|
|
6
|
+
import { a as listInstallationManifests, d as readInstallationRecoverySecrets, f as readPendingInstallationSecrets, g as savePlatformConnection, h as resolveInstallationManifest, i as latestPlatformWorkerCutoverGeneration, l as platformWorkerSecretUpdateIntentState, n as assertPlatformInstallationSlugAvailable, s as normalizePlatformApiUrl, t as acquirePlatformLifecycleLock, u as promoteInstallationSecrets, v as writeInstallationManifest, y as writePendingInstallationSecrets } from "./platform-registry-BJbgZLS1.mjs";
|
|
7
|
+
import { n as ensurePlatformAccessToken } from "./cf-access-rAZxzMkL.mjs";
|
|
8
|
+
import { B as text$1, E as confirm, F as password, G as settings, I as select, K as u$1, M as multiselect, N as note, O as intro, P as outro, R as symbol, U as CANCEL_SYMBOL, W as isCancel, g as S_PASSWORD_MASK, i as S_BAR_END, j as log, r as S_BAR } from "./dist-Dn6nn2IU.mjs";
|
|
9
|
+
import { o as resolveWranglerArgv } from "./preset-Dowh9tTt.mjs";
|
|
10
|
+
import { c as runCloudflareAuthCommand, n as announceCloudflareLogin } from "./cloudflare-auth-BCmTc1X_.mjs";
|
|
11
|
+
import { g as resolvePinnedApiBaseUrl, o as createDefaultRunWrangler } from "./provision-Cck2m3jJ.mjs";
|
|
9
12
|
import { mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
10
13
|
import { createHash, createHmac, randomBytes, randomUUID } from "node:crypto";
|
|
11
14
|
import { tmpdir } from "node:os";
|
|
@@ -16,7 +19,7 @@ import { encodeCloudflareVersionMessage, parseCloudflareVersionMessage, readClou
|
|
|
16
19
|
import { readFile } from "node:fs/promises";
|
|
17
20
|
import { createServer, request } from "node:http";
|
|
18
21
|
import { request as request$1 } from "node:https";
|
|
19
|
-
import { platformDatabaseSchemaDigest, resolvePlatformRuntime } from "@void/platform/installer";
|
|
22
|
+
import { PLATFORM_ADMIN_ASSETS_DIRECTORY, platformDatabaseSchemaDigest, resolvePlatformRuntime } from "@void/platform/installer";
|
|
20
23
|
//#region src/cli/platform-cloudflare.ts
|
|
21
24
|
var PlatformCloudflareApiError = class extends Error {
|
|
22
25
|
status;
|
|
@@ -1408,7 +1411,7 @@ async function resolvePlatformCloudflareCredentialWithInput(readInput, dependenc
|
|
|
1408
1411
|
credential: result.credential
|
|
1409
1412
|
};
|
|
1410
1413
|
announceCloudflareLogin();
|
|
1411
|
-
const login = await runWrangler(["login"
|
|
1414
|
+
const login = await runWrangler(["login"], false);
|
|
1412
1415
|
assertNotCancelled();
|
|
1413
1416
|
if (login.status !== 0) throw new Error("platform: Cloudflare browser login did not complete.");
|
|
1414
1417
|
const credential = await readWranglerOAuthCredential(runWrangler);
|
|
@@ -1430,11 +1433,6 @@ async function readExistingCredential(dependencies, runWrangler) {
|
|
|
1430
1433
|
token: environmentToken
|
|
1431
1434
|
};
|
|
1432
1435
|
if (!(dependencies.interactive ?? process.stdin.isTTY === true)) throw new Error("platform: Cloudflare authentication is required. Run `void cloudflare login` interactively, or set CLOUDFLARE_API_TOKEN in CI.");
|
|
1433
|
-
if ((await runWrangler([
|
|
1434
|
-
"auth",
|
|
1435
|
-
"keyring",
|
|
1436
|
-
"enable"
|
|
1437
|
-
], true)).status !== 0) throw new Error("platform: Could not enable secure Cloudflare credential storage. Refusing to use a plaintext OAuth credential.");
|
|
1438
1436
|
return await readWranglerOAuthCredential(runWrangler);
|
|
1439
1437
|
}
|
|
1440
1438
|
async function readWranglerOAuthCredential(runWrangler = (args) => runCloudflareAuthCommand(process.cwd(), args)) {
|
|
@@ -1501,7 +1499,7 @@ async function verifyInstalledPlatformAccessProtection(input) {
|
|
|
1501
1499
|
}
|
|
1502
1500
|
const existingWorkers = input.plan.actions.filter((action) => action.kind === "worker" && action.action === "update").map((action) => action.name);
|
|
1503
1501
|
if (existingWorkers.length) {
|
|
1504
|
-
const { verifyProtectionWorkerOrigins } = await import("./platform-auth-protection-
|
|
1502
|
+
const { verifyProtectionWorkerOrigins } = await import("./platform-auth-protection-Jb0yftay.mjs");
|
|
1505
1503
|
await verifyProtectionWorkerOrigins({
|
|
1506
1504
|
request: input.client.request.bind(input.client),
|
|
1507
1505
|
listWorkerDomains: input.client.listWorkerDomains.bind(input.client),
|
|
@@ -1554,13 +1552,36 @@ async function initializeInstalledPlatformAuthentication(apiUrl, installationId,
|
|
|
1554
1552
|
}
|
|
1555
1553
|
//#endregion
|
|
1556
1554
|
//#region src/cli/platform-auth-database.ts
|
|
1555
|
+
/** Read the database name from an owner URL without applying Hyperdrive origin restrictions. */
|
|
1556
|
+
function platformDatabaseNameFromOwnerUrl(databaseUrl) {
|
|
1557
|
+
let url;
|
|
1558
|
+
try {
|
|
1559
|
+
url = new URL(databaseUrl);
|
|
1560
|
+
} catch {
|
|
1561
|
+
throw new Error("platform: DATABASE_URL must be a PostgreSQL connection string.");
|
|
1562
|
+
}
|
|
1563
|
+
if (url.protocol !== "postgres:" && url.protocol !== "postgresql:" || !url.hostname) throw new Error("platform: DATABASE_URL must use postgres:// or postgresql://.");
|
|
1564
|
+
const database = decodeURIComponent(url.pathname.replace(/^\//, ""));
|
|
1565
|
+
if (!database) throw new Error("platform: DATABASE_URL must include a database.");
|
|
1566
|
+
return database;
|
|
1567
|
+
}
|
|
1568
|
+
/** Pin an externally managed Hyperdrive without treating the owner URL as its runtime origin. */
|
|
1569
|
+
function verifyExternalPlatformHyperdrive(input) {
|
|
1570
|
+
const { config, expected } = input;
|
|
1571
|
+
const database = platformDatabaseNameFromOwnerUrl(input.databaseUrl);
|
|
1572
|
+
const hash = hyperdriveOriginConfigHash(config.origin);
|
|
1573
|
+
if (config.id !== expected.id || config.name !== expected.name || config.origin.host !== expected.host.toLowerCase() || config.origin.user !== expected.user || config.origin.database !== database || input.recordedHash && input.recordedHash !== hash) throw new Error("platform: The Terraform-managed Hyperdrive does not match the expected database origin.");
|
|
1574
|
+
if (config.cachingDisabled !== true) throw new Error("platform: Disable SQL result caching on the Terraform-managed Hyperdrive before installing.");
|
|
1575
|
+
return hash;
|
|
1576
|
+
}
|
|
1557
1577
|
/** Authentication requires fresh reads; mutate only the installation-owned configuration. */
|
|
1558
1578
|
async function verifyPlatformAuthenticationDatabase(client, accountId, resource, databaseUrl) {
|
|
1559
1579
|
if (resource.kind !== "hyperdrive" || resource.key !== "hyperdrive" || resource.state !== "ready") throw new Error("platform: Authentication database verification requires the platform Hyperdrive resource.");
|
|
1560
|
-
const
|
|
1580
|
+
const expectedDatabase = resource.ownership === "adopted" ? platformDatabaseNameFromOwnerUrl(databaseUrl) : void 0;
|
|
1581
|
+
const expectedOrigin = resource.ownership !== "adopted" ? hyperdriveOriginFromConnectionString(databaseUrl) : void 0;
|
|
1561
1582
|
const read = async () => {
|
|
1562
1583
|
const current = await client.getHyperdriveConfig(accountId, resource.id);
|
|
1563
|
-
if (current.id !== resource.id || current.name !== resource.name || !hyperdriveOriginMatches(current.origin,
|
|
1584
|
+
if (current.id !== resource.id || current.name !== resource.name || (resource.ownership === "adopted" ? current.origin.database !== expectedDatabase || hyperdriveOriginConfigHash(current.origin) !== resource.configHash : expectedOrigin === void 0 || !hyperdriveOriginMatches(current.origin, expectedOrigin))) throw new Error("platform: Hyperdrive does not match this installation’s pinned database. No authentication configuration was activated.");
|
|
1564
1585
|
return current;
|
|
1565
1586
|
};
|
|
1566
1587
|
if ((await read()).cachingDisabled === true) return;
|
|
@@ -1599,6 +1620,7 @@ async function createPlatformInstallPlan(client, input, existing, options) {
|
|
|
1599
1620
|
const enableEmail = options?.includeEmailGateway !== false && !!emailSharedZoneId && !!normalizedEmailSenderDomain;
|
|
1600
1621
|
const capabilities = {
|
|
1601
1622
|
...existing?.deployment.capabilities,
|
|
1623
|
+
...options?.enableSandbox ? { sandbox: true } : {},
|
|
1602
1624
|
...input.authentication ? {
|
|
1603
1625
|
githubOAuth: input.authentication.providers.includes("github"),
|
|
1604
1626
|
googleOAuth: input.authentication.providers.includes("google")
|
|
@@ -1629,13 +1651,20 @@ async function createPlatformInstallPlan(client, input, existing, options) {
|
|
|
1629
1651
|
});
|
|
1630
1652
|
const { emailSharedZoneId: configuredEmailZone, emailSenderDomain: configuredSenderDomain, ...deploymentWithoutEmailZone } = deployment;
|
|
1631
1653
|
const { emailSharedZoneId: recordedEmailZone, emailSenderDomain: recordedSenderDomain, ...existingWithoutEmailZone } = existing?.deployment ?? deployment;
|
|
1632
|
-
const
|
|
1654
|
+
const existingWithSandbox = existing && options?.enableSandbox ? {
|
|
1633
1655
|
...existingWithoutEmailZone,
|
|
1634
1656
|
capabilities: {
|
|
1635
1657
|
...existingWithoutEmailZone.capabilities,
|
|
1636
|
-
|
|
1658
|
+
sandbox: true
|
|
1637
1659
|
}
|
|
1638
1660
|
} : existingWithoutEmailZone;
|
|
1661
|
+
const comparableExistingWithoutEmailZone = existing && deployment.capabilities.email && !existing.deployment.capabilities.email ? {
|
|
1662
|
+
...existingWithSandbox,
|
|
1663
|
+
capabilities: {
|
|
1664
|
+
...existingWithSandbox.capabilities,
|
|
1665
|
+
email: true
|
|
1666
|
+
}
|
|
1667
|
+
} : existingWithSandbox;
|
|
1639
1668
|
if (existing && (JSON.stringify(comparableExistingWithoutEmailZone) !== JSON.stringify(deploymentWithoutEmailZone) || recordedEmailZone !== void 0 && recordedEmailZone !== configuredEmailZone || recordedSenderDomain !== void 0 && recordedSenderDomain !== configuredSenderDomain)) throw new Error(`platform: --resume inputs do not match installation ${existing.id}. Use its recorded configuration.`);
|
|
1640
1669
|
const names = deployment.resources;
|
|
1641
1670
|
const wildcardHostname = `*.${deployment.application.baseDomain}`;
|
|
@@ -1750,7 +1779,21 @@ async function createPlatformInstallPlan(client, input, existing, options) {
|
|
|
1750
1779
|
addNamedPlan(actions, existing, "usage-queue", "queue", names.usageQueue, usageQueues, "reuse", options, remoteOwnership);
|
|
1751
1780
|
addNamedPlan(actions, existing, "cron-queue", "queue", names.cronQueue, cronQueues, "reuse", options, remoteOwnership);
|
|
1752
1781
|
addNamedPlan(actions, existing, "dispatch-namespace", "dispatch-namespace", names.dispatchNamespace, dispatchNamespaces.filter((resource) => resource.name === names.dispatchNamespace), "reuse", options, remoteOwnership);
|
|
1753
|
-
|
|
1782
|
+
const recordedHyperdrive = existing?.resources.find((resource) => resource.key === "hyperdrive");
|
|
1783
|
+
const externalHyperdriveId = input.externalHyperdrive?.id || (recordedHyperdrive?.ownership === "adopted" ? recordedHyperdrive.id : "");
|
|
1784
|
+
if (externalHyperdriveId) {
|
|
1785
|
+
if (recordedHyperdrive && (recordedHyperdrive.ownership !== "adopted" || recordedHyperdrive.id !== externalHyperdriveId)) throw new Error("platform: The Terraform-managed Hyperdrive differs from this installation.");
|
|
1786
|
+
const remote = hyperdrives.find((resource) => resource.id === externalHyperdriveId);
|
|
1787
|
+
if (!remote || remote.name !== names.hyperdrive) throw new Error(`platform: Terraform-managed Hyperdrive ${JSON.stringify(externalHyperdriveId)} must exist with the name ${JSON.stringify(names.hyperdrive)}.`);
|
|
1788
|
+
actions.push({
|
|
1789
|
+
action: recordedHyperdrive ? "reuse" : "adopt",
|
|
1790
|
+
id: remote.id,
|
|
1791
|
+
key: "hyperdrive",
|
|
1792
|
+
kind: "hyperdrive",
|
|
1793
|
+
name: remote.name,
|
|
1794
|
+
reason: recordedHyperdrive ? "Reuse the recorded Terraform-managed Hyperdrive." : "Use the Terraform-managed Hyperdrive without taking ownership."
|
|
1795
|
+
});
|
|
1796
|
+
} else addNamedPlan(actions, existing, "hyperdrive", "hyperdrive", names.hyperdrive, hyperdrives.filter((resource) => resource.name === names.hyperdrive), "reuse", options, remoteOwnership);
|
|
1754
1797
|
for (const [key, name] of [
|
|
1755
1798
|
["api-worker", names.apiWorker],
|
|
1756
1799
|
["proxy-worker", names.proxyWorker],
|
|
@@ -1770,13 +1813,16 @@ async function createPlatformInstallPlan(client, input, existing, options) {
|
|
|
1770
1813
|
...deployment,
|
|
1771
1814
|
resources: resolvedResources
|
|
1772
1815
|
});
|
|
1816
|
+
const apiUrl = resolvedDeployment.controlPlane.apiHostname ? `https://${deployment.controlPlane.apiHostname}` : `https://${resolvedDeployment.resources.apiWorker}.${workersSubdomain}.workers.dev`;
|
|
1817
|
+
const proxyUrl = resolvedDeployment.controlPlane.proxyHostname ? `https://${deployment.controlPlane.proxyHostname}` : `https://${resolvedDeployment.resources.proxyWorker}.${workersSubdomain}.workers.dev`;
|
|
1773
1818
|
return {
|
|
1774
1819
|
account,
|
|
1775
1820
|
actions,
|
|
1776
|
-
apiUrl
|
|
1821
|
+
apiUrl,
|
|
1777
1822
|
deployment: resolvedDeployment,
|
|
1823
|
+
...input.externalHyperdrive ? { externalHyperdrive: input.externalHyperdrive } : {},
|
|
1778
1824
|
installationId,
|
|
1779
|
-
proxyUrl
|
|
1825
|
+
proxyUrl,
|
|
1780
1826
|
workersSubdomain,
|
|
1781
1827
|
zone
|
|
1782
1828
|
};
|
|
@@ -1789,11 +1835,13 @@ async function revalidatePlatformInstallAction(client, original, manifest, actio
|
|
|
1789
1835
|
controlPlaneDomain: deployment.controlPlane.apiHostname ?? "",
|
|
1790
1836
|
dedicatedZone: deployment.application.dedicatedZone,
|
|
1791
1837
|
displayName: deployment.displayName,
|
|
1838
|
+
...original.externalHyperdrive ? { externalHyperdrive: original.externalHyperdrive } : {},
|
|
1792
1839
|
installationSlug: deployment.installationSlug,
|
|
1793
1840
|
zoneName: deployment.application.zoneName
|
|
1794
1841
|
}, manifest, {
|
|
1795
1842
|
...options,
|
|
1796
|
-
includeEmailGateway: original.actions.some((entry) => entry.key === "email-gateway-worker")
|
|
1843
|
+
includeEmailGateway: original.actions.some((entry) => entry.key === "email-gateway-worker"),
|
|
1844
|
+
enableSandbox: original.deployment.capabilities.sandbox
|
|
1797
1845
|
})).actions.find((entry) => entry.key === action.key);
|
|
1798
1846
|
if (!current || current.kind !== action.kind || current.name !== action.name || current.action !== action.action) throw new Error(`platform: Cloudflare changed after the installation plan was approved for ${action.kind} ${JSON.stringify(action.name)}. Review a new plan before retrying.`);
|
|
1799
1847
|
if (action.kind === "worker" && action.action === "update") {
|
|
@@ -2405,6 +2453,25 @@ async function installPlatform(plan, secrets, existing, dependencies) {
|
|
|
2405
2453
|
if (plan.deployment.authentication.configurable && runtime.authenticationProtocolVersion !== 1) throw new Error("platform: This runtime does not support configurable authentication. Upgrade Void or use a compatible runtime.");
|
|
2406
2454
|
if (plan.deployment.application.workersDev && runtime.applicationRoutingVersion !== 1) throw new Error("platform: This runtime does not support workers.dev application routing. Use a current platform runtime.");
|
|
2407
2455
|
verifyRuntimeArtifacts(runtimeDirectory, runtime);
|
|
2456
|
+
const hyperdriveAction = plan.actions.find((action) => action.key === "hyperdrive");
|
|
2457
|
+
const recordedHyperdrive = existing?.resources.find((resource) => resource.key === "hyperdrive");
|
|
2458
|
+
let externalHyperdriveOriginHash;
|
|
2459
|
+
if (hyperdriveAction && (hyperdriveAction.action === "adopt" || recordedHyperdrive?.ownership === "adopted")) {
|
|
2460
|
+
if (!hyperdriveAction.id) throw new Error("platform: The Terraform-managed Hyperdrive has no ID.");
|
|
2461
|
+
if (!plan.externalHyperdrive && !recordedHyperdrive) throw new Error("platform: The Terraform-managed Hyperdrive origin must be specified.");
|
|
2462
|
+
const live = await dependencies.client.getHyperdriveConfig(plan.account.id, hyperdriveAction.id);
|
|
2463
|
+
externalHyperdriveOriginHash = verifyExternalPlatformHyperdrive({
|
|
2464
|
+
config: live,
|
|
2465
|
+
databaseUrl: secrets.databaseUrl,
|
|
2466
|
+
expected: {
|
|
2467
|
+
id: hyperdriveAction.id,
|
|
2468
|
+
name: hyperdriveAction.name,
|
|
2469
|
+
host: plan.externalHyperdrive?.host ?? live.origin.host,
|
|
2470
|
+
user: plan.externalHyperdrive?.user ?? live.origin.user ?? ""
|
|
2471
|
+
},
|
|
2472
|
+
...recordedHyperdrive ? { recordedHash: recordedHyperdrive.configHash } : {}
|
|
2473
|
+
});
|
|
2474
|
+
}
|
|
2408
2475
|
const runtimeProvenance = {
|
|
2409
2476
|
manifestSha256: resolvedRuntime.manifestSha256,
|
|
2410
2477
|
source: resolvedRuntime.source,
|
|
@@ -2692,14 +2759,14 @@ async function installPlatform(plan, secrets, existing, dependencies) {
|
|
|
2692
2759
|
manifest = recordAdoptionIntent(manifest, action, action.id, now());
|
|
2693
2760
|
writeInstallationManifest(manifest);
|
|
2694
2761
|
await writeRemoteInstallationCheckpoint(dependencies.client, plan, manifest);
|
|
2695
|
-
manifest = recordResource(manifest, action, action.id, "adopted", now(), secrets.databaseUrl);
|
|
2762
|
+
manifest = recordResource(manifest, action, action.id, "adopted", now(), secrets.databaseUrl, action.kind === "hyperdrive" ? externalHyperdriveOriginHash : void 0);
|
|
2696
2763
|
writeInstallationManifest(manifest);
|
|
2697
2764
|
await writeRemoteInstallationCheckpoint(dependencies.client, plan, manifest);
|
|
2698
2765
|
continue;
|
|
2699
2766
|
}
|
|
2700
2767
|
if (action.action === "reuse") {
|
|
2701
2768
|
if (action.id && (action.kind === "hyperdrive" || !manifest.resources.some((resource) => resource.key === action.key))) {
|
|
2702
|
-
manifest = recordResource(manifest, action, action.id, void 0, now(), secrets.databaseUrl);
|
|
2769
|
+
manifest = recordResource(manifest, action, action.id, void 0, now(), secrets.databaseUrl, action.kind === "hyperdrive" ? externalHyperdriveOriginHash : void 0);
|
|
2703
2770
|
writeInstallationManifest(manifest);
|
|
2704
2771
|
await writeR2OwnershipMarkerIfNeeded(dependencies.client, plan, manifest, action);
|
|
2705
2772
|
await writeRemoteInstallationCheckpoint(dependencies.client, plan, manifest);
|
|
@@ -2710,7 +2777,7 @@ async function installPlatform(plan, secrets, existing, dependencies) {
|
|
|
2710
2777
|
writeInstallationManifest(manifest);
|
|
2711
2778
|
await writeRemoteInstallationCheckpoint(dependencies.client, plan, manifest);
|
|
2712
2779
|
const resource = await createResource(dependencies.client, plan, action, secrets.databaseUrl, zoneId);
|
|
2713
|
-
manifest = recordResource(manifest, action, resource.id, "created", now(), secrets.databaseUrl, resource.fingerprint);
|
|
2780
|
+
manifest = recordResource(manifest, action, resource.id, "created", now(), secrets.databaseUrl, action.kind === "hyperdrive" ? externalHyperdriveOriginHash : resource.fingerprint);
|
|
2714
2781
|
writeInstallationManifest(manifest);
|
|
2715
2782
|
await writeR2OwnershipMarkerIfNeeded(dependencies.client, plan, manifest, action);
|
|
2716
2783
|
await writeRemoteInstallationCheckpoint(dependencies.client, plan, manifest);
|
|
@@ -2771,7 +2838,8 @@ async function installPlatform(plan, secrets, existing, dependencies) {
|
|
|
2771
2838
|
const targetSandboxDrainProtocol = runtime.safetyProtocols?.sandboxDrain ?? 0;
|
|
2772
2839
|
const prepareSandboxDrain = dependencies.prepareSandboxDrain ?? releaseDatabaseLock.prepareSandboxDrain;
|
|
2773
2840
|
if (targetSandboxDrainProtocol >= 1 && !prepareSandboxDrain) throw new Error("platform: The PostgreSQL lifecycle lock cannot establish the sandbox-drain safety checkpoint.");
|
|
2774
|
-
const sandboxDrainPreparation = targetSandboxDrainProtocol >= 1 ? await prepareSandboxDrain(targetSandboxDrainProtocol >= 2 ? 2 : 0) : null;
|
|
2841
|
+
const sandboxDrainPreparation = targetSandboxDrainProtocol >= 1 ? await prepareSandboxDrain(targetSandboxDrainProtocol >= 3 ? 3 : targetSandboxDrainProtocol >= 2 ? 2 : 0) : null;
|
|
2842
|
+
if (sandboxDrainPreparation && sandboxDrainPreparation.admissionProtocol < targetSandboxDrainProtocol) throw new Error("platform: The database did not arm the Sandbox admission protocol required by this runtime.");
|
|
2775
2843
|
const sandboxDrainRoutingKvId = requireId(Object.fromEntries(manifest.resources.map((resource) => [resource.key, resource.id])), "routing-kv");
|
|
2776
2844
|
const writeSandboxDrainMirror = async (preparation) => {
|
|
2777
2845
|
await dependencies.client.putKvValue(plan.account.id, sandboxDrainRoutingKvId, PLATFORM_SANDBOX_DRAIN_KEY, preparation.mirrorValue);
|
|
@@ -2848,7 +2916,8 @@ async function installPlatform(plan, secrets, existing, dependencies) {
|
|
|
2848
2916
|
routingKv: requireId(ids, "routing-kv"),
|
|
2849
2917
|
zone: zoneId
|
|
2850
2918
|
},
|
|
2851
|
-
runtimeEntrypoints: entrypoints
|
|
2919
|
+
runtimeEntrypoints: entrypoints,
|
|
2920
|
+
...runtime.assets ? { runtimeApiAssetsDirectory: join(runtimeDirectory, PLATFORM_ADMIN_ASSETS_DIRECTORY) } : {}
|
|
2852
2921
|
};
|
|
2853
2922
|
const requiresStagedCommit = !preserveDisabled && requiresTrafficGuard;
|
|
2854
2923
|
const enabledConfigs = createPlatformWorkerConfigs({
|
|
@@ -3074,7 +3143,7 @@ async function installPlatform(plan, secrets, existing, dependencies) {
|
|
|
3074
3143
|
await writeRemoteInstallationCheckpoint(dependencies.client, plan, manifest);
|
|
3075
3144
|
}
|
|
3076
3145
|
dependencies.onProgress?.("Verifying platform health");
|
|
3077
|
-
const emailGatewayUrl = hasEmailGatewayArtifact ? `https://${plan.deployment.resources.emailGatewayWorker}.${plan.workersSubdomain}.workers.dev` : void 0;
|
|
3146
|
+
const emailGatewayUrl = hasEmailGatewayArtifact && plan.deployment.capabilities.email ? `https://${plan.deployment.resources.emailGatewayWorker}.${plan.workersSubdomain}.workers.dev` : void 0;
|
|
3078
3147
|
if (plan.deployment.authentication.accessProtection) {
|
|
3079
3148
|
ensurePlatformAccessToken(plan.apiUrl, false, true);
|
|
3080
3149
|
ensurePlatformAccessToken(plan.proxyUrl, false, true);
|
|
@@ -3084,7 +3153,7 @@ async function installPlatform(plan, secrets, existing, dependencies) {
|
|
|
3084
3153
|
workers: [
|
|
3085
3154
|
plan.deployment.resources.apiWorker,
|
|
3086
3155
|
plan.deployment.resources.proxyWorker,
|
|
3087
|
-
...
|
|
3156
|
+
...emailGatewayUrl ? [plan.deployment.resources.emailGatewayWorker] : [],
|
|
3088
3157
|
plan.deployment.resources.dispatchWorker
|
|
3089
3158
|
],
|
|
3090
3159
|
resumeCommand: dependencies.healthCheckResumeCommand,
|
|
@@ -3343,7 +3412,7 @@ async function createResource(client, plan, action, databaseUrl, zoneId) {
|
|
|
3343
3412
|
function recordResource(manifest, action, id, ownership, now, databaseUrl, resourceFingerprint) {
|
|
3344
3413
|
const previous = manifest.resources.find((resource) => resource.key === action.key);
|
|
3345
3414
|
return recordInstallationResource(manifest, {
|
|
3346
|
-
configHash: action.kind === "dns-record" ? dnsRecordConfigHash(action.name, "AAAA", "100::", true) : action.kind === "hyperdrive" && databaseUrl ? hyperdriveOriginConfigHash(hyperdriveOriginFromConnectionString(databaseUrl)) : action.kind === "r2-bucket" && resourceFingerprint ? r2BucketConfigHash(action.name, resourceFingerprint) : hash(JSON.stringify({
|
|
3415
|
+
configHash: action.kind === "dns-record" ? dnsRecordConfigHash(action.name, "AAAA", "100::", true) : action.kind === "hyperdrive" && resourceFingerprint ? resourceFingerprint : action.kind === "hyperdrive" && databaseUrl ? hyperdriveOriginConfigHash(hyperdriveOriginFromConnectionString(databaseUrl)) : action.kind === "r2-bucket" && resourceFingerprint ? r2BucketConfigHash(action.name, resourceFingerprint) : hash(JSON.stringify({
|
|
3347
3416
|
kind: action.kind,
|
|
3348
3417
|
name: action.name
|
|
3349
3418
|
})),
|
|
@@ -3583,7 +3652,7 @@ function assertRequiredPlatformSecrets(plan, manifest, secrets, authenticationWi
|
|
|
3583
3652
|
const requireSecret = (value, name) => {
|
|
3584
3653
|
if (!value) missing.add(name);
|
|
3585
3654
|
};
|
|
3586
|
-
if (plan.deployment.authentication.configurable && !manifest.steps.some((step) => step.key.startsWith("authentication-initialized:v1:"))) {
|
|
3655
|
+
if (plan.deployment.authentication.configurable && !manifest.steps.some((step) => step.key.startsWith("authentication-initialized:v1:")) && !(manifest.deployment.authentication.configurable && manifest.steps.some((step) => step.key === "bootstrap-access:v1"))) {
|
|
3587
3656
|
if (!authenticationWillBePrepared) requireSecret(secrets.authenticationSetupJson ?? "", "authentication setup configuration");
|
|
3588
3657
|
requireSecret(secrets.authSetupToken ?? "", "installation authentication setup authority");
|
|
3589
3658
|
requireSecret(secrets.authBootstrapCode ?? "", "administrator setup code");
|
|
@@ -3836,14 +3905,14 @@ async function preparePlatformSandboxDrainConnection(client, requiredAdmissionPr
|
|
|
3836
3905
|
AND table_name = 'sandbox_drain_checkpoints'
|
|
3837
3906
|
AND column_name = 'admission_protocol'
|
|
3838
3907
|
) AS "present"`)).rows[0]?.present === true;
|
|
3839
|
-
if (requiredAdmissionProtocol
|
|
3908
|
+
if (requiredAdmissionProtocol >= 2 && !hasAdmissionColumn) throw new Error("platform: The runtime database does not include the sandbox deployment admission barrier.");
|
|
3840
3909
|
const readCheckpoint = () => client.query(`SELECT ${hasAdmissionColumn ? "\"admission_protocol\"" : "0 AS \"admission_protocol\""}, "generation", "state", "phase", "cursor", "started_at", "updated_at", "completed_at"
|
|
3841
3910
|
FROM "sandbox_drain_checkpoints"
|
|
3842
3911
|
WHERE "singleton" = true`);
|
|
3843
3912
|
const classify = (row) => {
|
|
3844
3913
|
if (!row) return null;
|
|
3845
3914
|
const cursor = row.cursor;
|
|
3846
|
-
if (!row.generation || row.admission_protocol !== 0 && row.admission_protocol !== 2 || !row.started_at || !row.updated_at || row.state !== "draining" && row.state !== "complete" || row.phase !== "deployments" && row.phase !== "resources" || !cursor || cursor.pass !== "1" && cursor.pass !== "2" || row.state === "complete" && (!row.completed_at || row.phase !== "resources" || cursor.pass !== "2") || row.state === "draining" && row.completed_at !== null) throw new Error("platform: The authoritative sandbox-drain database checkpoint is invalid. Traffic remains disabled.");
|
|
3915
|
+
if (!row.generation || row.admission_protocol !== 0 && row.admission_protocol !== 2 && row.admission_protocol !== 3 || !row.started_at || !row.updated_at || row.state !== "draining" && row.state !== "complete" || row.phase !== "deployments" && row.phase !== "resources" || !cursor || cursor.pass !== "1" && cursor.pass !== "2" || row.state === "complete" && (!row.completed_at || row.phase !== "resources" || cursor.pass !== "2") || row.state === "draining" && row.completed_at !== null) throw new Error("platform: The authoritative sandbox-drain database checkpoint is invalid. Traffic remains disabled.");
|
|
3847
3916
|
return {
|
|
3848
3917
|
admissionProtocol: row.admission_protocol,
|
|
3849
3918
|
generation: row.generation,
|
|
@@ -3860,7 +3929,23 @@ async function preparePlatformSandboxDrainConnection(client, requiredAdmissionPr
|
|
|
3860
3929
|
};
|
|
3861
3930
|
const existingState = classify((await readCheckpoint()).rows[0]);
|
|
3862
3931
|
if (existingState && (requiredAdmissionProtocol === 0 || existingState.admissionProtocol >= requiredAdmissionProtocol)) return existingState;
|
|
3863
|
-
if (requiredAdmissionProtocol
|
|
3932
|
+
if (requiredAdmissionProtocol >= 2) {
|
|
3933
|
+
if (existingState && existingState.admissionProtocol >= 2) {
|
|
3934
|
+
await client.query("BEGIN");
|
|
3935
|
+
try {
|
|
3936
|
+
await client.query("LOCK TABLE \"deployments\" IN SHARE MODE");
|
|
3937
|
+
await client.query(`UPDATE "sandbox_drain_checkpoints"
|
|
3938
|
+
SET "admission_protocol" = GREATEST("admission_protocol", $1), "updated_at" = now()
|
|
3939
|
+
WHERE "singleton" = true`, [requiredAdmissionProtocol]);
|
|
3940
|
+
const advanced = classify((await readCheckpoint()).rows[0]);
|
|
3941
|
+
if (!advanced || advanced.admissionProtocol < requiredAdmissionProtocol) throw new Error("platform: The Sandbox controller admission barrier could not be armed.");
|
|
3942
|
+
await client.query("COMMIT");
|
|
3943
|
+
return advanced;
|
|
3944
|
+
} catch (error) {
|
|
3945
|
+
await client.query("ROLLBACK").catch(() => void 0);
|
|
3946
|
+
throw error;
|
|
3947
|
+
}
|
|
3948
|
+
}
|
|
3864
3949
|
const generation = randomUUID();
|
|
3865
3950
|
await client.query("BEGIN");
|
|
3866
3951
|
try {
|
|
@@ -3893,8 +3978,10 @@ async function preparePlatformSandboxDrainConnection(client, requiredAdmissionPr
|
|
|
3893
3978
|
WHERE "singleton" = true
|
|
3894
3979
|
AND "admission_protocol" = 2
|
|
3895
3980
|
AND "generation" = $1`, [generation]);
|
|
3981
|
+
if (requiredAdmissionProtocol >= 3) await client.query(`UPDATE "sandbox_drain_checkpoints" SET "admission_protocol" = $1
|
|
3982
|
+
WHERE "singleton" = true`, [requiredAdmissionProtocol]);
|
|
3896
3983
|
const armed = classify((await readCheckpoint()).rows[0]);
|
|
3897
|
-
if (!armed || armed.admissionProtocol
|
|
3984
|
+
if (!armed || armed.admissionProtocol < requiredAdmissionProtocol) throw new Error("platform: The sandbox deployment admission barrier could not be armed.");
|
|
3898
3985
|
await client.query("COMMIT");
|
|
3899
3986
|
return armed;
|
|
3900
3987
|
} catch (error) {
|
|
@@ -3937,12 +4024,17 @@ async function readRequiredPlatformSafetyProtocols(client) {
|
|
|
3937
4024
|
AND table_name = 'sandbox_drain_checkpoints'
|
|
3938
4025
|
AND column_name = 'admission_protocol'
|
|
3939
4026
|
) AS "present"`)).rows[0]?.present === true) {
|
|
3940
|
-
|
|
4027
|
+
const admission = await client.query(`SELECT EXISTS(
|
|
3941
4028
|
SELECT 1
|
|
3942
4029
|
FROM "sandbox_drain_checkpoints"
|
|
3943
4030
|
WHERE "singleton" = true
|
|
3944
4031
|
AND "admission_protocol" >= 2
|
|
3945
|
-
) AS "required"
|
|
4032
|
+
) AS "required", (SELECT "admission_protocol" FROM "sandbox_drain_checkpoints"
|
|
4033
|
+
WHERE "singleton" = true) AS "protocol"`);
|
|
4034
|
+
if (admission.rows[0]?.required === true) {
|
|
4035
|
+
if (admission.rows[0].protocol != null && admission.rows[0].protocol > 3) throw new Error("platform: The database requires a newer Sandbox controller protocol.");
|
|
4036
|
+
return { sandboxDrain: admission.rows[0].protocol === 3 ? 3 : 2 };
|
|
4037
|
+
}
|
|
3946
4038
|
}
|
|
3947
4039
|
return { sandboxDrain: (await client.query(`SELECT EXISTS(
|
|
3948
4040
|
SELECT 1
|
|
@@ -4598,15 +4690,15 @@ function readTriggerConfigFromObject(config) {
|
|
|
4598
4690
|
}
|
|
4599
4691
|
}
|
|
4600
4692
|
function verifyRuntimeArtifacts(runtimeDirectory, manifest) {
|
|
4601
|
-
for (const artifact of Object.values(manifest.artifacts)) {
|
|
4693
|
+
for (const artifact of [...Object.values(manifest.artifacts), ...manifest.assets ? [manifest.assets.adminClient, ...manifest.assets.adminStyle ? [manifest.assets.adminStyle] : []] : []]) {
|
|
4602
4694
|
const path = join(runtimeDirectory, artifact.path);
|
|
4603
4695
|
let contents;
|
|
4604
4696
|
try {
|
|
4605
4697
|
contents = readFileSync(path);
|
|
4606
4698
|
} catch (error) {
|
|
4607
|
-
throw new Error(`platform: Runtime
|
|
4699
|
+
throw new Error(`platform: Runtime artifact is missing: ${errorMessage(error)}`);
|
|
4608
4700
|
}
|
|
4609
|
-
if (contents.byteLength !== artifact.size || hash(contents) !== artifact.sha256) throw new Error(`platform: Runtime
|
|
4701
|
+
if (contents.byteLength !== artifact.size || hash(contents) !== artifact.sha256) throw new Error(`platform: Runtime artifact failed integrity verification: ${path}.`);
|
|
4610
4702
|
}
|
|
4611
4703
|
verifyPlatformDatabaseArtifacts(runtimeDirectory, manifest.database);
|
|
4612
4704
|
}
|
|
@@ -4817,7 +4909,7 @@ var PlatformAccessBlockedError = class extends Error {
|
|
|
4817
4909
|
"Void’s own authentication stays enabled. Keep account-wide Default-Deny on.",
|
|
4818
4910
|
"",
|
|
4819
4911
|
"For platforms that must remain Access-protected:",
|
|
4820
|
-
"https://void.cloud/guide/
|
|
4912
|
+
"https://void.cloud/guide/platform/installation/maintenance#cloudflare-access"
|
|
4821
4913
|
].join("\n"));
|
|
4822
4914
|
}
|
|
4823
4915
|
};
|
|
@@ -5199,9 +5291,9 @@ function platformSetupLink(page, hyperlinks = supportsSetupLinks()) {
|
|
|
5199
5291
|
return hyperlinks ? "\x1B]8;;" + page.url + "\x1B\\" + page.title + "\x1B]8;;\x1B\\" : page.title + ": " + page.url;
|
|
5200
5292
|
}
|
|
5201
5293
|
function platformSetupFieldHelp(key) {
|
|
5202
|
-
const docs = (section, title) => platformSetupLink({
|
|
5294
|
+
const docs = (page, section, title) => platformSetupLink({
|
|
5203
5295
|
title,
|
|
5204
|
-
url:
|
|
5296
|
+
url: `https://void.cloud/guide/platform/installation/${page}#${section}`
|
|
5205
5297
|
});
|
|
5206
5298
|
switch (key) {
|
|
5207
5299
|
case "databaseUrl": return {
|
|
@@ -5209,10 +5301,10 @@ function platformSetupFieldHelp(key) {
|
|
|
5209
5301
|
description: "Stores platform users, projects, and deployments; use an empty hosted database, e.g. " + platformSetupLink({
|
|
5210
5302
|
title: "Neon",
|
|
5211
5303
|
url: "https://neon.com/"
|
|
5212
|
-
}) + ". " + docs("platform-database", "Database setup")
|
|
5304
|
+
}) + ". " + docs("prerequisites", "platform-database", "Database setup")
|
|
5213
5305
|
};
|
|
5214
|
-
case "jwtSecret": return { description: "Signs platform login tokens. Run openssl rand -base64 32; save the key in your password manager. " + docs("signing-and-encryption-keys", "Key setup") };
|
|
5215
|
-
case "projectSecretKey": return { description: "Encrypts app secrets. Run openssl rand -base64 32 separately; save this key for recovery. " + docs("signing-and-encryption-keys", "Key setup") };
|
|
5306
|
+
case "jwtSecret": return { description: "Signs platform login tokens. Run openssl rand -base64 32; save the key in your password manager. " + docs("credentials", "signing-and-encryption-keys", "Key setup") };
|
|
5307
|
+
case "projectSecretKey": return { description: "Encrypts app secrets. Run openssl rand -base64 32 separately; save this key for recovery. " + docs("credentials", "signing-and-encryption-keys", "Key setup") };
|
|
5216
5308
|
default: return;
|
|
5217
5309
|
}
|
|
5218
5310
|
}
|
|
@@ -5352,6 +5444,39 @@ function formatPlatformSetupPlan(plan) {
|
|
|
5352
5444
|
...plan.deployment.authentication.accessProtection ? ["Cloudflare Access protection: configure API and proxy origins and admitted installer/CI credentials."] : []
|
|
5353
5445
|
].join("\n");
|
|
5354
5446
|
}
|
|
5447
|
+
function formatPlatformInstallCommand(options) {
|
|
5448
|
+
const quote = (value) => {
|
|
5449
|
+
if (/^[A-Za-z0-9_@%+=:,./-]+$/.test(value)) return value;
|
|
5450
|
+
return process.platform === "win32" ? `'${value.replaceAll("'", "''")}'` : `'${value.replaceAll("'", "'\\''")}'`;
|
|
5451
|
+
};
|
|
5452
|
+
const parts = [
|
|
5453
|
+
options.commandName,
|
|
5454
|
+
"platform",
|
|
5455
|
+
"install"
|
|
5456
|
+
];
|
|
5457
|
+
const flag = (name, value) => {
|
|
5458
|
+
if (value) parts.push(name, quote(value));
|
|
5459
|
+
};
|
|
5460
|
+
if (options.resumeId) {
|
|
5461
|
+
parts.push("--resume");
|
|
5462
|
+
flag("--name", options.resumeId);
|
|
5463
|
+
} else {
|
|
5464
|
+
flag("--name", options.installationSlug);
|
|
5465
|
+
flag("--account", options.accountId);
|
|
5466
|
+
flag("--display-name", options.displayName);
|
|
5467
|
+
if (options.workersDev) parts.push("--workers-dev");
|
|
5468
|
+
else {
|
|
5469
|
+
flag("--application-domain", options.applicationDomain);
|
|
5470
|
+
flag("--zone", options.zoneName);
|
|
5471
|
+
if (options.dedicatedZone) parts.push("--dedicated-zone");
|
|
5472
|
+
}
|
|
5473
|
+
flag("--control-plane-domain", options.controlPlaneDomain);
|
|
5474
|
+
}
|
|
5475
|
+
flag("--auth-config", options.authConfig ?? "");
|
|
5476
|
+
flag("--runtime", options.runtime);
|
|
5477
|
+
if (options.yes) parts.push("--yes");
|
|
5478
|
+
return parts.join(" ");
|
|
5479
|
+
}
|
|
5355
5480
|
function openPlatformSetupPage(page, dependencies = {}) {
|
|
5356
5481
|
log.info(page.title + "\n" + page.instructions);
|
|
5357
5482
|
console.log(platformSetupLink({
|
|
@@ -5407,14 +5532,14 @@ function resolvePlatformInstallDatabaseUrl(checkpoint, manifest = null) {
|
|
|
5407
5532
|
}
|
|
5408
5533
|
async function runPlatformLifecycleCommand(args) {
|
|
5409
5534
|
if (args.subcommand === "domain") {
|
|
5410
|
-
const { runPlatformDomainCommand } = await import("./platform-domain-
|
|
5535
|
+
const { runPlatformDomainCommand } = await import("./platform-domain-IjiXgrXJ.mjs");
|
|
5411
5536
|
await runPlatformDomainCommand(args);
|
|
5412
5537
|
return;
|
|
5413
5538
|
}
|
|
5414
5539
|
if (args.subcommand === "discover") {
|
|
5415
5540
|
const client = new PlatformCloudflareClient((await resolvePlatformCloudflareCredential()).token);
|
|
5416
5541
|
const accountId = await selectAccount(await readAccounts(client), args.account);
|
|
5417
|
-
const { recoverPlatformInstallations } = await import("./platform-recovery-
|
|
5542
|
+
const { recoverPlatformInstallations } = await import("./platform-recovery-DS8ih1SW.mjs");
|
|
5418
5543
|
const recovered = await recoverPlatformInstallations(client, accountId, void 0, args.selector);
|
|
5419
5544
|
if (recovered.length === 0) {
|
|
5420
5545
|
log.info(`No recoverable Void platform installations were found in ${accountId}.`);
|
|
@@ -5424,7 +5549,7 @@ async function runPlatformLifecycleCommand(args) {
|
|
|
5424
5549
|
return;
|
|
5425
5550
|
}
|
|
5426
5551
|
if (args.subcommand !== "install") {
|
|
5427
|
-
const { runInstalledPlatformCommand } = await import("./platform-management-
|
|
5552
|
+
const { runInstalledPlatformCommand } = await import("./platform-management-Cgyed0WY.mjs");
|
|
5428
5553
|
await runInstalledPlatformCommand(args);
|
|
5429
5554
|
return;
|
|
5430
5555
|
}
|
|
@@ -5566,6 +5691,68 @@ async function runPlatformLifecycleCommand(args) {
|
|
|
5566
5691
|
}
|
|
5567
5692
|
const checkpoint = existing ? readPendingInstallationSecrets(existing) : null;
|
|
5568
5693
|
const databaseUrl = resolvePlatformInstallDatabaseUrl(checkpoint, existing);
|
|
5694
|
+
const externalHyperdriveId = process.env.VOID_PLATFORM_HYPERDRIVE_ID?.trim() || "";
|
|
5695
|
+
const externalHyperdriveHost = process.env.VOID_PLATFORM_HYPERDRIVE_ORIGIN_HOST?.trim() || "";
|
|
5696
|
+
const externalHyperdriveUser = process.env.VOID_PLATFORM_HYPERDRIVE_ORIGIN_USER?.trim() || "";
|
|
5697
|
+
if ([
|
|
5698
|
+
externalHyperdriveId,
|
|
5699
|
+
externalHyperdriveHost,
|
|
5700
|
+
externalHyperdriveUser
|
|
5701
|
+
].some(Boolean) && ![
|
|
5702
|
+
externalHyperdriveId,
|
|
5703
|
+
externalHyperdriveHost,
|
|
5704
|
+
externalHyperdriveUser
|
|
5705
|
+
].every(Boolean)) throw new Error("platform: VOID_PLATFORM_HYPERDRIVE_ID, VOID_PLATFORM_HYPERDRIVE_ORIGIN_HOST, and VOID_PLATFORM_HYPERDRIVE_ORIGIN_USER must be set together.");
|
|
5706
|
+
let externalHyperdrive = externalHyperdriveId ? {
|
|
5707
|
+
id: externalHyperdriveId,
|
|
5708
|
+
host: externalHyperdriveHost,
|
|
5709
|
+
user: externalHyperdriveUser
|
|
5710
|
+
} : void 0;
|
|
5711
|
+
if (!externalHyperdrive && process.stdin.isTTY && (!existing || isPlatformSetupDraft(existing)) && !existing?.resources.some((resource) => resource.key === "hyperdrive")) {
|
|
5712
|
+
const expectedName = existing?.deployment.resources.hyperdrive ?? createPlatformResourceNames(installationSlug).hyperdrive;
|
|
5713
|
+
const matches = (await client.listHyperdriveConfigs(accountId)).filter((resource) => resource.name === expectedName);
|
|
5714
|
+
if (matches.length > 1) throw new Error(`platform: More than one Hyperdrive named ${expectedName} exists.`);
|
|
5715
|
+
const live = matches[0] ? await client.getHyperdriveConfig(accountId, matches[0].id) : null;
|
|
5716
|
+
if (live) {
|
|
5717
|
+
if (live.id !== matches[0].id || live.name !== expectedName || !live.origin.user) throw new Error(`platform: Could not verify the database user for existing Hyperdrive ${expectedName}.`);
|
|
5718
|
+
note(`Database: ${live.origin.database}\nHost: ${live.origin.host}\nPort: ${live.origin.port}\nUser: ${live.origin.user}\nSQL result caching: ${live.cachingDisabled ? "disabled" : "enabled"}`, `Existing Hyperdrive ${expectedName}`);
|
|
5719
|
+
const choice = await select({
|
|
5720
|
+
message: "How should Void set up Hyperdrive?",
|
|
5721
|
+
options: [{
|
|
5722
|
+
value: "existing",
|
|
5723
|
+
label: `Use existing Hyperdrive ${expectedName}`
|
|
5724
|
+
}, {
|
|
5725
|
+
value: "cancel",
|
|
5726
|
+
label: "Cancel installation"
|
|
5727
|
+
}]
|
|
5728
|
+
});
|
|
5729
|
+
if (isCancel(choice) || choice === "cancel") throw new Error("platform: Cancelled.");
|
|
5730
|
+
if (!live.cachingDisabled) throw new Error(`platform: Disable SQL result caching on existing Hyperdrive ${expectedName} before installing.`);
|
|
5731
|
+
externalHyperdrive = {
|
|
5732
|
+
id: live.id,
|
|
5733
|
+
host: live.origin.host,
|
|
5734
|
+
user: live.origin.user
|
|
5735
|
+
};
|
|
5736
|
+
} else {
|
|
5737
|
+
const choice = await select({
|
|
5738
|
+
message: "How should Void set up Hyperdrive?",
|
|
5739
|
+
options: [{
|
|
5740
|
+
value: "create",
|
|
5741
|
+
label: "Let Void create Hyperdrive",
|
|
5742
|
+
hint: "recommended"
|
|
5743
|
+
}, {
|
|
5744
|
+
value: "existing",
|
|
5745
|
+
label: "Use a separately managed Hyperdrive"
|
|
5746
|
+
}]
|
|
5747
|
+
});
|
|
5748
|
+
if (isCancel(choice)) throw new Error("platform: Cancelled.");
|
|
5749
|
+
if (choice === "existing") {
|
|
5750
|
+
note(`Create a Hyperdrive in account ${accountId} named ${expectedName}. Point it at the same dedicated PostgreSQL database you will give Void, use a runtime database user, and disable SQL result caching. If your organization manages Hyperdrive, ask its administrator to create it. Then rerun this command.\nSetup: https://developers.cloudflare.com/hyperdrive/get-started/`, "Set up Hyperdrive first");
|
|
5751
|
+
outro("No Cloudflare or local installation state was changed.");
|
|
5752
|
+
return;
|
|
5753
|
+
}
|
|
5754
|
+
}
|
|
5755
|
+
}
|
|
5569
5756
|
let authoritativeProvisionIntents = false;
|
|
5570
5757
|
if (existing && !isPlatformSetupDraft(existing)) {
|
|
5571
5758
|
if (!databaseUrl) throw new Error("platform: DATABASE_URL is required to verify an interrupted installation before resuming it.");
|
|
@@ -5574,7 +5761,7 @@ async function runPlatformLifecycleCommand(args) {
|
|
|
5574
5761
|
progress?.stop("Read the saved installation.");
|
|
5575
5762
|
progress = void 0;
|
|
5576
5763
|
if (authoritative) {
|
|
5577
|
-
const { selectAuthoritativePlatformManifest } = await import("./platform-management-
|
|
5764
|
+
const { selectAuthoritativePlatformManifest } = await import("./platform-management-Cgyed0WY.mjs");
|
|
5578
5765
|
const selected = selectAuthoritativePlatformManifest(existing, authoritative);
|
|
5579
5766
|
authoritativeProvisionIntents = true;
|
|
5580
5767
|
if (!args.plan && JSON.stringify(selected) !== JSON.stringify(existing)) writeInstallationManifest(selected);
|
|
@@ -5590,6 +5777,7 @@ async function runPlatformLifecycleCommand(args) {
|
|
|
5590
5777
|
controlPlaneDomain,
|
|
5591
5778
|
dedicatedZone,
|
|
5592
5779
|
displayName,
|
|
5780
|
+
...externalHyperdrive ? { externalHyperdrive } : {},
|
|
5593
5781
|
...process.env.VOID_EMAIL_SHARED_ZONE_ID ? { emailSharedZoneId: process.env.VOID_EMAIL_SHARED_ZONE_ID } : {},
|
|
5594
5782
|
...process.env.VOID_EMAIL_SENDER_DOMAIN ? { emailSenderDomain: process.env.VOID_EMAIL_SENDER_DOMAIN } : {},
|
|
5595
5783
|
installationSlug,
|
|
@@ -5599,12 +5787,29 @@ async function runPlatformLifecycleCommand(args) {
|
|
|
5599
5787
|
let plan = await createPlatformInstallPlan(client, planInput, existing, {
|
|
5600
5788
|
authoritativeProvisionIntents,
|
|
5601
5789
|
allowUnverifiedAiGateway: true,
|
|
5602
|
-
includeEmailGateway: runtime.manifest.artifacts.emailGateway !== void 0
|
|
5790
|
+
includeEmailGateway: runtime.manifest.artifacts.emailGateway !== void 0,
|
|
5791
|
+
enableSandbox: runtime.manifest.safetyProtocols.sandboxDrain >= 3
|
|
5603
5792
|
});
|
|
5604
5793
|
note(formatPlatformInstallPlan(plan), args.plan ? "Read-only installation plan" : "Installation plan");
|
|
5605
5794
|
note(formatPlatformRuntime(runtime), "Platform runtime");
|
|
5606
5795
|
if (args.plan) {
|
|
5607
5796
|
console.log(formatPlatformSetupPlan(plan));
|
|
5797
|
+
console.log(`\n${existing ? "To resume this installation later:" : "To install with these settings later:"}\n${formatPlatformInstallCommand({
|
|
5798
|
+
commandName: cliCommandName(),
|
|
5799
|
+
accountId,
|
|
5800
|
+
installationSlug,
|
|
5801
|
+
displayName,
|
|
5802
|
+
applicationDomain,
|
|
5803
|
+
zoneName,
|
|
5804
|
+
controlPlaneDomain,
|
|
5805
|
+
dedicatedZone,
|
|
5806
|
+
workersDev,
|
|
5807
|
+
authConfig: args.authConfig,
|
|
5808
|
+
runtime: args.runtime,
|
|
5809
|
+
...existing ? { resumeId: existing.id } : {},
|
|
5810
|
+
yes: args.yes || process.stdin.isTTY !== true
|
|
5811
|
+
})}\n`);
|
|
5812
|
+
if (!existing && !args.authConfig && process.stdin.isTTY) console.log("Choose the same login methods when prompted.\n");
|
|
5608
5813
|
outro("No Cloudflare or local installation state was changed.");
|
|
5609
5814
|
return;
|
|
5610
5815
|
}
|
|
@@ -5780,11 +5985,12 @@ async function runPlatformLifecycleCommand(args) {
|
|
|
5780
5985
|
replanWorkers: async (manifest) => (await createPlatformInstallPlan(client, planInput, manifest, {
|
|
5781
5986
|
authoritativeProvisionIntents: true,
|
|
5782
5987
|
repairMissing: true,
|
|
5783
|
-
includeEmailGateway: runtime.manifest.artifacts.emailGateway !== void 0
|
|
5988
|
+
includeEmailGateway: runtime.manifest.artifacts.emailGateway !== void 0,
|
|
5989
|
+
enableSandbox: runtime.manifest.safetyProtocols.sandboxDrain >= 3
|
|
5784
5990
|
})).actions.filter((action) => action.kind === "worker"),
|
|
5785
5991
|
revalidateBeforeWorkerDeploy: (manifest, action) => revalidatePlatformInstallAction(client, plan, manifest, action),
|
|
5786
5992
|
verifyExistingOwnership: async (manifest, databaseCheckpointExists) => {
|
|
5787
|
-
const { verifyPlatformInstallationOwnership } = await import("./platform-management-
|
|
5993
|
+
const { verifyPlatformInstallationOwnership } = await import("./platform-management-Cgyed0WY.mjs");
|
|
5788
5994
|
const retainedReplacementKeys = new Set(plan.actions.filter((action) => {
|
|
5789
5995
|
const previous = manifest.resources.find((resource) => resource.key === action.key);
|
|
5790
5996
|
return action.action === "create" && previous && previous.name !== action.name;
|
|
@@ -5849,7 +6055,8 @@ async function verifyPlatformAiGatewayPlan(client, input, existing, preview, aut
|
|
|
5849
6055
|
try {
|
|
5850
6056
|
verified = await createPlatformInstallPlan(client, input, existing, {
|
|
5851
6057
|
authoritativeProvisionIntents,
|
|
5852
|
-
includeEmailGateway: preview.actions.some((entry) => entry.key === "email-gateway-worker")
|
|
6058
|
+
includeEmailGateway: preview.actions.some((entry) => entry.key === "email-gateway-worker"),
|
|
6059
|
+
enableSandbox: preview.deployment.capabilities.sandbox
|
|
5853
6060
|
});
|
|
5854
6061
|
} catch (error) {
|
|
5855
6062
|
if (error instanceof PlatformCloudflareApiError && (error.status === 401 || error.status === 403) && error.requestPath?.includes("/ai-gateway/")) throw new Error("platform: The runtime token could not verify AI Gateway access. Include Account → AI Gateway → Edit for this account, then retry. No platform resources were created.", { cause: error });
|
|
@@ -5923,4 +6130,4 @@ async function promptSecret(message, masked = true, validate, placeholder) {
|
|
|
5923
6130
|
return value;
|
|
5924
6131
|
}
|
|
5925
6132
|
//#endregion
|
|
5926
|
-
export {
|
|
6133
|
+
export { hyperdriveOriginFromConnectionString as A, assertPlatformOperatorCredentialCanApplyPlan as C, preparePlatformAccessSetup as D, parsePlatformAccessSetupSpec as E, verifyPlatformRuntimeTokenPermissions as M, PlatformCloudflareClient as O, platformDatabaseNameFromOwnerUrl as S, checkpointPlatformAccessResources as T, createPlatformInstallPlan as _, REMOTE_INSTALLATION_MANIFEST_KEY as a, platformProvisionIntentHash as b, createPlatformHealthProbeToken as c, loadPlatformRuntime as d, platformDatabaseClientUrl as f, trackedPlatformWorkerTraffic as g, recordPlatformWorkerTraffic as h, verifyPlatformAiGatewayPlan as i, hyperdriveOriginMatches as j, hyperdriveOriginConfigHash as k, createPlatformInstallationSecrets as l, resolveBootstrapGitHubId as m, resolvePlatformInstallDatabaseUrl as n, acquirePlatformDatabaseLifecycleLock as o, recordResource as p, runPlatformLifecycleCommand as r, acquirePlatformDatabaseLifecycleLockConnection as s, assertNoninteractivePlatformMutationAcknowledged as t, installPlatform as u, formatPlatformInstallPlan as v, resolvePlatformCloudflareCredential as w, revalidatePlatformInstallAction as x, platformAdoptionIntentHash as y };
|