void 0.26.0 → 0.26.1
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/AGENTS_TEMPLATE.md +1 -3
- package/README.md +19 -9
- package/dist/{account-cmd-CDry3B5V.mjs → account-cmd-CfUXh_nU.mjs} +8 -7
- package/dist/{application-analysis-DC2yPvzY.mjs → application-analysis-DKy02UY0.mjs} +21 -32
- package/dist/{application-routing-C9khgLiS.mjs → application-routing-DQyUh_5S.mjs} +1 -1
- package/dist/{auth-D52yG7hl.mjs → auth-B5_tZLxT.mjs} +7 -7
- package/dist/{auth-B60QDbjg.mjs → auth-BgX2qYSY.mjs} +1 -1
- package/dist/{auth-link-DjeOptYi.mjs → auth-link-D5RmKnzh.mjs} +5 -5
- package/dist/{auth-migrations-9vif1uj8.mjs → auth-migrations-BwHgeEsD.mjs} +8 -18
- package/dist/{auth-router-BRxIuqDi.mjs → auth-router-Bap-pvbn.mjs} +4 -17
- package/dist/{better-auth-shared-BVkjZ3vM.d.mts → better-auth-shared-CPvWD3nG.d.mts} +0 -4
- package/dist/{better-auth-shared-hy6RPh9W.mjs → better-auth-shared-DPpj8zxc.mjs} +94 -16
- package/dist/{build-cmd-Ce3C8huo.mjs → build-cmd-B58c8iS8.mjs} +7 -6
- package/dist/{cache-CS8Yxr5a.mjs → cache-Bo52trKF.mjs} +7 -7
- package/dist/{cancel-deploy-mZsD88Xa.mjs → cancel-deploy-BZNz3Q26.mjs} +5 -4
- package/dist/{cf-access-YTlqvAsk.mjs → cf-access-ngGqZpHZ.mjs} +10 -11
- package/dist/{cf-build-output-U8o1Gl6X.mjs → cf-build-output-DjvB_872.mjs} +62 -85
- package/dist/cf-build-output-H9a97vME.mjs +2 -0
- package/dist/cli/cli.mjs +48 -83
- package/dist/cli/cloudflare-operation-process.mjs +71 -77
- package/dist/cli/env-schema-probe.mjs +5 -6
- package/dist/client-By4JjMw_.mjs +2 -0
- package/dist/{client-mC-dFGDD.mjs → client-C2Prx_Bi.mjs} +28 -6
- package/dist/{cloudflare-auth-Qdc7tw8F.mjs → cloudflare-auth-CuxfF6OA.mjs} +9 -17
- package/dist/{cloudflare-cmd-bhwCxAN6.mjs → cloudflare-cmd-lHqNlJGW.mjs} +6 -5
- package/dist/{cloudflare-config-Bktvwtpf.mjs → cloudflare-config-BmhBv3HV.mjs} +1 -1
- package/dist/{cloudflare-connect-CuhRgk3k.mjs → cloudflare-connect-2G3rL2rP.mjs} +4 -4
- package/dist/{cloudflare-operations-DoQrVHAt.mjs → cloudflare-operations-BlYLlowZ.mjs} +1 -1
- package/dist/{cloudflare-operations-DYa3coIk.mjs → cloudflare-operations-CwI1bChl.mjs} +41 -70
- package/dist/{cloudflare-process-B-wekeR6.mjs → cloudflare-process-2-TfIEzB.mjs} +20 -22
- package/dist/{config-CyQ-wVd7.mjs → config-5r-YpMC-.mjs} +1 -1
- package/dist/{config-C_XRIPx2.mjs → config-B_ggY-IO.mjs} +3 -3
- package/dist/config-BtSFvXZx.mjs +2 -0
- package/dist/config-CLYAosnQ.mjs +78 -0
- package/dist/{config-BMHb8RCj.d.mts → config-CSa15FvD.d.mts} +1 -1
- package/dist/{config-Br_JZD6u.mjs → config-DiowPT80.mjs} +24 -30
- package/dist/config-entry.d.mts +1 -1
- package/dist/{config-write-B1f88wJA.mjs → config-write-AHGesphx.mjs} +8 -7
- package/dist/{connect-H6EvP62X.mjs → connect-X0MUA1gk.mjs} +10 -9
- package/dist/{create-project-B2kk9Q0o.mjs → create-project-DxiyW6iX.mjs} +6 -6
- package/dist/{create-project-Dbb4uiN-.mjs → create-project-iwkbqiBU.mjs} +1 -1
- package/dist/{db-DpCKZto0.mjs → db-XnVMHzoV.mjs} +100 -132
- package/dist/{delete-CxlSvsvW.mjs → delete-esYlMiSJ.mjs} +6 -6
- package/dist/{deploy-CeEbnv4b.mjs → deploy-BsEvnlJl.mjs} +2346 -2495
- package/dist/deploy-C1d-YTfp.mjs +2 -0
- package/dist/{dev-inbox-D64ZKUod.mjs → dev-inbox-CK-UuPob.mjs} +7 -16
- package/dist/{discover-BcPPiF1o.mjs → discover-CkCYv9T_.mjs} +1 -2
- package/dist/discover-EDUf6JJw.mjs +2 -0
- package/dist/{prompts-ZAuJlyCj.mjs → dist-Bx1z6Eva.mjs} +1 -1
- package/dist/{dist-AoCzRTJE.mjs → dist-Cegxq8gs.mjs} +8 -8
- package/dist/{prompts-6OSVA7DJ.mjs → dist-D3m88sjf.mjs} +10 -53
- package/dist/{domain-B_9VgOm6.mjs → domain-CbbBWhWE.mjs} +28 -29
- package/dist/{dotenv-VQxupEUv.mjs → dotenv-BfU6eqFt.mjs} +20 -32
- package/dist/{drizzle-Beb2Am5S.mjs → drizzle-CF84FOVM.mjs} +16 -13
- package/dist/{email-BokHgjKj.mjs → email-CpuT42g7.mjs} +23 -18
- package/dist/{email--tEtMoj_.mjs → email-d_Aux1vM.mjs} +1 -1
- package/dist/{entry-CF5wvH4w.mjs → entry-CMAkqBmU.mjs} +6 -6
- package/dist/{env-_v349JBd.mjs → env-BxocywBB.mjs} +25 -6
- package/dist/{env-D5liuQYR.mjs → env-DMA3cXZt.mjs} +1 -1
- package/dist/{env-raw-Cx8ElDdj.mjs → env-raw-jZpP5n47.mjs} +1 -2
- package/dist/{env-types-D5kds_OZ.mjs → env-types-CwXgeMgL.mjs} +1 -1
- package/dist/{env-validation-cZBvGWaP.mjs → env-validation-CrVNjsPm.mjs} +1 -1
- package/dist/{env-validation-vBSQ8gw5.mjs → env-validation-Dxdx_5wo.mjs} +17 -21
- package/dist/{env-BdTc-K2L.mjs → env-w9jOyGZn.mjs} +9 -9
- package/dist/{fetch-_SeGZao9.d.mts → fetch-BPCYVi3H.d.mts} +20 -1
- package/dist/{fetch-BIZJh7vR.mjs → fetch-sAcwjzLO.mjs} +1 -1
- package/dist/{fetch-stream-Nm3hkZbT.mjs → fetch-stream-PGgz4uGz.mjs} +18 -23
- package/dist/{fetch-stream-Bjf0hoZb.d.mts → fetch-stream-obvZ7fvO.d.mts} +1 -16
- package/dist/{gen-BhDlTpwW.mjs → gen-DtkQhvQg.mjs} +40 -57
- package/dist/gen-dA9hW7AV.mjs +2 -0
- package/dist/{github-cmd-hhkTzlGS.mjs → github-cmd-D_FsOFxq.mjs} +64 -163
- package/dist/{handler-DghKr6dU.mjs → handler-BHAn2fZJ.mjs} +1 -0
- package/dist/{handler-BeK3weD4.d.mts → handler-CNAwjRcW.d.mts} +4 -11
- package/dist/{head-Do8P4puT.d.mts → head-C8K_iGe6.d.mts} +1 -1
- package/dist/{head-D_QRR5Yd.mjs → head-D2VF4ApL.mjs} +29 -51
- package/dist/{headers-2rKda9Y6.mjs → headers-DlfR78Nu.mjs} +3 -3
- package/dist/{help-Bv44e2tm.mjs → help-CVFBTmBx.mjs} +13 -32
- package/dist/help-DzKUrQvk.mjs +2 -0
- package/dist/{inbound-fRkqcXaC.mjs → inbound-PfQDLXc5.mjs} +23 -24
- package/dist/index.d.mts +19 -2
- package/dist/index.mjs +617 -530
- package/dist/{info-DhtTKh65.mjs → info-PYWwkWyt.mjs} +4 -4
- package/dist/{init-BMf4T03q.mjs → init-Bw-fRKGp.mjs} +160 -197
- package/dist/{link-BqYsSS_I.mjs → link-DlPG8iX3.mjs} +9 -9
- package/dist/{list-_kBToO-l.mjs → list-2GN7_ueV.mjs} +8 -7
- package/dist/{live-CB1y5IuC.mjs → live-CgQuTpqD.mjs} +15 -16
- package/dist/{live-iAuEH1hd.d.mts → live-Du8jXwOW.d.mts} +4 -2
- package/dist/{local-d1-fGxYrVD6.mjs → local-d1-ga5O_idV.mjs} +2 -2
- package/dist/{login-DFuo-RWO.mjs → login-D-Q4xw3Q.mjs} +7 -7
- package/dist/login-Dc-wuTDq.mjs +2 -0
- package/dist/{logs-DYgnh6dH.mjs → logs-rd8J-OFh.mjs} +27 -10
- package/dist/migrate-BHp07yJE.mjs +2 -0
- package/dist/{migrate-CV1on-yJ.mjs → migrate-NLsjBbuM.mjs} +34 -20
- package/dist/{mime-D5Nmdzf7.mjs → mime-DxCznlJq.mjs} +45 -95
- package/dist/{node-C6Q6e1Es.mjs → node-DJicPvPj.mjs} +5 -5
- package/dist/{operator-args-DdY54Bgb.mjs → operator-args-BNsW5gfp.mjs} +10 -1
- package/dist/{operator-auth-2dsGlTT5.mjs → operator-auth-AzVLbrr3.mjs} +1 -1
- package/dist/{operator-client-BFqpp6z0.mjs → operator-client-BQtzyG-g.mjs} +1 -1
- package/dist/{operator-cmd-CUGHXrQf.mjs → operator-cmd-B6f6Cg9Z.mjs} +24 -11
- package/dist/operator-cmd-Cwn50lOV.mjs +2 -0
- package/dist/{output-BvdaehtE.mjs → output-C50ag2r3.mjs} +20 -2
- package/dist/pages/client.d.mts +19 -51
- package/dist/pages/client.mjs +204 -225
- package/dist/pages/head-client.d.mts +1 -1
- package/dist/pages/head.d.mts +1 -1
- package/dist/pages/head.mjs +1 -1
- package/dist/pages/index.d.mts +2 -2
- package/dist/pages/index.mjs +6 -12
- package/dist/pages/islands-plugin.d.mts +1 -1
- package/dist/pages/islands-plugin.mjs +21 -25
- package/dist/pages/protocol.d.mts +2 -2
- package/dist/pages/protocol.mjs +2 -2
- package/dist/{plan-CJGEeTEI.mjs → plan-BhLO2p4w.mjs} +2 -1
- package/dist/plan-CH2G51je.mjs +2 -0
- package/dist/{platform-args-DSV2p4nY.mjs → platform-args-BoZkWQnJ.mjs} +1 -1
- package/dist/platform-args-DYgITk0D.mjs +2 -0
- package/dist/{platform-auth-config-Bosx7U1h.mjs → platform-auth-config-n603OANg.mjs} +40 -36
- package/dist/{platform-auth-protection-DcbL_LW_.mjs → platform-auth-protection-zxDr0hWW.mjs} +8 -7
- package/dist/{platform-auth-recovery-WfTZ8K6o.mjs → platform-auth-recovery-tw9lgtgE.mjs} +7 -6
- package/dist/{platform-cmd-DbKtQb_4.mjs → platform-cmd-B8-bCb7t.mjs} +10 -10
- package/dist/{platform-cmd-dyFUof0t.mjs → platform-cmd-C00YM14r.mjs} +1 -1
- package/dist/{platform-domain-Bsq43AJp.mjs → platform-domain-p0kobLV8.mjs} +5 -5
- package/dist/{platform-lifecycle-Cfi0o6xM.mjs → platform-lifecycle-D_QEY32D.mjs} +75 -386
- package/dist/{platform-lifecycle--5gWmDoI.mjs → platform-lifecycle-vFqtNPPa.mjs} +1 -1
- package/dist/{platform-management-BrF9STZp.mjs → platform-management-BdYblvvE.mjs} +6 -6
- package/dist/{platform-management-Bbwf6-Dq.mjs → platform-management-oi-SvI3f.mjs} +1 -1
- package/dist/{platform-plans-config-DU-8nC2Y.mjs → platform-plans-config-CjiFv5J4.mjs} +5 -4
- package/dist/{platform-recovery-DQAqAQYu.mjs → platform-recovery-PvNS9Nl2.mjs} +2 -2
- package/dist/platform-setup-DVe42Ws7.mjs +299 -0
- package/dist/{plugin-inference-CXWnn79A.mjs → plugin-inference-BlQbOL0P.mjs} +43 -42
- package/dist/prepare-DRUV-g3X.mjs +2 -0
- package/dist/{prepare-WoUubFKL.mjs → prepare-Do96654b.mjs} +8 -8
- package/dist/{prepare-BMrRWLwP.mjs → prepare-Dq9hTIbo.mjs} +4 -4
- package/dist/{prerender-render-D9qbLs2f.mjs → prerender-render-Ct20jftc.mjs} +17 -3
- package/dist/prerender-render.mjs +1 -1
- package/dist/{project-cmd-BbH2LptN.mjs → project-cmd-ti8_yTcA.mjs} +18 -18
- package/dist/{project-team-Yiww3-go.mjs → project-team-CDPE1Tsg.mjs} +14 -17
- package/dist/{project-token-BrtT2NkY.mjs → project-token-CkZ1cN0Z.mjs} +13 -16
- package/dist/{project-tsconfig-B8GeM0RM.mjs → project-tsconfig-CVJhNMxs.mjs} +2 -1
- package/dist/{project-zero-trust-nYJ2V2nc.mjs → project-zero-trust-DdjLR61k.mjs} +11 -8
- package/dist/{protocol-BX8t2jiw.d.mts → protocol-BPZaNqBo.d.mts} +4 -2
- package/dist/{protocol-U7bfjHmA.mjs → protocol-CfaUwNs8.mjs} +46 -49
- package/dist/{providers-CJlNS3kT.mjs → providers-BXuhmuub.mjs} +1 -12
- package/dist/{provision-VeqAC77A.mjs → provision-BfaLiWbj.mjs} +38 -41
- package/dist/{provision-DMTPG8Rh.mjs → provision-Wu9ZBk9L.mjs} +2 -3
- package/dist/{requests-TIz_jtSu.mjs → requests-DFAqyYy8.mjs} +4 -4
- package/dist/resolve-project-BIeYs9Cw.mjs +2 -0
- package/dist/{resolve-project-BG5ORGID.mjs → resolve-project-CP8rZs_p.mjs} +6 -1
- package/dist/{rollback-dBqICPzj.mjs → rollback-BKYXBduI.mjs} +29 -36
- package/dist/{route-types-Clm4WD0B.mjs → route-types-CbtsIeFn.mjs} +1 -1
- package/dist/route-url-BgPja1GS.d.mts +5 -0
- package/dist/route-url-BjGv_KKY.mjs +28 -0
- package/dist/runner-9wjsSZx-.mjs +2 -0
- package/dist/{runner--2KF6Kua.mjs → runner-DMBKSrRk.mjs} +2 -2
- package/dist/{runner-mysql-DmWchSWJ.mjs → runner-mysql-CEzKtmFb.mjs} +8 -8
- package/dist/{runner-mysql-CEG5JozK.mjs → runner-mysql-CkFqZ6CE.mjs} +1 -1
- package/dist/{runner-pg-Bh4AgZdj.mjs → runner-pg-BGYRFdRp.mjs} +1 -1
- package/dist/runtime/ai.d.mts +1 -1
- package/dist/runtime/ai.mjs +34 -95
- package/dist/runtime/better-auth-mysql.d.mts +1 -1
- package/dist/runtime/better-auth-mysql.mjs +4 -9
- package/dist/runtime/better-auth-pg.d.mts +1 -1
- package/dist/runtime/better-auth-pg.mjs +5 -10
- package/dist/runtime/better-auth.d.mts +1 -1
- package/dist/runtime/better-auth.mjs +3 -3
- package/dist/runtime/client-react.d.mts +2 -3
- package/dist/runtime/client-react.mjs +2 -2
- package/dist/runtime/client-solid.d.mts +2 -3
- package/dist/runtime/client-solid.mjs +2 -2
- package/dist/runtime/client-svelte.d.mts +2 -3
- package/dist/runtime/client-svelte.mjs +2 -2
- package/dist/runtime/client-vue.d.mts +2 -3
- package/dist/runtime/client-vue.mjs +2 -2
- package/dist/runtime/client.d.mts +2 -3
- package/dist/runtime/client.mjs +2 -2
- package/dist/runtime/db.mjs +1 -1
- package/dist/runtime/durable.mjs +3 -10
- package/dist/runtime/email/testing.mjs +5 -5
- package/dist/runtime/email.d.mts +2 -1
- package/dist/runtime/email.mjs +11 -27
- package/dist/runtime/env-public.mjs +15 -20
- package/dist/runtime/env.mjs +1 -1
- package/dist/runtime/fetch-stream.d.mts +2 -2
- package/dist/runtime/fetch-stream.mjs +1 -1
- package/dist/runtime/fetch.d.mts +2 -3
- package/dist/runtime/fetch.mjs +1 -1
- package/dist/runtime/handler.d.mts +1 -1
- package/dist/runtime/handler.mjs +2 -2
- package/dist/runtime/isr.mjs +1 -1
- package/dist/runtime/kv.mjs +10 -11
- package/dist/runtime/live-client.d.mts +1 -1
- package/dist/runtime/live-client.mjs +12 -22
- package/dist/runtime/live-server.mjs +27 -35
- package/dist/runtime/live.d.mts +2 -2
- package/dist/runtime/live.mjs +2 -2
- package/dist/runtime/migration-handler.mjs +4 -81
- package/dist/runtime/queues.mjs +1 -1
- package/dist/runtime/remote/binding-handler.d.mts +2 -2
- package/dist/runtime/remote/binding-handler.mjs +8 -9
- package/dist/runtime/remote/index.mjs +27 -77
- package/dist/runtime/route-url.d.mts +2 -4
- package/dist/runtime/route-url.mjs +1 -1
- package/dist/runtime/routing.d.mts +1 -1
- package/dist/runtime/routing.mjs +15 -26
- package/dist/runtime/sandbox.mjs +2 -2
- package/dist/runtime/sse.mjs +1 -1
- package/dist/runtime/storage.mjs +1 -1
- package/dist/runtime/validator.d.mts +1 -1
- package/dist/runtime/ws-server.d.mts +2 -2
- package/dist/runtime/ws-server.mjs +30 -61
- package/dist/runtime/ws.d.mts +1 -1
- package/dist/runtime/ws.mjs +1 -1
- package/dist/{scan-C8dA7iM4.mjs → scan-C3uDzz6J.mjs} +12 -13
- package/dist/{secret-AKnNXNP5.mjs → secret-BAt2KMmO.mjs} +14 -14
- package/dist/{skills-BPQUGClu.mjs → skills-BgVMvQdy.mjs} +2 -2
- package/dist/{sse-CQNaDFFV.mjs → sse-CMvCgjNk.mjs} +1 -1
- package/dist/{subcommand-prompt-B6WS9Aoz.mjs → subcommand-prompt-BSlnD1fI.mjs} +2 -2
- package/dist/sveltekit.d.mts +0 -2
- package/dist/terminal-log-text-D9ACPOuG.mjs +32 -0
- package/dist/validate-BJr9LfXy.mjs +2 -0
- package/dist/{validate-ymhap6M_.mjs → validate-C9qJArv7.mjs} +9 -28
- package/dist/{defer-YsYDUoii.mjs → validation-error-Dg9Recn1.mjs} +11 -11
- package/dist/{wrangler-DhUerFkW.mjs → wrangler-D9KTuqnv.mjs} +89 -194
- package/dist/{ws-C79j4aED.d.mts → ws-CChrrAU-.d.mts} +1 -1
- package/dist/{yarn-pnp-BV4AzNul.mjs → yarn-pnp-CUX_iTPA.mjs} +19 -27
- package/{skills/void/docs → docs}/guide/ai.md +5 -3
- package/{skills/void/docs → docs}/guide/auth.md +37 -1
- package/{skills/void/docs → docs}/guide/database/postgresql.md +2 -2
- package/{skills/void/docs → docs}/guide/edge/revalidation.md +1 -1
- package/{skills/void/docs → docs}/guide/edge/rewrites.md +2 -4
- package/{skills/void/docs → docs}/guide/email/receiving.md +2 -2
- package/{skills/void/docs → docs}/guide/email/sending.md +0 -2
- package/{skills/void/docs → docs}/guide/env-vars.md +4 -0
- package/{skills/void/docs → docs}/guide/jobs.md +2 -2
- package/{skills/void/docs → docs}/guide/live.md +10 -5
- package/{skills/void/docs → docs}/guide/pages-routing/actions-and-forms.md +20 -8
- package/{skills/void/docs → docs}/guide/pages-routing/loaders.md +7 -3
- package/{skills/void/docs → docs}/guide/pages-routing/markdown.md +15 -23
- package/{skills/void/docs → docs}/guide/pages-routing/overview.md +6 -4
- package/{skills/void/docs → docs}/guide/platform/administration/access.md +2 -10
- package/{skills/void/docs → docs}/guide/platform/administration/operations.md +3 -12
- package/{skills/void/docs → docs}/guide/platform/administration/projects.md +1 -1
- package/{skills/void/docs → docs}/guide/platform/development/local.md +4 -2
- package/{skills/void/docs → docs}/guide/platform/development/runtime.md +1 -1
- package/{skills/void/docs → docs}/guide/platform/development/schema-ci.md +1 -1
- package/{skills/void/docs → docs}/guide/platform/installation/domains.md +3 -1
- package/{skills/void/docs → docs}/guide/platform/installation/first-deployment.md +3 -1
- package/{skills/void/docs → docs}/guide/platform/installation/maintenance.md +4 -0
- package/{skills/void/docs → docs}/guide/project-collaboration.md +6 -2
- package/{skills/void/docs → docs}/guide/queues.md +0 -2
- package/{skills/void/docs → docs}/guide/remote-dev.md +5 -5
- package/{skills/void/docs → docs}/guide/sandboxes.md +2 -2
- package/{skills/void/docs → docs}/guide/sse.md +0 -2
- package/{skills/void/docs → docs}/guide/storage.md +7 -2
- package/{skills/void/docs → docs}/guide/websockets.md +4 -0
- package/docs/integrations/agents.md +37 -0
- package/{skills/void/docs → docs}/integrations/frameworks/astro.md +3 -3
- package/{skills/void/docs → docs}/integrations/frameworks/nuxt.md +6 -2
- package/{skills/void/docs → docs}/integrations/hono.md +15 -7
- package/{skills/void/docs → docs}/integrations/nodejs-bun-deno.md +1 -0
- package/{skills/void/docs → docs}/reference/api/auth.md +1 -1
- package/{skills/void/docs → docs}/reference/api/handlers.md +4 -2
- package/{skills/void/docs → docs}/reference/api/pages.md +4 -0
- package/{skills/void/docs → docs}/reference/cli/auth.md +0 -5
- package/{skills/void/docs → docs}/reference/cli/database.md +3 -4
- package/{skills/void/docs → docs}/reference/cli/generate.md +1 -1
- package/{skills/void/docs → docs}/reference/cli/github.md +3 -12
- package/{skills/void/docs → docs}/reference/cli/platform-config.md +1 -1
- package/{skills/void/docs → docs}/reference/cli/platform-email.md +2 -3
- package/{skills/void/docs → docs}/reference/cli/platform-installation.md +1 -1
- package/{skills/void/docs → docs}/reference/cli/platform-operations.md +3 -0
- package/{skills/void/docs → docs}/reference/cli/platform-users.md +2 -2
- package/{skills/void/docs → docs}/reference/cli/project.md +5 -4
- package/{skills/void/docs → docs}/reference/cli/secrets.md +3 -3
- package/{skills/void/docs → docs}/reference/cli/setup.md +9 -11
- package/{skills/void/docs → docs}/reference/cli.md +1 -1
- package/{skills/void/docs → docs}/reference/config.md +13 -13
- package/{skills/void/docs → docs}/reference/resource-inference.md +1 -16
- package/package.json +34 -30
- package/schema.json +1 -1
- package/skills/migrate-vite-cloudflare-to-void/SKILL.md +4 -1
- package/skills/void/SKILL.md +6 -3
- package/dist/cf-build-output-ChY6-XWP.mjs +0 -2
- package/dist/client-BxVixJBI.mjs +0 -2
- package/dist/config-0acf1oys.mjs +0 -2
- package/dist/config-D8MOgiQV.mjs +0 -32
- package/dist/deploy-qmiLE1G1.mjs +0 -2
- package/dist/discover-AMCBXivQ.mjs +0 -2
- package/dist/fetch-error-Sp1R4mZv.d.mts +0 -20
- package/dist/gen-qCBwH3fZ.mjs +0 -2
- package/dist/help-Dw5f9Xrg.mjs +0 -2
- package/dist/login-D7meQg_3.mjs +0 -2
- package/dist/migrate-CEu2X5DB.mjs +0 -2
- package/dist/operator-cmd-DRPvhpjM.mjs +0 -2
- package/dist/plan-COtUvdMA.mjs +0 -2
- package/dist/platform-args-Dcy_5b_Y.mjs +0 -2
- package/dist/prepare-BBknoZI1.mjs +0 -2
- package/dist/resolve-project-DtbidV4y.mjs +0 -2
- package/dist/route-url-CG7U-cRN.mjs +0 -15
- package/dist/runner-voIltZrY.mjs +0 -2
- package/dist/validate-pna7R3Pv.mjs +0 -2
- package/skills/void/docs/integrations/agents.md +0 -26
- package/dist/{runner-pg-D4OPlil-.mjs → runner-pg-DV8p_zjA.mjs} +4 -4
- package/{skills/void/docs → docs}/guide/app-types.md +0 -0
- package/{skills/void/docs → docs}/guide/database/d1.md +2 -2
- package/{skills/void/docs → docs}/guide/database/mysql.md +0 -0
- package/{skills/void/docs → docs}/guide/database.md +8 -8
- package/{skills/void/docs → docs}/guide/deployment.md +0 -0
- package/{skills/void/docs → docs}/guide/durable-state.md +0 -0
- package/{skills/void/docs → docs}/guide/edge/headers.md +0 -0
- package/{skills/void/docs → docs}/guide/edge/prerendering.md +0 -0
- package/{skills/void/docs → docs}/guide/edge/redirects.md +0 -0
- package/{skills/void/docs → docs}/guide/edge/static-assets.md +0 -0
- package/{skills/void/docs → docs}/guide/email/domains.md +0 -0
- package/{skills/void/docs → docs}/guide/email.md +0 -0
- package/{skills/void/docs → docs}/guide/index.md +0 -0
- package/{skills/void/docs → docs}/guide/kv.md +0 -0
- package/{skills/void/docs → docs}/guide/pages-routing/head.md +0 -0
- package/{skills/void/docs → docs}/guide/pages-routing/islands.md +2 -2
- package/{skills/void/docs → docs}/guide/pages-routing/layouts.md +0 -0
- package/{skills/void/docs → docs}/guide/pages-routing/view-transitions.md +0 -0
- package/{skills/void/docs → docs}/guide/platform/administration/email.md +0 -0
- package/{skills/void/docs → docs}/guide/platform/administration/plans.md +0 -0
- package/{skills/void/docs → docs}/guide/platform/administration/zero-trust.md +0 -0
- package/{skills/void/docs → docs}/guide/platform/installation/ci.md +0 -0
- package/{skills/void/docs → docs}/guide/platform/installation/credentials.md +0 -0
- package/{skills/void/docs → docs}/guide/platform/installation/prerequisites.md +0 -0
- package/{skills/void/docs → docs}/guide/platform/installation/setup.md +0 -0
- package/{skills/void/docs → docs}/guide/platform/installation/uninstall.md +0 -0
- package/{skills/void/docs → docs}/guide/platform-administration.md +0 -0
- package/{skills/void/docs → docs}/guide/platform-development.md +0 -0
- package/{skills/void/docs → docs}/guide/quickstart.md +0 -0
- package/{skills/void/docs → docs}/guide/self-hosted-platform.md +0 -0
- package/{skills/void/docs → docs}/guide/server-routing.md +3 -3
- package/{skills/void/docs → docs}/guide/ssg.md +0 -0
- package/{skills/void/docs → docs}/guide/ssr.md +0 -0
- package/{skills/void/docs → docs}/guide/type-safety.md +0 -0
- package/{skills/void/docs → docs}/guide/typed-fetch.md +0 -0
- package/{skills/void/docs → docs}/index.md +0 -0
- package/{skills/void/docs → docs}/integrations/cloudflare.md +0 -0
- package/{skills/void/docs → docs}/integrations/frameworks/analog.md +3 -3
- package/{skills/void/docs → docs}/integrations/frameworks/overview.md +0 -0
- package/{skills/void/docs → docs}/integrations/frameworks/react-router.md +3 -3
- package/{skills/void/docs → docs}/integrations/frameworks/sveltekit.md +1 -1
- package/{skills/void/docs → docs}/integrations/frameworks/tanstack-start.md +2 -2
- package/{skills/void/docs → docs}/reference/api/client.md +0 -0
- package/{skills/void/docs → docs}/reference/api/database.md +2 -2
- /package/{skills/void/docs → docs}/reference/api/durable.md +0 -0
- /package/{skills/void/docs → docs}/reference/api/env.md +0 -0
- /package/{skills/void/docs → docs}/reference/api/plugin.md +0 -0
- /package/{skills/void/docs → docs}/reference/api/resources.md +0 -0
- /package/{skills/void/docs → docs}/reference/api/rewrites.md +0 -0
- /package/{skills/void/docs → docs}/reference/api/types.md +0 -0
- /package/{skills/void/docs → docs}/reference/api.md +0 -0
- /package/{skills/void/docs → docs}/reference/cli/deploy.md +0 -0
- /package/{skills/void/docs → docs}/reference/cli/domains.md +0 -0
- /package/{skills/void/docs → docs}/reference/cli/email.md +0 -0
- /package/{skills/void/docs → docs}/reference/cli/platform-zero-trust.md +0 -0
- /package/{skills/void/docs → docs}/reference/cli/platform.md +0 -0
- /package/{skills/void/docs → docs}/reference/structure.md +0 -0
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { a as join, n as dirname, u as resolve } from "./dist-BVqXeR_h.mjs";
|
|
2
2
|
import { S as writePendingInstallationSecrets, a as latestPlatformWorkerCutoverGeneration, c as normalizePlatformApiUrl, d as platformRegistryDirectory, f as platformWorkerSecretUpdateIntentState, h as readPendingInstallationSecrets, m as readInstallationRecoverySecrets, n as assertPlatformInstallationSlugAvailable, o as listInstallationManifests, p as promoteInstallationSecrets, t as acquirePlatformLifecycleLock, v as resolveInstallationManifest, x as writeInstallationManifest, y as savePlatformConnection } from "./platform-registry-P387v42A.mjs";
|
|
3
3
|
import { t as cfAccessHeaders } from "./cf-access-TWNzXltp.mjs";
|
|
4
|
-
import { n as ensurePlatformAccessToken } from "./cf-access-
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import { o as
|
|
10
|
-
import {
|
|
11
|
-
import { t as
|
|
4
|
+
import { n as ensurePlatformAccessToken } from "./cf-access-ngGqZpHZ.mjs";
|
|
5
|
+
import { A as confirm, H as outro, K as select, L as log, U as password, X as text$1, tt as isCancel, z as multiselect } from "./dist-D3m88sjf.mjs";
|
|
6
|
+
import { d as printSuccess, l as import_picocolors, n as cliCommandName, r as createSpinner, u as note } from "./output-C50ag2r3.mjs";
|
|
7
|
+
import { l as resolveCloudflareOperationArgv } from "./cloudflare-process-2-TfIEzB.mjs";
|
|
8
|
+
import { o as runCloudflareAuthCommand } from "./cloudflare-auth-CuxfF6OA.mjs";
|
|
9
|
+
import { _ as resolvePinnedApiBaseUrl, o as createDefaultRunWrangler } from "./provision-BfaLiWbj.mjs";
|
|
10
|
+
import { t as parsePlatformArgs } from "./platform-args-BoZkWQnJ.mjs";
|
|
11
|
+
import { a as platformManagementSetupPage, c as platformSetupLink, i as platformInstallCommandArguments, l as platformSetupPages, n as formatPlatformSetupPlan, o as platformPromptAnswer, r as openPlatformSetupPage, s as platformSetupFieldHelp, t as formatPlatformInstallCommand } from "./platform-setup-DVe42Ws7.mjs";
|
|
12
12
|
import { copyFileSync, cpSync, existsSync, lstatSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
13
13
|
import { fileURLToPath } from "node:url";
|
|
14
14
|
import { isRecord } from "@void/deploy-core";
|
|
@@ -16,11 +16,10 @@ import { PLATFORM_APP_ACCESS_SETUP_PROOF_PREFIX, PLATFORM_AUTH_SETUP_PROOF_PREFI
|
|
|
16
16
|
import { createHash, createHmac, randomBytes, randomUUID } from "node:crypto";
|
|
17
17
|
import { tmpdir } from "node:os";
|
|
18
18
|
import { stripVTControlCharacters } from "node:util";
|
|
19
|
-
import { execFile } from "node:child_process";
|
|
20
19
|
import { encodeCloudflareVersionMessage, parseCloudflareVersionMessage, readCloudflareTriggerConfig, readCloudflareVersionMigrationTag, stabilizeCloudflareVersionTriggers } from "@void/deploy-cloudflare";
|
|
20
|
+
import { createServer, request } from "node:http";
|
|
21
21
|
import { readFile } from "node:fs/promises";
|
|
22
22
|
import { PLATFORM_ADMIN_ASSETS_DIRECTORY, platformDatabaseSchemaDigest, resolvePlatformRuntime } from "@void/platform/installer";
|
|
23
|
-
import { createServer, request } from "node:http";
|
|
24
23
|
import { request as request$1 } from "node:https";
|
|
25
24
|
//#region src/cli/platform-cloudflare.ts
|
|
26
25
|
var PlatformCloudflareApiError = class extends Error {
|
|
@@ -722,21 +721,6 @@ var PlatformCloudflareClient = class PlatformCloudflareClient {
|
|
|
722
721
|
async removeRoutes(_accountId, _zoneId, tracked) {
|
|
723
722
|
if (tracked.routes.length > 0 || tracked.customDomains.length > 0) throw new Error("platform: Cloudflare does not support conditional Worker traffic deletion. Retaining routes and custom domains for explicit dashboard cleanup.");
|
|
724
723
|
}
|
|
725
|
-
async setWorkerSubdomain(accountId, workerName, enabled) {
|
|
726
|
-
try {
|
|
727
|
-
await this.request(`/accounts/${encodeURIComponent(accountId)}/workers/scripts/${encodeURIComponent(workerName)}/subdomain`, {
|
|
728
|
-
body: JSON.stringify({
|
|
729
|
-
enabled,
|
|
730
|
-
previews_enabled: enabled
|
|
731
|
-
}),
|
|
732
|
-
headers: { "Cloudflare-Workers-Script-Api-Date": "2025-08-01" },
|
|
733
|
-
method: "POST"
|
|
734
|
-
});
|
|
735
|
-
} catch (error) {
|
|
736
|
-
if (!enabled && error instanceof PlatformCloudflareApiError && error.status === 404) return;
|
|
737
|
-
throw error;
|
|
738
|
-
}
|
|
739
|
-
}
|
|
740
724
|
};
|
|
741
725
|
function accessResourcePath(accountId, kind, id) {
|
|
742
726
|
return `/accounts/${encodeURIComponent(accountId)}/access/${kind === "application" ? "apps" : "service_tokens"}/${encodeURIComponent(id)}`;
|
|
@@ -997,6 +981,18 @@ function platformAccessOverlapsOrigin(destination, origin) {
|
|
|
997
981
|
const pattern = "^" + destination.split("/")[0].split("*").map((part) => part.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join(".*") + "$";
|
|
998
982
|
return new RegExp(pattern, "i").test(new URL(origin).hostname);
|
|
999
983
|
}
|
|
984
|
+
/** Whether an application path-covers, or exactly covers, any protected platform origin. */
|
|
985
|
+
function platformAccessOverlapsOrigins(application, origins) {
|
|
986
|
+
return platformAccessPublicDestinations(application).some((destination) => origins.some((origin) => platformAccessOverlapsOrigin(destination, origin)) && (destination.includes("/") || origins.some((origin) => destination === new URL(origin).hostname)));
|
|
987
|
+
}
|
|
988
|
+
/** A definitive 4xx means the create did not happen, so a retry may not find a hidden duplicate. */
|
|
989
|
+
function platformAccessCreateRejected(error) {
|
|
990
|
+
return error instanceof PlatformCloudflareApiError && error.status >= 400 && error.status < 500 && ![
|
|
991
|
+
408,
|
|
992
|
+
409,
|
|
993
|
+
429
|
|
994
|
+
].includes(error.status);
|
|
995
|
+
}
|
|
1000
996
|
async function inspectPlatformAccess(client, input) {
|
|
1001
997
|
const authDomain = text(object(await client.get("organizations"), "Access organization").auth_domain, "Access team domain");
|
|
1002
998
|
const teamDomain = authDomain.startsWith("https://") ? authDomain : `https://${authDomain}`;
|
|
@@ -1031,7 +1027,6 @@ async function provisionPlatformAccess(client, input, previous, save) {
|
|
|
1031
1027
|
if (url.origin !== value || url.protocol !== "https:") throw new Error("platform: Access requires exact HTTPS origins without credentials, paths, or query strings.");
|
|
1032
1028
|
return url.origin;
|
|
1033
1029
|
}))];
|
|
1034
|
-
for (const origin of origins) if (!origin.startsWith("https://")) throw new Error("platform: Access protection requires HTTPS platform origins.");
|
|
1035
1030
|
const state = previous ? structuredClone(previous) : {
|
|
1036
1031
|
version: 1,
|
|
1037
1032
|
accountId: input.accountId,
|
|
@@ -1063,7 +1058,7 @@ async function provisionPlatformAccess(client, input, previous, save) {
|
|
|
1063
1058
|
}
|
|
1064
1059
|
if (input.protection) for (const app of inventory) {
|
|
1065
1060
|
if (app.id === input.protection.applicationId || app.id === state.resources.protection?.id || app.name === state.resources.protection?.name) continue;
|
|
1066
|
-
if (
|
|
1061
|
+
if (platformAccessOverlapsOrigins(app, origins)) throw new Error("platform: An existing Access application overlaps a platform endpoint. Connect or reconcile it explicitly before provisioning protection.");
|
|
1067
1062
|
}
|
|
1068
1063
|
const output = { resources: [] };
|
|
1069
1064
|
const application = async (key, expected, existingId) => {
|
|
@@ -1118,11 +1113,7 @@ async function provisionPlatformAccess(client, input, previous, save) {
|
|
|
1118
1113
|
save(state);
|
|
1119
1114
|
return object(await client.get(`apps/${encodeURIComponent(checkpoint.id)}`), "Access application");
|
|
1120
1115
|
} catch (error) {
|
|
1121
|
-
if (error
|
|
1122
|
-
408,
|
|
1123
|
-
409,
|
|
1124
|
-
429
|
|
1125
|
-
].includes(error.status)) {
|
|
1116
|
+
if (platformAccessCreateRejected(error)) {
|
|
1126
1117
|
checkpoint.pending = false;
|
|
1127
1118
|
save(state);
|
|
1128
1119
|
}
|
|
@@ -1277,295 +1268,6 @@ async function verifyPlatformAccessApplication(client, input, app, type, machine
|
|
|
1277
1268
|
if (machineId && !currentPolicies.some((policy) => policy.decision === "non_identity")) throw new Error("platform: The platform service token is not admitted by Access.");
|
|
1278
1269
|
}
|
|
1279
1270
|
//#endregion
|
|
1280
|
-
//#region src/cli/platform-setup.ts
|
|
1281
|
-
function platformSetupLink(page, hyperlinks = supportsSetupLinks()) {
|
|
1282
|
-
return hyperlinks ? "\x1B]8;;" + page.url + "\x1B\\" + import_picocolors.default.underline(page.title) + "\x1B]8;;\x1B\\" : page.title + ": " + import_picocolors.default.underline(page.url);
|
|
1283
|
-
}
|
|
1284
|
-
function platformSetupFieldHelp(key) {
|
|
1285
|
-
const docs = (page, section, title) => platformSetupLink({
|
|
1286
|
-
title,
|
|
1287
|
-
url: `https://void.cloud/guide/platform/installation/${page}#${section}`
|
|
1288
|
-
});
|
|
1289
|
-
switch (key) {
|
|
1290
|
-
case "databaseUrl": return {
|
|
1291
|
-
placeholder: "postgresql://user:pw@…/database",
|
|
1292
|
-
description: "Provide a PostgreSQL database URL for platform users, projects, and deployments. Use an empty hosted database, e.g. " + platformSetupLink({
|
|
1293
|
-
title: "Neon",
|
|
1294
|
-
url: "https://neon.com/"
|
|
1295
|
-
}) + ". " + docs("prerequisites", "platform-database", "Database setup")
|
|
1296
|
-
};
|
|
1297
|
-
case "jwtSecret": return { description: `Create a JWT signing key for platform login tokens. Run ${import_picocolors.default.blue("openssl rand -base64 32")}. Save the key in your password manager. ` + docs("credentials", "signing-and-encryption-keys", "Key setup") };
|
|
1298
|
-
case "projectSecretKey": return { description: `Generate a project encryption key for app secrets. Run ${import_picocolors.default.blue("openssl rand -base64 32")} separately. Save this key for recovery. ` + docs("credentials", "signing-and-encryption-keys", "Key setup") };
|
|
1299
|
-
default: return;
|
|
1300
|
-
}
|
|
1301
|
-
}
|
|
1302
|
-
function supportsSetupLinks() {
|
|
1303
|
-
return !!process.stdout.isTTY && ([
|
|
1304
|
-
"ghostty",
|
|
1305
|
-
"iTerm.app",
|
|
1306
|
-
"WezTerm",
|
|
1307
|
-
"vscode",
|
|
1308
|
-
"WarpTerminal"
|
|
1309
|
-
].includes(process.env.TERM_PROGRAM ?? "") || !!process.env.WT_SESSION || !!process.env.VTE_VERSION || !!process.env.KONSOLE_VERSION || process.env.TERM === "xterm-kitty");
|
|
1310
|
-
}
|
|
1311
|
-
/** Dashboard keys use permission-catalog labels, which can differ from product names. */
|
|
1312
|
-
function platformAccountTokenPermissions(includeAiGateway) {
|
|
1313
|
-
return [
|
|
1314
|
-
{
|
|
1315
|
-
key: "account_settings",
|
|
1316
|
-
type: "read"
|
|
1317
|
-
},
|
|
1318
|
-
{
|
|
1319
|
-
key: "workers_scripts",
|
|
1320
|
-
type: "edit"
|
|
1321
|
-
},
|
|
1322
|
-
{
|
|
1323
|
-
key: "workers_kv_storage",
|
|
1324
|
-
type: "edit"
|
|
1325
|
-
},
|
|
1326
|
-
{
|
|
1327
|
-
key: "workers_r2",
|
|
1328
|
-
type: "edit"
|
|
1329
|
-
},
|
|
1330
|
-
{
|
|
1331
|
-
key: "d1",
|
|
1332
|
-
type: "edit"
|
|
1333
|
-
},
|
|
1334
|
-
{
|
|
1335
|
-
key: "queues",
|
|
1336
|
-
type: "edit"
|
|
1337
|
-
},
|
|
1338
|
-
{
|
|
1339
|
-
key: "account_analytics",
|
|
1340
|
-
type: "read"
|
|
1341
|
-
},
|
|
1342
|
-
{
|
|
1343
|
-
key: "workers_tail",
|
|
1344
|
-
type: "read"
|
|
1345
|
-
},
|
|
1346
|
-
{
|
|
1347
|
-
key: "query_cache",
|
|
1348
|
-
type: "edit"
|
|
1349
|
-
},
|
|
1350
|
-
...includeAiGateway ? [{
|
|
1351
|
-
key: "aig",
|
|
1352
|
-
type: "edit"
|
|
1353
|
-
}] : []
|
|
1354
|
-
];
|
|
1355
|
-
}
|
|
1356
|
-
/**
|
|
1357
|
-
* Account token links cannot preselect a zone: Cloudflare documents only
|
|
1358
|
-
* `permissionGroupKeys` and `name`, and the form puts zone permissions in an
|
|
1359
|
-
* "All Domains" policy. Tell the user which dashboard choice to change.
|
|
1360
|
-
*/
|
|
1361
|
-
function specifiedDomainsInstruction(zones) {
|
|
1362
|
-
return `Change the zone policy from All Domains to Specified Domains → ${zones.join(" and ")}.`;
|
|
1363
|
-
}
|
|
1364
|
-
function plansZoneCreation(plan) {
|
|
1365
|
-
return plan.actions.some((action) => action.kind === "zone" && action.action === "create");
|
|
1366
|
-
}
|
|
1367
|
-
function platformManagementSetupPage(plan, options = {}) {
|
|
1368
|
-
const createsZone = plansZoneCreation(plan);
|
|
1369
|
-
const zoneName = plan.deployment.application.zoneName;
|
|
1370
|
-
const apiHostname = plan.deployment.controlPlane.apiHostname;
|
|
1371
|
-
const access = options.access ?? (plan.deployment.authentication.accessProtection || plan.deployment.authentication.providers.includes("cloudflare-access") ? {
|
|
1372
|
-
protection: !!plan.deployment.authentication.accessProtection,
|
|
1373
|
-
readOnly: false
|
|
1374
|
-
} : void 0);
|
|
1375
|
-
const zones = [...zoneName ? [zoneName] : [], ...apiHostname && apiHostname !== zoneName && !apiHostname.endsWith(`.${zoneName}`) ? [`the zone for ${apiHostname}`] : []];
|
|
1376
|
-
const accessLevel = access && access.readOnly ? "read" : "edit";
|
|
1377
|
-
const appAccess = !!plan.deployment.appAccess;
|
|
1378
|
-
const appAccessLevel = appAccess ? "edit" : accessLevel;
|
|
1379
|
-
const permissions = [
|
|
1380
|
-
...platformAccountTokenPermissions(true),
|
|
1381
|
-
...zoneName || apiHostname || createsZone ? [
|
|
1382
|
-
{
|
|
1383
|
-
key: "zone",
|
|
1384
|
-
type: createsZone ? "edit" : "read"
|
|
1385
|
-
},
|
|
1386
|
-
{
|
|
1387
|
-
key: "dns",
|
|
1388
|
-
type: "edit"
|
|
1389
|
-
},
|
|
1390
|
-
{
|
|
1391
|
-
key: "workers_routes",
|
|
1392
|
-
type: "edit"
|
|
1393
|
-
}
|
|
1394
|
-
] : [],
|
|
1395
|
-
...access || appAccess ? [
|
|
1396
|
-
{
|
|
1397
|
-
key: "access",
|
|
1398
|
-
type: appAccessLevel
|
|
1399
|
-
},
|
|
1400
|
-
{
|
|
1401
|
-
key: "access_acct",
|
|
1402
|
-
type: "read"
|
|
1403
|
-
},
|
|
1404
|
-
...access && access.protection ? [{
|
|
1405
|
-
key: "access_service_token",
|
|
1406
|
-
type: accessLevel
|
|
1407
|
-
}] : []
|
|
1408
|
-
] : [],
|
|
1409
|
-
...zoneName && plan.deployment.application.baseDomain !== zoneName ? [{
|
|
1410
|
-
key: "ssl_and_certificates",
|
|
1411
|
-
type: "read"
|
|
1412
|
-
}] : []
|
|
1413
|
-
];
|
|
1414
|
-
return {
|
|
1415
|
-
title: "Cloudflare management API token",
|
|
1416
|
-
linkInTitle: true,
|
|
1417
|
-
url: "https://dash.cloudflare.com/?" + new URLSearchParams({
|
|
1418
|
-
to: "/" + plan.account.id + "/api-tokens",
|
|
1419
|
-
name: plan.deployment.displayName + " Management",
|
|
1420
|
-
permissionGroupKeys: JSON.stringify(permissions)
|
|
1421
|
-
}),
|
|
1422
|
-
instructions: [
|
|
1423
|
-
"This token lets the Void CLI install your platform. Void will now open a pre-configured token creation site. Please review the permissions and then paste the token here.",
|
|
1424
|
-
`Scope it to ${plan.account.name}.`,
|
|
1425
|
-
...createsZone ? [`Keep the zone policy on All Domains so Void can create ${zoneName}.`] : zones.length ? [specifiedDomainsInstruction(zones)] : []
|
|
1426
|
-
].join("\n")
|
|
1427
|
-
};
|
|
1428
|
-
}
|
|
1429
|
-
function platformSetupPages(plan) {
|
|
1430
|
-
const permissions = [
|
|
1431
|
-
...platformAccountTokenPermissions(plan.actions.some((action) => action.kind === "ai-gateway" && action.action === "inspect")),
|
|
1432
|
-
...plan.deployment.application.zoneName ? [{
|
|
1433
|
-
key: "cache",
|
|
1434
|
-
type: "purge"
|
|
1435
|
-
}] : [],
|
|
1436
|
-
...plan.deployment.capabilities.customDomains ? [{
|
|
1437
|
-
key: "ssl_and_certificates",
|
|
1438
|
-
type: "edit"
|
|
1439
|
-
}] : [],
|
|
1440
|
-
...plan.deployment.capabilities.email ? [
|
|
1441
|
-
{
|
|
1442
|
-
key: "zone",
|
|
1443
|
-
type: "read"
|
|
1444
|
-
},
|
|
1445
|
-
{
|
|
1446
|
-
key: "zone_settings",
|
|
1447
|
-
type: "edit"
|
|
1448
|
-
},
|
|
1449
|
-
{
|
|
1450
|
-
key: "email_routing_address",
|
|
1451
|
-
type: "edit"
|
|
1452
|
-
},
|
|
1453
|
-
{
|
|
1454
|
-
key: "email_routing_rule",
|
|
1455
|
-
type: "edit"
|
|
1456
|
-
},
|
|
1457
|
-
{
|
|
1458
|
-
key: "email_sending",
|
|
1459
|
-
type: "edit"
|
|
1460
|
-
}
|
|
1461
|
-
] : []
|
|
1462
|
-
];
|
|
1463
|
-
const zoneName = plan.deployment.application.zoneName;
|
|
1464
|
-
return {
|
|
1465
|
-
runtime: {
|
|
1466
|
-
title: "Cloudflare runtime token",
|
|
1467
|
-
linkInTitle: true,
|
|
1468
|
-
url: "https://dash.cloudflare.com/?" + new URLSearchParams({
|
|
1469
|
-
to: "/" + plan.account.id + "/api-tokens",
|
|
1470
|
-
name: plan.deployment.displayName + " Runtime",
|
|
1471
|
-
permissionGroupKeys: JSON.stringify(permissions)
|
|
1472
|
-
}),
|
|
1473
|
-
instructions: ["Create a Cloudflare runtime token that Void can use to manage the platform. Please review the permissions and then paste the token here.", ...zoneName && plansZoneCreation(plan) ? [`Keep the zone policy on All Domains so the token can purge cache on ${zoneName} after Void creates it.`] : zoneName ? [specifiedDomainsInstruction([zoneName, ...plan.deployment.capabilities.email ? ["every zone that will carry mail"] : []])] : []].join("\n")
|
|
1474
|
-
},
|
|
1475
|
-
github: {
|
|
1476
|
-
title: "GitHub OAuth App",
|
|
1477
|
-
url: "https://github.com/settings/applications/new",
|
|
1478
|
-
instructions: "GitHub Auth will be used by the users of your Void Platform instance. Register a GitHub app and generate a client secret.\nHomepage: " + plan.apiUrl + "\nRedirect URI: " + plan.apiUrl + "/auth/callback"
|
|
1479
|
-
},
|
|
1480
|
-
r2: {
|
|
1481
|
-
title: "R2 upload token",
|
|
1482
|
-
url: "https://dash.cloudflare.com/?" + new URLSearchParams({
|
|
1483
|
-
to: "/" + plan.account.id + "/r2/api-tokens/create",
|
|
1484
|
-
type: "account"
|
|
1485
|
-
}),
|
|
1486
|
-
instructions: [
|
|
1487
|
-
"Select Object Read & Write.",
|
|
1488
|
-
"Keep Apply to all buckets in this account selected.",
|
|
1489
|
-
"Create the token, then copy the Access Key ID and Secret Access Key into the CLI."
|
|
1490
|
-
].join("\n")
|
|
1491
|
-
}
|
|
1492
|
-
};
|
|
1493
|
-
}
|
|
1494
|
-
function formatPlatformSetupPlan(plan, options = {}) {
|
|
1495
|
-
const writesDns = plan.actions.some((action) => action.kind === "zone" && action.action === "create" || action.kind === "dns-record" && action.action !== "reuse");
|
|
1496
|
-
return [
|
|
1497
|
-
"The installation will guide you through setting up the following credentials:",
|
|
1498
|
-
"",
|
|
1499
|
-
...[
|
|
1500
|
-
...options.managementToken ? [options.managementAccess ? `Cloudflare management API token for ${writesDns ? "DNS changes and " : ""}Access setup` : "Cloudflare management API token for DNS changes"] : [],
|
|
1501
|
-
"PostgreSQL database URL",
|
|
1502
|
-
"Cloudflare runtime token",
|
|
1503
|
-
"R2 upload token",
|
|
1504
|
-
...plan.deployment.authentication.providers.includes("github") ? ["GitHub OAuth App client ID and secret"] : [],
|
|
1505
|
-
...plan.deployment.authentication.providers.filter((provider) => provider !== "github").map((provider) => (provider === "google" ? "Google OAuth" : provider === "oidc" ? "OIDC" : "Cloudflare Access OIDC") + " client ID and secret"),
|
|
1506
|
-
...plan.deployment.authentication.accessProtection ? ["Cloudflare Access application and installer credentials"] : [],
|
|
1507
|
-
...plan.deployment.appAccess ? ["Cloudflare Access check and app-management token when needed (stored encrypted)"] : [],
|
|
1508
|
-
"JWT signing key and project encryption key"
|
|
1509
|
-
].map((credential) => `• ${credential}`)
|
|
1510
|
-
].join("\n");
|
|
1511
|
-
}
|
|
1512
|
-
function platformInstallCommandArguments(options) {
|
|
1513
|
-
const parts = [
|
|
1514
|
-
options.commandName,
|
|
1515
|
-
"platform",
|
|
1516
|
-
"install"
|
|
1517
|
-
];
|
|
1518
|
-
const flag = (name, value) => {
|
|
1519
|
-
if (value) parts.push(name, value);
|
|
1520
|
-
};
|
|
1521
|
-
if (options.resumeId) {
|
|
1522
|
-
parts.push("--resume");
|
|
1523
|
-
flag("--name", options.resumeId);
|
|
1524
|
-
} else {
|
|
1525
|
-
flag("--name", options.installationSlug);
|
|
1526
|
-
flag("--account", options.accountId);
|
|
1527
|
-
flag("--display-name", options.displayName);
|
|
1528
|
-
if (options.workersDev) parts.push("--workers-dev");
|
|
1529
|
-
else {
|
|
1530
|
-
flag("--application-domain", options.applicationDomain);
|
|
1531
|
-
flag("--zone", options.zoneName);
|
|
1532
|
-
if (options.dedicatedZone) parts.push("--dedicated-zone");
|
|
1533
|
-
else parts.push("--no-dedicated-zone");
|
|
1534
|
-
}
|
|
1535
|
-
flag("--control-plane-domain", options.controlPlaneDomain);
|
|
1536
|
-
if (!options.controlPlaneDomain) parts.push("--no-control-plane-domain");
|
|
1537
|
-
}
|
|
1538
|
-
flag("--hyperdrive", options.hyperdrive ?? "");
|
|
1539
|
-
flag("--auth-config", options.authConfig ?? "");
|
|
1540
|
-
if (!options.resumeId && options.appAccess) flag("--app-access", options.appAccess);
|
|
1541
|
-
if (!options.authConfig && !options.resumeId && options.authentication) {
|
|
1542
|
-
flag("--login-methods", options.authentication.providers.join(","));
|
|
1543
|
-
parts.push(options.authentication.accessProtection ? "--access-protection" : "--no-access-protection");
|
|
1544
|
-
}
|
|
1545
|
-
flag("--dashboard-url", options.dashboardUrl ?? "");
|
|
1546
|
-
flag("--runtime", options.runtime);
|
|
1547
|
-
if (options.yes) parts.push("--yes");
|
|
1548
|
-
return parts;
|
|
1549
|
-
}
|
|
1550
|
-
function formatPlatformInstallCommand(options) {
|
|
1551
|
-
return platformInstallCommandArguments(options).map((value) => {
|
|
1552
|
-
if (/^[A-Za-z0-9_@%+=:,./-]+$/.test(value)) return value;
|
|
1553
|
-
return process.platform === "win32" ? `'${value.replaceAll("'", "''")}'` : `'${value.replaceAll("'", "'\\''")}'`;
|
|
1554
|
-
}).join(" ");
|
|
1555
|
-
}
|
|
1556
|
-
function openPlatformSetupPage(page, dependencies = {}) {
|
|
1557
|
-
log.info((page.linkInTitle ? platformSetupLink(page) : page.title) + "\n" + page.instructions);
|
|
1558
|
-
if (!page.linkInTitle) console.log(platformSetupLink({
|
|
1559
|
-
...page,
|
|
1560
|
-
title: "Open " + page.title
|
|
1561
|
-
}));
|
|
1562
|
-
if (dependencies.interactive ?? process.stdin.isTTY === true) try {
|
|
1563
|
-
(dependencies.open ?? ((url) => openBrowser(url, execFile)))(page.url);
|
|
1564
|
-
} catch {
|
|
1565
|
-
log.info("Could not open the browser. Use the link above.");
|
|
1566
|
-
}
|
|
1567
|
-
}
|
|
1568
|
-
//#endregion
|
|
1569
1271
|
//#region src/cli/platform-access-setup.ts
|
|
1570
1272
|
function accessSetupGuide() {
|
|
1571
1273
|
return platformSetupLink({
|
|
@@ -1596,11 +1298,11 @@ async function selectCompanyAccessPolicies(client, initialPolicies, accountId, m
|
|
|
1596
1298
|
let choices;
|
|
1597
1299
|
if (options.length === 0) {
|
|
1598
1300
|
log.info("No reusable Allow or Deny policies were found in this account. Create an Allow policy for your company, or refresh after saving one.");
|
|
1599
|
-
choices = [
|
|
1301
|
+
choices = [platformPromptAnswer(await select({
|
|
1600
1302
|
message: "Company Access policies:",
|
|
1601
1303
|
options: actions
|
|
1602
1304
|
}))];
|
|
1603
|
-
} else choices =
|
|
1305
|
+
} else choices = platformPromptAnswer(await multiselect({
|
|
1604
1306
|
message: "Company Access policies (select all that apply):",
|
|
1605
1307
|
options: [...options, ...actions],
|
|
1606
1308
|
initialValues: selectedIds,
|
|
@@ -1619,7 +1321,7 @@ async function selectCompanyAccessPolicies(client, initialPolicies, accountId, m
|
|
|
1619
1321
|
title: "Open Cloudflare account",
|
|
1620
1322
|
url: `https://dash.cloudflare.com/${encodeURIComponent(accountId)}`
|
|
1621
1323
|
}));
|
|
1622
|
-
if (!
|
|
1324
|
+
if (!platformPromptAnswer(await confirm({
|
|
1623
1325
|
message: "Have you saved the new policy?",
|
|
1624
1326
|
initialValue: true
|
|
1625
1327
|
}))) continue;
|
|
@@ -1700,10 +1402,6 @@ function parsePlatformAccessSetupSpec(input) {
|
|
|
1700
1402
|
}
|
|
1701
1403
|
return value;
|
|
1702
1404
|
}
|
|
1703
|
-
function answer$2(value) {
|
|
1704
|
-
if (isCancel(value) || typeof value === "symbol") throw new Error("platform: Cancelled.");
|
|
1705
|
-
return value;
|
|
1706
|
-
}
|
|
1707
1405
|
function secretReference(name) {
|
|
1708
1406
|
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(name) || !process.env[name]) throw new Error("platform: Supply the referenced Access credential in the environment.");
|
|
1709
1407
|
return process.env[name];
|
|
@@ -1742,7 +1440,7 @@ async function preparePlatformAccessSetup(input) {
|
|
|
1742
1440
|
if (input.protection) throw new Error("platform: Protection requires cloudflareAccess create or existing application verification in --auth-config.");
|
|
1743
1441
|
return;
|
|
1744
1442
|
}
|
|
1745
|
-
const mode =
|
|
1443
|
+
const mode = platformPromptAnswer(await select({
|
|
1746
1444
|
message: "Cloudflare Access setup:",
|
|
1747
1445
|
options: [
|
|
1748
1446
|
{
|
|
@@ -1765,17 +1463,17 @@ async function preparePlatformAccessSetup(input) {
|
|
|
1765
1463
|
spec = { mode };
|
|
1766
1464
|
if (mode === "existing") {
|
|
1767
1465
|
log.info("Enter the account that owns your company’s Access configuration. This may differ from the account hosting Void.");
|
|
1768
|
-
spec.accountId =
|
|
1466
|
+
spec.accountId = platformPromptAnswer(await text$1({
|
|
1769
1467
|
message: "Cloudflare identity account ID:",
|
|
1770
1468
|
initialValue: input.plan.account.id
|
|
1771
1469
|
}));
|
|
1772
1470
|
if (input.login) {
|
|
1773
1471
|
log.info("Enter the ID of the Access application that provides company sign-in to Void.");
|
|
1774
|
-
spec.loginApplicationId =
|
|
1472
|
+
spec.loginApplicationId = platformPromptAnswer(await text$1({ message: "Existing Access OIDC application ID:" }));
|
|
1775
1473
|
}
|
|
1776
1474
|
if (input.protection) {
|
|
1777
1475
|
log.info("Enter the ID of the Access application that protects the platform’s UI and APIs.");
|
|
1778
|
-
spec.protectionApplicationId =
|
|
1476
|
+
spec.protectionApplicationId = platformPromptAnswer(await text$1({ message: "Existing Access protection application ID:" }));
|
|
1779
1477
|
}
|
|
1780
1478
|
}
|
|
1781
1479
|
}
|
|
@@ -1795,7 +1493,7 @@ async function preparePlatformAccessSetup(input) {
|
|
|
1795
1493
|
if (!(error instanceof PlatformCloudflareApiError) || ![401, 403].includes(error.status) || !process.stdin.isTTY || credential) throw error;
|
|
1796
1494
|
log.info(`Your current token lacks the required Access permissions for account ${accountId}. Create a token for that account using the permissions in the setup guide.`);
|
|
1797
1495
|
console.log(accessSetupGuide());
|
|
1798
|
-
const token =
|
|
1496
|
+
const token = platformPromptAnswer(await password({ message: "Access setup API token:" }));
|
|
1799
1497
|
input.save({ accessManagementToken: token });
|
|
1800
1498
|
management = new PlatformCloudflareClient(token, { apiBase: input.client.apiBaseUrl });
|
|
1801
1499
|
client = new PlatformAccessClient(management, accountId);
|
|
@@ -1804,7 +1502,7 @@ async function preparePlatformAccessSetup(input) {
|
|
|
1804
1502
|
policies = await client.list("policies");
|
|
1805
1503
|
}
|
|
1806
1504
|
if (!spec.identityProviderIds && process.stdin.isTTY) log.info("Choose how employees sign in—for example, your company’s Okta or Google Workspace connection.");
|
|
1807
|
-
const identityProviderIds = spec.identityProviderIds ?? (process.stdin.isTTY ?
|
|
1505
|
+
const identityProviderIds = spec.identityProviderIds ?? (process.stdin.isTTY ? platformPromptAnswer(await multiselect({
|
|
1808
1506
|
message: "Company identity providers:",
|
|
1809
1507
|
required: true,
|
|
1810
1508
|
options: providers.filter((provider) => typeof provider.id === "string").map(platformAccessIdentityProvider).map((provider) => ({
|
|
@@ -1839,9 +1537,9 @@ async function preparePlatformAccessSetup(input) {
|
|
|
1839
1537
|
else if (process.stdin.isTTY) {
|
|
1840
1538
|
log.info("This lets the installer reach the protected platform during setup. Use a service token allowed by the existing Access application.");
|
|
1841
1539
|
serviceToken = {
|
|
1842
|
-
id:
|
|
1843
|
-
clientId:
|
|
1844
|
-
clientSecret:
|
|
1540
|
+
id: platformPromptAnswer(await text$1({ message: "Existing admitted Access service token ID:" })),
|
|
1541
|
+
clientId: platformPromptAnswer(await password({ message: "Access service token client ID:" })),
|
|
1542
|
+
clientSecret: platformPromptAnswer(await password({ message: "Access service token client secret:" }))
|
|
1845
1543
|
};
|
|
1846
1544
|
input.save({ accessExistingServiceTokenJson: JSON.stringify(serviceToken) });
|
|
1847
1545
|
}
|
|
@@ -1862,7 +1560,7 @@ async function preparePlatformAccessSetup(input) {
|
|
|
1862
1560
|
};
|
|
1863
1561
|
console.log(JSON.stringify({ accessPlan: reviewed }, null, 2));
|
|
1864
1562
|
if (!input.yes) {
|
|
1865
|
-
if (!process.stdin.isTTY || !
|
|
1563
|
+
if (!process.stdin.isTTY || !platformPromptAnswer(await confirm({
|
|
1866
1564
|
message: "Apply this Access configuration?",
|
|
1867
1565
|
initialValue: false
|
|
1868
1566
|
}))) throw new Error("platform: Access setup changes require confirmation or --yes.");
|
|
@@ -1877,7 +1575,7 @@ async function preparePlatformAccessSetup(input) {
|
|
|
1877
1575
|
let loginClientSecret = spec.loginClientSecretEnv ? secretReference(spec.loginClientSecretEnv) : input.checkpoint.accessExistingLoginSecret;
|
|
1878
1576
|
if (input.login && spec.mode === "existing" && !loginClientSecret && process.stdin.isTTY) {
|
|
1879
1577
|
log.info("Enter the client secret from the existing Access login application’s OIDC settings.");
|
|
1880
|
-
loginClientSecret =
|
|
1578
|
+
loginClientSecret = platformPromptAnswer(await password({ message: "Existing Access OIDC client secret:" }));
|
|
1881
1579
|
input.save({ accessExistingLoginSecret: loginClientSecret });
|
|
1882
1580
|
}
|
|
1883
1581
|
const result = await provisionPlatformAccess(client, {
|
|
@@ -1944,8 +1642,8 @@ async function verifyPlatformManagementAccess(client, accountId, access) {
|
|
|
1944
1642
|
}
|
|
1945
1643
|
function assertPlatformOperatorCredentialCanApplyPlan(credential, plan, access) {
|
|
1946
1644
|
if (!platformOperatorNeedsManagementToken(credential, plan, access)) return;
|
|
1947
|
-
const createsZone = plan
|
|
1948
|
-
const writesDns = plan
|
|
1645
|
+
const createsZone = planCreatesZone(plan);
|
|
1646
|
+
const writesDns = planWritesDns(plan);
|
|
1949
1647
|
const permissions = [
|
|
1950
1648
|
...createsZone ? ["Account → Zone → Edit"] : [],
|
|
1951
1649
|
...writesDns ? ["Zone → DNS → Edit"] : [],
|
|
@@ -1958,7 +1656,13 @@ function assertPlatformOperatorCredentialCanApplyPlan(credential, plan, access)
|
|
|
1958
1656
|
throw new Error(`platform: Cloudflare browser login cannot authorize the planned ${access ? "Access setup" : "zone or DNS changes"}. Set CLOUDFLARE_API_TOKEN with ${permissions.join(" and ")}, scoped to the selected account${createsZone || writesDns ? " and application zone" : ""}, then rerun the command.`);
|
|
1959
1657
|
}
|
|
1960
1658
|
function platformOperatorNeedsManagementToken(credential, plan, access) {
|
|
1961
|
-
return credential.source === "oauth" && (!!access || plan
|
|
1659
|
+
return credential.source === "oauth" && (!!access || planCreatesZone(plan) || planWritesDns(plan));
|
|
1660
|
+
}
|
|
1661
|
+
function planCreatesZone(plan) {
|
|
1662
|
+
return plan.actions.some((action) => action.kind === "zone" && action.action === "create");
|
|
1663
|
+
}
|
|
1664
|
+
function planWritesDns(plan) {
|
|
1665
|
+
return plan.actions.some((action) => action.kind === "dns-record" && action.action !== "reuse");
|
|
1962
1666
|
}
|
|
1963
1667
|
async function resolvePlatformCloudflareCredential(dependencies = {}) {
|
|
1964
1668
|
const { credential } = await resolvePlatformCloudflareCredentialWithInput(async () => void 0, dependencies);
|
|
@@ -2022,26 +1726,18 @@ async function readExistingCredential(dependencies, runWrangler) {
|
|
|
2022
1726
|
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.");
|
|
2023
1727
|
return await readWranglerOAuthCredential(runWrangler);
|
|
2024
1728
|
}
|
|
2025
|
-
async function readWranglerOAuthCredential(runWrangler
|
|
1729
|
+
async function readWranglerOAuthCredential(runWrangler) {
|
|
2026
1730
|
const result = await runWrangler({ type: "auth.token" }, true);
|
|
2027
1731
|
if (result.status !== 0 || result.signal || result.error) return null;
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
};
|
|
2035
|
-
} catch {
|
|
2036
|
-
return null;
|
|
2037
|
-
}
|
|
1732
|
+
const parsed = result.data;
|
|
1733
|
+
if (!parsed || parsed.type !== "oauth" || typeof parsed.token !== "string" || !parsed.token.trim()) return null;
|
|
1734
|
+
return {
|
|
1735
|
+
source: "oauth",
|
|
1736
|
+
token: parsed.token.trim()
|
|
1737
|
+
};
|
|
2038
1738
|
}
|
|
2039
1739
|
//#endregion
|
|
2040
1740
|
//#region src/cli/platform-app-access.ts
|
|
2041
|
-
function answer$1(value) {
|
|
2042
|
-
if (isCancel(value) || typeof value === "symbol") throw new Error("platform: Cancelled.");
|
|
2043
|
-
return value;
|
|
2044
|
-
}
|
|
2045
1741
|
async function selectInstallationAppAccess(authentication, recorded, choice) {
|
|
2046
1742
|
const config = authentication.file?.appAccess;
|
|
2047
1743
|
if (config && (typeof config !== "object" || Array.isArray(config) || "apiToken" in config || config.tokenEnv !== void 0 && (typeof config.tokenEnv !== "string" || !/^[A-Z_][A-Z0-9_]*$/.test(config.tokenEnv)))) throw new Error("platform: App access configuration must use tokenEnv; plaintext tokens are not accepted.");
|
|
@@ -2057,7 +1753,7 @@ async function selectInstallationAppAccess(authentication, recorded, choice) {
|
|
|
2057
1753
|
return recorded.appAccess;
|
|
2058
1754
|
}
|
|
2059
1755
|
const protectedPlatform = !!authentication.authentication.accessProtection;
|
|
2060
|
-
const selected = supplied ?? (!process.stdin.isTTY ? protectedPlatform ? "platform" : "public" :
|
|
1756
|
+
const selected = supplied ?? (!process.stdin.isTTY ? protectedPlatform ? "platform" : "public" : platformPromptAnswer(await select({
|
|
2061
1757
|
message: "Who should be able to access deployed apps?",
|
|
2062
1758
|
initialValue: protectedPlatform ? "platform" : "public",
|
|
2063
1759
|
options: [
|
|
@@ -2128,7 +1824,7 @@ async function prepareInstallationAppAccess(input) {
|
|
|
2128
1824
|
const collectToken = async () => {
|
|
2129
1825
|
if (!process.stdin.isTTY) throw new Error("platform: App access requires VOID_PLATFORM_APP_ACCESS_TOKEN or appAccess.tokenEnv in --auth-config, scoped to the hosting account.");
|
|
2130
1826
|
tokenPage();
|
|
2131
|
-
const value = String(
|
|
1827
|
+
const value = String(platformPromptAnswer(await password({ message: "App access API token (stored encrypted when app rules are needed):" }))).trim();
|
|
2132
1828
|
if (!value || /\s/.test(value)) throw new Error("platform: An app access token without whitespace is required.");
|
|
2133
1829
|
input.save({
|
|
2134
1830
|
appAccessToken: value,
|
|
@@ -2172,7 +1868,7 @@ async function prepareInstallationAppAccess(input) {
|
|
|
2172
1868
|
if (!organization) throw new Error(`platform: Enable Zero Trust in account ${input.plan.account.name}, then resume to configure app access.`);
|
|
2173
1869
|
if (!token) {
|
|
2174
1870
|
log.info("Void needs an Access-management token stored encrypted to manage access for future apps and custom domains.");
|
|
2175
|
-
if (reusable && process.stdin.isTTY &&
|
|
1871
|
+
if (reusable && process.stdin.isTTY && platformPromptAnswer(await confirm({
|
|
2176
1872
|
message: "Reuse the setup token for ongoing app access management?",
|
|
2177
1873
|
initialValue: true
|
|
2178
1874
|
}))) {
|
|
@@ -2192,7 +1888,7 @@ async function prepareInstallationAppAccess(input) {
|
|
|
2192
1888
|
if (!process.stdin.isTTY) throw new Error("platform: Set appAccess.identityProviderIds in --auth-config for the hosting account.");
|
|
2193
1889
|
const providers = (await access.list("identity_providers")).map(platformAccessIdentityProvider);
|
|
2194
1890
|
if (!providers.length) throw new Error(`platform: Add an identity provider in Zero Trust for ${input.plan.account.name}, then resume.`);
|
|
2195
|
-
identityProviderIds =
|
|
1891
|
+
identityProviderIds = platformPromptAnswer(await multiselect({
|
|
2196
1892
|
message: "App identity providers:",
|
|
2197
1893
|
required: true,
|
|
2198
1894
|
options: providers.map((p) => ({
|
|
@@ -5227,11 +4923,7 @@ async function ensurePlatformAccessHealthChecks(input) {
|
|
|
5227
4923
|
recorded.id = created.id;
|
|
5228
4924
|
save();
|
|
5229
4925
|
} catch (error) {
|
|
5230
|
-
if (error
|
|
5231
|
-
408,
|
|
5232
|
-
409,
|
|
5233
|
-
429
|
|
5234
|
-
].includes(error.status)) {
|
|
4926
|
+
if (platformAccessCreateRejected(error)) {
|
|
5235
4927
|
recorded.pending = false;
|
|
5236
4928
|
save();
|
|
5237
4929
|
}
|
|
@@ -5281,7 +4973,7 @@ async function verifyInstalledPlatformAccessProtection(input) {
|
|
|
5281
4973
|
].map((value) => new URL(value).origin).some((origin) => !origins.includes(origin)) || protection.applications.some((entry) => entry.audience !== app.aud || !platformAccessPublicDestinations(app).includes(new URL(entry.origin).hostname))) throw new Error("platform: Access audiences and complete origin coverage must match the active platform protection. Restore the current Access checkpoint or repair its applications.");
|
|
5282
4974
|
for (const other of await access.list("apps")) {
|
|
5283
4975
|
if (other.id === app.id) continue;
|
|
5284
|
-
if (
|
|
4976
|
+
if (platformAccessOverlapsOrigins(other, origins)) throw new Error("platform: Another Access application overlaps a protected platform origin. Reconcile it before maintenance.");
|
|
5285
4977
|
}
|
|
5286
4978
|
const liveToken = (await access.list("service_tokens")).find((entry) => entry.id === service.id);
|
|
5287
4979
|
const expiry = liveToken?.expires_at;
|
|
@@ -5292,7 +4984,7 @@ async function verifyInstalledPlatformAccessProtection(input) {
|
|
|
5292
4984
|
}
|
|
5293
4985
|
const existingWorkers = input.plan.actions.filter((action) => action.kind === "worker" && action.action === "update").map((action) => action.name);
|
|
5294
4986
|
if (existingWorkers.length) {
|
|
5295
|
-
const { verifyProtectionWorkerOrigins } = await import("./platform-auth-protection-
|
|
4987
|
+
const { verifyProtectionWorkerOrigins } = await import("./platform-auth-protection-zxDr0hWW.mjs");
|
|
5296
4988
|
await verifyProtectionWorkerOrigins({
|
|
5297
4989
|
request: input.client.request.bind(input.client),
|
|
5298
4990
|
listWorkerDomains: input.client.listWorkerDomains.bind(input.client),
|
|
@@ -7813,10 +7505,6 @@ function platformManagementAccessForAuthentication(selection, accountId, checkpo
|
|
|
7813
7505
|
readOnly: spec?.mode === "existing"
|
|
7814
7506
|
};
|
|
7815
7507
|
}
|
|
7816
|
-
function answer(value) {
|
|
7817
|
-
if (isCancel(value) || typeof value === "symbol") throw new Error("platform: Cancelled.");
|
|
7818
|
-
return value;
|
|
7819
|
-
}
|
|
7820
7508
|
async function selectInstallationAuthentication(file, recorded, choices = {}) {
|
|
7821
7509
|
if (file) {
|
|
7822
7510
|
const input = JSON.parse(await readFile(file, "utf8"));
|
|
@@ -7841,7 +7529,7 @@ async function selectInstallationAuthentication(file, recorded, choices = {}) {
|
|
|
7841
7529
|
return { authentication: recorded };
|
|
7842
7530
|
}
|
|
7843
7531
|
if (!process.stdin.isTTY && !choices.loginMethods && choices.accessProtection === void 0) return { authentication: { providers: ["github"] } };
|
|
7844
|
-
const providers = choices.loginMethods ?? (!process.stdin.isTTY ? ["github"] :
|
|
7532
|
+
const providers = choices.loginMethods ?? (!process.stdin.isTTY ? ["github"] : platformPromptAnswer(await multiselect({
|
|
7845
7533
|
message: "Platform login methods (select all that apply):",
|
|
7846
7534
|
initialValues: [],
|
|
7847
7535
|
required: true,
|
|
@@ -7864,7 +7552,7 @@ async function selectInstallationAuthentication(file, recorded, choices = {}) {
|
|
|
7864
7552
|
}
|
|
7865
7553
|
]
|
|
7866
7554
|
})));
|
|
7867
|
-
const protection = choices.accessProtection ?? (!process.stdin.isTTY ? false :
|
|
7555
|
+
const protection = choices.accessProtection ?? (!process.stdin.isTTY ? false : platformPromptAnswer(await confirm({
|
|
7868
7556
|
message: "Also protect the platform UI and APIs with Cloudflare Access?",
|
|
7869
7557
|
initialValue: false
|
|
7870
7558
|
})));
|
|
@@ -7887,7 +7575,7 @@ async function collectInstallationAuthentication(selection, plan, checkpoint, sa
|
|
|
7887
7575
|
}
|
|
7888
7576
|
const prompt = async (message, initialValue = "", masked = false) => {
|
|
7889
7577
|
if (!process.stdin.isTTY) throw new Error(`platform: ${message} Supply it through --auth-config and environment references.`);
|
|
7890
|
-
return masked ?
|
|
7578
|
+
return masked ? platformPromptAnswer(await password({ message })) : platformPromptAnswer(await text$1({
|
|
7891
7579
|
message,
|
|
7892
7580
|
initialValue
|
|
7893
7581
|
}));
|
|
@@ -7954,7 +7642,7 @@ async function collectInstallationAuthentication(selection, plan, checkpoint, sa
|
|
|
7954
7642
|
save({ [partialKey]: JSON.stringify(connection) });
|
|
7955
7643
|
connections.push(connection);
|
|
7956
7644
|
}
|
|
7957
|
-
const administratorConnectionId = selection.file?.administratorConnectionId ?? (connections.length === 1 ? connections[0].configuration.id : process.stdin.isTTY ?
|
|
7645
|
+
const administratorConnectionId = selection.file?.administratorConnectionId ?? (connections.length === 1 ? connections[0].configuration.id : process.stdin.isTTY ? platformPromptAnswer(await select({
|
|
7958
7646
|
message: "Login method for the first administrator:",
|
|
7959
7647
|
options: connections.map((entry) => ({
|
|
7960
7648
|
value: entry.configuration.id,
|
|
@@ -7985,7 +7673,7 @@ async function collectInstallationAuthentication(selection, plan, checkpoint, sa
|
|
|
7985
7673
|
} : { mode: "restricted" });
|
|
7986
7674
|
if (!selection.file && !protection && process.stdin.isTTY) {
|
|
7987
7675
|
const eligible = connections.filter((entry) => entry.configuration.kind !== "github" && (entry.configuration.kind !== "google" || entry.configuration.allowedDomains.length > 0));
|
|
7988
|
-
const mode =
|
|
7676
|
+
const mode = platformPromptAnswer(await select({
|
|
7989
7677
|
message: "Who can create an account?",
|
|
7990
7678
|
initialValue: eligible.length ? "company" : "restricted",
|
|
7991
7679
|
options: [
|
|
@@ -8003,7 +7691,7 @@ async function collectInstallationAuthentication(selection, plan, checkpoint, sa
|
|
|
8003
7691
|
}
|
|
8004
7692
|
]
|
|
8005
7693
|
}));
|
|
8006
|
-
const ids = mode === "company" ?
|
|
7694
|
+
const ids = mode === "company" ? platformPromptAnswer(await multiselect({
|
|
8007
7695
|
message: "Company login methods that qualify new users:",
|
|
8008
7696
|
required: true,
|
|
8009
7697
|
initialValues: eligible.map((entry) => entry.configuration.id),
|
|
@@ -8188,24 +7876,25 @@ function resolvePlatformInstallDatabaseUrl(checkpoint, manifest = null) {
|
|
|
8188
7876
|
}
|
|
8189
7877
|
async function runPlatformLifecycleCommand(commandArgs) {
|
|
8190
7878
|
if (commandArgs.subcommand === "domain") {
|
|
8191
|
-
const { runPlatformDomainCommand } = await import("./platform-domain-
|
|
7879
|
+
const { runPlatformDomainCommand } = await import("./platform-domain-p0kobLV8.mjs");
|
|
8192
7880
|
await runPlatformDomainCommand(commandArgs);
|
|
8193
7881
|
return;
|
|
8194
7882
|
}
|
|
8195
7883
|
if (commandArgs.subcommand === "discover") {
|
|
8196
7884
|
const client = new PlatformCloudflareClient((await resolvePlatformCloudflareCredential()).token);
|
|
8197
7885
|
const accountId = await selectAccount(await readAccounts(client), commandArgs.account);
|
|
8198
|
-
const { recoverPlatformInstallations } = await import("./platform-recovery-
|
|
7886
|
+
const { recoverPlatformInstallations } = await import("./platform-recovery-PvNS9Nl2.mjs");
|
|
8199
7887
|
const recovered = await recoverPlatformInstallations(client, accountId, void 0, commandArgs.selector);
|
|
8200
7888
|
if (recovered.length === 0) {
|
|
8201
7889
|
log.info(`No recoverable Void platform installations were found in ${accountId}.`);
|
|
8202
7890
|
return;
|
|
8203
7891
|
}
|
|
8204
|
-
for (const manifest of recovered) log.
|
|
7892
|
+
for (const manifest of recovered) log.step(`Recovered ${manifest.deployment.displayName} (${manifest.id}) at ${manifest.endpoints.apiUrl}.`);
|
|
7893
|
+
printSuccess(`Recovered ${recovered.length} platform installation${recovered.length === 1 ? "" : "s"}.`);
|
|
8205
7894
|
return;
|
|
8206
7895
|
}
|
|
8207
7896
|
if (commandArgs.subcommand !== "install") {
|
|
8208
|
-
const { runInstalledPlatformCommand } = await import("./platform-management-
|
|
7897
|
+
const { runInstalledPlatformCommand } = await import("./platform-management-oi-SvI3f.mjs");
|
|
8209
7898
|
await runInstalledPlatformCommand(commandArgs);
|
|
8210
7899
|
return;
|
|
8211
7900
|
}
|
|
@@ -8378,7 +8067,7 @@ async function runPlatformLifecycleCommand(commandArgs) {
|
|
|
8378
8067
|
progress?.stop("Read the saved installation.");
|
|
8379
8068
|
progress = void 0;
|
|
8380
8069
|
if (authoritative) {
|
|
8381
|
-
const { selectAuthoritativePlatformManifest } = await import("./platform-management-
|
|
8070
|
+
const { selectAuthoritativePlatformManifest } = await import("./platform-management-oi-SvI3f.mjs");
|
|
8382
8071
|
const selected = selectAuthoritativePlatformManifest(existing, authoritative);
|
|
8383
8072
|
authoritativeProvisionIntents = true;
|
|
8384
8073
|
if (!args.plan && JSON.stringify(selected) !== JSON.stringify(existing)) writeInstallationManifest(selected);
|
|
@@ -8783,7 +8472,7 @@ async function runPlatformLifecycleCommand(commandArgs) {
|
|
|
8783
8472
|
})).actions.filter((action) => action.kind === "worker"),
|
|
8784
8473
|
revalidateBeforeWorkerDeploy: (manifest, action) => revalidatePlatformInstallAction(client, plan, manifest, action),
|
|
8785
8474
|
verifyExistingOwnership: async (manifest, databaseCheckpointExists) => {
|
|
8786
|
-
const { verifyPlatformInstallationOwnership } = await import("./platform-management-
|
|
8475
|
+
const { verifyPlatformInstallationOwnership } = await import("./platform-management-oi-SvI3f.mjs");
|
|
8787
8476
|
const retainedReplacementKeys = new Set(plan.actions.filter((action) => {
|
|
8788
8477
|
const previous = manifest.resources.find((resource) => resource.key === action.key);
|
|
8789
8478
|
return action.action === "create" && previous && previous.name !== action.name;
|
|
@@ -8807,7 +8496,6 @@ async function runPlatformLifecycleCommand(commandArgs) {
|
|
|
8807
8496
|
outro(`Installation ${result.manifest.id} is safely checkpointed.`);
|
|
8808
8497
|
return;
|
|
8809
8498
|
}
|
|
8810
|
-
log.success(`${result.manifest.deployment.displayName} is installed at ${new URL("/admin", plan.apiUrl).href}.`);
|
|
8811
8499
|
log.info(`API URL: ${plan.apiUrl}`);
|
|
8812
8500
|
if (result.emailOperationId) log.info(`Shared email routing ready. Operation: ${result.emailOperationId}.`);
|
|
8813
8501
|
const completedAuthCode = readInstallationRecoverySecrets(result.manifest)?.authBootstrapCode;
|
|
@@ -8817,7 +8505,8 @@ async function runPlatformLifecycleCommand(commandArgs) {
|
|
|
8817
8505
|
log.info("Confirm your identity in the browser, then test and enable any additional login methods in Settings.");
|
|
8818
8506
|
}
|
|
8819
8507
|
if (!plan.deployment.application.zoneName) log.info("Apps will use workers.dev addresses. When your domain is ready: void platform domain set <domain>");
|
|
8820
|
-
|
|
8508
|
+
log.info("Run `void account login`, then deploy an app with `void deploy --platform void`.");
|
|
8509
|
+
printSuccess(`${result.manifest.deployment.displayName} is installed at ${new URL("/admin", plan.apiUrl).href}.`);
|
|
8821
8510
|
} catch (error) {
|
|
8822
8511
|
progress?.error("Platform installation failed.");
|
|
8823
8512
|
progress = void 0;
|