void 0.22.0 → 0.23.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 +5 -1
- package/dist/{account-cmd-CjyxcGkM.mjs → account-cmd-C84Ee8cO.mjs} +4 -4
- package/dist/{scan-ClYmX3sa.mjs → application-analysis-BVsVqc11.mjs} +135 -18
- package/dist/application-routing-B7QEjqSR.mjs +27 -0
- package/dist/{auth-CZuiVsFh.mjs → auth-CCjt0hcq.mjs} +1 -1
- package/dist/{auth-DLNN0D3Z.mjs → auth-CSkdO2Bb.mjs} +4 -47
- package/dist/{auth-link-BLO4ptzo.mjs → auth-link-CioEg6uY.mjs} +4 -4
- package/dist/{auth-router-ZUg9MF_U.mjs → auth-router-BsR981d4.mjs} +4 -4
- package/dist/{better-auth-shared-rsBGBvWJ.mjs → better-auth-shared-hy6RPh9W.mjs} +13 -2
- package/dist/{build-cmd-BxR5FROK.mjs → build-cmd-LzvNJORH.mjs} +17 -5
- package/dist/{cache-D0sWhgKI.mjs → cache-C4MvnrMH.mjs} +2 -2
- package/dist/{cancel-deploy-D4NUqFbi.mjs → cancel-deploy-abUxpP2n.mjs} +2 -2
- package/dist/{cf-build-output-BJ6yGEIS.mjs → cf-build-output-BPqOT964.mjs} +2 -1
- package/dist/cf-build-output-_0HNWysu.mjs +2 -0
- package/dist/cli/cli.mjs +80 -455
- package/dist/cli/{cf-compat.mjs → cloudflare-operation-process.mjs} +442 -421
- package/dist/cli/env-schema-probe.d.mts +2 -1
- package/dist/cli/env-schema-probe.mjs +3 -3
- package/dist/client-Cu7jWiF1.mjs +2 -0
- package/dist/{client-BTZ3XkrB.mjs → client-RV8NVeB8.mjs} +140 -21
- package/dist/{cloudflare-auth-DQkqoMYa.mjs → cloudflare-auth-Qdc7tw8F.mjs} +41 -38
- package/dist/{cloudflare-cmd-BKlfGHAy.mjs → cloudflare-cmd-BcrVyTmJ.mjs} +5 -5
- package/dist/cloudflare-config-Bktvwtpf.mjs +182 -0
- package/dist/{cloudflare-connect-Ctmrw579.mjs → cloudflare-connect-B8uPZ4nx.mjs} +3 -3
- package/dist/{cloudflare-operations-BT6OWFBk.mjs → cloudflare-operations-AiWashgg.mjs} +1 -1
- package/dist/{cloudflare-operations-B9tzgjmf.mjs → cloudflare-operations-fxHb-byx.mjs} +116 -172
- package/dist/{preset-UHj9ARyP.mjs → cloudflare-process-B-wekeR6.mjs} +93 -6
- package/dist/{config-VavjpDnp.d.mts → config-BMHb8RCj.d.mts} +1 -0
- package/dist/config-C_XRIPx2.mjs +89 -0
- package/dist/config-entry.d.mts +1 -1
- package/dist/{connect-Dg-WkW-C.mjs → connect-Bd4kJd9U.mjs} +5 -5
- package/dist/{create-project-DdoqwFLF.mjs → create-project-Boczwj5r.mjs} +1 -1
- package/dist/{create-project-l9J7pbtm.mjs → create-project-bMf6ffLZ.mjs} +2 -2
- package/dist/{db-gp2sCXyN.mjs → db-8uG64XLl.mjs} +21 -21
- package/dist/{delete-TTedbH6B.mjs → delete-NvbiyeJf.mjs} +2 -2
- package/dist/{deploy-CH-o2CaZ.mjs → deploy-DzAIwqNU.mjs} +908 -582
- package/dist/{deploy-B19L2Bra.mjs → deploy-bjXdFCtn.mjs} +1 -1
- package/dist/{domain-JRF59P_r.mjs → domain-y5Tvydvo.mjs} +3 -3
- package/dist/{email-Bo6G9LOZ.mjs → email-B3umsW75.mjs} +13 -28
- package/dist/{env-BYOrWQnv.mjs → env-BS6qYHDb.mjs} +4 -4
- package/dist/{env-public-BxU_0yTL.d.mts → env-public-BX_r8HR6.d.mts} +1 -1
- package/dist/{env-validation-BB4GkLxn.mjs → env-validation-BPn7vk-V.mjs} +18 -71
- package/dist/{env-validation-BXge7uyK.mjs → env-validation-DbTg7-ar.mjs} +1 -1
- package/dist/{fetch-CXDChK7B.mjs → fetch-BIZJh7vR.mjs} +2 -2
- package/dist/{fetch-stream-AOByI7Ki.mjs → fetch-stream-IvCYKyQL.mjs} +24 -4
- package/dist/{gen-sCtlCOdA.mjs → gen-B580--vC.mjs} +2 -2
- package/dist/gen-BVaUUumi.mjs +2 -0
- package/dist/{github-cmd-0-7PexDq.mjs → github-cmd-v45BdfKX.mjs} +2 -2
- package/dist/{handler-HEcZsaij.d.mts → handler-CZ4nAylQ.d.mts} +1 -1
- package/dist/help-DofyZuY7.mjs +2 -0
- package/dist/{help-GKtwl07I.mjs → help-daGKjXGk.mjs} +229 -747
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +288 -1502
- package/dist/info-B97bTX9N.mjs +113 -0
- package/dist/{init-FZx3Elvz.mjs → init-Bvy7zrBo.mjs} +46 -15
- package/dist/limits-Bq5LG8Id.d.mts +27 -0
- package/dist/limits-Cjuk2VPm.mjs +68 -0
- package/dist/{link-BrQfb_CU.mjs → link-CDqqCjFl.mjs} +3 -3
- package/dist/{list-D44jmIAM.mjs → list-CZj0dzKY.mjs} +3 -3
- package/dist/{live-CKJlvlNp.d.mts → live-Chw1eIMv.d.mts} +1 -1
- package/dist/{local-d1-Bg9OzEEO.mjs → local-d1-2CMnpuW_.mjs} +2 -2
- package/dist/login-DYt_An22.mjs +2 -0
- package/dist/{login-CAsAsQ-_.mjs → login-UZKFM_u7.mjs} +3 -3
- package/dist/{logs-BjKvFnVM.mjs → logs-CUZ6t9t3.mjs} +3 -3
- package/dist/migrate-8_2u55MD.mjs +2 -0
- package/dist/{migrate-BPITvDJN.mjs → migrate-DHul7PRV.mjs} +2 -1
- package/dist/{node-Dt7z256D.mjs → node-BkyRWRx8.mjs} +1 -1
- package/dist/operator-args-CLgKGlwU.mjs +690 -0
- package/dist/{operator-cmd-BK5CCiT9.mjs → operator-cmd-DBA6dl0m.mjs} +68 -22
- package/dist/pages/client.d.mts +34 -2
- package/dist/pages/client.mjs +59 -3
- package/dist/pages/index.d.mts +1 -1
- package/dist/pages/index.mjs +1 -1
- package/dist/pages/islands-plugin.mjs +1 -1
- package/dist/pages/protocol.d.mts +2 -2
- package/dist/pages/protocol.mjs +2 -308
- package/dist/{parse-filename-DioPHiR9.mjs → parse-filename-CUbj-1MP.mjs} +35 -1
- package/dist/plan-D1Q5rf-r.mjs +2 -0
- package/dist/plan-NPpwZ_kc.mjs +58 -0
- package/dist/platform-args-BJdRtlLq.mjs +506 -0
- package/dist/platform-args-D3RXyR6h.mjs +2 -0
- package/dist/{platform-auth-config-BlN8xTdD.mjs → platform-auth-config-B56E9YP1.mjs} +3 -3
- package/dist/{platform-auth-protection-7d5aV2Jg.mjs → platform-auth-protection-BDWO_aER.mjs} +2 -2
- package/dist/{platform-auth-recovery-Dxij8ZbR.mjs → platform-auth-recovery-1gg4CSRe.mjs} +3 -3
- package/dist/{platform-cmd-E0FuL212.mjs → platform-cmd-Bt-1w6pY.mjs} +1 -1
- package/dist/{platform-cmd-B3hwKrFK.mjs → platform-cmd-DMcQStSc.mjs} +24 -3
- package/dist/{platform-domain-D6Xcy9ZX.mjs → platform-domain-BNkcz0OB.mjs} +2 -2
- package/dist/{platform-lifecycle-k0E0xoxx.mjs → platform-lifecycle-9OyBALhH.mjs} +327 -215
- package/dist/{platform-lifecycle-DMh_qrry.mjs → platform-lifecycle-BE6C_jxh.mjs} +1 -1
- package/dist/{platform-management-Brz_BDiT.mjs → platform-management-CjwLVQwN.mjs} +6 -3
- package/dist/{platform-management-DOtss0BN.mjs → platform-management-CnyTdcWX.mjs} +1 -1
- package/dist/platform-plans-config-BNGKGr4P.mjs +359 -0
- package/dist/{platform-recovery-BvtcXON5.mjs → platform-recovery-D6KSpuFm.mjs} +2 -2
- package/dist/{plugin-inference-BMfKRSqE.mjs → plugin-inference-CXWnn79A.mjs} +174 -64
- package/dist/{prepare-C-6YZyyg.mjs → prepare-B5Mkic5u.mjs} +1 -1
- package/dist/{prepare-CRhJbVrG.mjs → prepare-DOsL0CC9.mjs} +4 -20
- package/dist/prepare-cgvDMtSb.mjs +2 -0
- package/dist/{project-cmd-BZLCqOqw.mjs → project-cmd-CNzrqvBv.mjs} +16 -16
- package/dist/{project-team-BvgM0WoX.mjs → project-team-DQOWPfQT.mjs} +2 -2
- package/dist/{project-token-l5DqK6Az.mjs → project-token-CTDYU0Cc.mjs} +2 -2
- package/dist/{project-zero-trust-v6Mvpp8y.mjs → project-zero-trust-BNAkW-_0.mjs} +2 -2
- package/dist/{protocol-BBa6cstI.d.mts → protocol-CjF_iI9X.d.mts} +2 -2
- package/dist/protocol-U7bfjHmA.mjs +331 -0
- package/dist/{provision-Fr9pRqce.mjs → provision-C4ORE7G7.mjs} +1 -1
- package/dist/{provision-C4IGqkBf.mjs → provision-CJFgTZY8.mjs} +89 -198
- package/dist/{requests-DN-BbNiM.mjs → requests-MhxYnau8.mjs} +2 -2
- package/dist/resource-name-C7LVpcRm.mjs +11 -0
- package/dist/{rollback-D7rzSaZM.mjs → rollback-CJ6iSDoU.mjs} +3 -3
- package/dist/route-url-CG7U-cRN.mjs +15 -0
- package/dist/{runner-B8wXwWlo.mjs → runner-CXA9Fh8h.mjs} +1 -1
- package/dist/{runner-p-dMs2UN.mjs → runner-Ol0TNjk6.mjs} +2 -2
- package/dist/runtime/ai.d.mts +12 -8
- package/dist/runtime/ai.mjs +84 -17
- package/dist/runtime/better-auth-mysql.mjs +1 -1
- package/dist/runtime/better-auth-pg.mjs +1 -1
- package/dist/runtime/better-auth.mjs +1 -1
- package/dist/runtime/client-react.mjs +2 -2
- package/dist/runtime/client-solid.mjs +2 -2
- package/dist/runtime/client-svelte.mjs +2 -2
- package/dist/runtime/client-vue.mjs +2 -2
- package/dist/runtime/client.mjs +2 -2
- package/dist/runtime/durable.d.mts +3 -1
- package/dist/runtime/durable.mjs +4 -1
- package/dist/runtime/email/testing.mjs +1 -1
- package/dist/runtime/env-public.d.mts +1 -1
- package/dist/runtime/fetch-stream.mjs +1 -1
- package/dist/runtime/fetch.mjs +1 -1
- package/dist/runtime/handler.d.mts +1 -1
- package/dist/runtime/kv.mjs +0 -1
- package/dist/runtime/limits.d.mts +2 -0
- package/dist/runtime/limits.mjs +2 -0
- package/dist/runtime/live-client.d.mts +1 -1
- package/dist/runtime/live-server.mjs +25 -16
- package/dist/runtime/live.d.mts +1 -1
- package/dist/runtime/migration-handler.mjs +62 -42
- package/dist/runtime/route-url.d.mts +4 -0
- package/dist/runtime/route-url.mjs +2 -0
- package/dist/runtime/routing.d.mts +180 -0
- package/dist/runtime/routing.mjs +1082 -0
- package/dist/runtime/sandbox-container.d.mts +1 -1
- package/dist/runtime/sandbox-container.mjs +1 -1
- package/dist/runtime/sandbox.d.mts +3 -3
- package/dist/runtime/sandbox.mjs +75 -45
- package/dist/runtime/sse.mjs +1 -1
- package/dist/runtime/validator.d.mts +1 -1
- package/dist/runtime/ws-server.d.mts +4 -2
- package/dist/runtime/ws-server.mjs +27 -2
- package/dist/runtime/ws.d.mts +2 -2
- package/dist/runtime/ws.mjs +8 -6
- package/dist/{sandbox-qpNBT8a3.d.mts → sandbox-XZAqzFlG.d.mts} +11 -8
- package/dist/{sandbox-container-DdNEBfCc.d.mts → sandbox-container-Bo0eiFKz.d.mts} +2 -1
- package/dist/{sandbox-container-4fdqLnyb.mjs → sandbox-container-C6ItmVuN.mjs} +4 -2
- package/dist/{scan-4tfN-PSn.mjs → scan-C7okrLyM.mjs} +4 -35
- package/dist/{secret-BOtOl_cb.mjs → secret-Dli5fP0B.mjs} +4 -4
- package/dist/{sse-BaC1jXko.mjs → sse-CQNaDFFV.mjs} +6 -3
- package/dist/validate-Dq_L3s0S.mjs +2 -0
- package/dist/{validate-CIUwFpjB.mjs → validate-ctOrgiS3.mjs} +2 -1
- package/dist/{wrangler-DQF1vKyf.mjs → wrangler-7K-bW_DL.mjs} +8 -239
- package/dist/{ws-BoY7vQML.d.mts → ws-CL1w7GXU.d.mts} +13 -2
- package/package.json +15 -8
- package/skills/migrate-vite-cloudflare-to-void/SKILL.md +34 -157
- package/skills/void/SKILL.md +50 -135
- package/skills/void/docs/guide/ai.md +94 -84
- package/skills/void/docs/guide/app-types.md +3 -32
- package/skills/void/docs/guide/auth.md +12 -116
- package/skills/void/docs/guide/database/d1.md +9 -54
- package/skills/void/docs/guide/database/mysql.md +1 -1
- package/skills/void/docs/guide/database/postgresql.md +5 -26
- package/skills/void/docs/guide/database.md +23 -75
- package/skills/void/docs/guide/deployment.md +27 -113
- package/skills/void/docs/guide/durable-state.md +43 -18
- package/skills/void/docs/guide/edge/headers.md +3 -47
- package/skills/void/docs/guide/edge/prerendering.md +5 -20
- package/skills/void/docs/guide/edge/redirects.md +11 -64
- package/skills/void/docs/guide/edge/revalidation.md +5 -18
- package/skills/void/docs/guide/edge/rewrites.md +56 -284
- package/skills/void/docs/guide/edge/static-assets.md +22 -72
- package/skills/void/docs/guide/email/domains.md +112 -0
- package/skills/void/docs/guide/email/receiving.md +139 -0
- package/skills/void/docs/guide/email/sending.md +231 -0
- package/skills/void/docs/guide/email.md +13 -619
- package/skills/void/docs/guide/env-migration.md +11 -11
- package/skills/void/docs/guide/env-vars.md +9 -29
- package/skills/void/docs/guide/index.md +0 -15
- package/skills/void/docs/guide/jobs.md +3 -18
- package/skills/void/docs/guide/kv.md +5 -11
- package/skills/void/docs/guide/live.md +5 -56
- package/skills/void/docs/guide/pages-routing/actions-and-forms.md +78 -125
- package/skills/void/docs/guide/pages-routing/head.md +10 -10
- package/skills/void/docs/guide/pages-routing/islands.md +6 -36
- package/skills/void/docs/guide/pages-routing/layouts.md +6 -128
- package/skills/void/docs/guide/pages-routing/loaders.md +3 -19
- package/skills/void/docs/guide/pages-routing/markdown.md +13 -171
- package/skills/void/docs/guide/pages-routing/overview.md +7 -17
- package/skills/void/docs/guide/pages-routing/view-transitions.md +1 -1
- package/skills/void/docs/guide/platform/administration/access.md +1 -4
- package/skills/void/docs/guide/platform/administration/email.md +35 -8
- package/skills/void/docs/guide/platform/administration/operations.md +26 -4
- package/skills/void/docs/guide/platform/administration/plans.md +126 -0
- package/skills/void/docs/guide/platform/administration/projects.md +5 -2
- package/skills/void/docs/guide/platform/administration/zero-trust.md +23 -152
- package/skills/void/docs/guide/platform/development/runtime.md +3 -13
- package/skills/void/docs/guide/platform/development/schema-ci.md +0 -58
- package/skills/void/docs/guide/platform/installation/credentials.md +6 -4
- package/skills/void/docs/guide/platform/installation/domains.md +30 -2
- package/skills/void/docs/guide/platform/installation/first-deployment.md +2 -0
- package/skills/void/docs/guide/platform/installation/maintenance.md +3 -1
- package/skills/void/docs/guide/platform/installation/prerequisites.md +20 -15
- package/skills/void/docs/guide/platform/installation/setup.md +9 -5
- package/skills/void/docs/guide/platform-administration.md +1 -0
- package/skills/void/docs/guide/queues.md +7 -9
- package/skills/void/docs/guide/quickstart.md +38 -37
- package/skills/void/docs/guide/remote-dev.md +4 -9
- package/skills/void/docs/guide/sandboxes.md +29 -21
- package/skills/void/docs/guide/server-routing.md +9 -72
- package/skills/void/docs/guide/sse.md +4 -18
- package/skills/void/docs/guide/ssg.md +3 -15
- package/skills/void/docs/guide/ssr.md +14 -62
- package/skills/void/docs/guide/storage.md +9 -4
- package/skills/void/docs/guide/type-safety.md +3 -14
- package/skills/void/docs/guide/typed-fetch.md +3 -7
- package/skills/void/docs/guide/websockets.md +68 -40
- package/skills/void/docs/integrations/agents.md +3 -3
- package/skills/void/docs/integrations/cloudflare.md +85 -316
- package/skills/void/docs/integrations/frameworks/analog.md +5 -64
- package/skills/void/docs/integrations/frameworks/astro.md +4 -73
- package/skills/void/docs/integrations/frameworks/nuxt.md +5 -62
- package/skills/void/docs/integrations/frameworks/overview.md +11 -54
- package/skills/void/docs/integrations/frameworks/react-router.md +5 -60
- package/skills/void/docs/integrations/frameworks/sveltekit.md +6 -65
- package/skills/void/docs/integrations/frameworks/tanstack-start.md +4 -62
- package/skills/void/docs/integrations/nodejs-bun-deno.md +5 -69
- package/skills/void/docs/reference/api/auth.md +156 -0
- package/skills/void/docs/reference/api/client.md +87 -0
- package/skills/void/docs/reference/api/database.md +95 -0
- package/skills/void/docs/reference/api/durable.md +46 -0
- package/skills/void/docs/reference/api/env.md +50 -0
- package/skills/void/docs/reference/api/handlers.md +254 -0
- package/skills/void/docs/reference/api/pages.md +241 -0
- package/skills/void/docs/reference/api/plugin.md +39 -0
- package/skills/void/docs/reference/api/resources.md +109 -0
- package/skills/void/docs/reference/api/rewrites.md +76 -0
- package/skills/void/docs/reference/api/types.md +92 -0
- package/skills/void/docs/reference/api.md +56 -1218
- package/skills/void/docs/reference/cli/auth.md +88 -0
- package/skills/void/docs/reference/cli/database.md +128 -0
- package/skills/void/docs/reference/cli/deploy.md +85 -0
- package/skills/void/docs/reference/cli/domains.md +41 -0
- package/skills/void/docs/reference/cli/email.md +129 -0
- package/skills/void/docs/reference/cli/generate.md +116 -0
- package/skills/void/docs/reference/cli/github.md +189 -0
- package/skills/void/docs/reference/cli/platform-config.md +92 -0
- package/skills/void/docs/reference/cli/platform-email.md +81 -0
- package/skills/void/docs/reference/cli/platform-installation.md +127 -0
- package/skills/void/docs/reference/cli/platform-operations.md +90 -0
- package/skills/void/docs/reference/cli/platform-users.md +89 -0
- package/skills/void/docs/reference/cli/platform-zero-trust.md +45 -0
- package/skills/void/docs/reference/cli/platform.md +70 -0
- package/skills/void/docs/reference/cli/project.md +214 -0
- package/skills/void/docs/reference/cli/secrets.md +76 -0
- package/skills/void/docs/reference/cli/setup.md +70 -0
- package/skills/void/docs/reference/cli.md +32 -1682
- package/skills/void/docs/reference/config.md +12 -18
- package/skills/void/docs/reference/resource-inference.md +3 -58
- package/skills/void/docs/reference/structure.md +14 -41
- package/dist/canonical-json-DuDiiUsQ.mjs +0 -13
- package/dist/client-Czz8o5jP.mjs +0 -2
- package/dist/gen-CNJ62MM7.mjs +0 -2
- package/dist/help-CmZzxUba.mjs +0 -2
- package/dist/login-CGcRKEoi.mjs +0 -2
- package/dist/migrate-CYfbKkXh.mjs +0 -2
- package/dist/plan-BEZ8VJW0.mjs +0 -256
- package/dist/plan-DpuOr14e.mjs +0 -2
- package/dist/prepare-Bm3iq-u4.mjs +0 -2
- package/dist/validate-EKmJWxmy.mjs +0 -2
- /package/dist/cli/{cf-compat.d.mts → cloudflare-operation-process.d.mts} +0 -0
|
@@ -1,51 +1,52 @@
|
|
|
1
1
|
import { n as __toESM, t as __commonJSMin } from "./rolldown-runtime-DXIUcv95.mjs";
|
|
2
2
|
import { a as join, l as relative, n as dirname, o as normalize, r as extname, t as basename, u as resolve } from "./dist-BVqXeR_h.mjs";
|
|
3
3
|
import { t as require_picocolors } from "./picocolors-BTps1_gs.mjs";
|
|
4
|
-
import {
|
|
5
|
-
import { t as
|
|
4
|
+
import { m as needsApplicationDatabase, r as detectFramework } from "./plugin-inference-CXWnn79A.mjs";
|
|
5
|
+
import { n as readProjectPaths, t as assertNoRootSourceConventionConflicts } from "./project-paths-GgcMozYz.mjs";
|
|
6
|
+
import { d as isNodeTarget, h as resolveBindingNames, m as readConfig } from "./config-Br_JZD6u.mjs";
|
|
7
|
+
import { n as isIdentifier, r as isLiteral } from "./ast-CPGPjb0V.mjs";
|
|
8
|
+
import { o as scanDurableObjectModules, t as analyzeApplicationSync } from "./application-analysis-BVsVqc11.mjs";
|
|
9
|
+
import { t as collectMigrations } from "./collect-DiTn9yr6.mjs";
|
|
10
|
+
import { o as validateSsrEntry } from "./entry-CF5wvH4w.mjs";
|
|
11
|
+
import { r as hasEmailHandlers } from "./email--tEtMoj_.mjs";
|
|
12
|
+
import { a as hasSandboxSqliteMigration, c as resolveSandboxConfig, i as assertSandboxNamespaceConfig, l as sandboxContainerConfig, r as SANDBOX_MIGRATION_TAG, s as requiresSandboxPlatformImage } from "./config-C_XRIPx2.mjs";
|
|
6
13
|
import { i as trustedCloudflareWorkerAccessHeaders, r as scopedAccessCredentials, t as cfAccessHeaders } from "./cf-access-DRsQRe6k.mjs";
|
|
7
|
-
import { a as getApiUrl, c as getToken, l as getTokenSource, o as getProxyUrl, u as isStagingMode } from "./auth-
|
|
14
|
+
import { a as getApiUrl, c as getToken, l as getTokenSource, o as getProxyUrl, u as isStagingMode } from "./auth-CSkdO2Bb.mjs";
|
|
8
15
|
import { r as ensurePlatformProxyAccess, t as ensureCloudflaredToken } from "./cf-access-P0iZnu0q.mjs";
|
|
9
16
|
import { d as writeProjectConfig, i as readDeploymentPlatform, l as writeDeploymentPlatform, o as readProjectConfig, t as attachSelectedPlatform } from "./project-C0Fqu05O.mjs";
|
|
10
|
-
import {
|
|
11
|
-
import { A as
|
|
17
|
+
import { i as persistCloudflareConfig, r as materializeCloudflareConfig, s as stashCloudflareDeployPointer } from "./cloudflare-config-Bktvwtpf.mjs";
|
|
18
|
+
import { A as writeProvisionedWranglerConfig, C as readWranglerPublishedTrafficSnapshot, D as syncWranglerDurableObjects, E as syncWranglerBindings, O as syncWranglerWebSockets, S as readWranglerManagedQueueCleanupCandidates, T as resolveLiveBindingConfig, _ as readExistingLiveBindingConfig, a as LIVE_MIGRATION_TAG, c as bindingEntriesForField, g as normalizeWranglerCompatibilityFlags, h as nextDurableObjectMigrationTag, j as writeWranglerPublishedTrafficSnapshot, l as bindingNamesForField, m as hasDurableObjectSqliteMigration, o as acknowledgeWranglerManagedQueueRemovals, p as findBindingNameOwner, r as FRIENDLY_BINDING_NAMES, u as ensureWranglerCompat } from "./wrangler-7K-bW_DL.mjs";
|
|
12
19
|
import { i as voidWarn, r as voidLog } from "./log-ChfPKsVd.mjs";
|
|
13
20
|
import { n as lintDuplicateSources, r as mergeRoutingRules, t as lintDestinationSplats } from "./headers-DWi2IXWx.mjs";
|
|
14
|
-
import { n as
|
|
15
|
-
import { t as scanPages } from "./scan-4tfN-PSn.mjs";
|
|
16
|
-
import { a as scanJobsSync, i as scanQueuesSync, r as scanRoutes } from "./scan-ClYmX3sa.mjs";
|
|
17
|
-
import { i as inferProjectBindings, n as FRAMEWORK_SCAN_DIRS, r as detectFramework, s as scanWebSocketRoutesSync } from "./plugin-inference-BMfKRSqE.mjs";
|
|
18
|
-
import { t as collectMigrations } from "./collect-DiTn9yr6.mjs";
|
|
19
|
-
import { r as buildMigrationPlanBundle } from "./plan-BEZ8VJW0.mjs";
|
|
21
|
+
import { n as buildMigrationPlanBundle } from "./plan-NPpwZ_kc.mjs";
|
|
20
22
|
import { r as scanWranglerDotenvKeys } from "./dotenv-VQxupEUv.mjs";
|
|
21
23
|
import { t as discoverSchema } from "./discover-BcPPiF1o.mjs";
|
|
22
24
|
import { t as MagicString } from "./dist-AoCzRTJE.mjs";
|
|
23
25
|
import { t as findEnvFile } from "./env-types-C2_bIk_b.mjs";
|
|
24
|
-
import { d as formatEnvReport, f as listSelfHostSecretNames, g as validateProdEnv, h as selfHostSchemaFailureMessage, i as SelfHostSecretListError, l as dischargeSelfHostEnvContext, n as SelfHostFirstDeployError, p as readEmittedWorkerVars, r as SelfHostSchemaError, s as deriveSelfHostEnvContextFromVars, t as SelfHostEnvValidationError, u as fetchRemoteSecretNames, v as readGeneratedWranglerConfigFile } from "./env-validation-
|
|
26
|
+
import { d as formatEnvReport, f as listSelfHostSecretNames, g as validateProdEnv, h as selfHostSchemaFailureMessage, i as SelfHostSecretListError, l as dischargeSelfHostEnvContext, n as SelfHostFirstDeployError, p as readEmittedWorkerVars, r as SelfHostSchemaError, s as deriveSelfHostEnvContextFromVars, t as SelfHostEnvValidationError, u as fetchRemoteSecretNames, v as readGeneratedWranglerConfigFile } from "./env-validation-BPn7vk-V.mjs";
|
|
25
27
|
import { n as CLOUDFLARE_DEPLOY_BUILD_ENV, o as resolveRemoteMode, s as stripInternalEnvKeys } from "./env-_v349JBd.mjs";
|
|
26
|
-
import { o as validateSsrEntry } from "./entry-CF5wvH4w.mjs";
|
|
27
28
|
import { E as confirm, I as select, N as note, O as intro, P as outro, W as isCancel, j as log$1 } from "./dist-CTBk70IR.mjs";
|
|
29
|
+
import { n as completeApplicationAnalysis, t as analyzeApplication } from "./application-routing-B7QEjqSR.mjs";
|
|
28
30
|
import { t as writeDrizzleConfig } from "./config-D8MOgiQV.mjs";
|
|
29
31
|
import { i as runMySqlMigrations } from "./runner-mysql-DmWchSWJ.mjs";
|
|
30
32
|
import { i as runPgMigrations } from "./runner-pg-D4OPlil-.mjs";
|
|
31
33
|
import { n as openMigrationValidationDatabase, t as SqliteMigrationError } from "./sqlite-validation-BzKMWnO4.mjs";
|
|
32
|
-
import { i as validateMigrations, t as assertJournalCoherence } from "./validate-
|
|
34
|
+
import { i as validateMigrations, t as assertJournalCoherence } from "./validate-ctOrgiS3.mjs";
|
|
33
35
|
import { t as renderPrerenderPaths } from "./prerender-render-D9qbLs2f.mjs";
|
|
34
|
-
import {
|
|
35
|
-
import { i as migrateBuiltWranglerConfig, n as prepareCfFrameworkBuildOutput, r as prepareCfStaticBuildOutput, t as prepareCfBuildOutput } from "./cf-build-output-BJ6yGEIS.mjs";
|
|
36
|
+
import { i as migrateBuiltWranglerConfig, n as prepareCfFrameworkBuildOutput, r as prepareCfStaticBuildOutput, t as prepareCfBuildOutput } from "./cf-build-output-BPqOT964.mjs";
|
|
36
37
|
import { n as getPackageDir } from "./agents-B_pX_HmQ.mjs";
|
|
37
|
-
import { i as isExpiredTokenError, n as PlatformClient, o as parsePlatformErrorBody, r as isCliOutdatedError, s as platformErrorMessage, t as PlatformApiError } from "./client-
|
|
38
|
-
import { a as
|
|
39
|
-
import { a as
|
|
38
|
+
import { i as isExpiredTokenError, n as PlatformClient, o as parsePlatformErrorBody, r as isCliOutdatedError, s as platformErrorMessage, t as PlatformApiError } from "./client-RV8NVeB8.mjs";
|
|
39
|
+
import { a as detectPreset, c as resolveCloudflareOperationArgv, i as FRAMEWORK_PRESETS, l as resolveProjectCommand, o as formatProjectCommand, s as hasBackendFiles, t as createCloudflareProcessRunner } from "./cloudflare-process-B-wekeR6.mjs";
|
|
40
|
+
import { a as parseCloudflareAuthSession, i as ensureCloudflareAuthentication, n as cloudflareCredentialOverrides, t as CloudflareAuthenticationError } from "./cloudflare-auth-Qdc7tw8F.mjs";
|
|
40
41
|
import { n as writeVoidProjectConfig } from "./config-write-B1f88wJA.mjs";
|
|
41
|
-
import { r as discoverFrameworkWranglerFiles, t as migrateLegacyVoidConfig } from "./migrate-
|
|
42
|
-
import { a as createCloudflareEmptyDomainPublisher, i as createCloudflareEmptyCronPublisher } from "./cloudflare-operations-
|
|
42
|
+
import { r as discoverFrameworkWranglerFiles, t as migrateLegacyVoidConfig } from "./migrate-DHul7PRV.mjs";
|
|
43
|
+
import { a as createCloudflareEmptyDomainPublisher, i as createCloudflareEmptyCronPublisher } from "./cloudflare-operations-fxHb-byx.mjs";
|
|
43
44
|
import { t as formatCloudflareUserMessage } from "./cloudflare-user-output-Q-k0QoNQ.mjs";
|
|
44
45
|
import { c as import_picocolors$1, i as createSpinner, r as cliTitle } from "./output-Dm_A4Tbv.mjs";
|
|
45
|
-
import { a as promptProjectSelection, i as reportProjectCreationWarnings, o as promptProjectSetupAction, r as promptAndCreateProject } from "./create-project-
|
|
46
|
+
import { a as promptProjectSelection, i as reportProjectCreationWarnings, o as promptProjectSetupAction, r as promptAndCreateProject } from "./create-project-bMf6ffLZ.mjs";
|
|
46
47
|
import { t as getRequestedProjectSlug } from "./resolve-project-BG5ORGID.mjs";
|
|
47
48
|
import { t as collectGitDeployMetadata } from "./git-metadata-D-gurjzG.mjs";
|
|
48
|
-
import { t as promptForLoginToken } from "./login-
|
|
49
|
+
import { t as promptForLoginToken } from "./login-UZKFM_u7.mjs";
|
|
49
50
|
import { createRequire } from "node:module";
|
|
50
51
|
import { copyFileSync, cpSync, createWriteStream, existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, readlinkSync, realpathSync, renameSync, rmSync, statSync, unlinkSync, writeFileSync } from "node:fs";
|
|
51
52
|
import { fileURLToPath } from "node:url";
|
|
@@ -60,6 +61,7 @@ import { Minimatch } from "minimatch";
|
|
|
60
61
|
import { CloudflareWorkerInspectionError, activateCloudflareVersion, assertCloudflareBindingsPreserved, assertCloudflareDurableObjectLifecycleSupported, assertExistingCloudflareConfig, encodeCloudflareVersionMessage, extractWorkersDevSubdomain, normalizeWorkersDevSubdomain, parseRootWranglerConfig, parseRootWranglerConfig as parseRootWranglerConfig$1, readBindingFieldPresence, readCloudflareTriggerConfig, readConfigEntryString, readExistingCloudflareWorker, readStoredResourceName, readWranglerTopLevelString, renderCloudflareStaticEntry, resolveD1MigrateTarget, stageCloudflareStaticAssets, writeCloudflareFrameworkDeployConfig, writeCloudflareStaticDeployConfig } from "@void/deploy-cloudflare";
|
|
61
62
|
import { getWorkerAssetsDir, getWorkerBundleDir, getWorkerConfigPath, readBuildOutput } from "@cloudflare/build-output-utils";
|
|
62
63
|
import ignore from "ignore";
|
|
64
|
+
import { setTimeout as setTimeout$1 } from "node:timers/promises";
|
|
63
65
|
import mime from "mime";
|
|
64
66
|
import { hash } from "blake3-jit";
|
|
65
67
|
//#region src/asset-routing.ts
|
|
@@ -240,127 +242,84 @@ function deriveAddresses(handlers, domain, mode) {
|
|
|
240
242
|
routes
|
|
241
243
|
};
|
|
242
244
|
}
|
|
243
|
-
function parseWhoamiJson(
|
|
244
|
-
|
|
245
|
-
if (
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
if (!parsed || typeof parsed !== "object" || typeof parsed.loggedIn !== "boolean") return null;
|
|
249
|
-
return parsed;
|
|
250
|
-
} catch {
|
|
251
|
-
return null;
|
|
252
|
-
}
|
|
245
|
+
function parseWhoamiJson(data) {
|
|
246
|
+
if (!isRecord(data) || typeof data.loggedIn !== "boolean") return null;
|
|
247
|
+
if (data.tokenPermissions !== void 0 && (!Array.isArray(data.tokenPermissions) || data.tokenPermissions.some((scope) => typeof scope !== "string"))) return null;
|
|
248
|
+
if (data.accounts !== void 0 && (!Array.isArray(data.accounts) || data.accounts.some((account) => !isRecord(account) || typeof account.id !== "string" || typeof account.name !== "string"))) return null;
|
|
249
|
+
return data;
|
|
253
250
|
}
|
|
254
|
-
function
|
|
255
|
-
|
|
256
|
-
const enabled = /^\s*Enabled:\s+(true|false)\s*$/m.exec(stdout)?.[1];
|
|
257
|
-
const status = /^\s*Status:\s+(\S+)\s*$/m.exec(stdout)?.[1];
|
|
258
|
-
const tag = /^\s*Tag:\s+([0-9a-f]{32})\s*$/m.exec(stdout)?.[1];
|
|
259
|
-
if (!name || !enabled || !status || !tag) return null;
|
|
260
|
-
return {
|
|
261
|
-
name,
|
|
262
|
-
enabled: enabled === "true",
|
|
263
|
-
status,
|
|
264
|
-
tag
|
|
265
|
-
};
|
|
251
|
+
function isRecord(value) {
|
|
252
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
266
253
|
}
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
* Catch-all rule: disabled, action: drop
|
|
278
|
-
* (use `wrangler email routing rules get catch-all` to view details)
|
|
279
|
-
*
|
|
280
|
-
* With no rule at all: `No routing rules found.` / no custom rule: `No custom routing
|
|
281
|
-
* rules found.`. Both forms are pinned by fixture.
|
|
282
|
-
*/
|
|
283
|
-
function parseRoutingRules(stdout) {
|
|
284
|
-
const lines = stdout.split(/\r?\n/);
|
|
254
|
+
function readRoutingSettings(data) {
|
|
255
|
+
return isRecord(data) && typeof data.name === "string" && data.name.length > 0 && typeof data.enabled === "boolean" && typeof data.status === "string" && data.status.length > 0 && typeof data.tag === "string" && /^[0-9a-f]{32}$/.test(data.tag) ? {
|
|
256
|
+
name: data.name,
|
|
257
|
+
enabled: data.enabled,
|
|
258
|
+
status: data.status,
|
|
259
|
+
tag: data.tag
|
|
260
|
+
} : null;
|
|
261
|
+
}
|
|
262
|
+
function readRoutingRules(data) {
|
|
263
|
+
if (!Array.isArray(data)) return null;
|
|
285
264
|
const rules = [];
|
|
286
265
|
let catchAll = null;
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
const
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
266
|
+
for (const entry of data) {
|
|
267
|
+
if (!isRecord(entry) || typeof entry.enabled !== "boolean" || !Array.isArray(entry.actions) || entry.actions.length === 0 || !Array.isArray(entry.matchers) || entry.matchers.length === 0) return null;
|
|
268
|
+
const actions = [];
|
|
269
|
+
for (const action of entry.actions) {
|
|
270
|
+
if (!isRecord(action) || typeof action.type !== "string") return null;
|
|
271
|
+
if (action.type === "drop") actions.push("drop");
|
|
272
|
+
else if (action.type === "worker" || action.type === "forward") {
|
|
273
|
+
const values = typeof action.value === "string" ? [action.value] : action.value;
|
|
274
|
+
if (!Array.isArray(values) || values.length === 0 || !values.every((value) => typeof value === "string" && value.length > 0)) return null;
|
|
275
|
+
if (action.type === "worker") actions.push("worker:" + values.join(","));
|
|
276
|
+
else actions.push("forward:" + values.join(","));
|
|
277
|
+
} else return null;
|
|
278
|
+
}
|
|
279
|
+
const to = [];
|
|
280
|
+
let all = false;
|
|
281
|
+
for (const matcher of entry.matchers) {
|
|
282
|
+
if (!isRecord(matcher)) return null;
|
|
283
|
+
if (matcher.type === "all") all = true;
|
|
284
|
+
else if (matcher.type === "literal" && matcher.field === "to" || matcher.type === "to") {
|
|
285
|
+
if (typeof matcher.value !== "string" || matcher.value.length === 0) return null;
|
|
286
|
+
to.push(matcher.value.toLowerCase());
|
|
287
|
+
} else return null;
|
|
288
|
+
}
|
|
289
|
+
if (all) {
|
|
290
|
+
if (catchAll || entry.matchers.length !== 1) return null;
|
|
297
291
|
catchAll = {
|
|
298
|
-
enabled:
|
|
299
|
-
actions
|
|
292
|
+
enabled: entry.enabled,
|
|
293
|
+
actions
|
|
300
294
|
};
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
to: [],
|
|
311
|
-
actions: []
|
|
312
|
-
};
|
|
313
|
-
rules.push(current);
|
|
314
|
-
continue;
|
|
315
|
-
}
|
|
316
|
-
if (!current) continue;
|
|
317
|
-
const field = /^\s{2}(Name|Enabled|Matchers|Actions|Priority):\s*(.*)$/.exec(line);
|
|
318
|
-
if (!field) continue;
|
|
319
|
-
const value = (field[2] ?? "").trim();
|
|
320
|
-
switch (field[1]) {
|
|
321
|
-
case "Name":
|
|
322
|
-
current.name = value;
|
|
323
|
-
break;
|
|
324
|
-
case "Enabled":
|
|
325
|
-
current.enabled = value === "true";
|
|
326
|
-
break;
|
|
327
|
-
case "Matchers":
|
|
328
|
-
current.to = value.split(", ").filter((m) => m.startsWith("to:")).map((m) => m.slice(3).toLowerCase());
|
|
329
|
-
break;
|
|
330
|
-
case "Actions": current.actions = splitActionList(value);
|
|
295
|
+
} else {
|
|
296
|
+
if (typeof entry.id !== "string" || entry.id.length === 0 || entry.name !== void 0 && typeof entry.name !== "string") return null;
|
|
297
|
+
rules.push({
|
|
298
|
+
id: entry.id,
|
|
299
|
+
name: entry.name ?? "",
|
|
300
|
+
enabled: entry.enabled,
|
|
301
|
+
to,
|
|
302
|
+
actions
|
|
303
|
+
});
|
|
331
304
|
}
|
|
332
305
|
}
|
|
333
|
-
if (!sawSentinel && rules.length === 0 && !catchAll) return null;
|
|
334
306
|
return {
|
|
335
307
|
rules,
|
|
336
308
|
catchAll
|
|
337
309
|
};
|
|
338
310
|
}
|
|
339
|
-
function
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
const tag = /^\s*Tag:\s+([0-9a-f]{32})\s*$/m.exec(stdout)?.[1];
|
|
346
|
-
if (!name || !enabled || !tag) return null;
|
|
347
|
-
return {
|
|
348
|
-
name,
|
|
349
|
-
enabled: enabled === "true",
|
|
311
|
+
function readSendingSettings(data) {
|
|
312
|
+
if (!isRecord(data)) return null;
|
|
313
|
+
const tag = data.tag ?? data.id;
|
|
314
|
+
return typeof data.name === "string" && data.name.length > 0 && typeof data.enabled === "boolean" && typeof tag === "string" && /^[0-9a-f]{32}$/.test(tag) ? {
|
|
315
|
+
name: data.name,
|
|
316
|
+
enabled: data.enabled,
|
|
350
317
|
tag
|
|
351
|
-
};
|
|
352
|
-
}
|
|
353
|
-
/** wrangler renders an `APIError` note as `<message> [code: <n>]`; extract the code. */
|
|
354
|
-
function wranglerApiErrorCode(text) {
|
|
355
|
-
const match = /\[code:\s*(\d+)\]/.exec(stripAnsi(text));
|
|
356
|
-
return match ? Number(match[1]) : null;
|
|
318
|
+
} : null;
|
|
357
319
|
}
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
return text.replace(ANSI_SGR_RE, "");
|
|
320
|
+
function providerErrorCode(result) {
|
|
321
|
+
return result.errorCode ?? result.errors?.find((error) => error.code !== void 0)?.code ?? null;
|
|
361
322
|
}
|
|
362
|
-
const ZONE_NOT_FOUND_RE = /Could not find (?:a )?zone for `([^`]+)`/;
|
|
363
|
-
const SENDING_NOT_FOUND_RE = /No sending subdomain found for `([^`]+)`/;
|
|
364
323
|
function isHardFailure(result) {
|
|
365
324
|
return Boolean(result.signal) || Boolean(result.error);
|
|
366
325
|
}
|
|
@@ -417,8 +376,10 @@ async function preflightEmail(inputs) {
|
|
|
417
376
|
const domain = emailFromDomain(inputs.from);
|
|
418
377
|
if (!domain) throw new Error(`email.from must be an address like you@mail.example.com (got ${JSON.stringify(inputs.from)})`);
|
|
419
378
|
const apiBaseUrl = inputs.apiBaseUrl ?? "https://api.cloudflare.com/client/v4";
|
|
420
|
-
const
|
|
421
|
-
|
|
379
|
+
const run = async (operation) => inputs.runWrangler({
|
|
380
|
+
...operation,
|
|
381
|
+
...inputs.configPath ? { configPath: inputs.configPath } : {}
|
|
382
|
+
}, { capture: true });
|
|
422
383
|
const usageHandlers = [...inputs.handlers.addresses.map((d) => `email/${d.filePath}`), ...inputs.handlers.defaultHandler ? [`email/${inputs.handlers.defaultHandler}`] : []];
|
|
423
384
|
const pre = {
|
|
424
385
|
from: inputs.from,
|
|
@@ -481,8 +442,8 @@ async function preflightEmail(inputs) {
|
|
|
481
442
|
});
|
|
482
443
|
};
|
|
483
444
|
for (const conflict of inputs.configConflicts ?? []) block("all", conflict);
|
|
484
|
-
const whoami = await run(
|
|
485
|
-
const who = isHardFailure(whoami) || whoami.status !== 0 ? null : parseWhoamiJson(whoami.
|
|
445
|
+
const whoami = await run({ type: "auth.whoami" });
|
|
446
|
+
const who = isHardFailure(whoami) || whoami.status !== 0 ? null : parseWhoamiJson(whoami.data);
|
|
486
447
|
if (!who) {
|
|
487
448
|
pre.session.state = "unknown";
|
|
488
449
|
block("all", "could not read the Cloudflare session — run `void cloudflare login`");
|
|
@@ -509,22 +470,20 @@ async function preflightEmail(inputs) {
|
|
|
509
470
|
let settings = null;
|
|
510
471
|
let settingsMiss = false;
|
|
511
472
|
if (pre.session.state === "ok") for (const candidate of zoneCandidates(domain)) {
|
|
512
|
-
const result = await run(
|
|
513
|
-
"email",
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
candidate
|
|
517
|
-
]);
|
|
473
|
+
const result = await run({
|
|
474
|
+
type: "email.routing.settings",
|
|
475
|
+
domain: candidate
|
|
476
|
+
});
|
|
518
477
|
if (isHardFailure(result)) {
|
|
519
478
|
settingsMiss = true;
|
|
520
479
|
break;
|
|
521
480
|
}
|
|
481
|
+
if (result.status === 0 && result.data === null) continue;
|
|
522
482
|
if (result.status !== 0) {
|
|
523
|
-
if (ZONE_NOT_FOUND_RE.test(stripAnsi(result.stderr))) continue;
|
|
524
483
|
settingsMiss = true;
|
|
525
484
|
break;
|
|
526
485
|
}
|
|
527
|
-
settings =
|
|
486
|
+
settings = readRoutingSettings(result.data);
|
|
528
487
|
if (!settings) settingsMiss = true;
|
|
529
488
|
break;
|
|
530
489
|
}
|
|
@@ -621,14 +580,11 @@ async function preflightEmail(inputs) {
|
|
|
621
580
|
else if (pre.domainMx.state === "unknown") block("all", `could not read the MX records of ${domain} — unknown — run \`void email setup --platform cloudflare\``);
|
|
622
581
|
}
|
|
623
582
|
pre.derived = deriveAddresses(inputs.handlers, domain, mode);
|
|
624
|
-
const rulesResult = await run(
|
|
625
|
-
"email",
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
apex
|
|
630
|
-
]);
|
|
631
|
-
const rules = isHardFailure(rulesResult) || rulesResult.status !== 0 ? null : parseRoutingRules(rulesResult.stdout);
|
|
583
|
+
const rulesResult = await run({
|
|
584
|
+
type: "email.routing.rules.list",
|
|
585
|
+
domain: apex
|
|
586
|
+
});
|
|
587
|
+
const rules = isHardFailure(rulesResult) || rulesResult.status !== 0 ? null : readRoutingRules(rulesResult.data);
|
|
632
588
|
if (!rules) {
|
|
633
589
|
pre.rules.state = "unknown";
|
|
634
590
|
block("all", `could not read Email Routing rules — unknown — run \`void email setup --platform cloudflare\`${tokenHint}`);
|
|
@@ -658,18 +614,16 @@ async function preflightEmail(inputs) {
|
|
|
658
614
|
}
|
|
659
615
|
const foreign = new Set(pre.rules.foreign.map((f) => f.address));
|
|
660
616
|
pre.addresses = pre.derived.addresses.filter((a) => !foreign.has(a));
|
|
661
|
-
const sendingResult = await run(
|
|
662
|
-
"email",
|
|
663
|
-
"sending",
|
|
664
|
-
"settings",
|
|
617
|
+
const sendingResult = await run({
|
|
618
|
+
type: "email.sending.settings",
|
|
665
619
|
domain
|
|
666
|
-
|
|
620
|
+
});
|
|
667
621
|
if (isHardFailure(sendingResult)) pre.sending.state = "unknown";
|
|
622
|
+
else if (sendingResult.status === 0 && sendingResult.data === null) pre.sending.state = "pending";
|
|
668
623
|
else if (sendingResult.status === 0) {
|
|
669
|
-
const parsed =
|
|
624
|
+
const parsed = readSendingSettings(sendingResult.data);
|
|
670
625
|
pre.sending.state = parsed ? parsed.enabled ? "ready" : "pending" : "unknown";
|
|
671
|
-
} else
|
|
672
|
-
else pre.sending.state = "unknown";
|
|
626
|
+
} else pre.sending.state = "unknown";
|
|
673
627
|
if (pre.sending.state === "unknown") block("sending", `could not read Email Sending settings — unknown — run \`void email setup --platform cloudflare\`${tokenHint}`);
|
|
674
628
|
else if (pre.sending.state === "pending" && pre.sending.dnsConflicts.length > 0) block("sending", `${pre.sending.dnsConflicts.join(", ")} already exists; onboarding writes its own _dmarc (p=reject) and DKIM records and would conflict — remove them or keep sending off`);
|
|
675
629
|
const names = (inputs.existingSendEmail ?? []).map((e) => typeof e?.name === "string" ? e.name : "");
|
|
@@ -849,8 +803,10 @@ async function applyEmailSetup(pre, inputs) {
|
|
|
849
803
|
}
|
|
850
804
|
const apex = pre.apex;
|
|
851
805
|
const apiBaseUrl = inputs.apiBaseUrl ?? "https://api.cloudflare.com/client/v4";
|
|
852
|
-
const
|
|
853
|
-
|
|
806
|
+
const run = async (operation) => inputs.runWrangler({
|
|
807
|
+
...operation,
|
|
808
|
+
...inputs.configPath ? { configPath: inputs.configPath } : {}
|
|
809
|
+
}, { capture: true });
|
|
854
810
|
let bearer;
|
|
855
811
|
let bearerFailed = false;
|
|
856
812
|
let bearerObtained = false;
|
|
@@ -879,17 +835,15 @@ async function applyEmailSetup(pre, inputs) {
|
|
|
879
835
|
const apexRoutingOff = pre.mode === "subdomain" && pre.routing.enabled !== true;
|
|
880
836
|
if (!result.routingReady) {
|
|
881
837
|
if (pre.mode === "apex") {
|
|
882
|
-
const enable = await run(
|
|
883
|
-
"email",
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
apex
|
|
887
|
-
]);
|
|
838
|
+
const enable = await run({
|
|
839
|
+
type: "email.routing.enable",
|
|
840
|
+
domain: apex
|
|
841
|
+
});
|
|
888
842
|
if (!isHardFailure(enable) && enable.status === 0) {
|
|
889
843
|
result.routingReady = true;
|
|
890
844
|
lines.push(` ✔ routing ${apex} enabled`);
|
|
891
845
|
} else {
|
|
892
|
-
const code =
|
|
846
|
+
const code = providerErrorCode(enable);
|
|
893
847
|
lines.push(` ✘ routing could not enable Email Routing on ${apex}${code ? ` [code: ${code}]${CF_EMAIL_ERROR_CODES[code] ? ` — ${CF_EMAIL_ERROR_CODES[code]}` : ""}` : ""}`);
|
|
894
848
|
}
|
|
895
849
|
} else if (apexRoutingOff) {
|
|
@@ -920,13 +874,11 @@ async function applyEmailSetup(pre, inputs) {
|
|
|
920
874
|
const sendingBlocked = pre.blockers.filter((b) => b.scope === "sending");
|
|
921
875
|
if (!result.sendingReady && sendingBlocked.length > 0) for (const b of sendingBlocked) lines.push(` ! sending ${b.message}`);
|
|
922
876
|
else if (!result.sendingReady) {
|
|
923
|
-
const enable = await run(
|
|
924
|
-
"email",
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
]);
|
|
929
|
-
const code = isHardFailure(enable) ? null : wranglerApiErrorCode(enable.stderr);
|
|
877
|
+
const enable = await run({
|
|
878
|
+
type: "email.sending.enable",
|
|
879
|
+
domain: pre.domain
|
|
880
|
+
});
|
|
881
|
+
const code = isHardFailure(enable) ? null : providerErrorCode(enable);
|
|
930
882
|
if (!isHardFailure(enable) && (enable.status === 0 || code === 2040)) {
|
|
931
883
|
result.sendingReady = true;
|
|
932
884
|
lines.push(` ✔ sending ${pre.domain} onboarded`);
|
|
@@ -976,37 +928,6 @@ async function createNodeEmailDns() {
|
|
|
976
928
|
};
|
|
977
929
|
}
|
|
978
930
|
//#endregion
|
|
979
|
-
//#region src/durable/scan.ts
|
|
980
|
-
const MODULE_PATTERN = /\.(?:[cm]?[jt]s)$/;
|
|
981
|
-
function words(value) {
|
|
982
|
-
return value.split(/[^a-zA-Z0-9]+/).filter(Boolean);
|
|
983
|
-
}
|
|
984
|
-
function scanDurableObjectModules(root) {
|
|
985
|
-
const directory = join(root, "durable-objects");
|
|
986
|
-
if (!existsSync(directory)) return [];
|
|
987
|
-
const modules = readdirSync(directory, { withFileTypes: true }).filter((entry) => entry.isFile() && MODULE_PATTERN.test(entry.name) && !entry.name.endsWith(".d.ts")).sort((a, b) => a.name.localeCompare(b.name)).map((entry) => {
|
|
988
|
-
const parts = words(entry.name.replace(MODULE_PATTERN, ""));
|
|
989
|
-
if (parts.length === 0) throw new Error(`durable: cannot derive a name from durable-objects/${entry.name}.`);
|
|
990
|
-
const classBase = parts.map((part) => part[0].toUpperCase() + part.slice(1)).join("");
|
|
991
|
-
const bindingName = parts.join("_").toUpperCase();
|
|
992
|
-
const slug = parts.join("-").toLowerCase();
|
|
993
|
-
return {
|
|
994
|
-
filePath: join(directory, entry.name),
|
|
995
|
-
bindingName,
|
|
996
|
-
className: `${classBase}DurableObject`,
|
|
997
|
-
migrationTag: `void-durable-${slug}-v1`
|
|
998
|
-
};
|
|
999
|
-
});
|
|
1000
|
-
const bindings = /* @__PURE__ */ new Set();
|
|
1001
|
-
const classes = /* @__PURE__ */ new Set();
|
|
1002
|
-
for (const module of modules) {
|
|
1003
|
-
if (bindings.has(module.bindingName) || classes.has(module.className)) throw new Error(`durable: duplicate generated name for '${module.filePath}'. Rename one of the durable-objects files.`);
|
|
1004
|
-
bindings.add(module.bindingName);
|
|
1005
|
-
classes.add(module.className);
|
|
1006
|
-
}
|
|
1007
|
-
return modules;
|
|
1008
|
-
}
|
|
1009
|
-
//#endregion
|
|
1010
931
|
//#region ../../node_modules/.pnpm/ci-info@4.4.0/node_modules/ci-info/vendors.json
|
|
1011
932
|
var require_vendors = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
1012
933
|
module.exports = [
|
|
@@ -1859,7 +1780,38 @@ async function prerenderPagesNode(options) {
|
|
|
1859
1780
|
return result;
|
|
1860
1781
|
}
|
|
1861
1782
|
//#endregion
|
|
1783
|
+
//#region src/shared/version-metadata.ts
|
|
1784
|
+
/** Build-only marker: an existing-site handoff must not add Worker bindings. */
|
|
1785
|
+
const CLOUDFLARE_PRESERVE_BINDINGS_BUILD_ENV = "VOID_CLOUDFLARE_PRESERVE_BINDINGS";
|
|
1786
|
+
const DEFAULT_VERSION_METADATA_BINDING = "__VOID_VERSION_METADATA";
|
|
1787
|
+
/** Keep the authored singleton name, and reject a cross-type binding collision. */
|
|
1788
|
+
function readVersionMetadataBinding(config) {
|
|
1789
|
+
const name = bindingNamesForField("version_metadata", config.version_metadata)[0];
|
|
1790
|
+
if (!name) return;
|
|
1791
|
+
const owner = findBindingNameOwner(config, "version_metadata", name);
|
|
1792
|
+
if (owner) throw new Error(`Cloudflare version metadata binding ${name} conflicts with ${owner}.`);
|
|
1793
|
+
return name;
|
|
1794
|
+
}
|
|
1795
|
+
/** Self-metadata adds no remote resource or plan entitlement. */
|
|
1796
|
+
function selectNativeVersionMetadataBinding(config, options) {
|
|
1797
|
+
if (!options.nativeBuild) return;
|
|
1798
|
+
const authored = readVersionMetadataBinding(config);
|
|
1799
|
+
if (authored || options.preserveBindings) return authored;
|
|
1800
|
+
const owner = findBindingNameOwner(config, "version_metadata", DEFAULT_VERSION_METADATA_BINDING);
|
|
1801
|
+
if (owner) throw new Error(`Cloudflare version metadata binding ${DEFAULT_VERSION_METADATA_BINDING} conflicts with ${owner}.`);
|
|
1802
|
+
return DEFAULT_VERSION_METADATA_BINDING;
|
|
1803
|
+
}
|
|
1804
|
+
//#endregion
|
|
1862
1805
|
//#region src/cli/cf-version-api.ts
|
|
1806
|
+
var CloudflareApiError = class extends Error {
|
|
1807
|
+
status;
|
|
1808
|
+
code;
|
|
1809
|
+
constructor(message, status, code) {
|
|
1810
|
+
super(message);
|
|
1811
|
+
this.status = status;
|
|
1812
|
+
this.code = code;
|
|
1813
|
+
}
|
|
1814
|
+
};
|
|
1863
1815
|
function object(value) {
|
|
1864
1816
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
1865
1817
|
}
|
|
@@ -1959,38 +1911,181 @@ function bindingsFromOutput(env, workerName, activeSecrets, explicitSecrets) {
|
|
|
1959
1911
|
...value.worker !== workerName ? { script_name: requiredString(value.worker, name) } : {}
|
|
1960
1912
|
});
|
|
1961
1913
|
break;
|
|
1914
|
+
case "unsafe:durable_object_namespace":
|
|
1915
|
+
if (Object.keys(value).some((key) => ![
|
|
1916
|
+
"type",
|
|
1917
|
+
"class_name",
|
|
1918
|
+
"dev"
|
|
1919
|
+
].includes(key))) throw new Error(`Cloudflare binding ${name} is not a verified local Durable Object.`);
|
|
1920
|
+
bindings.push({
|
|
1921
|
+
name,
|
|
1922
|
+
type: "durable_object_namespace",
|
|
1923
|
+
class_name: requiredString(value.class_name, name)
|
|
1924
|
+
});
|
|
1925
|
+
break;
|
|
1926
|
+
case "queue":
|
|
1927
|
+
bindings.push({
|
|
1928
|
+
name,
|
|
1929
|
+
type: "queue",
|
|
1930
|
+
queue_name: requiredString(value.name, name),
|
|
1931
|
+
...value.deliveryDelay === void 0 ? {} : { delivery_delay: value.deliveryDelay }
|
|
1932
|
+
});
|
|
1933
|
+
break;
|
|
1934
|
+
case "ai":
|
|
1935
|
+
case "browser":
|
|
1936
|
+
case "images":
|
|
1937
|
+
bindings.push({
|
|
1938
|
+
name,
|
|
1939
|
+
type: value.type
|
|
1940
|
+
});
|
|
1941
|
+
break;
|
|
1942
|
+
case "hyperdrive":
|
|
1943
|
+
bindings.push({
|
|
1944
|
+
name,
|
|
1945
|
+
type: "hyperdrive",
|
|
1946
|
+
id: requiredString(value.id, name)
|
|
1947
|
+
});
|
|
1948
|
+
break;
|
|
1949
|
+
case "worker":
|
|
1950
|
+
bindings.push({
|
|
1951
|
+
name,
|
|
1952
|
+
type: "service",
|
|
1953
|
+
service: requiredString(value.worker, name),
|
|
1954
|
+
...value.exportName === void 0 ? {} : { entrypoint: value.exportName },
|
|
1955
|
+
...value.props === void 0 ? {} : { props: value.props }
|
|
1956
|
+
});
|
|
1957
|
+
break;
|
|
1958
|
+
case "workflow":
|
|
1959
|
+
bindings.push({
|
|
1960
|
+
name,
|
|
1961
|
+
type: "workflow",
|
|
1962
|
+
workflow_name: requiredString(value.name, name),
|
|
1963
|
+
...value.worker === workerName ? { class_name: requiredString(value.exportName, name) } : { script_name: requiredString(value.worker, name) }
|
|
1964
|
+
});
|
|
1965
|
+
break;
|
|
1966
|
+
case "send-email":
|
|
1967
|
+
bindings.push({
|
|
1968
|
+
name,
|
|
1969
|
+
type: "send_email",
|
|
1970
|
+
...value.destinationAddress === void 0 ? {} : { destination_address: value.destinationAddress },
|
|
1971
|
+
...value.allowedDestinationAddresses === void 0 ? {} : { allowed_destination_addresses: value.allowedDestinationAddresses },
|
|
1972
|
+
...value.allowedSenderAddresses === void 0 ? {} : { allowed_sender_addresses: value.allowedSenderAddresses }
|
|
1973
|
+
});
|
|
1974
|
+
break;
|
|
1975
|
+
case "analytics-engine-dataset":
|
|
1976
|
+
bindings.push({
|
|
1977
|
+
name,
|
|
1978
|
+
type: "analytics_engine",
|
|
1979
|
+
...value.name === void 0 ? {} : { dataset: value.name }
|
|
1980
|
+
});
|
|
1981
|
+
break;
|
|
1982
|
+
case "vectorize":
|
|
1983
|
+
bindings.push({
|
|
1984
|
+
name,
|
|
1985
|
+
type: "vectorize",
|
|
1986
|
+
index_name: requiredString(value.name, name)
|
|
1987
|
+
});
|
|
1988
|
+
break;
|
|
1989
|
+
case "dispatch-namespace": {
|
|
1990
|
+
const outbound = object(value.outbound);
|
|
1991
|
+
bindings.push({
|
|
1992
|
+
name,
|
|
1993
|
+
type: "dispatch_namespace",
|
|
1994
|
+
namespace: requiredString(value.namespace, name),
|
|
1995
|
+
...outbound ? { outbound: {
|
|
1996
|
+
worker: { service: requiredString(outbound.worker, name) },
|
|
1997
|
+
...Array.isArray(outbound.parameters) ? { params: outbound.parameters.map((parameter) => ({ name: parameter })) } : {}
|
|
1998
|
+
} } : {}
|
|
1999
|
+
});
|
|
2000
|
+
break;
|
|
2001
|
+
}
|
|
1962
2002
|
case "assets":
|
|
1963
2003
|
bindings.push({
|
|
1964
2004
|
name,
|
|
1965
2005
|
type: "assets"
|
|
1966
2006
|
});
|
|
1967
2007
|
break;
|
|
2008
|
+
case "version-metadata":
|
|
2009
|
+
bindings.push({
|
|
2010
|
+
name,
|
|
2011
|
+
type: "version_metadata"
|
|
2012
|
+
});
|
|
2013
|
+
break;
|
|
1968
2014
|
default: throw new Error(`Cloudflare binding ${name} cannot be uploaded with pinned secrets.`);
|
|
1969
2015
|
}
|
|
1970
2016
|
}
|
|
1971
2017
|
return bindings;
|
|
1972
2018
|
}
|
|
1973
|
-
function exportsFromOutput(exports) {
|
|
2019
|
+
function exportsFromOutput(exports, bindings) {
|
|
1974
2020
|
if (exports === void 0) return;
|
|
1975
2021
|
const entries = object(exports);
|
|
1976
2022
|
if (!entries) throw new Error("Cloudflare Durable Object exports were not readable.");
|
|
1977
2023
|
const result = {};
|
|
2024
|
+
const workflows = /* @__PURE__ */ new Map();
|
|
1978
2025
|
for (const [name, raw] of Object.entries(entries)) {
|
|
1979
2026
|
const value = object(raw);
|
|
2027
|
+
if (value?.type === "workflow") {
|
|
2028
|
+
const workflowName = requiredString(value.name, `Workflow export ${name} name`);
|
|
2029
|
+
if (workflows.has(workflowName)) throw new Error(`Cloudflare Workflow ${workflowName} has multiple local exports.`);
|
|
2030
|
+
workflows.set(workflowName, name);
|
|
2031
|
+
result[name] = {
|
|
2032
|
+
type: "workflow",
|
|
2033
|
+
name: workflowName
|
|
2034
|
+
};
|
|
2035
|
+
continue;
|
|
2036
|
+
}
|
|
2037
|
+
if (value?.type === "worker") {
|
|
2038
|
+
result[name] = {
|
|
2039
|
+
type: "worker",
|
|
2040
|
+
...value.cache === void 0 ? {} : { cache: value.cache }
|
|
2041
|
+
};
|
|
2042
|
+
continue;
|
|
2043
|
+
}
|
|
1980
2044
|
if (!value || value.type !== "durable-object") throw new Error(`Cloudflare export ${name} cannot be uploaded with pinned secrets.`);
|
|
1981
2045
|
if (value.state === "deleted") result[name] = {
|
|
1982
2046
|
type: "durable-object",
|
|
1983
2047
|
state: "deleted"
|
|
1984
2048
|
};
|
|
1985
|
-
else if (value.
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
2049
|
+
else if (value.state === "renamed" || value.state === "transferred") {
|
|
2050
|
+
const renamed = value.state === "renamed";
|
|
2051
|
+
result[name] = {
|
|
2052
|
+
type: "durable-object",
|
|
2053
|
+
state: value.state,
|
|
2054
|
+
[renamed ? "renamed_to" : "transferred_to"]: requiredString(value[renamed ? "renamedTo" : "transferredTo"], name)
|
|
2055
|
+
};
|
|
2056
|
+
} else if (value.storage === "sqlite" || value.storage === "legacy-kv") {
|
|
2057
|
+
if (value.state !== void 0 && !["created", "expecting-transfer"].includes(String(value.state))) throw new Error(`Cloudflare Durable Object export ${name} has an unsupported state.`);
|
|
2058
|
+
result[name] = {
|
|
2059
|
+
type: "durable-object",
|
|
2060
|
+
storage: value.storage,
|
|
2061
|
+
state: value.state ?? "created",
|
|
2062
|
+
...value.container === void 0 ? {} : { container: requiredString(value.container, name) },
|
|
2063
|
+
...value.state === "expecting-transfer" ? { transfer_from: requiredString(value.transferFrom, name) } : {}
|
|
2064
|
+
};
|
|
2065
|
+
} else throw new Error(`Cloudflare Durable Object export ${name} has no storage type.`);
|
|
2066
|
+
}
|
|
2067
|
+
for (const binding of bindings) {
|
|
2068
|
+
if (binding.type !== "workflow") continue;
|
|
2069
|
+
const localExport = workflows.get(String(binding.workflow_name));
|
|
2070
|
+
if (localExport !== void 0 && (binding.script_name !== void 0 || binding.class_name !== localExport)) throw new Error(`Cloudflare Workflow binding ${binding.name} conflicts with its local export.`);
|
|
1991
2071
|
}
|
|
1992
2072
|
return result;
|
|
1993
2073
|
}
|
|
2074
|
+
async function preflightWorkflowExports(options) {
|
|
2075
|
+
for (const raw of Object.values(options.exports ?? {})) {
|
|
2076
|
+
const entry = object(raw);
|
|
2077
|
+
if (entry?.type !== "workflow") continue;
|
|
2078
|
+
const name = requiredString(entry.name, "Workflow name");
|
|
2079
|
+
let workflow;
|
|
2080
|
+
try {
|
|
2081
|
+
workflow = await apiResult(`${options.accountUrl}/workflows/${encodeURIComponent(name)}`, options.token, "GET", void 0, options.verifyUploader);
|
|
2082
|
+
} catch (cause) {
|
|
2083
|
+
if (cause instanceof CloudflareApiError && cause.status === 404 && cause.code === 10200) continue;
|
|
2084
|
+
throw cause;
|
|
2085
|
+
}
|
|
2086
|
+
if (workflow.name !== name || workflow.script_name !== options.workerName || typeof workflow.class_name !== "string" || !workflow.class_name) throw new Error(`Cloudflare Workflow ${name} is not owned by this Worker.`);
|
|
2087
|
+
}
|
|
2088
|
+
}
|
|
1994
2089
|
function assetConfigFromOutput(value) {
|
|
1995
2090
|
if (value === void 0) return;
|
|
1996
2091
|
const config = object(value);
|
|
@@ -2027,11 +2122,211 @@ async function apiResult(url, token, method, body, verifyUploader, timeout = 12e
|
|
|
2027
2122
|
if (!response.ok || parsed?.success !== true || !result) {
|
|
2028
2123
|
const error = Array.isArray(parsed?.errors) ? object(parsed.errors[0]) : null;
|
|
2029
2124
|
const code = Number.isSafeInteger(error?.code) ? ` [code: ${error.code}]` : "";
|
|
2030
|
-
|
|
2031
|
-
throw new Error(`Cloudflare version upload failed (${response.status})${code}.${message}`);
|
|
2125
|
+
throw new CloudflareApiError(`Cloudflare version upload failed (${response.status})${code}.`, response.status, typeof error?.code === "number" ? error.code : void 0);
|
|
2032
2126
|
}
|
|
2033
2127
|
return result;
|
|
2034
2128
|
}
|
|
2129
|
+
function assertContainerApplicationIdentity(application, plan, namespace) {
|
|
2130
|
+
if (application.id !== namespace || application.name !== plan.name || application.scheduling_policy !== "durable_object" || object(application.durable_objects)?.namespace_id !== namespace) throw new Error(`Cloudflare Container ${plan.name} application identity does not match the uploaded namespace.`);
|
|
2131
|
+
}
|
|
2132
|
+
function assertContainerApplicationSettings(application, plan) {
|
|
2133
|
+
const desired = object(plan.settings.configuration) ?? {};
|
|
2134
|
+
const current = object(application.configuration) ?? {};
|
|
2135
|
+
const changedConfiguration = Object.entries(desired).some(([key, value]) => {
|
|
2136
|
+
if (key === "wrangler_ssh") {
|
|
2137
|
+
const ssh = object(current.wrangler_ssh) ?? {};
|
|
2138
|
+
const expected = object(value) ?? {};
|
|
2139
|
+
return !isDeepStrictEqual(ssh.enabled ?? false, expected.enabled) || expected.enabled === true && expected.port !== void 0 && !isDeepStrictEqual(ssh.port, expected.port);
|
|
2140
|
+
}
|
|
2141
|
+
if (key === "experimental_flags" && Array.isArray(value)) {
|
|
2142
|
+
const flags = current.experimental_flags ?? [];
|
|
2143
|
+
return !Array.isArray(flags) || !isDeepStrictEqual([...flags].sort(), [...value].sort());
|
|
2144
|
+
}
|
|
2145
|
+
return !isDeepStrictEqual(current[key] ?? [], value);
|
|
2146
|
+
});
|
|
2147
|
+
const logs = object(object(plan.settings.observability)?.logs);
|
|
2148
|
+
const currentLogs = object(object(application.observability)?.logs);
|
|
2149
|
+
if (changedConfiguration || logs !== null && !isDeepStrictEqual(currentLogs?.enabled ?? false, logs.enabled)) throw new Error(`Cloudflare Container ${plan.name} settings differ from the live application. Version-aware deployment cannot safely change these shared settings. Keep the existing Container settings in your configuration, or update this Container explicitly in the Cloudflare dashboard before retrying.`);
|
|
2150
|
+
}
|
|
2151
|
+
async function preflightContainerApplications(plans, bindings, accountUrl, workerName, token, verifyUploader) {
|
|
2152
|
+
for (const plan of plans) {
|
|
2153
|
+
const matches = bindings.map(object).filter((binding) => binding?.type === "durable_object_namespace" && binding.class_name === plan.className && (binding.script_name === void 0 || binding.script_name === workerName) && binding.environment === void 0 && binding.dispatch_namespace === void 0 && binding.namespace_id !== void 0);
|
|
2154
|
+
const namespaces = new Set(matches.map((binding) => binding.namespace_id));
|
|
2155
|
+
if (namespaces.size > 1) throw new Error(`Cloudflare Container ${plan.name} active namespace was ambiguous.`);
|
|
2156
|
+
const namespace = [...namespaces][0];
|
|
2157
|
+
if (namespace === void 0) {
|
|
2158
|
+
if (Object.keys(plan.images).length === 0) throw new Error(`Cloudflare Container ${plan.name} has no images and no verified existing namespace application.`);
|
|
2159
|
+
continue;
|
|
2160
|
+
}
|
|
2161
|
+
if (typeof namespace !== "string" || !/^[a-f0-9]{32}$/.test(namespace)) throw new Error("The active Container namespace ID was invalid.");
|
|
2162
|
+
try {
|
|
2163
|
+
const application = await apiResult(`${accountUrl}/containers/applications/${encodeURIComponent(namespace)}`, token, "GET", void 0, verifyUploader);
|
|
2164
|
+
assertContainerApplicationIdentity(application, plan, namespace);
|
|
2165
|
+
assertContainerApplicationSettings(application, plan);
|
|
2166
|
+
} catch (cause) {
|
|
2167
|
+
if (!(cause instanceof CloudflareApiError) || cause.status !== 404 || Object.keys(plan.images).length === 0) throw cause;
|
|
2168
|
+
}
|
|
2169
|
+
}
|
|
2170
|
+
}
|
|
2171
|
+
function containerPlansFromOutput(containers, exports, bindings) {
|
|
2172
|
+
const plans = [];
|
|
2173
|
+
for (const { config } of containers) {
|
|
2174
|
+
if (config.schedulingPolicy !== "durable-object") throw new Error("Scheduler-managed Cloudflare Containers cannot be uploaded with pinned secrets.");
|
|
2175
|
+
const classes = Object.entries(exports ?? {}).filter(([, value]) => object(value)?.container === config.name);
|
|
2176
|
+
if (classes.length !== 1) throw new Error(`Cloudflare Container ${config.name} needs exactly one local SQLite export.`);
|
|
2177
|
+
const [className, raw] = classes[0];
|
|
2178
|
+
const declaration = object(raw);
|
|
2179
|
+
const localBindings = bindings.filter((binding) => binding.type === "durable_object_namespace" && binding.class_name === className && binding.script_name === void 0);
|
|
2180
|
+
if (declaration.storage !== "sqlite" || localBindings.length === 0) throw new Error(`Cloudflare Container ${config.name} needs a local SQLite Durable Object binding.`);
|
|
2181
|
+
const unsafe = object(config.unsafe);
|
|
2182
|
+
const configuration = object(unsafe?.configuration);
|
|
2183
|
+
if (unsafe && Object.keys(unsafe).some((key) => key !== "configuration") || configuration && Object.keys(configuration).some((key) => key !== "experimental_flags")) throw new Error(`Cloudflare Container ${config.name} has an unsupported setting.`);
|
|
2184
|
+
const settings = {
|
|
2185
|
+
...configuration || config.ssh || config.authorizedKeys ? { configuration: {
|
|
2186
|
+
...configuration ?? {},
|
|
2187
|
+
...config.ssh ? { wrangler_ssh: config.ssh } : {},
|
|
2188
|
+
...config.authorizedKeys ? { authorized_keys: config.authorizedKeys.map(({ name, publicKey }) => ({
|
|
2189
|
+
name,
|
|
2190
|
+
public_key: publicKey
|
|
2191
|
+
})) } : {}
|
|
2192
|
+
} } : {},
|
|
2193
|
+
...config.observability ? { observability: { logs: { enabled: config.observability.enabled === true || config.observability.logs?.enabled === true } } } : {}
|
|
2194
|
+
};
|
|
2195
|
+
plans.push({
|
|
2196
|
+
name: config.name,
|
|
2197
|
+
className,
|
|
2198
|
+
images: config.images ?? {},
|
|
2199
|
+
settings
|
|
2200
|
+
});
|
|
2201
|
+
}
|
|
2202
|
+
for (const [name, raw] of Object.entries(exports ?? {})) {
|
|
2203
|
+
const container = object(raw)?.container;
|
|
2204
|
+
if (container !== void 0 && !plans.some((plan) => plan.name === container && plan.className === name)) throw new Error(`Cloudflare export ${name} references a Container outside the verified output.`);
|
|
2205
|
+
}
|
|
2206
|
+
return plans;
|
|
2207
|
+
}
|
|
2208
|
+
async function dockerImageDigest(image, timeout, verifyUploader) {
|
|
2209
|
+
if (!verifyUploader()) throw new Error("The Cloudflare uploader changed during deployment.");
|
|
2210
|
+
const stdout = await new Promise((resolve, reject) => {
|
|
2211
|
+
execFile(process.env.WRANGLER_DOCKER_BIN ?? "docker", [
|
|
2212
|
+
"image",
|
|
2213
|
+
"inspect",
|
|
2214
|
+
"--format",
|
|
2215
|
+
"{{json .RepoDigests}}",
|
|
2216
|
+
image
|
|
2217
|
+
], {
|
|
2218
|
+
encoding: "utf8",
|
|
2219
|
+
timeout,
|
|
2220
|
+
maxBuffer: 1048576,
|
|
2221
|
+
windowsHide: true
|
|
2222
|
+
}, (error, stdout) => error ? reject(/* @__PURE__ */ new Error("Cloudflare Container image digest could not be verified after push.")) : resolve(stdout));
|
|
2223
|
+
});
|
|
2224
|
+
const digests = JSON.parse(stdout);
|
|
2225
|
+
const repository = image.replace(/:[^/:]+$/, "");
|
|
2226
|
+
const matching = Array.isArray(digests) ? digests.filter((digest) => typeof digest === "string" && digest.startsWith(`${repository}@sha256:`) && /^[a-f0-9]{64}$/.test(digest.slice(digest.lastIndexOf(":") + 1))) : [];
|
|
2227
|
+
if (matching.length !== 1) throw new Error("Cloudflare Container image digest could not be verified after push.");
|
|
2228
|
+
return matching[0];
|
|
2229
|
+
}
|
|
2230
|
+
async function prepareContainerMetadata(options) {
|
|
2231
|
+
if (options.plans.length === 0) return [];
|
|
2232
|
+
const deadline = Date.now() + 9e5;
|
|
2233
|
+
const remaining = () => {
|
|
2234
|
+
const duration = deadline - Date.now();
|
|
2235
|
+
if (duration <= 0) throw new Error("Cloudflare Container image preparation timed out.");
|
|
2236
|
+
return duration;
|
|
2237
|
+
};
|
|
2238
|
+
const prepared = /* @__PURE__ */ new Map();
|
|
2239
|
+
const result = [];
|
|
2240
|
+
for (const plan of options.plans) {
|
|
2241
|
+
const images = {};
|
|
2242
|
+
for (const [name, raw] of Object.entries(plan.images)) {
|
|
2243
|
+
const source = object(raw);
|
|
2244
|
+
const reference = requiredString(source.localReference ?? source.reference, `Container ${plan.name} image`);
|
|
2245
|
+
let image = prepared.get(reference);
|
|
2246
|
+
if (!image) {
|
|
2247
|
+
image = reference;
|
|
2248
|
+
if (source.localReference !== void 0) {
|
|
2249
|
+
if (!options.runCf || !options.verifyUploader()) throw new Error("The verified Cloudflare Container image uploader is unavailable.");
|
|
2250
|
+
const pushed = await options.runCf([
|
|
2251
|
+
"containers",
|
|
2252
|
+
"push",
|
|
2253
|
+
"--tag",
|
|
2254
|
+
reference
|
|
2255
|
+
], {
|
|
2256
|
+
cwd: options.directory,
|
|
2257
|
+
capture: true,
|
|
2258
|
+
timeoutMs: remaining(),
|
|
2259
|
+
maxOutputBytes: 16777216
|
|
2260
|
+
});
|
|
2261
|
+
if (pushed.status !== 0 || pushed.signal || pushed.error) throw new Error("Cloudflare Container image push failed.");
|
|
2262
|
+
const matches = [...pushed.stdout.matchAll(/Pushed image:\s*(\S+)/g)];
|
|
2263
|
+
const remote = matches.length === 1 ? matches[0][1] : "";
|
|
2264
|
+
if (!remote.startsWith(`registry.cloudflare.com/${options.accountId}/`) || [...remote].some((character) => character.charCodeAt(0) <= 32 || character.charCodeAt(0) === 127)) throw new Error("Cloudflare Container image push did not return the verified account registry.");
|
|
2265
|
+
image = await dockerImageDigest(remote, Math.min(12e4, remaining()), options.verifyUploader);
|
|
2266
|
+
}
|
|
2267
|
+
for (;;) {
|
|
2268
|
+
const ready = await apiResult(`${options.accountUrl}/containers/image-preparations`, options.token, "POST", { image }, options.verifyUploader, Math.min(12e4, remaining()));
|
|
2269
|
+
if (ready.image !== image) throw new Error("Cloudflare Container image preparation returned another image.");
|
|
2270
|
+
if (ready.status === "ready") break;
|
|
2271
|
+
if (ready.status !== "pending") throw new Error("Cloudflare Container image preparation failed or returned an unsupported state.");
|
|
2272
|
+
await setTimeout$1(Math.min(2e3, remaining()));
|
|
2273
|
+
}
|
|
2274
|
+
prepared.set(reference, image);
|
|
2275
|
+
}
|
|
2276
|
+
images[name] = image;
|
|
2277
|
+
}
|
|
2278
|
+
result.push({
|
|
2279
|
+
name: plan.name,
|
|
2280
|
+
class_name: plan.className,
|
|
2281
|
+
...Object.keys(images).length ? { images } : {}
|
|
2282
|
+
});
|
|
2283
|
+
}
|
|
2284
|
+
return result;
|
|
2285
|
+
}
|
|
2286
|
+
async function ensureContainerApplications(options) {
|
|
2287
|
+
if (options.plans.length === 0) return;
|
|
2288
|
+
const deadline = Date.now() + 6e4;
|
|
2289
|
+
let version;
|
|
2290
|
+
for (;;) try {
|
|
2291
|
+
version = await apiResult(`${options.accountUrl}/workers/scripts/${encodeURIComponent(options.workerName)}/versions/${encodeURIComponent(options.versionId)}`, options.token, "GET", void 0, options.verifyUploader, Math.max(1, Math.min(3e4, deadline - Date.now())));
|
|
2292
|
+
break;
|
|
2293
|
+
} catch (cause) {
|
|
2294
|
+
if (!(cause instanceof CloudflareApiError) || cause.code !== 100146 || Date.now() >= deadline) throw cause;
|
|
2295
|
+
await setTimeout$1(Math.min(2e3, deadline - Date.now()));
|
|
2296
|
+
}
|
|
2297
|
+
const versionBindings = object(version.resources)?.bindings;
|
|
2298
|
+
if (version.id !== options.versionId || !Array.isArray(versionBindings)) throw new Error("The uploaded Container namespace could not be verified.");
|
|
2299
|
+
const metadata = object(object(version.resources)?.script_runtime)?.containers;
|
|
2300
|
+
if (!Array.isArray(metadata) || metadata.length !== options.containers.length || options.containers.some((expected) => {
|
|
2301
|
+
const matching = metadata.map(object).filter((entry) => entry !== null && entry.name === expected.name && entry.class_name === expected.class_name);
|
|
2302
|
+
return matching.length !== 1 || !isDeepStrictEqual(matching[0].images ?? {}, expected.images ?? {});
|
|
2303
|
+
})) throw new Error("The uploaded Worker version did not retain the verified Container image metadata.");
|
|
2304
|
+
for (const plan of options.plans) {
|
|
2305
|
+
const matches = versionBindings.map(object).filter((binding) => binding?.type === "durable_object_namespace" && binding.class_name === plan.className && (binding.script_name === void 0 || binding.script_name === options.workerName) && binding.environment === void 0 && binding.dispatch_namespace === void 0);
|
|
2306
|
+
const namespaces = new Set(matches.map((binding) => binding.namespace_id));
|
|
2307
|
+
if (matches.length === 0 || namespaces.size !== 1) throw new Error(`Cloudflare Container ${plan.name} has no unambiguous uploaded local namespace.`);
|
|
2308
|
+
const namespace = requiredString([...namespaces][0], `Container ${plan.name} namespace`);
|
|
2309
|
+
if (!/^[a-f0-9]{32}$/.test(namespace)) throw new Error("The uploaded Container namespace ID was invalid.");
|
|
2310
|
+
const url = `${options.accountUrl}/containers/applications/${encodeURIComponent(namespace)}`;
|
|
2311
|
+
let application;
|
|
2312
|
+
try {
|
|
2313
|
+
application = await apiResult(url, options.token, "GET", void 0, options.verifyUploader);
|
|
2314
|
+
} catch (cause) {
|
|
2315
|
+
if (!(cause instanceof CloudflareApiError) || cause.status !== 404) throw cause;
|
|
2316
|
+
application = await apiResult(`${options.accountUrl}/containers/applications`, options.token, "POST", {
|
|
2317
|
+
name: plan.name,
|
|
2318
|
+
scheduling_policy: "durable_object",
|
|
2319
|
+
durable_objects: { namespace_id: namespace },
|
|
2320
|
+
...plan.settings
|
|
2321
|
+
}, options.verifyUploader);
|
|
2322
|
+
}
|
|
2323
|
+
assertContainerApplicationIdentity(application, plan, namespace);
|
|
2324
|
+
assertContainerApplicationSettings(application, plan);
|
|
2325
|
+
const confirmed = await apiResult(url, options.token, "GET", void 0, options.verifyUploader);
|
|
2326
|
+
assertContainerApplicationIdentity(confirmed, plan, namespace);
|
|
2327
|
+
assertContainerApplicationSettings(confirmed, plan);
|
|
2328
|
+
}
|
|
2329
|
+
}
|
|
2035
2330
|
async function uploadAssets(options) {
|
|
2036
2331
|
if (!options.output.assetsDirectory) return;
|
|
2037
2332
|
const directory = getWorkerAssetsDir(options.output.directory);
|
|
@@ -2094,7 +2389,8 @@ async function uploadAssets(options) {
|
|
|
2094
2389
|
async function uploadPinnedCloudflareVersion(options) {
|
|
2095
2390
|
const activeSecrets = options.output.activeSecrets;
|
|
2096
2391
|
if (!activeSecrets) throw new Error("The active Worker secret source was not verified.");
|
|
2097
|
-
const
|
|
2392
|
+
const built = await readBuildOutput(options.output.directory);
|
|
2393
|
+
const config = built.workers.default.config;
|
|
2098
2394
|
if (config.name !== options.workerName || !config.manifest || config.manifest.type !== "complete") throw new Error("The verified Cloudflare Worker output changed before upload.");
|
|
2099
2395
|
const unsupported = Object.keys(config).filter((key) => !(/* @__PURE__ */ new Set([
|
|
2100
2396
|
"name",
|
|
@@ -2118,6 +2414,8 @@ async function uploadPinnedCloudflareVersion(options) {
|
|
|
2118
2414
|
const explicitSecrets = options.secretsFilePath ? object(JSON.parse(readFileSync(options.secretsFilePath, "utf8"))) : {};
|
|
2119
2415
|
if (!explicitSecrets) throw new Error("The explicit Cloudflare secrets file was not readable.");
|
|
2120
2416
|
const bindings = bindingsFromOutput(config.env ?? {}, options.workerName, activeSecrets, explicitSecrets);
|
|
2417
|
+
const exports = exportsFromOutput(config.exports, bindings);
|
|
2418
|
+
const containerPlans = containerPlansFromOutput(built.containers, exports, bindings);
|
|
2121
2419
|
const active = await apiResult(`${options.apiBaseUrl.replace(/\/$/, "")}/accounts/${encodeURIComponent(options.accountId)}/workers/workers/${encodeURIComponent(options.workerName)}/versions/${encodeURIComponent(activeSecrets.versionId)}`, options.token, "GET", void 0, options.verifyUploader);
|
|
2122
2420
|
if (active.id !== activeSecrets.versionId || !Array.isArray(active.bindings)) throw new Error("The active Cloudflare Worker bindings could not be verified.");
|
|
2123
2421
|
const activeBindingNames = /* @__PURE__ */ new Set();
|
|
@@ -2137,7 +2435,6 @@ async function uploadPinnedCloudflareVersion(options) {
|
|
|
2137
2435
|
}
|
|
2138
2436
|
}
|
|
2139
2437
|
if (activeSecrets.bindings.some(({ name }) => !activeBindingNames.has(name))) throw new Error("The active Cloudflare Worker secrets changed before upload.");
|
|
2140
|
-
const exports = exportsFromOutput(config.exports);
|
|
2141
2438
|
const assetConfig = assetConfigFromOutput(config.assets);
|
|
2142
2439
|
if (bindings.some((binding) => binding.type === "assets") && !options.output.assetsDirectory) throw new Error("The Cloudflare Worker has an assets binding without verified assets.");
|
|
2143
2440
|
const modules = [];
|
|
@@ -2151,6 +2448,23 @@ async function uploadPinnedCloudflareVersion(options) {
|
|
|
2151
2448
|
});
|
|
2152
2449
|
}
|
|
2153
2450
|
const accountUrl = `${options.apiBaseUrl.replace(/\/$/, "")}/accounts/${encodeURIComponent(options.accountId)}`;
|
|
2451
|
+
await preflightWorkflowExports({
|
|
2452
|
+
exports,
|
|
2453
|
+
accountUrl,
|
|
2454
|
+
workerName: options.workerName,
|
|
2455
|
+
token: options.token,
|
|
2456
|
+
verifyUploader: options.verifyUploader
|
|
2457
|
+
});
|
|
2458
|
+
await preflightContainerApplications(containerPlans, active.bindings, accountUrl, options.workerName, options.token, options.verifyUploader);
|
|
2459
|
+
const containers = await prepareContainerMetadata({
|
|
2460
|
+
plans: containerPlans,
|
|
2461
|
+
directory: options.output.directory,
|
|
2462
|
+
accountUrl,
|
|
2463
|
+
accountId: options.accountId,
|
|
2464
|
+
token: options.token,
|
|
2465
|
+
verifyUploader: options.verifyUploader,
|
|
2466
|
+
runCf: options.runCf
|
|
2467
|
+
});
|
|
2154
2468
|
const jwt = await uploadAssets({
|
|
2155
2469
|
output: options.output,
|
|
2156
2470
|
accountUrl,
|
|
@@ -2165,14 +2479,30 @@ async function uploadPinnedCloudflareVersion(options) {
|
|
|
2165
2479
|
compatibility_flags: config.compatibilityFlags,
|
|
2166
2480
|
bindings,
|
|
2167
2481
|
...exports ? { exports } : {},
|
|
2482
|
+
...containers.length ? { containers } : {},
|
|
2168
2483
|
...jwt ? { assets: {
|
|
2169
2484
|
jwt,
|
|
2170
2485
|
...assetConfig ? { config: assetConfig } : {}
|
|
2171
2486
|
} } : {},
|
|
2172
2487
|
annotations: { "workers/message": options.message ?? "" }
|
|
2173
2488
|
}, options.verifyUploader);
|
|
2489
|
+
const versionId = uploaded.id;
|
|
2490
|
+
if (typeof versionId !== "string" || !/^[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12}$/i.test(versionId)) throw new Error("Cloudflare accepted the Worker upload but returned an invalid version identity. Read back the Worker deployment before retrying.");
|
|
2491
|
+
try {
|
|
2492
|
+
await ensureContainerApplications({
|
|
2493
|
+
plans: containerPlans,
|
|
2494
|
+
containers,
|
|
2495
|
+
accountUrl,
|
|
2496
|
+
workerName: options.workerName,
|
|
2497
|
+
versionId,
|
|
2498
|
+
token: options.token,
|
|
2499
|
+
verifyUploader: options.verifyUploader
|
|
2500
|
+
});
|
|
2501
|
+
} catch {
|
|
2502
|
+
throw new Error(`Cloudflare Worker version ${versionId} was uploaded${options.atomic ? " and may already be published" : ""}, but its Container applications could not be verified. Read back the Worker deployment and Container identities before retrying.`);
|
|
2503
|
+
}
|
|
2174
2504
|
return {
|
|
2175
|
-
id:
|
|
2505
|
+
id: versionId,
|
|
2176
2506
|
urls: Array.isArray(uploaded.urls) ? uploaded.urls.filter((url) => typeof url === "string") : []
|
|
2177
2507
|
};
|
|
2178
2508
|
}
|
|
@@ -2185,10 +2515,6 @@ function failed(message) {
|
|
|
2185
2515
|
stderr: message
|
|
2186
2516
|
};
|
|
2187
2517
|
}
|
|
2188
|
-
function flag(args, name) {
|
|
2189
|
-
const index = args.indexOf(name);
|
|
2190
|
-
return index < 0 ? void 0 : args[index + 1];
|
|
2191
|
-
}
|
|
2192
2518
|
function parseJson(value) {
|
|
2193
2519
|
try {
|
|
2194
2520
|
return JSON.parse(value);
|
|
@@ -2257,15 +2583,12 @@ function createCfResourceVerifier(options) {
|
|
|
2257
2583
|
const name = identifier("name");
|
|
2258
2584
|
if (!name) return failed(`Cloudflare Queue binding ${bindingName} has no name.`);
|
|
2259
2585
|
if (!options.verifyCompatibilityRunner()) return failed("The Cloudflare resource verifier changed during deployment.");
|
|
2260
|
-
const found = await Promise.resolve(options.runWrangler(
|
|
2261
|
-
"queues",
|
|
2262
|
-
"info",
|
|
2586
|
+
const found = await Promise.resolve(options.runWrangler({
|
|
2587
|
+
type: "queues.info",
|
|
2263
2588
|
name,
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
], { capture: true }));
|
|
2268
|
-
if (found.status !== 0 || found.signal || found.error || found.stdout.trim() !== `Queue Name: ${name}`) return failed(`Cloudflare Queue ${name} is unavailable; refusing automatic provisioning.`);
|
|
2589
|
+
configPath: options.configPath
|
|
2590
|
+
}, { capture: true }));
|
|
2591
|
+
if (found.status !== 0 || found.signal || found.error || !record(found.data) || found.data.name !== name) return failed(`Cloudflare Queue ${name} is unavailable; refusing automatic provisioning.`);
|
|
2269
2592
|
continue;
|
|
2270
2593
|
}
|
|
2271
2594
|
const resource = value.type === "r2" ? {
|
|
@@ -2314,7 +2637,7 @@ function createCfResourceVerifier(options) {
|
|
|
2314
2637
|
cwd: directory,
|
|
2315
2638
|
capture: true
|
|
2316
2639
|
});
|
|
2317
|
-
const body = parseJson(result.stdout);
|
|
2640
|
+
const body = result.data ?? parseJson(result.stdout);
|
|
2318
2641
|
if (result.status !== 0 || result.signal || result.error || !record(body) || body[resource.response] !== name) return failed(`Cloudflare ${resource.kind} ${name} is unavailable; refusing automatic provisioning.`);
|
|
2319
2642
|
}
|
|
2320
2643
|
return {
|
|
@@ -2339,6 +2662,8 @@ function createCfCommand(options) {
|
|
|
2339
2662
|
if (env.HTTP_PROXY || env.HTTPS_PROXY || env.http_proxy || env.https_proxy) env.NODE_USE_ENV_PROXY = "1";
|
|
2340
2663
|
if (options.token) env.CLOUDFLARE_API_TOKEN = options.token;
|
|
2341
2664
|
return await new Promise((resolve) => {
|
|
2665
|
+
const bounded = run.timeoutMs !== void 0;
|
|
2666
|
+
const processGroup = bounded && process.platform !== "win32";
|
|
2342
2667
|
const child = spawn(process.execPath, [cf, ...args], {
|
|
2343
2668
|
cwd: run.cwd,
|
|
2344
2669
|
env,
|
|
@@ -2348,17 +2673,49 @@ function createCfCommand(options) {
|
|
|
2348
2673
|
"ignore",
|
|
2349
2674
|
"pipe",
|
|
2350
2675
|
"pipe"
|
|
2351
|
-
]
|
|
2676
|
+
],
|
|
2677
|
+
detached: processGroup
|
|
2352
2678
|
});
|
|
2353
2679
|
const stdout = [];
|
|
2354
2680
|
const stderr = [];
|
|
2355
2681
|
let bytes = 0;
|
|
2356
2682
|
let error = null;
|
|
2683
|
+
const stop = () => {
|
|
2684
|
+
if (processGroup && child.pid) try {
|
|
2685
|
+
process.kill(-child.pid, "SIGKILL");
|
|
2686
|
+
} catch (cause) {
|
|
2687
|
+
if (cause.code !== "ESRCH") child.kill("SIGKILL");
|
|
2688
|
+
}
|
|
2689
|
+
else if (bounded && process.platform === "win32" && child.pid) execFile("taskkill", [
|
|
2690
|
+
"/PID",
|
|
2691
|
+
String(child.pid),
|
|
2692
|
+
"/T",
|
|
2693
|
+
"/F"
|
|
2694
|
+
], {
|
|
2695
|
+
windowsHide: true,
|
|
2696
|
+
timeout: 1e4
|
|
2697
|
+
}, (cause) => {
|
|
2698
|
+
if (cause) child.kill("SIGKILL");
|
|
2699
|
+
});
|
|
2700
|
+
else child.kill("SIGKILL");
|
|
2701
|
+
};
|
|
2702
|
+
const interrupted = () => {
|
|
2703
|
+
error = "Cloudflare command interrupted.";
|
|
2704
|
+
stop();
|
|
2705
|
+
};
|
|
2706
|
+
if (bounded) {
|
|
2707
|
+
process.on("SIGINT", interrupted);
|
|
2708
|
+
process.on("SIGTERM", interrupted);
|
|
2709
|
+
}
|
|
2710
|
+
const timer = run.timeoutMs === void 0 ? void 0 : setTimeout(() => {
|
|
2711
|
+
error = "Cloudflare command timed out.";
|
|
2712
|
+
stop();
|
|
2713
|
+
}, run.timeoutMs);
|
|
2357
2714
|
const collect = (chunks, chunk) => {
|
|
2358
2715
|
bytes += chunk.length;
|
|
2359
|
-
if (bytes > 268435456) {
|
|
2360
|
-
error = "Cloudflare command output exceeded
|
|
2361
|
-
|
|
2716
|
+
if (bytes > (run.maxOutputBytes ?? 268435456)) {
|
|
2717
|
+
error = "Cloudflare command output exceeded its verified limit.";
|
|
2718
|
+
stop();
|
|
2362
2719
|
} else chunks.push(chunk);
|
|
2363
2720
|
};
|
|
2364
2721
|
child.stdout.on("data", (chunk) => collect(stdout, chunk));
|
|
@@ -2367,10 +2724,23 @@ function createCfCommand(options) {
|
|
|
2367
2724
|
error = cause.message;
|
|
2368
2725
|
});
|
|
2369
2726
|
child.on("close", (status, signal) => {
|
|
2727
|
+
clearTimeout(timer);
|
|
2728
|
+
if (bounded) {
|
|
2729
|
+
process.off("SIGINT", interrupted);
|
|
2730
|
+
process.off("SIGTERM", interrupted);
|
|
2731
|
+
}
|
|
2732
|
+
const output = Buffer.concat(stdout).toString("utf8");
|
|
2733
|
+
const diagnostic = Buffer.concat(stderr).toString("utf8");
|
|
2734
|
+
const completed = typeof status === "number" && signal == null && error == null;
|
|
2735
|
+
const code = completed ? (output + "\n" + diagnostic).match(/\[(?:code:\s*)?(\d{4,})\]/)?.[1] : void 0;
|
|
2736
|
+
const missingUploadTarget = completed && status !== 0 && code === void 0 && args[0] === "workers" && args[1] === "versions" && args[2] === "create" && (output + "\n" + diagnostic).replace(/\s+/g, " ").includes("You cannot upload a new version of a Worker that does not yet exist.");
|
|
2370
2737
|
resolve({
|
|
2371
2738
|
status: typeof status === "number" ? status : 1,
|
|
2372
|
-
stdout:
|
|
2373
|
-
stderr:
|
|
2739
|
+
stdout: output,
|
|
2740
|
+
stderr: diagnostic,
|
|
2741
|
+
...code ? { errorCode: Number(code) } : {},
|
|
2742
|
+
...missingUploadTarget ? { failure: "not-found" } : {},
|
|
2743
|
+
...completed && status !== 0 ? { errors: [{ message: output + "\n" + diagnostic }] } : {},
|
|
2374
2744
|
signal,
|
|
2375
2745
|
error
|
|
2376
2746
|
});
|
|
@@ -2384,10 +2754,31 @@ function createCfCommand(options) {
|
|
|
2384
2754
|
*/
|
|
2385
2755
|
function createCfVersionRunner(options) {
|
|
2386
2756
|
const { output, workerName, runCf } = options;
|
|
2387
|
-
const run = async (args, capture, cwd = output.directory) =>
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2757
|
+
const run = async (args, capture, cwd = output.directory) => {
|
|
2758
|
+
const result = await runCf(args, {
|
|
2759
|
+
cwd,
|
|
2760
|
+
capture
|
|
2761
|
+
});
|
|
2762
|
+
return {
|
|
2763
|
+
...result,
|
|
2764
|
+
data: result.data ?? parseJson(result.stdout)
|
|
2765
|
+
};
|
|
2766
|
+
};
|
|
2767
|
+
const uploadedResult = (result) => {
|
|
2768
|
+
if (result.status !== 0 || result.signal || result.error) return result;
|
|
2769
|
+
if (record(result.data) && typeof result.data.versionId === "string") return result;
|
|
2770
|
+
const versionId = result.stdout.match(/(?:Worker|Current) Version ID:\s*([0-9a-f]{8}-[0-9a-f-]{27})/i)?.[1];
|
|
2771
|
+
const previewUrl = result.stdout.match(/Version Preview(?: Alias)? URL:\s*(https:\/\/\S+)/i)?.[1];
|
|
2772
|
+
const workersDevUrl = result.stdout.match(/(https:\/\/[a-z0-9.-]+\.workers\.dev(?:\/[^\s]*)?)/i)?.[1];
|
|
2773
|
+
return {
|
|
2774
|
+
...result,
|
|
2775
|
+
data: versionId ? {
|
|
2776
|
+
versionId,
|
|
2777
|
+
...previewUrl ? { previewUrl } : {},
|
|
2778
|
+
...workersDevUrl ? { workersDevUrl } : {}
|
|
2779
|
+
} : void 0
|
|
2780
|
+
};
|
|
2781
|
+
};
|
|
2391
2782
|
const verifyResources = async (directory) => {
|
|
2392
2783
|
try {
|
|
2393
2784
|
return await options.verifyResources(directory);
|
|
@@ -2395,7 +2786,7 @@ function createCfVersionRunner(options) {
|
|
|
2395
2786
|
return failed("Cloudflare resources could not be verified before upload.");
|
|
2396
2787
|
}
|
|
2397
2788
|
};
|
|
2398
|
-
const uploadPinnedVersion = async (
|
|
2789
|
+
const uploadPinnedVersion = async (operation, atomic) => {
|
|
2399
2790
|
if (!options.pinnedUpload || !options.pinnedUpload.verifyUploader()) return failed("The version-aware Cloudflare uploader is unavailable.");
|
|
2400
2791
|
const token = await options.pinnedUpload.getToken();
|
|
2401
2792
|
if (!token) return failed("Cloudflare session has no bearer for version-aware upload.");
|
|
@@ -2406,23 +2797,28 @@ function createCfVersionRunner(options) {
|
|
|
2406
2797
|
apiBaseUrl: options.pinnedUpload.apiBaseUrl,
|
|
2407
2798
|
workerName,
|
|
2408
2799
|
token,
|
|
2409
|
-
...
|
|
2410
|
-
...
|
|
2800
|
+
...operation.message ? { message: operation.message } : {},
|
|
2801
|
+
...operation.secretsFilePath ? { secretsFilePath: operation.secretsFilePath } : {},
|
|
2411
2802
|
atomic,
|
|
2412
|
-
verifyUploader: options.pinnedUpload.verifyUploader
|
|
2803
|
+
verifyUploader: options.pinnedUpload.verifyUploader,
|
|
2804
|
+
runCf
|
|
2413
2805
|
});
|
|
2414
2806
|
const preview = version.urls.find((url) => /^https:\/\//.test(url));
|
|
2415
2807
|
return {
|
|
2416
2808
|
status: 0,
|
|
2417
|
-
stdout:
|
|
2809
|
+
stdout: "",
|
|
2810
|
+
data: {
|
|
2811
|
+
versionId: version.id,
|
|
2812
|
+
...preview ? { previewUrl: preview } : {}
|
|
2813
|
+
},
|
|
2418
2814
|
stderr: ""
|
|
2419
2815
|
};
|
|
2420
2816
|
} catch (cause) {
|
|
2421
2817
|
return failed(cause instanceof Error ? cause.message : "Cloudflare version upload failed.");
|
|
2422
2818
|
}
|
|
2423
2819
|
};
|
|
2424
|
-
return async (
|
|
2425
|
-
if (
|
|
2820
|
+
return async (operation, command) => {
|
|
2821
|
+
if (operation.type === "deployments.status") {
|
|
2426
2822
|
const result = await run([
|
|
2427
2823
|
"workers",
|
|
2428
2824
|
"deployments",
|
|
@@ -2430,17 +2826,20 @@ function createCfVersionRunner(options) {
|
|
|
2430
2826
|
"--worker",
|
|
2431
2827
|
workerName
|
|
2432
2828
|
], true);
|
|
2433
|
-
if (result.status !== 0) return result;
|
|
2434
|
-
const body =
|
|
2829
|
+
if (result.status !== 0 || result.signal || result.error) return result;
|
|
2830
|
+
const body = result.data;
|
|
2435
2831
|
const deployments = record(body) ? body.deployments : void 0;
|
|
2436
|
-
if (Array.isArray(deployments) && deployments.length === 0) return
|
|
2832
|
+
if (Array.isArray(deployments) && deployments.length === 0) return {
|
|
2833
|
+
...failed("The Cloudflare Worker has no deployments."),
|
|
2834
|
+
errorCode: 10007
|
|
2835
|
+
};
|
|
2437
2836
|
if (!Array.isArray(deployments) || !record(deployments[0])) return failed("The Cloudflare Worker deployment was not readable.");
|
|
2438
2837
|
return {
|
|
2439
2838
|
...result,
|
|
2440
|
-
|
|
2839
|
+
data: deployments[0]
|
|
2441
2840
|
};
|
|
2442
2841
|
}
|
|
2443
|
-
if (
|
|
2842
|
+
if (operation.type === "versions.list") {
|
|
2444
2843
|
const pageSize = 10;
|
|
2445
2844
|
const readPage = async (page) => {
|
|
2446
2845
|
const result = await run([
|
|
@@ -2454,19 +2853,20 @@ function createCfVersionRunner(options) {
|
|
|
2454
2853
|
"--page",
|
|
2455
2854
|
String(page)
|
|
2456
2855
|
], true);
|
|
2457
|
-
const body =
|
|
2856
|
+
const body = result.data;
|
|
2458
2857
|
return {
|
|
2459
2858
|
result,
|
|
2460
2859
|
versions: Array.isArray(body) && body.length <= pageSize && body.every((item) => record(item) && typeof item.id === "string" && Number.isSafeInteger(item.number)) && new Set(body.map((item) => item.number)).size === body.length ? body : null
|
|
2461
2860
|
};
|
|
2462
2861
|
};
|
|
2463
2862
|
const first = await readPage(1);
|
|
2464
|
-
if (first.result.status !== 0) return first.result;
|
|
2863
|
+
if (first.result.status !== 0 || first.result.signal || first.result.error) return first.result;
|
|
2465
2864
|
if (!first.versions) return failed("The Cloudflare Worker version list was not readable.");
|
|
2466
2865
|
const versions = [...first.versions];
|
|
2467
2866
|
if (versions.length === pageSize) {
|
|
2468
2867
|
const second = await readPage(2);
|
|
2469
|
-
if (second.result.status !== 0 ||
|
|
2868
|
+
if (second.result.status !== 0 || second.result.signal || second.result.error) return second.result;
|
|
2869
|
+
if (!second.versions) return failed("The Cloudflare Worker version history was not readable.");
|
|
2470
2870
|
if (second.versions.length > 0) {
|
|
2471
2871
|
const firstNumbers = versions.map((item) => item.number);
|
|
2472
2872
|
const secondNumbers = second.versions.map((item) => item.number);
|
|
@@ -2475,7 +2875,8 @@ function createCfVersionRunner(options) {
|
|
|
2475
2875
|
let last = Math.max(...secondNumbers);
|
|
2476
2876
|
for (let page = 3; page <= 1e3 && second.versions.length === pageSize; page++) {
|
|
2477
2877
|
const next = await readPage(page);
|
|
2478
|
-
if (next.result.status !== 0 ||
|
|
2878
|
+
if (next.result.status !== 0 || next.result.signal || next.result.error) return next.result;
|
|
2879
|
+
if (!next.versions) return failed("The Cloudflare Worker version history was not readable.");
|
|
2479
2880
|
if (next.versions.length === 0) break;
|
|
2480
2881
|
const numbers = next.versions.map((item) => item.number);
|
|
2481
2882
|
if (Math.min(...numbers) <= last) return failed("The Cloudflare Worker version history changed during inspection.");
|
|
@@ -2489,56 +2890,51 @@ function createCfVersionRunner(options) {
|
|
|
2489
2890
|
}
|
|
2490
2891
|
return {
|
|
2491
2892
|
...first.result,
|
|
2492
|
-
|
|
2893
|
+
data: versions.sort((a, b) => a.number - b.number).slice(-10)
|
|
2493
2894
|
};
|
|
2494
2895
|
}
|
|
2495
|
-
if (
|
|
2896
|
+
if (operation.type === "versions.view") {
|
|
2496
2897
|
const result = await run([
|
|
2497
2898
|
"workers",
|
|
2498
2899
|
"versions",
|
|
2499
2900
|
"get",
|
|
2500
|
-
|
|
2901
|
+
operation.versionId,
|
|
2501
2902
|
"--worker-id",
|
|
2502
2903
|
workerName
|
|
2503
2904
|
], true);
|
|
2504
|
-
if (result.status !== 0) return result;
|
|
2505
|
-
const version =
|
|
2506
|
-
if (!record(version) || version.id !==
|
|
2905
|
+
if (result.status !== 0 || result.signal || result.error) return result;
|
|
2906
|
+
const version = result.data;
|
|
2907
|
+
if (!record(version) || version.id !== operation.versionId || !Array.isArray(version.bindings)) return failed("The Cloudflare Worker version was not readable.");
|
|
2507
2908
|
return {
|
|
2508
2909
|
...result,
|
|
2509
|
-
|
|
2910
|
+
data: {
|
|
2510
2911
|
...version,
|
|
2511
2912
|
resources: { bindings: version.bindings }
|
|
2512
|
-
}
|
|
2913
|
+
}
|
|
2513
2914
|
};
|
|
2514
2915
|
}
|
|
2515
|
-
if (
|
|
2516
|
-
if (
|
|
2916
|
+
if (operation.type === "versions.upload") {
|
|
2917
|
+
if (operation.workerName !== workerName || operation.assetsDirectory !== void 0 && operation.assetsDirectory !== output.assetsDirectory) return failed("The Cloudflare version upload target changed.");
|
|
2517
2918
|
const verified = await verifyResources(output.directory);
|
|
2518
2919
|
if (verified.status !== 0 || verified.signal || verified.error) return verified;
|
|
2519
|
-
if (output.activeSecrets) return uploadPinnedVersion(
|
|
2520
|
-
return run([
|
|
2920
|
+
if (output.activeSecrets) return uploadPinnedVersion(operation, false);
|
|
2921
|
+
return uploadedResult(await run([
|
|
2521
2922
|
"workers",
|
|
2522
2923
|
"versions",
|
|
2523
2924
|
"create",
|
|
2524
2925
|
"--prebuilt",
|
|
2525
|
-
...
|
|
2526
|
-
...
|
|
2527
|
-
...
|
|
2528
|
-
], command.capture);
|
|
2529
|
-
}
|
|
2530
|
-
if (
|
|
2531
|
-
if (
|
|
2532
|
-
const
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
return {
|
|
2538
|
-
version_id,
|
|
2539
|
-
percentage: Number(percentage)
|
|
2540
|
-
};
|
|
2541
|
-
});
|
|
2926
|
+
...operation.message ? ["--message", operation.message] : [],
|
|
2927
|
+
...operation.secretsFilePath ? ["--secrets-file", operation.secretsFilePath] : [],
|
|
2928
|
+
...operation.previewAlias ? ["--preview-alias", operation.previewAlias] : []
|
|
2929
|
+
], command.capture));
|
|
2930
|
+
}
|
|
2931
|
+
if (operation.type === "versions.deploy") {
|
|
2932
|
+
if (operation.workerName !== workerName) return failed("The Cloudflare deployment target changed.");
|
|
2933
|
+
const parsed = operation.versions.map(({ versionId, percentage }) => ({
|
|
2934
|
+
version_id: versionId,
|
|
2935
|
+
percentage
|
|
2936
|
+
}));
|
|
2937
|
+
if (!parsed.every((version) => /^[0-9a-f-]{36}$/i.test(version.version_id) && Number.isFinite(version.percentage))) return failed("The Cloudflare deployment versions were invalid.");
|
|
2542
2938
|
if (parsed.length === 0 || new Set(parsed.map((item) => item.version_id)).size !== parsed.length || parsed.some((item) => item.percentage < 0 || item.percentage > 100) || Math.abs(parsed.reduce((sum, item) => sum + item.percentage, 0) - 100) > .001) return failed("The Cloudflare deployment percentages were invalid.");
|
|
2543
2939
|
return run([
|
|
2544
2940
|
"workers",
|
|
@@ -2550,28 +2946,28 @@ function createCfVersionRunner(options) {
|
|
|
2550
2946
|
"percentage",
|
|
2551
2947
|
"--versions",
|
|
2552
2948
|
JSON.stringify(parsed),
|
|
2553
|
-
...
|
|
2949
|
+
...operation.message ? ["--body", JSON.stringify({
|
|
2554
2950
|
strategy: "percentage",
|
|
2555
2951
|
versions: parsed,
|
|
2556
|
-
annotations: { "workers/message":
|
|
2952
|
+
annotations: { "workers/message": operation.message }
|
|
2557
2953
|
})] : []
|
|
2558
2954
|
], command.capture);
|
|
2559
2955
|
}
|
|
2560
|
-
if (
|
|
2561
|
-
if (
|
|
2956
|
+
if (operation.type === "worker.deploy") {
|
|
2957
|
+
if (operation.workerName !== workerName || operation.assetsDirectory !== void 0 && operation.assetsDirectory !== output.assetsDirectory) return failed("The Cloudflare bootstrap target changed.");
|
|
2562
2958
|
const verified = await verifyResources(output.directory);
|
|
2563
2959
|
if (verified.status !== 0 || verified.signal || verified.error) return verified;
|
|
2564
|
-
if (output.activeSecrets) return uploadPinnedVersion(
|
|
2565
|
-
return run([
|
|
2960
|
+
if (output.activeSecrets) return uploadPinnedVersion(operation, true);
|
|
2961
|
+
return uploadedResult(await run([
|
|
2566
2962
|
"deploy",
|
|
2567
2963
|
"--prebuilt",
|
|
2568
|
-
...
|
|
2569
|
-
...
|
|
2570
|
-
], command.capture);
|
|
2964
|
+
...operation.message ? ["--message", operation.message] : [],
|
|
2965
|
+
...operation.secretsFilePath ? ["--secrets-file", operation.secretsFilePath] : []
|
|
2966
|
+
], command.capture));
|
|
2571
2967
|
}
|
|
2572
|
-
if (
|
|
2573
|
-
const configPath =
|
|
2574
|
-
if (!configPath ||
|
|
2968
|
+
if (operation.type === "triggers.deploy") {
|
|
2969
|
+
const configPath = operation.configPath;
|
|
2970
|
+
if (!configPath || operation.workerName !== workerName) return failed("The Cloudflare trigger target changed.");
|
|
2575
2971
|
const raw = parseJson(readFileSync(configPath, "utf8"));
|
|
2576
2972
|
if (!record(raw) || raw.name !== workerName) return failed("The Cloudflare trigger snapshot was not readable.");
|
|
2577
2973
|
const directory = mkdtempSync(join(tmpdir(), "void-cf-triggers-"));
|
|
@@ -2621,12 +3017,12 @@ function createCfVersionRunner(options) {
|
|
|
2621
3017
|
});
|
|
2622
3018
|
}
|
|
2623
3019
|
}
|
|
2624
|
-
if (
|
|
2625
|
-
const queueName =
|
|
2626
|
-
if (!queueName ||
|
|
3020
|
+
if (operation.type === "queues.consumer.remove") {
|
|
3021
|
+
const queueName = operation.queueName;
|
|
3022
|
+
if (!queueName || operation.workerName !== workerName) return failed("The Cloudflare Queue consumer target changed.");
|
|
2627
3023
|
const queues = await run(["queues", "list"], true);
|
|
2628
|
-
if (queues.status !== 0) return queues;
|
|
2629
|
-
const allQueues =
|
|
3024
|
+
if (queues.status !== 0 || queues.signal || queues.error) return queues;
|
|
3025
|
+
const allQueues = queues.data;
|
|
2630
3026
|
if (!Array.isArray(allQueues)) return failed("The Cloudflare Queue list was not readable.");
|
|
2631
3027
|
const queue = allQueues.find((item) => record(item) && item.queue_name === queueName);
|
|
2632
3028
|
if (!record(queue) || typeof queue.queue_id !== "string") return failed(`Cloudflare Queue ${queueName} was not found.`);
|
|
@@ -2637,16 +3033,22 @@ function createCfVersionRunner(options) {
|
|
|
2637
3033
|
"--queue-id",
|
|
2638
3034
|
queue.queue_id
|
|
2639
3035
|
], true);
|
|
2640
|
-
if (consumers.status !== 0) return consumers;
|
|
2641
|
-
const allConsumers =
|
|
3036
|
+
if (consumers.status !== 0 || consumers.signal || consumers.error) return consumers;
|
|
3037
|
+
const allConsumers = consumers.data;
|
|
2642
3038
|
if (!Array.isArray(allConsumers)) return failed("The Cloudflare Queue consumers were not readable.");
|
|
2643
|
-
const matching =
|
|
3039
|
+
const matching = [];
|
|
3040
|
+
for (const item of allConsumers) {
|
|
3041
|
+
if (!record(item)) return failed("The Cloudflare Queue consumers were not readable.");
|
|
3042
|
+
const name = item.script_name ?? item.script;
|
|
3043
|
+
if (item.script_name !== void 0 && !safePositional(item.script_name) || item.script !== void 0 && !safePositional(item.script) || item.script_name !== void 0 && item.script !== void 0 && item.script_name !== item.script || item.type === "worker" && name === void 0) return failed("The Cloudflare Queue consumer Worker identity was ambiguous.");
|
|
3044
|
+
if (name === workerName) matching.push(item);
|
|
3045
|
+
}
|
|
2644
3046
|
if (matching.length === 0) return {
|
|
2645
3047
|
status: 0,
|
|
2646
3048
|
stdout: "",
|
|
2647
3049
|
stderr: ""
|
|
2648
3050
|
};
|
|
2649
|
-
if (matching.length !== 1 || !
|
|
3051
|
+
if (matching.length !== 1 || !safePositional(matching[0].consumer_id) || matching[0].type !== void 0 && matching[0].type !== "worker") return failed("The Cloudflare Queue consumer identity was ambiguous.");
|
|
2650
3052
|
return run([
|
|
2651
3053
|
"queues",
|
|
2652
3054
|
"consumers",
|
|
@@ -2657,7 +3059,7 @@ function createCfVersionRunner(options) {
|
|
|
2657
3059
|
"--force"
|
|
2658
3060
|
], command.capture);
|
|
2659
3061
|
}
|
|
2660
|
-
return failed(`Unsupported Cloudflare activation operation: ${
|
|
3062
|
+
return failed(`Unsupported Cloudflare activation operation: ${operation.type}`);
|
|
2661
3063
|
};
|
|
2662
3064
|
}
|
|
2663
3065
|
//#endregion
|
|
@@ -2708,13 +3110,13 @@ function clearCloudflareCandidate(root) {
|
|
|
2708
3110
|
* Narrow native Cloudflare deploys to app shapes whose emitted Worker artifact
|
|
2709
3111
|
* the current verifier understands. This runs before any account operation.
|
|
2710
3112
|
*/
|
|
2711
|
-
function classifyCloudflareDeployApp(root, voidConfig, options) {
|
|
3113
|
+
function classifyCloudflareDeployApp(root, voidConfig, options, application) {
|
|
2712
3114
|
if (isNodeTarget(voidConfig.target)) return unsupported([
|
|
2713
3115
|
`deploy: --platform cloudflare is not supported for the "${voidConfig.target}" target.`,
|
|
2714
3116
|
"This backend deploys Cloudflare Workers only. Deploy a node/bun/deno build with its",
|
|
2715
3117
|
"own host/runtime, or use the default Cloudflare target for --platform cloudflare."
|
|
2716
3118
|
].join("\n"));
|
|
2717
|
-
const framework = detectFramework(root);
|
|
3119
|
+
const framework = application?.framework ?? detectFramework(root);
|
|
2718
3120
|
if (framework) {
|
|
2719
3121
|
if (!FRAMEWORK_PRESETS[framework.name]) return unsupported(`deploy: --platform cloudflare has no deployment preset for framework ${framework.name}.`);
|
|
2720
3122
|
}
|
|
@@ -2733,13 +3135,16 @@ function classifyCloudflareDeployApp(root, voidConfig, options) {
|
|
|
2733
3135
|
"A full Void app has at least one of: routes/, pages/, middleware, crons/, queues/,",
|
|
2734
3136
|
"email/, or an SSR entry. Add your server code, or use `void deploy` for a static site."
|
|
2735
3137
|
].join("\n"));
|
|
2736
|
-
const paths = resolveProjectPaths(root, voidConfig);
|
|
2737
3138
|
try {
|
|
3139
|
+
const analysis = application ?? analyzeApplicationSync(root, {
|
|
3140
|
+
config: voidConfig,
|
|
3141
|
+
environment: "prod"
|
|
3142
|
+
});
|
|
3143
|
+
const paths = analysis.paths;
|
|
2738
3144
|
assertNoRootSourceConventionConflicts(paths);
|
|
2739
3145
|
validateSsrEntry(root, paths);
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
syncWranglerWebSockets(root, scanWebSocketRoutesSync(root, paths, "prod"));
|
|
3146
|
+
syncWranglerDurableObjects(root, analysis.durableObjects);
|
|
3147
|
+
syncWranglerWebSockets(root, analysis.websockets);
|
|
2743
3148
|
} catch (error) {
|
|
2744
3149
|
return unsupported(`deploy: ${getErrorMessage$1(error)}`);
|
|
2745
3150
|
}
|
|
@@ -2886,7 +3291,7 @@ async function prepareExistingCloudflareDeploy(options) {
|
|
|
2886
3291
|
}
|
|
2887
3292
|
/** Offer the existing destination before the legacy hosted-platform fallback. */
|
|
2888
3293
|
async function maybeLinkCloudflareDeploy(root, options = {}, deps = {}) {
|
|
2889
|
-
if (options.platform || options.
|
|
3294
|
+
if (options.platform || options.projectSlug || process.env.VOID_PROJECT || readDeploymentPlatform(root) !== null) return null;
|
|
2890
3295
|
const files = [.../* @__PURE__ */ new Set([...[
|
|
2891
3296
|
"wrangler.jsonc",
|
|
2892
3297
|
"wrangler.json",
|
|
@@ -4029,8 +4434,7 @@ function buildVoidManifest(opts) {
|
|
|
4029
4434
|
};
|
|
4030
4435
|
if (opts.hasEmailHandlers) manifest.emailProtocolVersion = 1;
|
|
4031
4436
|
if (bindings.needsAuth) manifest.auth = true;
|
|
4032
|
-
|
|
4033
|
-
if (bindings.needsD1 || bindings.needsAuth || hasMigrations) {
|
|
4437
|
+
if (needsApplicationDatabase(bindings, migrations?.length ?? 0)) {
|
|
4034
4438
|
if (resolvedDialect !== "sqlite") manifest.bindings.hyperdrive = ["HYPERDRIVE"];
|
|
4035
4439
|
else manifest.bindings.d1 = [options?.bindingNames?.d1 ?? "DB"];
|
|
4036
4440
|
}
|
|
@@ -4145,8 +4549,7 @@ function buildFrameworkManifest(opts) {
|
|
|
4145
4549
|
assetManifestVersion: 2,
|
|
4146
4550
|
bindings: {}
|
|
4147
4551
|
};
|
|
4148
|
-
|
|
4149
|
-
if (opts.bindings.needsD1 || opts.bindings.needsAuth || hasMigrations) {
|
|
4552
|
+
if (needsApplicationDatabase(opts.bindings, opts.migrations?.length ?? 0)) {
|
|
4150
4553
|
if (dialect !== "sqlite") manifest.bindings.hyperdrive = ["HYPERDRIVE"];
|
|
4151
4554
|
else manifest.bindings.d1 = [po?.bindingNames?.d1 ?? "DB"];
|
|
4152
4555
|
}
|
|
@@ -4395,7 +4798,7 @@ async function generateWrapper(workerDir, workerMain, root, features) {
|
|
|
4395
4798
|
let migrationPlanBundle;
|
|
4396
4799
|
if (features.hasMigrations) {
|
|
4397
4800
|
const { collectMigrations } = await import("./collect-DLyFDiKW.mjs");
|
|
4398
|
-
const { buildMigrationPlanBundle } = await import("./plan-
|
|
4801
|
+
const { buildMigrationPlanBundle } = await import("./plan-D1Q5rf-r.mjs");
|
|
4399
4802
|
const migrationsDir = readProjectPaths(root).migrationsDir;
|
|
4400
4803
|
migrations = collectMigrations(migrationsDir);
|
|
4401
4804
|
migrationPlanBundle = features.migrationDialect === "sqlite" ? buildMigrationPlanBundle(migrations) : void 0;
|
|
@@ -4636,7 +5039,7 @@ function generateWrapperSource(renamedEntry, handlersModule, features, migration
|
|
|
4636
5039
|
}
|
|
4637
5040
|
if (features.readiness || features.crons.length > 0 || features.queues.length > 0 || features.hasMigrations) {
|
|
4638
5041
|
lines.push(" if (request.method === \"GET\" && url.pathname === \"/__void/ready\") {");
|
|
4639
|
-
lines.push(
|
|
5042
|
+
lines.push(` return Response.json({ ready: true${features.versionMetadataBinding ? `, versionId: env[${JSON.stringify(features.versionMetadataBinding)}]?.id` : ""} }${features.versionMetadataBinding ? ", { headers: { \"cache-control\": \"no-store\" } }" : ""});`);
|
|
4640
5043
|
lines.push(" }");
|
|
4641
5044
|
}
|
|
4642
5045
|
if (features.queues.length > 0) {
|
|
@@ -4806,7 +5209,7 @@ let loadedProvisionModule;
|
|
|
4806
5209
|
* so a managed deploy never imports it — and thus never loads `proper-lockfile`.
|
|
4807
5210
|
*/
|
|
4808
5211
|
async function loadProvisionModule() {
|
|
4809
|
-
loadedProvisionModule ??= await import("./provision-
|
|
5212
|
+
loadedProvisionModule ??= await import("./provision-C4ORE7G7.mjs");
|
|
4810
5213
|
return loadedProvisionModule;
|
|
4811
5214
|
}
|
|
4812
5215
|
/**
|
|
@@ -4829,7 +5232,7 @@ const log = {
|
|
|
4829
5232
|
};
|
|
4830
5233
|
var DeployEventError = class extends Error {};
|
|
4831
5234
|
function resolveDeploymentPlatform(root, options) {
|
|
4832
|
-
return options?.platform ??
|
|
5235
|
+
return options?.platform ?? readDeploymentPlatform(root) ?? "void";
|
|
4833
5236
|
}
|
|
4834
5237
|
async function generateDeployWrapperIfNeeded(root, workerDir, workerMain, features) {
|
|
4835
5238
|
if (!needsWrapper(features)) return false;
|
|
@@ -4965,7 +5368,7 @@ async function runDeploy(root, options) {
|
|
|
4965
5368
|
* `VOID_DEPLOY_PROJECT_ID` is, so it cannot leak into an unrelated child process or a
|
|
4966
5369
|
* later `void dev` in the same shell.
|
|
4967
5370
|
*
|
|
4968
|
-
* Deliberately NOT set by `runCloudflareDeploy` (`--
|
|
5371
|
+
* Deliberately NOT set by `runCloudflareDeploy` (`--platform cloudflare`): that flow
|
|
4969
5372
|
* hands the built output to `wrangler deploy` against the user's own account and IS the
|
|
4970
5373
|
* self-host path the warning is about. (It rejects framework SSR outright today, so no
|
|
4971
5374
|
* Class A build reaches it either way.)
|
|
@@ -4975,6 +5378,7 @@ const MANAGED_DEPLOY_BUILD_ENV = { VOID_DEPLOY_BUILD: "1" };
|
|
|
4975
5378
|
function scrubManagedDeployBuildMarkers(env) {
|
|
4976
5379
|
const { deleteEnvVarCaseAware } = requireProvisionModule();
|
|
4977
5380
|
deleteEnvVarCaseAware(env, "VOID_DEPLOY_PROJECT_ID");
|
|
5381
|
+
deleteEnvVarCaseAware(env, CLOUDFLARE_PRESERVE_BINDINGS_BUILD_ENV);
|
|
4978
5382
|
for (const name of Object.keys(MANAGED_DEPLOY_BUILD_ENV)) deleteEnvVarCaseAware(env, name);
|
|
4979
5383
|
return env;
|
|
4980
5384
|
}
|
|
@@ -5391,14 +5795,14 @@ function reconstructExpectedDurableObjectState(config, root, rootConfig, options
|
|
|
5391
5795
|
name: sandbox.binding,
|
|
5392
5796
|
class_name: sandbox.className
|
|
5393
5797
|
});
|
|
5394
|
-
if (!migrations
|
|
5798
|
+
if (!hasSandboxSqliteMigration(migrations, sandbox.className)) migrations.push({
|
|
5395
5799
|
tag: SANDBOX_MIGRATION_TAG,
|
|
5396
5800
|
new_sqlite_classes: [sandbox.className]
|
|
5397
5801
|
});
|
|
5398
5802
|
}
|
|
5399
|
-
const
|
|
5400
|
-
const websocketRoutes =
|
|
5401
|
-
const durableObjects =
|
|
5803
|
+
const analysis = options.analysis ?? analyzeApplicationSync(root, { config });
|
|
5804
|
+
const websocketRoutes = analysis.allWebsockets;
|
|
5805
|
+
const durableObjects = analysis.durableObjects;
|
|
5402
5806
|
const live = options.needsLive ? resolveLiveBindingConfig(root, {
|
|
5403
5807
|
reservedBindings: [...websocketRoutes.map((route) => route.bindingName), ...durableObjects.map((module) => module.bindingName)],
|
|
5404
5808
|
reservedClasses: [
|
|
@@ -5428,11 +5832,11 @@ function reconstructExpectedDurableObjectState(config, root, rootConfig, options
|
|
|
5428
5832
|
* chunks from its own `__dirname` (the proxy workers, the experimental-config module), so the
|
|
5429
5833
|
* whole directory is the trust surface, not just the entry file. Content hash of the bytes, NOT
|
|
5430
5834
|
* mtime. Resolves the SAME entry {@link createDeployWranglerRunner} spawns (via
|
|
5431
|
-
* {@link
|
|
5835
|
+
* {@link resolveCloudflareOperationArgv}, whose launcher's LAST argv element is the JS entry). Returns
|
|
5432
5836
|
* `undefined` when the entry cannot be resolved or a file cannot be read, so the caller FAILS
|
|
5433
5837
|
* CLOSED — it never deploys a binary it could not verify. The resolver is injectable for tests.
|
|
5434
5838
|
*/
|
|
5435
|
-
function hashWranglerUploader(root, resolveArgv =
|
|
5839
|
+
function hashWranglerUploader(root, resolveArgv = resolveCloudflareOperationArgv) {
|
|
5436
5840
|
let entry;
|
|
5437
5841
|
try {
|
|
5438
5842
|
const argv = resolveArgv(root);
|
|
@@ -6261,42 +6665,30 @@ function assertDistinctKvNamespaces(kvNamespaces, config, configPath, isRealKvId
|
|
|
6261
6665
|
/**
|
|
6262
6666
|
* Compute the DESIRED id/name-bearing Cloudflare resources from SOURCE
|
|
6263
6667
|
* (pre-build, fail-fast) — the single set shared by the provision and drift
|
|
6264
|
-
* paths.
|
|
6265
|
-
*
|
|
6266
|
-
* signals) rather than `assembleVoidManifest`, which runs only inside the
|
|
6267
|
-
* managed `runFullDeploy` branches that need a `PlatformClient`.
|
|
6668
|
+
* paths. Consumes the same application analysis as the plugin and managed
|
|
6669
|
+
* packaging; provider identities and stored resource names are resolved here.
|
|
6268
6670
|
*
|
|
6269
6671
|
* Resource NAMES prefer the value already stored in the root wrangler config
|
|
6270
6672
|
* (so a re-provision reuses the same database/bucket and the provisioner's
|
|
6271
6673
|
* stored-name identity check passes); otherwise they default off the worker
|
|
6272
6674
|
* name. Returns a per-binding REASON map used to explain drift.
|
|
6273
6675
|
*/
|
|
6274
|
-
async function computeDesiredCloudflareResources(root, voidConfig, configPath) {
|
|
6676
|
+
async function computeDesiredCloudflareResources(root, voidConfig, configPath, application) {
|
|
6275
6677
|
const { isRealD1Id, isRealKvId } = await loadProvisionModule();
|
|
6276
|
-
const
|
|
6678
|
+
const analysis = application ? await completeApplicationAnalysis(application) : await analyzeApplication(root, {
|
|
6679
|
+
config: voidConfig,
|
|
6680
|
+
environment: "prod"
|
|
6681
|
+
});
|
|
6682
|
+
const { paths, bindings, authEnabled, dialect, bindingNames, migrations, needsDatabase } = analysis;
|
|
6277
6683
|
const config = parseRootWranglerConfig(configPath);
|
|
6278
6684
|
const workerName = readWranglerTopLevelString(config, "name") ?? deriveWorkerName(root);
|
|
6279
|
-
const isFrameworkMode = detectFramework(root) != null;
|
|
6280
|
-
const scanDirs = voidConfig.inference?.scanDirs ?? (isFrameworkMode ? FRAMEWORK_SCAN_DIRS : void 0);
|
|
6281
|
-
const inferenceOptions = voidConfig.inference?.bindings ? { bindings: voidConfig.inference.bindings } : void 0;
|
|
6282
|
-
const bindings = inferProjectBindings(root, {
|
|
6283
|
-
...inferenceOptions,
|
|
6284
|
-
paths,
|
|
6285
|
-
environment: "prod"
|
|
6286
|
-
}, scanDirs);
|
|
6287
|
-
const authEnabled = bindings.needsAuth || findVoidAuthConfig(root, paths) !== null || voidConfig.auth !== void 0;
|
|
6288
|
-
const dialect = getDatabaseDialect(voidConfig);
|
|
6289
|
-
const bindingNames = resolveBindingNames(voidConfig.inference?.bindings);
|
|
6290
|
-
const migrations = collectMigrations(paths.migrationsDir);
|
|
6291
|
-
const hasMigrations = migrations.length > 0;
|
|
6292
6685
|
const migrationsDirRelative = paths.sourceDir ? `./${paths.sourceDir}/db/migrations` : "./db/migrations";
|
|
6293
6686
|
const desired = {
|
|
6294
6687
|
kvNamespaces: [],
|
|
6295
6688
|
queues: []
|
|
6296
6689
|
};
|
|
6297
6690
|
const reasons = /* @__PURE__ */ new Map();
|
|
6298
|
-
const
|
|
6299
|
-
const databaseReason = bindings.needsD1 ? "app uses env.DB (D1)" : authEnabled ? "auth requires a D1 database" : "checked-in migrations need a D1 database";
|
|
6691
|
+
const databaseReason = analysis.reasons.database[0];
|
|
6300
6692
|
if (needsDatabase && dialect === "sqlite") {
|
|
6301
6693
|
const binding = bindingNames?.d1 ?? "DB";
|
|
6302
6694
|
const storedName = readStoredResourceName(config, "d1_databases", binding, "database_name");
|
|
@@ -6315,7 +6707,7 @@ async function computeDesiredCloudflareResources(root, voidConfig, configPath) {
|
|
|
6315
6707
|
binding,
|
|
6316
6708
|
title: suffixedResourceName(workerName, "kv")
|
|
6317
6709
|
});
|
|
6318
|
-
reasons.set(binding,
|
|
6710
|
+
reasons.set(binding, analysis.reasons.kv[0]);
|
|
6319
6711
|
}
|
|
6320
6712
|
if (bindings.needsR2) {
|
|
6321
6713
|
const binding = bindingNames?.r2 ?? "STORAGE";
|
|
@@ -6325,9 +6717,9 @@ async function computeDesiredCloudflareResources(root, voidConfig, configPath) {
|
|
|
6325
6717
|
binding,
|
|
6326
6718
|
bucketName: storedName && !generatedDefault ? storedName : suffixedResourceName(workerName, "storage")
|
|
6327
6719
|
};
|
|
6328
|
-
reasons.set(binding,
|
|
6720
|
+
reasons.set(binding, analysis.reasons.r2[0]);
|
|
6329
6721
|
}
|
|
6330
|
-
desired.queues =
|
|
6722
|
+
desired.queues = analysis.queues.map((q) => q.name);
|
|
6331
6723
|
if (needsDatabase && dialect !== "sqlite") {
|
|
6332
6724
|
const binding = "HYPERDRIVE";
|
|
6333
6725
|
desired.hyperdrive = {
|
|
@@ -6337,10 +6729,8 @@ async function computeDesiredCloudflareResources(root, voidConfig, configPath) {
|
|
|
6337
6729
|
};
|
|
6338
6730
|
reasons.set(binding, `app uses ${dialect === "mysql" ? "MySQL" : "PostgreSQL"} (needs a Hyperdrive config)`);
|
|
6339
6731
|
}
|
|
6340
|
-
|
|
6341
|
-
|
|
6342
|
-
paths
|
|
6343
|
-
}) : null))) {
|
|
6732
|
+
const pageScan = analysis.scan.pages;
|
|
6733
|
+
if (hasRevalidate(collectRevalidate(voidConfig, pageScan))) {
|
|
6344
6734
|
const binding = "ISR_CACHE";
|
|
6345
6735
|
desired.kvNamespaces.push({
|
|
6346
6736
|
binding,
|
|
@@ -6349,9 +6739,10 @@ async function computeDesiredCloudflareResources(root, voidConfig, configPath) {
|
|
|
6349
6739
|
reasons.set(binding, "routes use `revalidate` (ISR) — needs an ISR_CACHE KV namespace");
|
|
6350
6740
|
}
|
|
6351
6741
|
assertDistinctKvNamespaces(desired.kvNamespaces, config, configPath, isRealKvId);
|
|
6352
|
-
const expectedCrons = [...new Set(
|
|
6353
|
-
const emailHandlers =
|
|
6742
|
+
const expectedCrons = [...new Set(analysis.jobs.flatMap((job) => job.crons))];
|
|
6743
|
+
const emailHandlers = analysis.email;
|
|
6354
6744
|
return {
|
|
6745
|
+
analysis,
|
|
6355
6746
|
desired,
|
|
6356
6747
|
reasons,
|
|
6357
6748
|
authEnabled,
|
|
@@ -6363,7 +6754,7 @@ async function computeDesiredCloudflareResources(root, voidConfig, configPath) {
|
|
|
6363
6754
|
expectedCrons,
|
|
6364
6755
|
needsEmail: bindings.needsEmail === true || hasEmailHandlers(emailHandlers),
|
|
6365
6756
|
emailHandlers,
|
|
6366
|
-
needsSandbox:
|
|
6757
|
+
needsSandbox: bindings.needsSandbox,
|
|
6367
6758
|
needsLive: bindings.needsLive === true
|
|
6368
6759
|
};
|
|
6369
6760
|
}
|
|
@@ -6717,49 +7108,15 @@ async function checkWranglerMigrationApplySet(configPath, config, binding, migra
|
|
|
6717
7108
|
};
|
|
6718
7109
|
return { ok: true };
|
|
6719
7110
|
}
|
|
6720
|
-
/**
|
|
6721
|
-
* Default {@link DeployWranglerRun}: spawns the project-local wrangler REAL CLI
|
|
6722
|
-
* (via {@link resolveWranglerArgv}, shell-free) with ONE pinned transport in the
|
|
6723
|
-
* child env (via {@link deployChildEnv} — reused provisioner scrub/pin: CF Access +
|
|
6724
|
-
* every transport selector incl. `CLOUDFLARE_ENV` + the deploy config-override vars
|
|
6725
|
-
* scrubbed, one account + API base pinned), so `whoami`/`migrate`/`deploy` can never
|
|
6726
|
-
* consult a different ambient account or endpoint. Noninteractive output is captured so Void
|
|
6727
|
-
* controls the terminal; browser login still inherits stdio. `opts.env` layers one more pin
|
|
6728
|
-
* over the child env for a single spawn (`auth token` gets
|
|
6729
|
-
* `WRANGLER_WRITE_LOGS=false`, see {@link runWranglerAuthToken}).
|
|
6730
|
-
*/
|
|
7111
|
+
/** Run typed provider operations in the pinned account and API context. */
|
|
6731
7112
|
function createDeployWranglerRunner(root, accountId, apiBaseUrl) {
|
|
6732
|
-
const
|
|
6733
|
-
|
|
6734
|
-
|
|
6735
|
-
|
|
6736
|
-
|
|
6737
|
-
|
|
6738
|
-
|
|
6739
|
-
cwd: root,
|
|
6740
|
-
stdio: interactiveLogin ? "inherit" : opts.input === void 0 ? [
|
|
6741
|
-
"ignore",
|
|
6742
|
-
"pipe",
|
|
6743
|
-
"pipe"
|
|
6744
|
-
] : [
|
|
6745
|
-
"pipe",
|
|
6746
|
-
"pipe",
|
|
6747
|
-
"pipe"
|
|
6748
|
-
],
|
|
6749
|
-
input: opts.input,
|
|
6750
|
-
encoding: "utf-8",
|
|
6751
|
-
env: childEnv,
|
|
6752
|
-
shell: false,
|
|
6753
|
-
windowsHide: true
|
|
6754
|
-
});
|
|
6755
|
-
return {
|
|
6756
|
-
status: typeof result.status === "number" ? result.status : 1,
|
|
6757
|
-
stdout: result.stdout ?? "",
|
|
6758
|
-
stderr: result.stderr ?? "",
|
|
6759
|
-
signal: result.signal ?? null,
|
|
6760
|
-
error: result.error ? result.error.message : null
|
|
6761
|
-
};
|
|
6762
|
-
};
|
|
7113
|
+
const runner = createCloudflareProcessRunner({
|
|
7114
|
+
root,
|
|
7115
|
+
accountId,
|
|
7116
|
+
apiBaseUrl,
|
|
7117
|
+
env: () => deployChildEnv(accountId, apiBaseUrl)
|
|
7118
|
+
});
|
|
7119
|
+
return (operation, opts) => runner(operation, opts);
|
|
6763
7120
|
}
|
|
6764
7121
|
/** Retry an existing-Worker read only when a fresh identity check proves the session is gone. */
|
|
6765
7122
|
async function prepareExistingCloudflareDeployWithAuth(options, beforeRun) {
|
|
@@ -6768,18 +7125,17 @@ async function prepareExistingCloudflareDeployWithAuth(options, beforeRun) {
|
|
|
6768
7125
|
} catch (error) {
|
|
6769
7126
|
if (!(error instanceof CloudflareWorkerInspectionError)) throw error;
|
|
6770
7127
|
if (!beforeRun()) throw new CloudflareAuthenticationError("The Cloudflare uploader changed during Worker verification.", "uploader-changed");
|
|
6771
|
-
const
|
|
6772
|
-
const identity = await options.runWrangler(
|
|
6773
|
-
"whoami",
|
|
6774
|
-
|
|
6775
|
-
|
|
6776
|
-
|
|
6777
|
-
const session = isCleanWranglerExit(identity) ? parseCloudflareAuthSession(identity.stdout) : null;
|
|
7128
|
+
const configPath = existsSync(options.configPath) ? options.configPath : void 0;
|
|
7129
|
+
const identity = await options.runWrangler({
|
|
7130
|
+
type: "auth.whoami",
|
|
7131
|
+
configPath
|
|
7132
|
+
}, { capture: true });
|
|
7133
|
+
const session = isCleanWranglerExit(identity) ? parseCloudflareAuthSession(identity.data) : null;
|
|
6778
7134
|
const wrongAccount = session !== null && session.accounts.length > 0 && !session.accounts.some((account) => account.id === options.accountId);
|
|
6779
7135
|
if (session && !wrongAccount) throw error;
|
|
6780
7136
|
let loggedOut = false;
|
|
6781
7137
|
try {
|
|
6782
|
-
loggedOut =
|
|
7138
|
+
loggedOut = identity.data?.loggedIn === false;
|
|
6783
7139
|
} catch {}
|
|
6784
7140
|
if (!(loggedOut || wrongAccount || /authentication is required|not authenticated|no api token|invalid.*token|expired.*token|unauthorized/i.test(identity.stderr)) || identity.signal || identity.error) throw new Error("Could not verify the Cloudflare session after the Worker check failed. Run `void cloudflare status` and retry.");
|
|
6785
7141
|
const overrides = cloudflareCredentialOverrides();
|
|
@@ -6790,8 +7146,8 @@ async function prepareExistingCloudflareDeployWithAuth(options, beforeRun) {
|
|
|
6790
7146
|
forceLogin: true,
|
|
6791
7147
|
requireAccounts: true,
|
|
6792
7148
|
beforeRun,
|
|
6793
|
-
runWrangler: (
|
|
6794
|
-
|
|
7149
|
+
runWrangler: (operation, capture) => options.runWrangler(operation, { capture }),
|
|
7150
|
+
configPath
|
|
6795
7151
|
})).accounts.some((account) => account.id === options.accountId)) throw new Error(`The signed-in Cloudflare user cannot access account ${options.accountId}. Sign in with a user who can access it, then retry.`);
|
|
6796
7152
|
if (!beforeRun()) throw new CloudflareAuthenticationError("The Cloudflare uploader changed during sign-in.", "uploader-changed");
|
|
6797
7153
|
return await prepareExistingCloudflareDeploy(options);
|
|
@@ -6801,8 +7157,8 @@ async function chooseCloudflareDeployAccount(options) {
|
|
|
6801
7157
|
const accounts = (await ensureCloudflareAuthentication({
|
|
6802
7158
|
beforeRun: options.beforeWranglerRun,
|
|
6803
7159
|
requireAccounts: true,
|
|
6804
|
-
runWrangler: (
|
|
6805
|
-
|
|
7160
|
+
runWrangler: (operation, capture) => options.runWrangler(operation, { capture }),
|
|
7161
|
+
configPath: existsSync(options.configPath) ? options.configPath : void 0
|
|
6806
7162
|
})).accounts;
|
|
6807
7163
|
let account = accounts[0];
|
|
6808
7164
|
if (accounts.length > 1) {
|
|
@@ -6848,14 +7204,10 @@ function isWranglerNonInteractiveOrCI() {
|
|
|
6848
7204
|
async function runWranglerAuthToken(runWrangler, configPath) {
|
|
6849
7205
|
let result;
|
|
6850
7206
|
try {
|
|
6851
|
-
result = await Promise.resolve(runWrangler(
|
|
6852
|
-
"auth",
|
|
6853
|
-
|
|
6854
|
-
|
|
6855
|
-
"-c",
|
|
6856
|
-
configPath,
|
|
6857
|
-
"--env="
|
|
6858
|
-
], {
|
|
7207
|
+
result = await Promise.resolve(runWrangler({
|
|
7208
|
+
type: "auth.token",
|
|
7209
|
+
configPath
|
|
7210
|
+
}, {
|
|
6859
7211
|
capture: true,
|
|
6860
7212
|
env: { WRANGLER_WRITE_LOGS: "false" }
|
|
6861
7213
|
}));
|
|
@@ -6863,15 +7215,7 @@ async function runWranglerAuthToken(runWrangler, configPath) {
|
|
|
6863
7215
|
return null;
|
|
6864
7216
|
}
|
|
6865
7217
|
if (!isCleanWranglerExit(result)) return null;
|
|
6866
|
-
const
|
|
6867
|
-
const end = result.stdout.lastIndexOf("}");
|
|
6868
|
-
if (start === -1 || end <= start) return null;
|
|
6869
|
-
let parsed;
|
|
6870
|
-
try {
|
|
6871
|
-
parsed = JSON.parse(result.stdout.slice(start, end + 1));
|
|
6872
|
-
} catch {
|
|
6873
|
-
return null;
|
|
6874
|
-
}
|
|
7218
|
+
const parsed = result.data;
|
|
6875
7219
|
const type = parsed?.type;
|
|
6876
7220
|
const token = parsed?.token;
|
|
6877
7221
|
return (type === "oauth" || type === "api_token") && typeof token === "string" && token.length > 0 ? token : null;
|
|
@@ -6921,11 +7265,7 @@ async function runCloudflareEmailStep(input) {
|
|
|
6921
7265
|
existingAddresses: rootConfig.addresses,
|
|
6922
7266
|
existingVars: rootConfig.vars && typeof rootConfig.vars === "object" && !Array.isArray(rootConfig.vars) ? rootConfig.vars : void 0,
|
|
6923
7267
|
configConflicts: findEmailConfigConflicts(rootConfig),
|
|
6924
|
-
|
|
6925
|
-
"-c",
|
|
6926
|
-
input.configPath,
|
|
6927
|
-
"--env="
|
|
6928
|
-
],
|
|
7268
|
+
configPath: input.configPath,
|
|
6929
7269
|
apiBaseUrl: input.apiBaseUrl,
|
|
6930
7270
|
runWrangler: input.runWrangler,
|
|
6931
7271
|
getSessionBearer: () => runWranglerAuthToken(input.runWrangler, input.configPath),
|
|
@@ -7086,14 +7426,12 @@ async function ensureCloudflareAuthSecret(options) {
|
|
|
7086
7426
|
beforeRun();
|
|
7087
7427
|
let put;
|
|
7088
7428
|
try {
|
|
7089
|
-
put = await Promise.resolve(options.runWrangler(
|
|
7090
|
-
"secret",
|
|
7091
|
-
|
|
7092
|
-
|
|
7093
|
-
|
|
7094
|
-
|
|
7095
|
-
"--env="
|
|
7096
|
-
], {
|
|
7429
|
+
put = await Promise.resolve(options.runWrangler({
|
|
7430
|
+
type: "secret.put",
|
|
7431
|
+
name: BETTER_AUTH_SECRET_NAME,
|
|
7432
|
+
configPath: options.configPath,
|
|
7433
|
+
workerName: options.workerName
|
|
7434
|
+
}, {
|
|
7097
7435
|
capture: true,
|
|
7098
7436
|
input: `${secret}\n`
|
|
7099
7437
|
}));
|
|
@@ -7120,13 +7458,23 @@ async function prepareCloudflareDeploySource(root, options, voidConfig) {
|
|
|
7120
7458
|
].join("\n"));
|
|
7121
7459
|
return null;
|
|
7122
7460
|
}
|
|
7123
|
-
|
|
7461
|
+
let application;
|
|
7462
|
+
try {
|
|
7463
|
+
application = analyzeApplicationSync(root, {
|
|
7464
|
+
config: voidConfig,
|
|
7465
|
+
environment: "prod"
|
|
7466
|
+
});
|
|
7467
|
+
} catch (error) {
|
|
7468
|
+
log.error(`deploy: ${getErrorMessage(error)}`);
|
|
7469
|
+
return null;
|
|
7470
|
+
}
|
|
7471
|
+
const classification = classifyCloudflareDeployApp(root, voidConfig, options, application);
|
|
7124
7472
|
if (!classification.supported) {
|
|
7125
7473
|
log.error(classification.reason);
|
|
7126
7474
|
return null;
|
|
7127
7475
|
}
|
|
7128
7476
|
const configPath = discoverRootWranglerConfig(root);
|
|
7129
|
-
const facts = await computeDesiredCloudflareResources(root, voidConfig, configPath);
|
|
7477
|
+
const facts = await computeDesiredCloudflareResources(root, voidConfig, configPath, application);
|
|
7130
7478
|
const { desired, dialect, migrations: preBuildMigrations, migrationsDir } = facts;
|
|
7131
7479
|
if (dialect !== "sqlite" && preBuildMigrations.length > 0 && !process.env.DATABASE_URL) {
|
|
7132
7480
|
log.error([
|
|
@@ -7154,51 +7502,35 @@ async function applyAndVerifyRemoteD1Migrations(d1MigrateToken, configPath, runW
|
|
|
7154
7502
|
if (d1MigrateToken) {
|
|
7155
7503
|
log.step("Applying D1 migrations...");
|
|
7156
7504
|
if (!assertUploaderStillPinned()) return false;
|
|
7157
|
-
const migrate = await Promise.resolve(runWrangler(
|
|
7158
|
-
"d1",
|
|
7159
|
-
|
|
7160
|
-
|
|
7161
|
-
|
|
7162
|
-
"--remote",
|
|
7163
|
-
"-c",
|
|
7164
|
-
configPath,
|
|
7165
|
-
"--env="
|
|
7166
|
-
], { capture: false }));
|
|
7505
|
+
const migrate = await Promise.resolve(runWrangler({
|
|
7506
|
+
type: "d1.migrations.apply",
|
|
7507
|
+
database: d1MigrateToken,
|
|
7508
|
+
configPath
|
|
7509
|
+
}, { capture: false }));
|
|
7167
7510
|
if (!isCleanWranglerExit(migrate)) {
|
|
7168
7511
|
log.error(`deploy: remote D1 migrations failed for "${d1MigrateToken}" (exit ${String(migrate.status)}). Fix the migration and rerun. Note: D1 always enforces foreign_keys=ON — a Drizzle table-rebuild using PRAGMA foreign_keys=OFF must use PRAGMA defer_foreign_keys instead.`);
|
|
7169
7512
|
return false;
|
|
7170
7513
|
}
|
|
7171
7514
|
if (!assertUploaderStillPinned()) return false;
|
|
7172
|
-
const migrateList = await Promise.resolve(runWrangler(
|
|
7173
|
-
"d1",
|
|
7174
|
-
|
|
7175
|
-
|
|
7176
|
-
|
|
7177
|
-
"--remote",
|
|
7178
|
-
"-c",
|
|
7179
|
-
configPath,
|
|
7180
|
-
"--env="
|
|
7181
|
-
], { capture: true }));
|
|
7515
|
+
const migrateList = await Promise.resolve(runWrangler({
|
|
7516
|
+
type: "d1.migrations.list",
|
|
7517
|
+
database: d1MigrateToken,
|
|
7518
|
+
configPath
|
|
7519
|
+
}, { capture: true }));
|
|
7182
7520
|
if (!isCleanWranglerExit(migrateList)) {
|
|
7183
7521
|
log.error(`deploy: could not verify the remote migration state for "${d1MigrateToken}" (\`d1 migrations list\` exit ${String(migrateList.status)}). Refusing to deploy against an unverified schema — rerun once wrangler can reach your account.`);
|
|
7184
7522
|
return false;
|
|
7185
7523
|
}
|
|
7186
|
-
|
|
7187
|
-
|
|
7188
|
-
|
|
7189
|
-
"`wrangler d1 migrations apply` exits 0 even when its confirmation is declined, so",
|
|
7190
|
-
"the schema may be un-migrated while the code that needs it is about to deploy.",
|
|
7191
|
-
"Re-run and confirm the migration (or apply it non-interactively), then rerun."
|
|
7192
|
-
].join("\n"));
|
|
7524
|
+
const migrationState = migrateList.data;
|
|
7525
|
+
if (Array.isArray(migrationState?.pending) && migrationState.pending.length > 0) {
|
|
7526
|
+
log.error([`deploy: remote D1 still has UNAPPLIED migrations for "${d1MigrateToken}" after apply.`, "The schema is not current for this deployment. Fix or apply the pending migrations, then retry."].join("\n"));
|
|
7193
7527
|
return false;
|
|
7194
7528
|
}
|
|
7195
|
-
if (!
|
|
7529
|
+
if (!Array.isArray(migrationState?.pending) || !migrationState.pending.every((name) => typeof name === "string")) {
|
|
7196
7530
|
log.error([
|
|
7197
7531
|
`deploy: could not confirm the remote migration state for "${d1MigrateToken}".`,
|
|
7198
|
-
"
|
|
7199
|
-
"
|
|
7200
|
-
"suppressed) — refusing to deploy against an unverified schema. Rerun once wrangler",
|
|
7201
|
-
"can reach your account."
|
|
7532
|
+
"Cloudflare returned an invalid pending migration set. Refusing to deploy against an unverified schema.",
|
|
7533
|
+
"Retry once the database migration state can be read."
|
|
7202
7534
|
].join("\n"));
|
|
7203
7535
|
return false;
|
|
7204
7536
|
}
|
|
@@ -7334,6 +7666,12 @@ async function runCloudflareDeploy(root, options, cliLog, deps = {}) {
|
|
|
7334
7666
|
if (!source) return exit(1);
|
|
7335
7667
|
const { configPath, desired, reasons, authEnabled, dialect, migrationsDir, migrations: preBuildMigrations, needsAI, aiBindingName, needsSandbox, needsLive, expectedCrons, needsEmail, emailHandlers } = source;
|
|
7336
7668
|
let rootConfig = parseRootWranglerConfig(configPath);
|
|
7669
|
+
if (needsSandbox) try {
|
|
7670
|
+
assertSandboxNamespaceConfig(rootConfig, resolveSandboxConfig(voidConfig, root));
|
|
7671
|
+
} catch (error) {
|
|
7672
|
+
log.error(`deploy: ${getErrorMessage(error)}`);
|
|
7673
|
+
return exit(1);
|
|
7674
|
+
}
|
|
7337
7675
|
let apiBaseUrl;
|
|
7338
7676
|
try {
|
|
7339
7677
|
apiBaseUrl = resolveDeployTransport(root, rootConfig);
|
|
@@ -7449,8 +7787,8 @@ async function runCloudflareDeploy(root, options, cliLog, deps = {}) {
|
|
|
7449
7787
|
await ensureCloudflareAuthentication({
|
|
7450
7788
|
acceptApiToken: true,
|
|
7451
7789
|
beforeRun: assertUploaderStillPinned,
|
|
7452
|
-
runWrangler: (
|
|
7453
|
-
|
|
7790
|
+
runWrangler: (operation, capture) => runWrangler(operation, { capture }),
|
|
7791
|
+
configPath: existsSync(configPath) ? configPath : void 0
|
|
7454
7792
|
});
|
|
7455
7793
|
} catch (error) {
|
|
7456
7794
|
if (error instanceof CloudflareAuthenticationError && error.reason === "uploader-changed") return exit(1);
|
|
@@ -7509,13 +7847,10 @@ async function runCloudflareDeploy(root, options, cliLog, deps = {}) {
|
|
|
7509
7847
|
}
|
|
7510
7848
|
if (needsSandbox) {
|
|
7511
7849
|
if (!assertUploaderStillPinned()) return exit(1);
|
|
7512
|
-
if (!isCleanWranglerExit(await Promise.resolve(runWrangler(
|
|
7513
|
-
"containers",
|
|
7514
|
-
|
|
7515
|
-
|
|
7516
|
-
...existingWranglerConfigArgs(configPath),
|
|
7517
|
-
"--env="
|
|
7518
|
-
], { capture: true })))) {
|
|
7850
|
+
if (!isCleanWranglerExit(await Promise.resolve(runWrangler({
|
|
7851
|
+
type: "containers.list",
|
|
7852
|
+
configPath: existsSync(configPath) ? configPath : void 0
|
|
7853
|
+
}, { capture: true })))) {
|
|
7519
7854
|
log.error(formatCloudflareSandboxUnavailable({ preflight: true }));
|
|
7520
7855
|
return exit(1);
|
|
7521
7856
|
}
|
|
@@ -7594,19 +7929,16 @@ async function runCloudflareDeploy(root, options, cliLog, deps = {}) {
|
|
|
7594
7929
|
}
|
|
7595
7930
|
const absentQueues = [];
|
|
7596
7931
|
for (const name of desired.queues) {
|
|
7597
|
-
const info = await Promise.resolve(runWrangler(
|
|
7598
|
-
"queues",
|
|
7599
|
-
"info",
|
|
7932
|
+
const info = await Promise.resolve(runWrangler({
|
|
7933
|
+
type: "queues.info",
|
|
7600
7934
|
name,
|
|
7601
|
-
|
|
7602
|
-
|
|
7603
|
-
"--env="
|
|
7604
|
-
], { capture: true }));
|
|
7935
|
+
configPath
|
|
7936
|
+
}, { capture: true }));
|
|
7605
7937
|
if (provisionModule.isQueueConfirmedAbsent(info, name)) absentQueues.push(name);
|
|
7606
7938
|
}
|
|
7607
7939
|
if (absentQueues.length > 0) await provisionAndVerify();
|
|
7608
7940
|
}
|
|
7609
|
-
const frameworkQueues = detectedFramework ?
|
|
7941
|
+
const frameworkQueues = detectedFramework ? source.analysis.queues : [];
|
|
7610
7942
|
writeProvisionedWranglerConfig(root, {
|
|
7611
7943
|
name: workerName,
|
|
7612
7944
|
accountId,
|
|
@@ -7632,12 +7964,15 @@ async function runCloudflareDeploy(root, options, cliLog, deps = {}) {
|
|
|
7632
7964
|
const expectedContainers = reconstructExpectedContainers(voidConfig, root, preBuildRootConfig, needsSandbox);
|
|
7633
7965
|
const expectedDurableObjectState = reconstructExpectedDurableObjectState(voidConfig, root, preBuildRootConfig, {
|
|
7634
7966
|
needsSandbox,
|
|
7635
|
-
needsLive
|
|
7967
|
+
needsLive,
|
|
7968
|
+
analysis: source.analysis
|
|
7636
7969
|
});
|
|
7637
7970
|
removeDeployPointer(root);
|
|
7638
7971
|
const buildChildEnv = scrubManagedDeployBuildMarkers(scrubWranglerAuthCredentials(deployChildEnv(accountId, apiBaseUrl)));
|
|
7639
7972
|
requireProvisionModule().deleteEnvVarCaseAware(buildChildEnv, CLOUDFLARE_DEPLOY_BUILD_ENV);
|
|
7640
7973
|
buildChildEnv[CLOUDFLARE_DEPLOY_BUILD_ENV] = "1";
|
|
7974
|
+
requireProvisionModule().deleteEnvVarCaseAware(buildChildEnv, CLOUDFLARE_PRESERVE_BINDINGS_BUILD_ENV);
|
|
7975
|
+
if (existingWorker) buildChildEnv[CLOUDFLARE_PRESERVE_BINDINGS_BUILD_ENV] = "1";
|
|
7641
7976
|
requireProvisionModule().deleteEnvVarCaseAware(buildChildEnv, "NODE_ENV");
|
|
7642
7977
|
buildChildEnv.NODE_ENV = "production";
|
|
7643
7978
|
const runBuild = deps.runBuild ?? ((env) => {
|
|
@@ -7656,7 +7991,7 @@ async function runCloudflareDeploy(root, options, cliLog, deps = {}) {
|
|
|
7656
7991
|
}
|
|
7657
7992
|
log.step("Preparing deployment...");
|
|
7658
7993
|
if (detectedFramework && frameworkPreset) try {
|
|
7659
|
-
await (deps.prepareFrameworkArtifact ?? prepareCloudflareFrameworkArtifact)(root, configPath, accountId, workerName, voidConfig, detectedFramework, frameworkPreset, schemaFacts.requiredKeys, needsAI ? { binding: aiBindingName } : void 0);
|
|
7994
|
+
await (deps.prepareFrameworkArtifact ?? prepareCloudflareFrameworkArtifact)(root, configPath, accountId, workerName, voidConfig, detectedFramework, frameworkPreset, schemaFacts.requiredKeys, needsAI ? { binding: aiBindingName } : void 0, existingWorker !== null);
|
|
7660
7995
|
} catch (error) {
|
|
7661
7996
|
log.error(`deploy: could not prepare ${detectedFramework.name} for Cloudflare — ${getErrorMessage(error)}`);
|
|
7662
7997
|
return exit(1);
|
|
@@ -7907,6 +8242,8 @@ async function runCloudflareDeploy(root, options, cliLog, deps = {}) {
|
|
|
7907
8242
|
workerName,
|
|
7908
8243
|
configPath: generatedConfigPath,
|
|
7909
8244
|
preserveTriggers: existingWorker !== null,
|
|
8245
|
+
requireVersionMetadata: existingWorker === null || readVersionMetadataBinding(parseRootWranglerConfig(generatedConfigPath)) !== void 0,
|
|
8246
|
+
requirePreviewForReadiness: existingWorker !== null && readVersionMetadataBinding(parseRootWranglerConfig(generatedConfigPath)) === void 0,
|
|
7910
8247
|
expectedPreviousVersionId: existingWorker?.versionId,
|
|
7911
8248
|
trustedInheritanceVersionIds: existingWorker ? candidateReceipt?.parentVersionId === existingWorker.versionId ? candidateReceipt.versionIds : void 0 : initialCloudflareCandidate?.versionIds,
|
|
7912
8249
|
validateUploadedVersion: existingWorker ? async (versionId) => {
|
|
@@ -7982,10 +8319,6 @@ function discoverRootWranglerConfig(root) {
|
|
|
7982
8319
|
if (existsSync(join(root, "wrangler.toml"))) throw new Error("Found wrangler.toml. Direct Cloudflare deployment needs one root wrangler.jsonc or wrangler.json with the same settings. Convert the config before deploying.");
|
|
7983
8320
|
return materializeCloudflareConfig(root);
|
|
7984
8321
|
}
|
|
7985
|
-
/** Avoid making Wrangler open a config path that Void has not created yet. */
|
|
7986
|
-
function existingWranglerConfigArgs(configPath) {
|
|
7987
|
-
return existsSync(configPath) ? ["-c", configPath] : [];
|
|
7988
|
-
}
|
|
7989
8322
|
async function reportCloudflareActivationFailure(cliLog, message) {
|
|
7990
8323
|
cliLog.error("cloudflare_deploy_failed", new Error(message));
|
|
7991
8324
|
await cliLog.close().catch(() => {});
|
|
@@ -8018,7 +8351,9 @@ function formatCloudflareActivationError(result) {
|
|
|
8018
8351
|
if (result.rollback === "failed") return "deploy: the verified Wrangler uploader changed after version activation, and automatic traffic restoration failed. Inspect `void project status` immediately.";
|
|
8019
8352
|
if (result.rollback === "unsafe") return "deploy: the verified Wrangler uploader changed after version activation. Void did not invoke the changed binary to restore traffic; reinstall Wrangler from a trusted lockfile and inspect `void project status` immediately.";
|
|
8020
8353
|
return "deploy: the verified Wrangler uploader changed before version activation.";
|
|
8021
|
-
case "status-failed":
|
|
8354
|
+
case "status-failed":
|
|
8355
|
+
if (result.versionId) return `deploy: Worker version ${result.versionId} was published, but current deployment status could not be verified${status}. Inspect \`void project status\` before retrying.`;
|
|
8356
|
+
return `deploy: could not snapshot the current Cloudflare deployment${status}; no version was uploaded.`;
|
|
8022
8357
|
case "deployment-changed": return result.triggerRepair === "succeeded" ? `deploy: another Cloudflare operation superseded this deployment. Void restored triggers for the active version ${result.activeVersionId ?? "(unknown)"}; retry from fresh deployment status.` : `deploy: another Cloudflare operation superseded this deployment, but its trigger state could not be verified. Inspect the active Worker version ${result.activeVersionId ?? "(unknown)"} immediately.`;
|
|
8023
8358
|
case "inheritance-source-unavailable": return "deploy: could not verify which Worker Version would supply inherited secrets; production traffic is unchanged.";
|
|
8024
8359
|
case "inheritance-source-changed": return [
|
|
@@ -8034,16 +8369,18 @@ function formatCloudflareActivationError(result) {
|
|
|
8034
8369
|
].join("\n");
|
|
8035
8370
|
case "upload-failed": return `deploy: Cloudflare Worker Version upload failed${status}; production traffic is unchanged.${cloudflareCode}${diagnostic}`;
|
|
8036
8371
|
case "upload-output-invalid": return "deploy: Wrangler uploaded a version but did not report its version id; production traffic is unchanged.";
|
|
8037
|
-
case "preview-unavailable":
|
|
8038
|
-
|
|
8039
|
-
|
|
8040
|
-
|
|
8041
|
-
|
|
8372
|
+
case "preview-unavailable":
|
|
8373
|
+
if (result.diagnostic) return `deploy: candidate readiness cannot be verified.\n\n${result.diagnostic}`;
|
|
8374
|
+
return [
|
|
8375
|
+
"deploy: the uploaded Worker Version has no preview URL, so Void cannot verify readiness.",
|
|
8376
|
+
"Set CLOUDFLARE_WORKERS_SUBDOMAIN to your account subdomain (for example \"my-team\")",
|
|
8377
|
+
"and retry. Void caches it after a successful workers.dev deployment; production traffic is unchanged."
|
|
8378
|
+
].join("\n");
|
|
8042
8379
|
case "readiness-staging-failed": return `deploy: Cloudflare could not stage the uploaded Worker Version at zero-percent traffic${status}; production traffic is unchanged.${cloudflareCode}${diagnostic}${result.cloudflareErrorCode === 10210 && /Durable Object migration/i.test(result.diagnostic ?? "") ? "\n\nReview the Durable Object migration, then run `void deploy --platform cloudflare --atomic`. For future deploys, set deploy.cloudflare.mode to \"atomic\" in void.config.ts." : ""}`;
|
|
8043
8380
|
case "atomic-failed": return `deploy: Cloudflare could not publish the Worker atomically${status}; inspect production status before retrying.${cloudflareCode}${diagnostic}`;
|
|
8044
8381
|
case "atomic-output-invalid": return "deploy: Cloudflare published atomically but did not report a version id or URL. Inspect `void project status` immediately.";
|
|
8045
8382
|
case "atomic-readiness-failed":
|
|
8046
|
-
case "atomic-readiness-access-denied": return
|
|
8383
|
+
case "atomic-readiness-access-denied": return `deploy: the atomic Worker deployment is live, but /__void/ready could not be verified. Inspect \`void project status\` and Worker logs immediately.${diagnostic}`;
|
|
8047
8384
|
case "readiness-failed": return ["deploy: the uploaded Worker Version did not pass /__void/ready.", formatCloudflareReadinessRestoration(result)].join("\n");
|
|
8048
8385
|
case "readiness-access-denied": return [
|
|
8049
8386
|
"deploy: Cloudflare Access blocked the uploaded Worker Version readiness probe.",
|
|
@@ -8058,7 +8395,7 @@ function formatCloudflareActivationError(result) {
|
|
|
8058
8395
|
"deploy: the first Worker deployment did not pass /__void/ready.",
|
|
8059
8396
|
"Cloudflare requires this bootstrap to be non-versioned, so the new Worker is already active;",
|
|
8060
8397
|
"inspect its logs and `void project status` before retrying."
|
|
8061
|
-
].join("\n");
|
|
8398
|
+
].join("\n") + diagnostic;
|
|
8062
8399
|
case "bootstrap-readiness-access-denied": return [
|
|
8063
8400
|
"deploy: Cloudflare Access blocked the first Worker deployment readiness probe.",
|
|
8064
8401
|
"For CI, set CF_ACCESS_CLIENT_ID and CF_ACCESS_CLIENT_SECRET to an admitted service token;",
|
|
@@ -8068,7 +8405,7 @@ function formatCloudflareActivationError(result) {
|
|
|
8068
8405
|
"Worker is already active behind Access."
|
|
8069
8406
|
].join("\n");
|
|
8070
8407
|
case "activation-failed": return `deploy: the ready Worker Version could not be activated${status}; production traffic is unchanged.`;
|
|
8071
|
-
case "triggers-failed": return `deploy: the Worker activated, but Cloudflare trigger synchronization failed${status}. ${result.rollback === "succeeded" ? "Traffic was restored to the previous version." : result.rollback === "unavailable" ? result.previousVersionId === null ? "This was the first deployment, so no previous version was available to restore." : "Traffic
|
|
8408
|
+
case "triggers-failed": return `deploy: the Worker activated, but Cloudflare trigger synchronization failed${status}. ${result.rollback === "succeeded" ? "Traffic was restored to the previous version." : result.rollback === "unavailable" ? result.previousVersionId === null ? "This was the first deployment, so no previous version was available to restore." : "Traffic or trigger restoration could not be completed. Inspect its routes, schedules, queues, and workflows in Cloudflare before retrying." : "Automatic traffic restoration failed; inspect `void project status` immediately."}`;
|
|
8072
8409
|
}
|
|
8073
8410
|
}
|
|
8074
8411
|
function formatCloudflareReadinessRestoration(result) {
|
|
@@ -8089,29 +8426,36 @@ function cloudflareWorkerReadinessHeaders() {
|
|
|
8089
8426
|
});
|
|
8090
8427
|
}
|
|
8091
8428
|
/** Build the trusted Wrangler pointer for a framework that emits Worker files directly. */
|
|
8092
|
-
async function prepareCloudflareFrameworkArtifact(root, configPath, accountId, workerName, voidConfig, framework, preset, requiredSecretNames = [], ai) {
|
|
8429
|
+
async function prepareCloudflareFrameworkArtifact(root, configPath, accountId, workerName, voidConfig, framework, preset, requiredSecretNames = [], ai, preserveBindings = false) {
|
|
8093
8430
|
const workerMain = join(root, preset.workerDir, preset.workerMain);
|
|
8094
8431
|
const assetsDirectory = join(root, preset.assetsDir);
|
|
8095
8432
|
if (!existsSync(workerMain)) throw new Error(`framework ${framework.name} did not emit its Worker entry at ${preset.workerDir}/${preset.workerMain}`);
|
|
8096
8433
|
if (!existsSync(assetsDirectory)) throw new Error(`framework ${framework.name} did not emit its asset directory at ${preset.assetsDir}`);
|
|
8097
|
-
const
|
|
8098
|
-
|
|
8099
|
-
|
|
8434
|
+
const analysis = analyzeApplicationSync(root, {
|
|
8435
|
+
config: voidConfig,
|
|
8436
|
+
environment: "prod"
|
|
8437
|
+
});
|
|
8438
|
+
const crons = analysis.jobs;
|
|
8439
|
+
const queues = analysis.queues;
|
|
8100
8440
|
const revalidate = collectRevalidate(voidConfig, null);
|
|
8441
|
+
const rootConfig = parseRootWranglerConfig(configPath);
|
|
8442
|
+
const versionMetadataBinding = selectNativeVersionMetadataBinding(rootConfig, {
|
|
8443
|
+
nativeBuild: true,
|
|
8444
|
+
preserveBindings
|
|
8445
|
+
});
|
|
8101
8446
|
await generateDeployWrapperIfNeeded(root, join(root, preset.workerDir), preset.workerMain, {
|
|
8102
|
-
auth: null,
|
|
8103
8447
|
crons,
|
|
8104
8448
|
queues,
|
|
8105
8449
|
hasMigrations: false,
|
|
8106
|
-
migrationDialect:
|
|
8450
|
+
migrationDialect: analysis.dialect,
|
|
8107
8451
|
readiness: true,
|
|
8452
|
+
versionMetadataBinding,
|
|
8108
8453
|
...hasRevalidate(revalidate) && { isr: {
|
|
8109
8454
|
revalidate,
|
|
8110
8455
|
queryAllowlist: voidConfig.routing?.revalidateQueryAllowlist
|
|
8111
8456
|
} }
|
|
8112
8457
|
});
|
|
8113
8458
|
if (preset.cloudflareArtifact === "vite-plugin") return;
|
|
8114
|
-
const rootConfig = parseRootWranglerConfig(configPath);
|
|
8115
8459
|
writeCloudflareFrameworkDeployConfig({
|
|
8116
8460
|
configPath,
|
|
8117
8461
|
deployPointerPath: deployPointerPath(root),
|
|
@@ -8123,6 +8467,7 @@ async function prepareCloudflareFrameworkArtifact(root, configPath, accountId, w
|
|
|
8123
8467
|
compatibilityFlags: preset.cloudflareCompatibilityFlags,
|
|
8124
8468
|
crons: [...new Set(crons.flatMap((job) => job.crons))],
|
|
8125
8469
|
requiredSecrets: requiredSecretNames,
|
|
8470
|
+
versionMetadataBinding,
|
|
8126
8471
|
...ai ? { ai: {
|
|
8127
8472
|
...ai,
|
|
8128
8473
|
gateway: voidConfig.ai?.gateway
|
|
@@ -8162,23 +8507,14 @@ function resolveCloudflareStaticPreset(root, voidConfig, options) {
|
|
|
8162
8507
|
*/
|
|
8163
8508
|
async function resolveCloudflareVoidStaticPreset(root, voidConfig) {
|
|
8164
8509
|
if (voidConfig.output !== "static") return null;
|
|
8165
|
-
const
|
|
8166
|
-
|
|
8167
|
-
const routeScan = await scanRoutes(root, {
|
|
8168
|
-
output: voidConfig.output,
|
|
8169
|
-
paths,
|
|
8510
|
+
const analysis = await analyzeApplication(root, {
|
|
8511
|
+
config: voidConfig,
|
|
8170
8512
|
environment: "prod"
|
|
8171
8513
|
});
|
|
8172
|
-
const
|
|
8173
|
-
|
|
8174
|
-
|
|
8175
|
-
});
|
|
8514
|
+
const { paths, authEnabled, bindings, scan: routeScan } = analysis;
|
|
8515
|
+
if (!existsSync(paths.pagesDir) || validateSsrEntry(root, paths) !== null) return null;
|
|
8516
|
+
const pageScan = routeScan.pages;
|
|
8176
8517
|
if (pageScan.pages.length === 0 || !pageScan.pages.every((page) => page.shouldPrerender && (page.params.length === 0 && !page.catchAll || page.hasGetPrerenderPaths))) return null;
|
|
8177
|
-
const bindings = inferProjectBindings(root, {
|
|
8178
|
-
paths,
|
|
8179
|
-
environment: "prod"
|
|
8180
|
-
});
|
|
8181
|
-
const authEnabled = bindings.needsAuth || findVoidAuthConfig(root, paths) !== null || voidConfig.auth !== void 0;
|
|
8182
8518
|
if (hasNonPageBackend({
|
|
8183
8519
|
hasRoutes: routeScan.routes.length > 0,
|
|
8184
8520
|
hasMiddleware: routeScan.middleware.length > 0,
|
|
@@ -8186,7 +8522,7 @@ async function resolveCloudflareVoidStaticPreset(root, voidConfig) {
|
|
|
8186
8522
|
hasEmail: routeScan.email !== void 0 && hasEmailHandlers(routeScan.email),
|
|
8187
8523
|
authEnabled,
|
|
8188
8524
|
hasLive: bindings.needsLive === true
|
|
8189
|
-
}) ||
|
|
8525
|
+
}) || analysis.jobs.length > 0 || analysis.queues.length > 0) return null;
|
|
8190
8526
|
return {
|
|
8191
8527
|
buildCommand: resolveFullDeployBuildCommand(root, voidConfig.inference?.build).command,
|
|
8192
8528
|
outputDir: join(root, "dist", "client"),
|
|
@@ -8247,8 +8583,8 @@ async function runCloudflareStaticDeploy(root, options, voidConfig, preset, cliL
|
|
|
8247
8583
|
await ensureCloudflareAuthentication({
|
|
8248
8584
|
acceptApiToken: true,
|
|
8249
8585
|
beforeRun: uploaderIsPinned,
|
|
8250
|
-
runWrangler: (
|
|
8251
|
-
|
|
8586
|
+
runWrangler: (operation, capture) => runWrangler(operation, { capture }),
|
|
8587
|
+
configPath: existsSync(configPath) ? configPath : void 0
|
|
8252
8588
|
});
|
|
8253
8589
|
} catch (error) {
|
|
8254
8590
|
if (error instanceof CloudflareAuthenticationError && error.reason === "uploader-changed") return exit(1);
|
|
@@ -8316,12 +8652,6 @@ async function runCloudflareStaticDeploy(root, options, voidConfig, preset, cliL
|
|
|
8316
8652
|
});
|
|
8317
8653
|
const entryPath = join(root, ".void", "deploy", "cloudflare", "static-edge.mjs");
|
|
8318
8654
|
mkdirSync(dirname(entryPath), { recursive: true });
|
|
8319
|
-
writeFileSync(entryPath, renderCloudflareStaticEntry({
|
|
8320
|
-
runtimeImport: "void/edge",
|
|
8321
|
-
headerRules: manifest.headerRules,
|
|
8322
|
-
redirectRules: manifest.redirectRules,
|
|
8323
|
-
fallbackRules: manifest.fallbackRules
|
|
8324
|
-
}));
|
|
8325
8655
|
const workerName = readWranglerTopLevelString(rootConfig, "name") ?? deriveWorkerName(root);
|
|
8326
8656
|
const staticConfigPath = join(dirname(entryPath), "wrangler-static.json");
|
|
8327
8657
|
writeFileSync(staticConfigPath, `${JSON.stringify(rootConfig, null, 2)}\n`, { mode: 384 });
|
|
@@ -8335,6 +8665,22 @@ async function runCloudflareStaticDeploy(root, options, voidConfig, preset, cliL
|
|
|
8335
8665
|
assetConfig: manifest.assetConfig ?? { not_found_handling: "none" }
|
|
8336
8666
|
});
|
|
8337
8667
|
deduplicateGeneratedCompatibilityFlags(staticConfigPath, configPath);
|
|
8668
|
+
const staticConfig = parseRootWranglerConfig(staticConfigPath);
|
|
8669
|
+
const versionMetadataBinding = selectNativeVersionMetadataBinding(staticConfig, {
|
|
8670
|
+
nativeBuild: true,
|
|
8671
|
+
preserveBindings: existingWorker !== null
|
|
8672
|
+
});
|
|
8673
|
+
if (versionMetadataBinding && staticConfig.version_metadata === void 0) writeFileSync(staticConfigPath, `${JSON.stringify({
|
|
8674
|
+
...staticConfig,
|
|
8675
|
+
version_metadata: { binding: versionMetadataBinding }
|
|
8676
|
+
}, null, 2)}\n`, { mode: 384 });
|
|
8677
|
+
writeFileSync(entryPath, renderCloudflareStaticEntry({
|
|
8678
|
+
runtimeImport: "void/edge",
|
|
8679
|
+
headerRules: manifest.headerRules,
|
|
8680
|
+
redirectRules: manifest.redirectRules,
|
|
8681
|
+
fallbackRules: manifest.fallbackRules,
|
|
8682
|
+
versionMetadataBinding
|
|
8683
|
+
}));
|
|
8338
8684
|
if (existingWorker) assertExistingCloudflareConfig(existingWorker, parseRootWranglerConfig(staticConfigPath), true);
|
|
8339
8685
|
const stagedAssetsDirectory = join(root, ".void", "deploy", "cloudflare", "assets");
|
|
8340
8686
|
stageCloudflareStaticAssets({
|
|
@@ -8385,6 +8731,8 @@ async function runCloudflareStaticDeploy(root, options, voidConfig, preset, cliL
|
|
|
8385
8731
|
verifyUploader: cfOutput ? cfUploaderIsPinned : uploaderIsPinned,
|
|
8386
8732
|
configPath: staticConfigPath,
|
|
8387
8733
|
preserveTriggers: existingWorker !== null,
|
|
8734
|
+
requireVersionMetadata: existingWorker === null || versionMetadataBinding !== void 0,
|
|
8735
|
+
requirePreviewForReadiness: existingWorker !== null && versionMetadataBinding === void 0,
|
|
8388
8736
|
expectedPreviousVersionId: existingWorker?.versionId,
|
|
8389
8737
|
trustedInheritanceVersionIds: existingWorker ? candidateReceipt?.parentVersionId === existingWorker.versionId ? candidateReceipt.versionIds : void 0 : initialCloudflareCandidate?.versionIds,
|
|
8390
8738
|
validateUploadedVersion: existingWorker ? async (versionId) => {
|
|
@@ -9142,7 +9490,6 @@ async function runFrameworkDeploy(root, config, client, detected, fwPreset, void
|
|
|
9142
9490
|
mode: "framework",
|
|
9143
9491
|
framework: detected.name
|
|
9144
9492
|
});
|
|
9145
|
-
const dialect = getDatabaseDialect(voidConfig);
|
|
9146
9493
|
const buildCmd = voidConfig.inference?.build ?? formatProjectCommand(root, fwPreset.buildCommand);
|
|
9147
9494
|
if (!skipBuild) {
|
|
9148
9495
|
log.step(`Building (${buildCmd})...`);
|
|
@@ -9172,15 +9519,12 @@ async function runFrameworkDeploy(root, config, client, detected, fwPreset, void
|
|
|
9172
9519
|
log.error(`deploy: Worker output '${fwPreset.workerDir}' not found. Run '${buildCmd}' first.`);
|
|
9173
9520
|
process.exit(1);
|
|
9174
9521
|
}
|
|
9175
|
-
const
|
|
9176
|
-
|
|
9177
|
-
const scanDirs = voidConfig.inference?.scanDirs ?? FRAMEWORK_SCAN_DIRS;
|
|
9178
|
-
const bindings = inferProjectBindings(root, {
|
|
9179
|
-
...inferenceOptions,
|
|
9180
|
-
paths,
|
|
9522
|
+
const analysis = analyzeApplicationSync(root, {
|
|
9523
|
+
config: voidConfig,
|
|
9181
9524
|
environment: "prod"
|
|
9182
|
-
}
|
|
9183
|
-
|
|
9525
|
+
});
|
|
9526
|
+
const { paths, bindings, authEnabled, dialect } = analysis;
|
|
9527
|
+
if (authEnabled) {
|
|
9184
9528
|
log.error("deploy: Void-managed Better Auth is only supported in Void apps. Use Better Auth's official integration for this framework instead.");
|
|
9185
9529
|
process.exit(1);
|
|
9186
9530
|
}
|
|
@@ -9190,7 +9534,7 @@ async function runFrameworkDeploy(root, config, client, detected, fwPreset, void
|
|
|
9190
9534
|
}
|
|
9191
9535
|
const migrationsDir = paths.migrationsDir;
|
|
9192
9536
|
assertDeploySchemaDriftFree(root, dialect);
|
|
9193
|
-
const rawMigrations =
|
|
9537
|
+
const rawMigrations = analysis.migrations;
|
|
9194
9538
|
let validatedMigrations;
|
|
9195
9539
|
try {
|
|
9196
9540
|
assertJournalCoherence(migrationsDir, rawMigrations);
|
|
@@ -9205,7 +9549,7 @@ async function runFrameworkDeploy(root, config, client, detected, fwPreset, void
|
|
|
9205
9549
|
log.error(getErrorMessage(err));
|
|
9206
9550
|
process.exit(1);
|
|
9207
9551
|
}
|
|
9208
|
-
if (dialect !== "sqlite" &&
|
|
9552
|
+
if (dialect !== "sqlite" && analysis.needsDatabase) {
|
|
9209
9553
|
let resources = null;
|
|
9210
9554
|
try {
|
|
9211
9555
|
resources = await client.getResources(config.projectId);
|
|
@@ -9229,11 +9573,10 @@ async function runFrameworkDeploy(root, config, client, detected, fwPreset, void
|
|
|
9229
9573
|
}
|
|
9230
9574
|
}
|
|
9231
9575
|
}
|
|
9232
|
-
const rawJobs =
|
|
9233
|
-
const rawQueues =
|
|
9576
|
+
const rawJobs = analysis.jobs;
|
|
9577
|
+
const rawQueues = analysis.queues;
|
|
9234
9578
|
const originalEntry = join(workerDir, fwPreset.workerMain);
|
|
9235
9579
|
const wrapperFeatures = {
|
|
9236
|
-
auth: null,
|
|
9237
9580
|
crons: rawJobs,
|
|
9238
9581
|
queues: rawQueues,
|
|
9239
9582
|
hasMigrations: validatedMigrations != null && validatedMigrations.length > 0,
|
|
@@ -9289,7 +9632,7 @@ async function runFrameworkDeploy(root, config, client, detected, fwPreset, void
|
|
|
9289
9632
|
const packageStartedAt = Date.now();
|
|
9290
9633
|
const neededSet = skipped > 0 ? new Set(needed) : null;
|
|
9291
9634
|
const packageOptions = {
|
|
9292
|
-
bindingNames:
|
|
9635
|
+
bindingNames: analysis.bindingNames,
|
|
9293
9636
|
workerMain: actualWorkerMain,
|
|
9294
9637
|
compatibilityDate: wranglerCompat?.compatibilityDate,
|
|
9295
9638
|
compatibilityFlags: wranglerCompat?.compatibilityFlags,
|
|
@@ -9396,20 +9739,12 @@ async function runFullDeploy(root, config, client, voidConfig, fwPreset, skipBui
|
|
|
9396
9739
|
if (result.paths.length === 0) log.info("No pages to prerender");
|
|
9397
9740
|
else if (result.failed.length > 0) voidWarn(`${result.failed.length} page(s) failed to prerender`);
|
|
9398
9741
|
}
|
|
9399
|
-
const
|
|
9400
|
-
|
|
9401
|
-
const deployScanDirs = deployConfig.inference?.scanDirs ?? (isFrameworkMode ? FRAMEWORK_SCAN_DIRS : void 0);
|
|
9402
|
-
const bindings = inferProjectBindings(root, {
|
|
9403
|
-
paths,
|
|
9742
|
+
const analysis = await analyzeApplication(root, {
|
|
9743
|
+
config: deployConfig,
|
|
9404
9744
|
environment: "prod"
|
|
9405
|
-
}
|
|
9406
|
-
|
|
9407
|
-
const
|
|
9408
|
-
const effectiveBindings = authEnabled ? {
|
|
9409
|
-
...bindings,
|
|
9410
|
-
needsAuth: true,
|
|
9411
|
-
needsD1: true
|
|
9412
|
-
} : bindings;
|
|
9745
|
+
});
|
|
9746
|
+
const { paths, dialect, bindings, authEnabled, scan: routeScan } = analysis;
|
|
9747
|
+
const effectiveBindings = bindings;
|
|
9413
9748
|
if (isFrameworkMode && authEnabled) {
|
|
9414
9749
|
log.error("Void-managed Better Auth is only supported in Void apps. Use Better Auth's official integration for this framework instead.");
|
|
9415
9750
|
process.exit(1);
|
|
@@ -9439,7 +9774,7 @@ async function runFullDeploy(root, config, client, voidConfig, fwPreset, skipBui
|
|
|
9439
9774
|
lintDestinationSplats(fallbackRules, "fallbacks (post-asset)");
|
|
9440
9775
|
const migrationsDir = paths.migrationsDir;
|
|
9441
9776
|
assertDeploySchemaDriftFree(root, dialect);
|
|
9442
|
-
const rawMigrations =
|
|
9777
|
+
const rawMigrations = analysis.migrations;
|
|
9443
9778
|
let validatedMigrations;
|
|
9444
9779
|
try {
|
|
9445
9780
|
assertJournalCoherence(migrationsDir, rawMigrations);
|
|
@@ -9454,7 +9789,7 @@ async function runFullDeploy(root, config, client, voidConfig, fwPreset, skipBui
|
|
|
9454
9789
|
log.error(getErrorMessage(err));
|
|
9455
9790
|
process.exit(1);
|
|
9456
9791
|
}
|
|
9457
|
-
if (dialect !== "sqlite" &&
|
|
9792
|
+
if (dialect !== "sqlite" && analysis.needsDatabase) {
|
|
9458
9793
|
let resources = null;
|
|
9459
9794
|
try {
|
|
9460
9795
|
resources = await client.getResources(config.projectId);
|
|
@@ -9478,18 +9813,13 @@ async function runFullDeploy(root, config, client, voidConfig, fwPreset, skipBui
|
|
|
9478
9813
|
}
|
|
9479
9814
|
}
|
|
9480
9815
|
}
|
|
9481
|
-
const rawJobs =
|
|
9482
|
-
const rawQueues =
|
|
9816
|
+
const rawJobs = analysis.jobs;
|
|
9817
|
+
const rawQueues = analysis.queues;
|
|
9483
9818
|
const schedules = rawJobs.flatMap((job) => job.crons.map((cron) => ({
|
|
9484
9819
|
name: job.name,
|
|
9485
9820
|
cron
|
|
9486
9821
|
})));
|
|
9487
|
-
const
|
|
9488
|
-
output: deployConfig.output,
|
|
9489
|
-
paths,
|
|
9490
|
-
environment: "prod"
|
|
9491
|
-
});
|
|
9492
|
-
const webSockets = routeScan.websockets ?? scanWebSocketRoutesSync(root, paths, "prod");
|
|
9822
|
+
const webSockets = analysis.websockets;
|
|
9493
9823
|
const liveConfig = await resolveDeployLiveBindingConfig(root, client, config.projectId, {
|
|
9494
9824
|
isFrameworkMode,
|
|
9495
9825
|
needsLive: effectiveBindings.needsLive,
|
|
@@ -9511,10 +9841,7 @@ async function runFullDeploy(root, config, client, voidConfig, fwPreset, skipBui
|
|
|
9511
9841
|
const hasWebSockets = webSockets.length > 0;
|
|
9512
9842
|
const ssrEntry = isFrameworkMode ? null : validateSsrEntry(root, paths);
|
|
9513
9843
|
const isSsr = isFrameworkMode ? true : Boolean(ssrEntry) || hasPages && deployConfig.output !== "static";
|
|
9514
|
-
const pageScan =
|
|
9515
|
-
output: deployConfig.output,
|
|
9516
|
-
paths
|
|
9517
|
-
}) : null;
|
|
9844
|
+
const pageScan = hasPages ? routeScan.pages : null;
|
|
9518
9845
|
const revalidate = collectRevalidate(deployConfig, pageScan);
|
|
9519
9846
|
if (deployConfig.output === "static" && pageScan && !isSsr) {
|
|
9520
9847
|
const allPrerenderable = pageScan.pages.every((p) => p.shouldPrerender && (p.params.length === 0 && !p.catchAll || p.hasGetPrerenderPaths));
|
|
@@ -9638,7 +9965,6 @@ async function runFullDeploy(root, config, client, voidConfig, fwPreset, skipBui
|
|
|
9638
9965
|
const workerDir = join(distDir, workerDirName);
|
|
9639
9966
|
if (isFrameworkMode) {
|
|
9640
9967
|
const wrapperFeatures = {
|
|
9641
|
-
auth: null,
|
|
9642
9968
|
crons: rawJobs,
|
|
9643
9969
|
queues: rawQueues,
|
|
9644
9970
|
hasMigrations: validatedMigrations != null && validatedMigrations.length > 0,
|
|
@@ -9909,4 +10235,4 @@ function resolveWorkerDirName(distDir, fwPreset, buildCommand) {
|
|
|
9909
10235
|
throw new Error("deploy: Worker output not found. Expected dist/ssr/ or dist/rsc/.");
|
|
9910
10236
|
}
|
|
9911
10237
|
//#endregion
|
|
9912
|
-
export { snapshotPassthroughRawFields as $, parseRootWranglerConfig$1 as A, resolveDeploymentPlatform as B, generateDeployWrapperIfNeeded as C,
|
|
10238
|
+
export { snapshotPassthroughRawFields as $, parseRootWranglerConfig$1 as A, resolveDeploymentPlatform as B, generateDeployWrapperIfNeeded as C, hasDocumentRoutes as Ct, hashWranglerUploader as D, hasPrerenderSources as E, resolveCloudflareVoidStaticPreset as F, resolveWorkerDirName as G, resolveFullDeployBuildCommand as H, resolveDeployLiveBindingConfig as I, runDeploy as J, resolveWranglerMigrationPattern as K, resolveDeployTransport as L, promptDeployProjectConfig as M, reconstructExpectedContainers as N, isWranglerNonInteractiveOrCI as O, reconstructExpectedDurableObjectState as P, snapshotPassthroughIdentities as Q, resolveDeployWorkerMain as R, formatCloudflareSandboxUnavailable as S, hasApiRoutes as St, hasNonPageBackend as T, resolveAssetRoutingPolicy as Tt, resolveStaticBuildCommand as U, resolveDistDir as V, resolveStaticDeployPreset as W, runWranglerAuthToken as X, runStaticDeploy as Y, snapshotBindingIdentities as Z, deriveWorkerName as _, createNodeEmailDns as _t, applyDeployEvent as a, warnUnpublishedRouting as at, ensurePreviouslyDeployedLiveBindingConfig as b, renderAddressMap as bt, assertMigrationsProduceAuthSchema as c, selectNativeVersionMetadataBinding as ct, assertWranglerUploaderUnchanged as d, buildEnv as dt, streamDeployEvents as et, checkWranglerMigrationApplySet as f, collectPages as ft, deployChildEnv as g, applyEmailSetup as gt, createDeployWranglerRunner as h, SEND_EMAIL_BINDING as ht, DEPLOY_WHOLE_OBJECT_PINNED_FIELDS as i, warnRedundantForceOn3xx as it, prepareCloudflareFrameworkArtifact as j, loadProvisionModule as k, assertNoConfigOverrideInProjectDotenv as l, prerenderPages as lt, computeDesiredCloudflareResources as m, hasRevalidate as mt, DEPLOY_PASSTHROUGH_ASSERT_FIELDS as n, verifyGeneratedDeployConfig as nt, assembleVoidManifest as o, generateQueueResolverSource as ot, compareWranglerMigrationPaths as p, collectRevalidate as pt, runCloudflareDeploy as q, DEPLOY_PASSTHROUGH_EXCLUDE_FIELDS as r, warnIgnoredNotFoundForFramework as rt, assertManagedDurableStateSupported as s, CLOUDFLARE_PRESERVE_BINDINGS_BUILD_ENV as st, CloudflareAuthSecretError as t, validateAuthMigrationSchema as tt, assertRemoteMigrationsDeployable as u, prerenderPagesNode as ut, discoverRootWranglerConfig as v, findEmailConfigConflicts as vt, hasDeploySchemaDrift as w, resolveAssetConfig as wt, formatCloudflareActivationError as x, renderEmailChecklist as xt, ensureCloudflareAuthSecret as y, preflightEmail as yt, resolveDeployWranglerCompat as z };
|