void 0.21.2 → 0.21.4
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/dist/{account-cmd-D8OC-U7y.mjs → account-cmd-DGt9cpRe.mjs} +4 -4
- package/dist/{agents-gni4eqBu.mjs → agents-B_pX_HmQ.mjs} +1 -1
- package/dist/ast-CPGPjb0V.mjs +18 -0
- package/dist/{auth-CAw7zHqj.mjs → auth-CZuiVsFh.mjs} +1 -1
- package/dist/{auth-B9_D6ygs.mjs → auth-DLNN0D3Z.mjs} +4 -4
- package/dist/{auth-link-BYFeMJAp.mjs → auth-link-Cl9vOuf7.mjs} +4 -4
- package/dist/{auth-router-OHZNmrb_.mjs → auth-router-D4ZcMUSf.mjs} +6 -6
- package/dist/{better-auth-shared-BoVwA5Vm.d.mts → better-auth-shared-BVkjZ3vM.d.mts} +1 -0
- package/dist/{better-auth-shared-syGYYmnY.mjs → better-auth-shared-rsBGBvWJ.mjs} +3 -6
- package/dist/{build-cmd-Bft7EY51.mjs → build-cmd-Dpt0jd-x.mjs} +4 -4
- package/dist/{cache-CKV1Gz2w.mjs → cache-7_UeZdTk.mjs} +4 -4
- package/dist/{cancel-deploy-BAKmkX4f.mjs → cancel-deploy-D23R1RXT.mjs} +3 -3
- package/dist/{cf-access-rAZxzMkL.mjs → cf-access-P0iZnu0q.mjs} +1 -1
- package/dist/{cf-build-output-CTdlo6Rt.mjs → cf-build-output-CGT03qCD.mjs} +2 -2
- package/dist/cli/cf-compat.mjs +2 -2
- package/dist/cli/cli.mjs +47 -43
- package/dist/cli/env-schema-probe.mjs +3 -3
- package/dist/client-4cDVv7BO.mjs +2 -0
- package/dist/{client-PdAJ-F0t.mjs → client-QTl6ko_D.mjs} +28 -5
- package/dist/{cloudflare-auth-BCmTc1X_.mjs → cloudflare-auth-B9jPCkV2.mjs} +1 -1
- package/dist/{cloudflare-cmd-D6PrKn7o.mjs → cloudflare-cmd-BjNxR1XF.mjs} +3 -3
- package/dist/{cloudflare-connect-DloREDlc.mjs → cloudflare-connect-CCUozPOe.mjs} +3 -3
- package/dist/{cloudflare-operations-BHNJVDbN.mjs → cloudflare-operations-BipGMJ5O.mjs} +1 -1
- package/dist/{cloudflare-operations-CPEdHYhM.mjs → cloudflare-operations-sMZXpk_S.mjs} +4 -4
- package/dist/collect-DLyFDiKW.mjs +2 -0
- package/dist/{collect-DXHNWHcT.mjs → collect-DiTn9yr6.mjs} +1 -1
- package/dist/config-0acf1oys.mjs +2 -0
- package/dist/{config-DywxBLQC.d.mts → config-CF69HgXc.d.mts} +7 -0
- package/dist/{config-Dxr6cTXn.mjs → config-CafTW6Cz.mjs} +12 -1
- package/dist/{config-BSe70f4T.mjs → config-D8MOgiQV.mjs} +3 -3
- package/dist/config-DPByhVck.mjs +32 -0
- package/dist/config-entry.d.mts +1 -1
- package/dist/{config--T87TD8T.mjs → config-s7Xj7tPb.mjs} +1 -1
- package/dist/{config-write-y3CBI_ux.mjs → config-write-BSduPMY8.mjs} +3 -3
- package/dist/{connect-DLx1pRYk.mjs → connect-4Ph5Y0QE.mjs} +7 -7
- package/dist/{create-project-JV9-6ICF.mjs → create-project-BniEV0OW.mjs} +1 -1
- package/dist/{create-project-BZBl_gQ0.mjs → create-project-DBfFSZKY.mjs} +4 -4
- package/dist/{db-B98_UV4H.mjs → db-CTXIWD42.mjs} +123 -55
- package/dist/{delete-BEEyqlwd.mjs → delete-D6dZ9B6B.mjs} +4 -4
- package/dist/deploy-BVwow28d.mjs +2 -0
- package/dist/{deploy-Bsymb0_c.mjs → deploy-F1exK5F4.mjs} +567 -263
- package/dist/discover-AMCBXivQ.mjs +2 -0
- package/dist/{discover-C4O6YxVS.mjs → discover-BcPPiF1o.mjs} +2 -2
- package/dist/{dist-4WkAWhWx.mjs → dist-BVqXeR_h.mjs} +9 -1
- package/dist/dist-_UUlL6bg.mjs +2 -0
- package/dist/{domain-Av2AkLQP.mjs → domain-Dmhvb2oU.mjs} +4 -4
- package/dist/{email-C5kaZXzJ.mjs → email--tEtMoj_.mjs} +1 -1
- package/dist/{email-CUqa6TtH.mjs → email-BxHabktK.mjs} +9 -9
- package/dist/{entry-DdRFGK0y.mjs → entry-CF5wvH4w.mjs} +4 -21
- package/dist/{env-D4RIGEzz.mjs → env-Csi-tMbT.mjs} +7 -7
- package/dist/{env-Yz4HcvHs.mjs → env-D5liuQYR.mjs} +5 -2
- package/dist/{env-DX_v-Q-v.mjs → env-_v349JBd.mjs} +1 -1
- package/dist/{env-types-CWDtqHgw.mjs → env-types-C2_bIk_b.mjs} +2 -2
- package/dist/{env-validation-BsFEXps5.mjs → env-validation-BB4GkLxn.mjs} +4 -4
- package/dist/{env-validation-DIDGM7h4.mjs → env-validation-BXge7uyK.mjs} +1 -1
- package/dist/{gen-pg-Ojg8Y.mjs → gen-Dz3X1Qab.mjs} +8 -8
- package/dist/gen-Vnv2f65C.mjs +2 -0
- package/dist/{generate-C0VY6RVf.mjs → generate-GDbL7sUr.mjs} +2 -2
- package/dist/{github-cmd-BEK4VprE.mjs → github-cmd-BED3_9JD.mjs} +4 -4
- package/dist/{headers-B_HBMgi0.mjs → headers-BOg_velo.mjs} +2 -2
- package/dist/{help-iQOt7WHk.mjs → help-DC7gdz7L.mjs} +7 -3
- package/dist/help-DQMfeKMz.mjs +2 -0
- package/dist/index.mjs +132 -158
- package/dist/{init-D5niUPAz.mjs → init-CRGDXzVC.mjs} +105 -289
- package/dist/{link-3lGrfXzd.mjs → link-CsHOinF7.mjs} +5 -5
- package/dist/{list-CVjGr_C6.mjs → list-CDb-4bZ1.mjs} +5 -5
- package/dist/{local-d1-DzykTWY8.mjs → local-d1-CC8sKFGu.mjs} +3 -3
- package/dist/{login-BgQJzxAl.mjs → login-BQyISZuW.mjs} +3 -3
- package/dist/login-r2gL8l7B.mjs +2 -0
- package/dist/{logs-DbzD-QDf.mjs → logs-BdfiOezj.mjs} +4 -4
- package/dist/{migrate-BV8qHiCb.mjs → migrate-B8KuoYsO.mjs} +69 -44
- package/dist/migrate-TsHGBnDA.mjs +2 -0
- package/dist/{node-Cupyf7-s.mjs → node-BM43oz4G.mjs} +5 -5
- package/dist/{operator-auth-BkVgJqv-.mjs → operator-auth-8KnOVXVd.mjs} +2 -2
- package/dist/{operator-client-A0iex2yi.mjs → operator-client-DUwumHpQ.mjs} +2 -2
- package/dist/{operator-cmd-CR6Lxzt0.mjs → operator-cmd-Co-PeaeD.mjs} +6 -6
- package/dist/{package-json-iCbMg5XF.mjs → package-json-DXfiT1jV.mjs} +1 -1
- package/dist/pages/index.d.mts +1 -1
- package/dist/pages/index.mjs +11 -6
- package/dist/pages/islands-plugin.d.mts +271 -1
- package/dist/pages/islands-plugin.mjs +95 -18
- package/dist/parse-filename-DioPHiR9.mjs +77 -0
- package/dist/{platform-auth-config-De7BqRJm.mjs → platform-auth-config-TSw8edHw.mjs} +5 -5
- package/dist/{platform-auth-protection-Dcat-6zu.mjs → platform-auth-protection-Ba1XqGhn.mjs} +6 -6
- package/dist/{platform-auth-recovery-C9gsM640.mjs → platform-auth-recovery-BkT3EsF2.mjs} +5 -5
- package/dist/{platform-cmd-Cl9Uhzru.mjs → platform-cmd-C8OqhqPt.mjs} +1 -1
- package/dist/{platform-cmd-CudokNIg.mjs → platform-cmd-CRSKfu8k.mjs} +5 -5
- package/dist/{platform-domain-Ckpd2kXw.mjs → platform-domain-j9YCXRm6.mjs} +3 -3
- package/dist/{platform-lifecycle-DVzM2T4j.mjs → platform-lifecycle-78H0XQUA.mjs} +277 -229
- package/dist/{platform-lifecycle-DlpiGcjr.mjs → platform-lifecycle-DDc9zCeJ.mjs} +1 -1
- package/dist/{platform-management-ibuS1as0.mjs → platform-management-6w8-DUjC.mjs} +2 -2
- package/dist/{platform-management-44Bxd3YC.mjs → platform-management-DzKNsMlt.mjs} +1 -1
- package/dist/{platform-recovery-D_KmvdSk.mjs → platform-recovery-Do8VOyDE.mjs} +3 -3
- package/dist/{platform-registry-BJbgZLS1.mjs → platform-registry-QBa4DK32.mjs} +1 -1
- package/dist/{plugin-inference-DsvtJLll.mjs → plugin-inference-BMfKRSqE.mjs} +188 -85
- package/dist/prepare-BZXkjdNe.mjs +2 -0
- package/dist/{prepare-pcWcxSCh.mjs → prepare-C3kt3Rst.mjs} +11 -11
- package/dist/{prepare-_T-Haxrr.mjs → prepare-DyZ-Yok5.mjs} +1 -1
- package/dist/{prerender-render-Cf_WDE9W.mjs → prerender-render-D9qbLs2f.mjs} +1 -1
- package/dist/prerender-render.mjs +1 -1
- package/dist/{preset-Dowh9tTt.mjs → preset-UHj9ARyP.mjs} +4 -4
- package/dist/{project-BEBFDFLz.mjs → project-BuUwfj6f.mjs} +1 -1
- package/dist/{project-CWNIPoXc.mjs → project-C0Fqu05O.mjs} +2 -2
- package/dist/{project-cmd-BuF9doku.mjs → project-cmd-B44I8J_W.mjs} +15 -15
- package/dist/{project-paths-CKQ-Q5JS.mjs → project-paths-GgcMozYz.mjs} +1 -1
- package/dist/{project-team-B1Tia8vd.mjs → project-team-BkbYIsXN.mjs} +4 -4
- package/dist/{project-token-Bwxjf4y6.mjs → project-token-C8xEEQnB.mjs} +4 -4
- package/dist/{project-tsconfig-CwfqUnVp.mjs → project-tsconfig-B8GeM0RM.mjs} +2 -2
- package/dist/{provision-Cck2m3jJ.mjs → provision-BhreDAOS.mjs} +141 -78
- package/dist/provision-DNtrtaVD.mjs +3 -0
- package/dist/{requests-CphRF98D.mjs → requests-DFyhBMaf.mjs} +3 -3
- package/dist/{resolve-project-Xvis70DG.mjs → resolve-project-BG5ORGID.mjs} +1 -1
- package/dist/resolve-project-DtbidV4y.mjs +2 -0
- package/dist/{rollback-BYHJV2yD.mjs → rollback-DHHxXZiS.mjs} +4 -4
- package/dist/{route-types-Id82-veQ.mjs → route-types-Clm4WD0B.mjs} +39 -16
- package/dist/{runner-CQs_cDSG.mjs → runner-B8wXwWlo.mjs} +1 -1
- package/dist/{runner-mysql-1o47achK.mjs → runner-mysql-CEG5JozK.mjs} +1 -1
- package/dist/{runner-mysql-BhwMk2Bm.mjs → runner-mysql-DmWchSWJ.mjs} +1 -1
- package/dist/{runner-BGVsGgkb.mjs → runner-p-dMs2UN.mjs} +3 -3
- package/dist/{runner-pg-D7z01mQS.mjs → runner-pg-Bh4AgZdj.mjs} +1 -1
- package/dist/{runner-pg-CJ_JeGF6.mjs → runner-pg-D4OPlil-.mjs} +1 -1
- package/dist/runtime/better-auth-mysql.d.mts +1 -1
- package/dist/runtime/better-auth-mysql.mjs +1 -1
- package/dist/runtime/better-auth-pg.d.mts +1 -1
- package/dist/runtime/better-auth-pg.mjs +1 -1
- package/dist/runtime/better-auth.d.mts +1 -1
- package/dist/runtime/better-auth.mjs +2 -2
- package/dist/runtime/db.mjs +8 -5
- package/dist/runtime/durable.mjs +1 -1
- package/dist/runtime/email/testing.mjs +1 -1
- package/dist/runtime/env-public.mjs +1 -1
- package/dist/runtime/env.d.mts +1 -1
- package/dist/runtime/env.mjs +1 -1
- package/dist/runtime/kv.mjs +1 -1
- package/dist/runtime/live-server.mjs +38 -23
- package/dist/runtime/queues.mjs +1 -1
- package/dist/runtime/sandbox.mjs +1 -1
- package/dist/runtime/storage.mjs +1 -1
- package/dist/runtime/ws-server.d.mts +1 -1
- package/dist/runtime/ws-server.mjs +1 -1
- package/dist/{scan-DJbooZm2.mjs → scan-4tfN-PSn.mjs} +113 -99
- package/dist/{scan-DdDvRCU1.mjs → scan-ClYmX3sa.mjs} +35 -137
- package/dist/{secret-Rt9c4Ttw.mjs → secret-DN9sSNiV.mjs} +6 -6
- package/dist/{skills-B-690E7h.mjs → skills-O6FUaizK.mjs} +2 -2
- package/dist/sveltekit.mjs +1 -1
- package/dist/{validate-qNhV00PD.mjs → validate-CIUwFpjB.mjs} +2 -2
- package/dist/validate-EKmJWxmy.mjs +2 -0
- package/dist/{wrangler-D01qs6VB.mjs → wrangler-BymcxrRa.mjs} +3 -3
- package/dist/{yarn-pnp-CVEc3gE7.mjs → yarn-pnp-BV4AzNul.mjs} +1 -1
- package/package.json +7 -7
- package/schema.json +18 -0
- package/skills/void/docs/guide/app-types.md +1 -1
- package/skills/void/docs/guide/auth.md +2 -2
- package/skills/void/docs/guide/database/d1.md +6 -0
- package/skills/void/docs/guide/durable-state.md +1 -1
- package/skills/void/docs/guide/edge/rewrites.md +2 -3
- package/skills/void/docs/guide/env-migration.md +1 -1
- package/skills/void/docs/guide/pages-routing/markdown.md +1 -1
- package/skills/void/docs/guide/platform/development/local.md +1 -1
- package/skills/void/docs/guide/platform/installation/prerequisites.md +2 -2
- package/skills/void/docs/guide/platform/installation/setup.md +1 -1
- package/skills/void/docs/guide/server-routing.md +2 -3
- package/skills/void/docs/guide/ssr.md +4 -10
- package/skills/void/docs/guide/websockets.md +1 -1
- package/skills/void/docs/integrations/cloudflare.md +3 -0
- package/skills/void/docs/reference/api.md +1 -1
- package/skills/void/docs/reference/cli.md +10 -3
- package/skills/void/docs/reference/config.md +11 -0
- package/skills/void/docs/reference/resource-inference.md +1 -1
- package/dist/client-DAAivdid.mjs +0 -2
- package/dist/collect-DAUItMDS.mjs +0 -2
- package/dist/config-DDIFxQYx.mjs +0 -2
- package/dist/config-uP7ZDtVZ.mjs +0 -21
- package/dist/deploy-CsjbRNyv.mjs +0 -2
- package/dist/discover-BBzDZe_o.mjs +0 -2
- package/dist/dist-D7-nEOXi.mjs +0 -2
- package/dist/gen-B87rlalt.mjs +0 -2
- package/dist/help-r_vrpH_d.mjs +0 -2
- package/dist/login-Bz0zEPoy.mjs +0 -2
- package/dist/migrate-BXY3B3m7.mjs +0 -2
- package/dist/prepare-D4CkM3_v.mjs +0 -2
- package/dist/provision-CNgEBkVA.mjs +0 -3
- package/dist/resolve-project-BTotl8Nn.mjs +0 -2
- package/dist/validate-DqJ33oHj.mjs +0 -2
|
@@ -1,58 +1,60 @@
|
|
|
1
1
|
import { n as __toESM, t as __commonJSMin } from "./rolldown-runtime-DXIUcv95.mjs";
|
|
2
|
-
import { a as join, l as relative, n as dirname, o as normalize, r as extname, t as basename, u as resolve } from "./dist-
|
|
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 { c as import_picocolors$1, d as require_picocolors, i as createSpinner, r as cliTitle } from "./output-CCH48AMM.mjs";
|
|
4
|
-
import { i as resolveProjectPaths, n as readProjectPaths, t as assertNoRootSourceConventionConflicts } from "./project-paths-
|
|
5
|
-
import { t as findVoidAuthConfig } from "./config-
|
|
4
|
+
import { i as resolveProjectPaths, n as readProjectPaths, t as assertNoRootSourceConventionConflicts } from "./project-paths-GgcMozYz.mjs";
|
|
5
|
+
import { t as findVoidAuthConfig } from "./config-DPByhVck.mjs";
|
|
6
6
|
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-
|
|
8
|
-
import { r as ensurePlatformProxyAccess, t as ensureCloudflaredToken } from "./cf-access-
|
|
9
|
-
import { d as writeProjectConfig, i as readDeploymentPlatform, l as writeDeploymentPlatform, o as readProjectConfig, t as attachSelectedPlatform } from "./project-
|
|
10
|
-
import { d as isNodeTarget, h as resolveBindingNames, m as readConfig, u as getDatabaseDialect } from "./config-
|
|
11
|
-
import { A as writeWranglerPublishedTrafficSnapshot, D as syncWranglerWebSockets, E as syncWranglerDurableObjects, L as materializeCloudflareConfig, M as isSandboxEnabled, N as requiresSandboxPlatformImage, P as resolveSandboxConfig, R as persistCloudflareConfig, S as readWranglerPublishedTrafficSnapshot, T as syncWranglerBindings, V as stashCloudflareDeployPointer, a as LIVE_MIGRATION_TAG, c as bindingEntriesForField, f as findBindingNameOwner, g as readExistingLiveBindingConfig, h as normalizeWranglerCompatibilityFlags, k as writeProvisionedWranglerConfig, l as ensureWranglerCompat, o as acknowledgeWranglerManagedQueueRemovals, r as FRIENDLY_BINDING_NAMES, w as resolveLiveBindingConfig, x as readWranglerManagedQueueCleanupCandidates } from "./wrangler-
|
|
7
|
+
import { a as getApiUrl, c as getToken, l as getTokenSource, o as getProxyUrl, u as isStagingMode } from "./auth-DLNN0D3Z.mjs";
|
|
8
|
+
import { r as ensurePlatformProxyAccess, t as ensureCloudflaredToken } from "./cf-access-P0iZnu0q.mjs";
|
|
9
|
+
import { d as writeProjectConfig, i as readDeploymentPlatform, l as writeDeploymentPlatform, o as readProjectConfig, t as attachSelectedPlatform } from "./project-C0Fqu05O.mjs";
|
|
10
|
+
import { d as isNodeTarget, h as resolveBindingNames, m as readConfig, u as getDatabaseDialect } from "./config-CafTW6Cz.mjs";
|
|
11
|
+
import { A as writeWranglerPublishedTrafficSnapshot, D as syncWranglerWebSockets, E as syncWranglerDurableObjects, L as materializeCloudflareConfig, M as isSandboxEnabled, N as requiresSandboxPlatformImage, P as resolveSandboxConfig, R as persistCloudflareConfig, S as readWranglerPublishedTrafficSnapshot, T as syncWranglerBindings, V as stashCloudflareDeployPointer, a as LIVE_MIGRATION_TAG, c as bindingEntriesForField, f as findBindingNameOwner, g as readExistingLiveBindingConfig, h as normalizeWranglerCompatibilityFlags, j as SANDBOX_MIGRATION_TAG, k as writeProvisionedWranglerConfig, l as ensureWranglerCompat, m as nextDurableObjectMigrationTag, o as acknowledgeWranglerManagedQueueRemovals, p as hasDurableObjectSqliteMigration, r as FRIENDLY_BINDING_NAMES, w as resolveLiveBindingConfig, x as readWranglerManagedQueueCleanupCandidates } from "./wrangler-BymcxrRa.mjs";
|
|
12
12
|
import { i as voidWarn, r as voidLog } from "./log-ChfPKsVd.mjs";
|
|
13
|
-
import { n as lintDuplicateSources, r as mergeRoutingRules, t as lintDestinationSplats } from "./headers-
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
13
|
+
import { n as lintDuplicateSources, r as mergeRoutingRules, t as lintDestinationSplats } from "./headers-BOg_velo.mjs";
|
|
14
|
+
import { n as isIdentifier, r as isLiteral } from "./ast-CPGPjb0V.mjs";
|
|
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";
|
|
18
19
|
import { r as buildMigrationPlanBundle } from "./plan-BEZ8VJW0.mjs";
|
|
19
20
|
import { r as scanWranglerDotenvKeys } from "./dotenv-VQxupEUv.mjs";
|
|
20
|
-
import { t as discoverSchema } from "./discover-
|
|
21
|
-
import { t as
|
|
22
|
-
import {
|
|
23
|
-
import { n as
|
|
21
|
+
import { t as discoverSchema } from "./discover-BcPPiF1o.mjs";
|
|
22
|
+
import { t as MagicString } from "./dist-BR1quN_w.mjs";
|
|
23
|
+
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-BB4GkLxn.mjs";
|
|
25
|
+
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";
|
|
24
27
|
import { E as confirm, I as select, N as note, O as intro, P as outro, W as isCancel, j as log$1 } from "./dist-Dn6nn2IU.mjs";
|
|
25
|
-
import { t as writeDrizzleConfig } from "./config-
|
|
26
|
-
import { i as runMySqlMigrations } from "./runner-mysql-
|
|
27
|
-
import { i as runPgMigrations } from "./runner-pg-
|
|
28
|
+
import { t as writeDrizzleConfig } from "./config-D8MOgiQV.mjs";
|
|
29
|
+
import { i as runMySqlMigrations } from "./runner-mysql-DmWchSWJ.mjs";
|
|
30
|
+
import { i as runPgMigrations } from "./runner-pg-D4OPlil-.mjs";
|
|
28
31
|
import { n as openMigrationValidationDatabase, t as SqliteMigrationError } from "./sqlite-validation-BzKMWnO4.mjs";
|
|
29
|
-
import { i as validateMigrations, t as assertJournalCoherence } from "./validate-
|
|
30
|
-
import { t as
|
|
31
|
-
import {
|
|
32
|
-
import {
|
|
33
|
-
import {
|
|
34
|
-
import { n as
|
|
35
|
-
import {
|
|
36
|
-
import {
|
|
37
|
-
import {
|
|
38
|
-
import {
|
|
39
|
-
import {
|
|
40
|
-
import { a as createCloudflareEmptyDomainPublisher, i as createCloudflareEmptyCronPublisher } from "./cloudflare-operations-CPEdHYhM.mjs";
|
|
32
|
+
import { i as validateMigrations, t as assertJournalCoherence } from "./validate-CIUwFpjB.mjs";
|
|
33
|
+
import { t as renderPrerenderPaths } from "./prerender-render-D9qbLs2f.mjs";
|
|
34
|
+
import { a as scanEmailHandlersSync, r as hasEmailHandlers } from "./email--tEtMoj_.mjs";
|
|
35
|
+
import { i as migrateBuiltWranglerConfig, n as prepareCfFrameworkBuildOutput, r as prepareCfStaticBuildOutput, t as prepareCfBuildOutput } from "./cf-build-output-CGT03qCD.mjs";
|
|
36
|
+
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-QTl6ko_D.mjs";
|
|
38
|
+
import { a as resolveProjectCommand, i as hasBackendFiles, n as detectPreset, o as resolveWranglerArgv, r as formatProjectCommand, t as FRAMEWORK_PRESETS } from "./preset-UHj9ARyP.mjs";
|
|
39
|
+
import { o as ensureCloudflareAuthentication, r as cloudflareAuthNeedsTerminal, t as CloudflareAuthenticationError } from "./cloudflare-auth-B9jPCkV2.mjs";
|
|
40
|
+
import { n as writeVoidProjectConfig } from "./config-write-BSduPMY8.mjs";
|
|
41
|
+
import { r as discoverFrameworkWranglerFiles, t as migrateLegacyVoidConfig } from "./migrate-B8KuoYsO.mjs";
|
|
42
|
+
import { a as createCloudflareEmptyDomainPublisher, i as createCloudflareEmptyCronPublisher } from "./cloudflare-operations-sMZXpk_S.mjs";
|
|
41
43
|
import { t as formatCloudflareUserMessage } from "./cloudflare-user-output-Q-k0QoNQ.mjs";
|
|
42
|
-
import { a as promptProjectSetupAction, i as promptProjectSelection, r as promptAndCreateProject } from "./create-project-
|
|
43
|
-
import {
|
|
44
|
+
import { a as promptProjectSetupAction, i as promptProjectSelection, r as promptAndCreateProject } from "./create-project-DBfFSZKY.mjs";
|
|
45
|
+
import { t as getRequestedProjectSlug } from "./resolve-project-BG5ORGID.mjs";
|
|
44
46
|
import { t as collectGitDeployMetadata } from "./git-metadata-D-gurjzG.mjs";
|
|
45
|
-
import { t as promptForLoginToken } from "./login-
|
|
47
|
+
import { t as promptForLoginToken } from "./login-BQyISZuW.mjs";
|
|
46
48
|
import { createRequire } from "node:module";
|
|
47
|
-
import { copyFileSync, cpSync, createWriteStream, existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, unlinkSync, writeFileSync } from "node:fs";
|
|
49
|
+
import { copyFileSync, cpSync, createWriteStream, existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, readlinkSync, realpathSync, renameSync, rmSync, statSync, unlinkSync, writeFileSync } from "node:fs";
|
|
48
50
|
import { fileURLToPath } from "node:url";
|
|
49
51
|
import { createDeployArtifact, createDeployUploadPayload } from "@void/deploy-core";
|
|
52
|
+
import { build, parseSync } from "vite";
|
|
50
53
|
import { createHash, randomBytes } from "node:crypto";
|
|
51
54
|
import { homedir, tmpdir } from "node:os";
|
|
52
55
|
import { execFile, execSync, spawn, spawnSync } from "node:child_process";
|
|
53
56
|
import { applyEdits, modify, parse } from "jsonc-parser";
|
|
54
57
|
import { isDeepStrictEqual } from "node:util";
|
|
55
|
-
import { build } from "vite";
|
|
56
58
|
import { Minimatch } from "minimatch";
|
|
57
59
|
import { activateCloudflareVersion, assertCloudflareBindingsPreserved, assertCloudflareDurableObjectLifecycleSupported, assertExistingCloudflareConfig, encodeCloudflareVersionMessage, extractWorkersDevSubdomain, normalizeWorkersDevSubdomain, parseRootWranglerConfig, parseRootWranglerConfig as parseRootWranglerConfig$1, readBindingFieldPresence, readCloudflareTriggerConfig, readConfigEntryString, readExistingCloudflareWorker, readStoredResourceName, readWranglerTopLevelString, renderCloudflareStaticEntry, resolveD1MigrateTarget, stageCloudflareStaticAssets, writeCloudflareFrameworkDeployConfig, writeCloudflareStaticDeployConfig } from "@void/deploy-cloudflare";
|
|
58
60
|
import { getWorkerConfigPath, readBuildOutput } from "@cloudflare/build-output-utils";
|
|
@@ -1883,6 +1885,44 @@ function safePositional(value) {
|
|
|
1883
1885
|
return code < 32 || code === 127;
|
|
1884
1886
|
});
|
|
1885
1887
|
}
|
|
1888
|
+
/** Pin opaque secrets to the live version in the private, disposable Build Output. */
|
|
1889
|
+
async function pinActiveWorkerSecrets(options) {
|
|
1890
|
+
const { activeVersionId, bindings, requiredNames, explicitNames = [] } = options;
|
|
1891
|
+
if (!/^[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12}$/i.test(activeVersionId)) return false;
|
|
1892
|
+
const secretNames = new Set(bindings.map((binding) => binding.name));
|
|
1893
|
+
const explicit = new Set(explicitNames);
|
|
1894
|
+
if (bindings.some((binding) => !safePositional(binding.name)) || secretNames.size !== bindings.length) return false;
|
|
1895
|
+
if (requiredNames.some((name) => !secretNames.has(name) && !explicit.has(name))) return false;
|
|
1896
|
+
const path = getWorkerConfigPath(options.output.directory);
|
|
1897
|
+
const worker = parseJson(readFileSync(path, "utf8"));
|
|
1898
|
+
if (!record(worker) || worker.env !== void 0 && !record(worker.env)) return false;
|
|
1899
|
+
const env = { ...worker.env ?? {} };
|
|
1900
|
+
for (const name of explicit) delete env[name];
|
|
1901
|
+
for (const [name, value] of Object.entries(env)) if (record(value) && (value.type === "secret" || value.type === "inherit" || value.type === "unsafe:inherit") && !secretNames.has(name) && !explicit.has(name)) return false;
|
|
1902
|
+
for (const { name } of bindings) {
|
|
1903
|
+
if (explicit.has(name)) continue;
|
|
1904
|
+
const current = env[name];
|
|
1905
|
+
if (current !== void 0 && (!record(current) || current.type !== "secret" && current.type !== "inherit" && current.type !== "unsafe:inherit")) return false;
|
|
1906
|
+
env[name] = {
|
|
1907
|
+
type: "unsafe:inherit",
|
|
1908
|
+
version_id: activeVersionId
|
|
1909
|
+
};
|
|
1910
|
+
}
|
|
1911
|
+
const unsafe = record(worker.unsafe) ? { ...worker.unsafe } : {};
|
|
1912
|
+
const metadata = record(unsafe.metadata) ? { ...unsafe.metadata } : {};
|
|
1913
|
+
if (metadata.bindings !== void 0) return false;
|
|
1914
|
+
if (metadata.keep_bindings !== void 0 && (!Array.isArray(metadata.keep_bindings) || !metadata.keep_bindings.every((type) => typeof type === "string"))) return false;
|
|
1915
|
+
metadata.keep_bindings = (metadata.keep_bindings ?? []).filter((type) => type !== "secret_text" && type !== "secret_key");
|
|
1916
|
+
unsafe.metadata = metadata;
|
|
1917
|
+
const next = {
|
|
1918
|
+
...worker,
|
|
1919
|
+
env,
|
|
1920
|
+
unsafe
|
|
1921
|
+
};
|
|
1922
|
+
writeFileSync(path, JSON.stringify(next), { mode: 384 });
|
|
1923
|
+
await readBuildOutput(options.output.directory);
|
|
1924
|
+
return true;
|
|
1925
|
+
}
|
|
1886
1926
|
/** Prevent cf's prebuilt uploader from creating a resource as a side effect. */
|
|
1887
1927
|
function createCfResourceVerifier(options) {
|
|
1888
1928
|
return async (directory) => {
|
|
@@ -2275,6 +2315,48 @@ function createCfVersionRunner(options) {
|
|
|
2275
2315
|
};
|
|
2276
2316
|
}
|
|
2277
2317
|
//#endregion
|
|
2318
|
+
//#region src/cli/cloudflare-candidate.ts
|
|
2319
|
+
const CANDIDATE_FILE = ".void/cloudflare-candidate.json";
|
|
2320
|
+
/** A failed normal deploy keeps its locally verified upload chain across retries. */
|
|
2321
|
+
function readCloudflareCandidate(root) {
|
|
2322
|
+
const path = join(root, CANDIDATE_FILE);
|
|
2323
|
+
if (!existsSync(path)) return null;
|
|
2324
|
+
let value;
|
|
2325
|
+
try {
|
|
2326
|
+
value = JSON.parse(readFileSync(path, "utf8"));
|
|
2327
|
+
} catch {
|
|
2328
|
+
throw new Error("The saved Cloudflare candidate receipt is invalid. Restore or remove .void/cloudflare-candidate.json before retrying.");
|
|
2329
|
+
}
|
|
2330
|
+
if (typeof value !== "object" || value === null || Array.isArray(value) || !("accountId" in value) || typeof value.accountId !== "string" || !value.accountId || !("workerName" in value) || typeof value.workerName !== "string" || !value.workerName || !("parentVersionId" in value) || typeof value.parentVersionId !== "string" || !value.parentVersionId || !("versionIds" in value) || !Array.isArray(value.versionIds) || !value.versionIds.length || !value.versionIds.every((id) => typeof id === "string" && id.length > 0) || new Set(value.versionIds).size !== value.versionIds.length) throw new Error("The saved Cloudflare candidate receipt is invalid. Restore or remove .void/cloudflare-candidate.json before retrying.");
|
|
2331
|
+
return value;
|
|
2332
|
+
}
|
|
2333
|
+
function assertCloudflareCandidateUnchanged(root, expected) {
|
|
2334
|
+
if (JSON.stringify(readCloudflareCandidate(root)) !== JSON.stringify(expected)) throw new Error("The Cloudflare candidate receipt changed while project code was running. Retry from a trusted checkout.");
|
|
2335
|
+
}
|
|
2336
|
+
function recordCloudflareCandidateUpload(root, expected, accountId, workerName, parentVersionId, versionId) {
|
|
2337
|
+
assertCloudflareCandidateUnchanged(root, expected);
|
|
2338
|
+
if (expected && (expected.accountId !== accountId || expected.workerName !== workerName || expected.parentVersionId !== parentVersionId)) throw new Error("The saved Cloudflare candidate belongs to a different Worker or live version. Inspect the deployment before retrying.");
|
|
2339
|
+
const versionIds = [...expected?.versionIds ?? [], versionId];
|
|
2340
|
+
mkdirSync(join(root, ".void"), { recursive: true });
|
|
2341
|
+
const path = join(root, CANDIDATE_FILE);
|
|
2342
|
+
const temp = `${path}.${process.pid}.tmp`;
|
|
2343
|
+
try {
|
|
2344
|
+
writeFileSync(temp, `${JSON.stringify({
|
|
2345
|
+
accountId,
|
|
2346
|
+
workerName,
|
|
2347
|
+
parentVersionId,
|
|
2348
|
+
versionIds
|
|
2349
|
+
})}\n`, { mode: 384 });
|
|
2350
|
+
renameSync(temp, path);
|
|
2351
|
+
} finally {
|
|
2352
|
+
if (existsSync(temp)) unlinkSync(temp);
|
|
2353
|
+
}
|
|
2354
|
+
}
|
|
2355
|
+
function clearCloudflareCandidate(root) {
|
|
2356
|
+
const path = join(root, CANDIDATE_FILE);
|
|
2357
|
+
if (existsSync(path)) unlinkSync(path);
|
|
2358
|
+
}
|
|
2359
|
+
//#endregion
|
|
2278
2360
|
//#region src/cli/cloudflare-deploy/classify.ts
|
|
2279
2361
|
/**
|
|
2280
2362
|
* Narrow native Cloudflare deploys to app shapes whose emitted Worker artifact
|
|
@@ -3837,6 +3919,69 @@ function __resolveQueueIndex(queueName) {
|
|
|
3837
3919
|
}`;
|
|
3838
3920
|
}
|
|
3839
3921
|
//#endregion
|
|
3922
|
+
//#region src/cli/pg-bundle-transform.ts
|
|
3923
|
+
function nodes(root) {
|
|
3924
|
+
const found = [];
|
|
3925
|
+
const pending = [root];
|
|
3926
|
+
while (pending.length > 0) {
|
|
3927
|
+
const node = pending.pop();
|
|
3928
|
+
found.push(node);
|
|
3929
|
+
for (const value of Object.values(node)) if (Array.isArray(value)) {
|
|
3930
|
+
for (const child of value) if (child && typeof child === "object" && typeof child.type === "string") pending.push(child);
|
|
3931
|
+
} else if (value && typeof value === "object" && typeof value.type === "string") pending.push(value);
|
|
3932
|
+
}
|
|
3933
|
+
return found;
|
|
3934
|
+
}
|
|
3935
|
+
/** Rewrite the two CommonJS constructs emitted by the PG migration bundle. */
|
|
3936
|
+
function transformPgWorkerBundle(code, filename, requireShim) {
|
|
3937
|
+
if (!code.includes("createRequire") && !code.includes("pgpass")) return code;
|
|
3938
|
+
const program = parseSync(filename, code).program;
|
|
3939
|
+
const edits = [];
|
|
3940
|
+
let hasRequireBinding = false;
|
|
3941
|
+
let pgpassCalls = 0;
|
|
3942
|
+
for (const statement of program.body ?? []) {
|
|
3943
|
+
if (statement.type === "ImportDeclaration" && statement.source?.value === "node:module") {
|
|
3944
|
+
const specifiers = statement.specifiers;
|
|
3945
|
+
if (specifiers?.length !== 1 || !isIdentifier(specifiers[0]?.imported) || specifiers[0].imported.name !== "createRequire") throw new Error(`deploy: Unsupported node:module import in PostgreSQL bundle ${filename}.`);
|
|
3946
|
+
edits.push({
|
|
3947
|
+
start: statement.start,
|
|
3948
|
+
end: statement.end,
|
|
3949
|
+
replacement: ""
|
|
3950
|
+
});
|
|
3951
|
+
}
|
|
3952
|
+
if (statement.type === "VariableDeclaration") {
|
|
3953
|
+
const declarations = statement.declarations;
|
|
3954
|
+
if (declarations?.some((declaration) => isIdentifier(declaration.id) && declaration.id.name === "__require")) {
|
|
3955
|
+
if (declarations.length !== 1 || hasRequireBinding) throw new Error(`deploy: Unsupported require binding in PostgreSQL bundle ${filename}.`);
|
|
3956
|
+
hasRequireBinding = true;
|
|
3957
|
+
edits.push({
|
|
3958
|
+
start: statement.start,
|
|
3959
|
+
end: statement.end,
|
|
3960
|
+
replacement: requireShim
|
|
3961
|
+
});
|
|
3962
|
+
}
|
|
3963
|
+
}
|
|
3964
|
+
}
|
|
3965
|
+
for (const node of nodes(program)) {
|
|
3966
|
+
if (node.type !== "CallExpression" || !isIdentifier(node.callee) || node.callee.name !== "__require") continue;
|
|
3967
|
+
const args = node.arguments;
|
|
3968
|
+
if (args?.length !== 1 || !isLiteral(args[0]) || args[0].value !== "pgpass") continue;
|
|
3969
|
+
pgpassCalls++;
|
|
3970
|
+
edits.push({
|
|
3971
|
+
start: node.start,
|
|
3972
|
+
end: node.end,
|
|
3973
|
+
replacement: "__voidPgpassNoop"
|
|
3974
|
+
});
|
|
3975
|
+
}
|
|
3976
|
+
if (code.includes("createRequire") && !hasRequireBinding) throw new Error(`deploy: Could not locate the generated require binding in PostgreSQL bundle ${filename}.`);
|
|
3977
|
+
if (code.includes("pgpass") && pgpassCalls === 0 && code.includes("__require")) throw new Error(`deploy: Could not locate the pgpass require in PostgreSQL bundle ${filename}.`);
|
|
3978
|
+
const ms = new MagicString(code);
|
|
3979
|
+
for (const edit of edits.sort((a, b) => b.start - a.start)) ms.overwrite(edit.start, edit.end, edit.replacement);
|
|
3980
|
+
const transformed = ms.toString();
|
|
3981
|
+
if (transformed.includes("createRequire") || transformed.includes("__require(\"pgpass\")")) throw new Error(`deploy: PostgreSQL bundle ${filename} still contains an unsupported require.`);
|
|
3982
|
+
return pgpassCalls > 0 ? `const __voidPgpassNoop = Object.assign(function pgpass(_connectionInfo, callback) { callback(undefined); }, { warnTo() {} });\n${transformed}` : transformed;
|
|
3983
|
+
}
|
|
3984
|
+
//#endregion
|
|
3840
3985
|
//#region src/cli/wrapper.ts
|
|
3841
3986
|
const BUNDLED_ENTRY_RE = /^index\.(?:m?js|cjs)$/;
|
|
3842
3987
|
const WRAPPER_MARKER = "// Generated by Void: deployment wrapper.";
|
|
@@ -3904,7 +4049,7 @@ async function generateWrapper(workerDir, workerMain, root, features) {
|
|
|
3904
4049
|
let migrations;
|
|
3905
4050
|
let migrationPlanBundle;
|
|
3906
4051
|
if (features.hasMigrations) {
|
|
3907
|
-
const { collectMigrations } = await import("./collect-
|
|
4052
|
+
const { collectMigrations } = await import("./collect-DLyFDiKW.mjs");
|
|
3908
4053
|
const { buildMigrationPlanBundle } = await import("./plan-DpuOr14e.mjs");
|
|
3909
4054
|
const migrationsDir = readProjectPaths(root).migrationsDir;
|
|
3910
4055
|
migrations = collectMigrations(migrationsDir);
|
|
@@ -4017,11 +4162,9 @@ function patchPgWorkerBundle(outDir) {
|
|
|
4017
4162
|
for (const file of readdirSync(outDir)) {
|
|
4018
4163
|
if (!file.endsWith(".mjs") && !file.endsWith(".js")) continue;
|
|
4019
4164
|
const path = join(outDir, file);
|
|
4020
|
-
|
|
4021
|
-
|
|
4022
|
-
|
|
4023
|
-
code = `const __voidPgpassNoop = Object.assign(function pgpass(_connectionInfo, callback) { callback(undefined); }, { warnTo() {} });\n` + code;
|
|
4024
|
-
writeFileSync(path, code);
|
|
4165
|
+
const code = readFileSync(path, "utf-8");
|
|
4166
|
+
const transformed = transformPgWorkerBundle(code, file, pgWorkerRequireShim());
|
|
4167
|
+
if (transformed !== code) writeFileSync(path, transformed);
|
|
4025
4168
|
}
|
|
4026
4169
|
}
|
|
4027
4170
|
function createPgPackageRequire(fromPath) {
|
|
@@ -4318,7 +4461,7 @@ let loadedProvisionModule;
|
|
|
4318
4461
|
* so a managed deploy never imports it — and thus never loads `proper-lockfile`.
|
|
4319
4462
|
*/
|
|
4320
4463
|
async function loadProvisionModule() {
|
|
4321
|
-
loadedProvisionModule ??= await import("./provision-
|
|
4464
|
+
loadedProvisionModule ??= await import("./provision-DNtrtaVD.mjs");
|
|
4322
4465
|
return loadedProvisionModule;
|
|
4323
4466
|
}
|
|
4324
4467
|
/**
|
|
@@ -4884,6 +5027,47 @@ function reconstructExpectedContainers(config, root, rootConfig, needsSandbox) {
|
|
|
4884
5027
|
}
|
|
4885
5028
|
return expected;
|
|
4886
5029
|
}
|
|
5030
|
+
/** Reconstruct the Durable Object state emitted after the pre-build root config is synced. */
|
|
5031
|
+
function reconstructExpectedDurableObjectState(config, root, rootConfig, options) {
|
|
5032
|
+
const bindings = bindingEntriesForField("durable_objects", rootConfig.durable_objects).map(({ entry }) => entry);
|
|
5033
|
+
const migrations = Array.isArray(rootConfig.migrations) ? [...rootConfig.migrations] : [];
|
|
5034
|
+
const sandbox = options.needsSandbox ? resolveSandboxConfig(config, root) : void 0;
|
|
5035
|
+
if (sandbox) {
|
|
5036
|
+
if (!bindings.some((binding) => binding.name === sandbox.binding)) bindings.push({
|
|
5037
|
+
name: sandbox.binding,
|
|
5038
|
+
class_name: sandbox.className
|
|
5039
|
+
});
|
|
5040
|
+
if (!migrations.some((migration) => migration.tag === "void-sandbox-v1" || Array.isArray(migration.new_sqlite_classes) && migration.new_sqlite_classes.includes(sandbox.className))) migrations.push({
|
|
5041
|
+
tag: SANDBOX_MIGRATION_TAG,
|
|
5042
|
+
new_sqlite_classes: [sandbox.className]
|
|
5043
|
+
});
|
|
5044
|
+
}
|
|
5045
|
+
const paths = resolveProjectPaths(root, config);
|
|
5046
|
+
const websocketRoutes = scanWebSocketRoutesSync(root, paths);
|
|
5047
|
+
const durableObjects = scanDurableObjectModules(root);
|
|
5048
|
+
const live = options.needsLive ? resolveLiveBindingConfig(root, {
|
|
5049
|
+
reservedBindings: [...websocketRoutes.map((route) => route.bindingName), ...durableObjects.map((module) => module.bindingName)],
|
|
5050
|
+
reservedClasses: [
|
|
5051
|
+
...websocketRoutes.map((route) => route.className),
|
|
5052
|
+
...durableObjects.map((module) => module.className),
|
|
5053
|
+
sandbox?.className
|
|
5054
|
+
]
|
|
5055
|
+
}) : readExistingLiveBindingConfig(root);
|
|
5056
|
+
if (live) {
|
|
5057
|
+
if (!bindings.some((binding) => binding.name === live.bindingName)) bindings.push({
|
|
5058
|
+
name: live.bindingName,
|
|
5059
|
+
class_name: live.className
|
|
5060
|
+
});
|
|
5061
|
+
if (!hasDurableObjectSqliteMigration(migrations, live.className)) migrations.push({
|
|
5062
|
+
tag: nextDurableObjectMigrationTag(migrations, LIVE_MIGRATION_TAG),
|
|
5063
|
+
new_sqlite_classes: [live.className]
|
|
5064
|
+
});
|
|
5065
|
+
}
|
|
5066
|
+
return {
|
|
5067
|
+
bindings,
|
|
5068
|
+
migrations
|
|
5069
|
+
};
|
|
5070
|
+
}
|
|
4887
5071
|
/**
|
|
4888
5072
|
* Deterministic sha256 over the wrangler uploader BUNDLE the credentialed deploy executes — the
|
|
4889
5073
|
* resolved `wrangler-dist/cli.js` PLUS every sibling file in its directory. `cli.js` loads sibling
|
|
@@ -4941,17 +5125,39 @@ function hashCfUploader() {
|
|
|
4941
5125
|
function hashDirectoryContents(dir) {
|
|
4942
5126
|
try {
|
|
4943
5127
|
const hash = createHash("sha256");
|
|
5128
|
+
const visiting = /* @__PURE__ */ new Set();
|
|
4944
5129
|
const walk = (rel) => {
|
|
4945
|
-
const
|
|
4946
|
-
|
|
4947
|
-
|
|
4948
|
-
|
|
4949
|
-
|
|
5130
|
+
const real = realpathSync(join(dir, rel));
|
|
5131
|
+
if (visiting.has(real)) throw new Error(`Cyclic symlink in uploader: ${rel}`);
|
|
5132
|
+
visiting.add(real);
|
|
5133
|
+
try {
|
|
5134
|
+
const entries = readdirSync(join(dir, rel), { withFileTypes: true }).sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0);
|
|
5135
|
+
for (const entry of entries) {
|
|
5136
|
+
const childRel = rel ? `${rel}/${entry.name}` : entry.name;
|
|
5137
|
+
const childPath = join(dir, childRel);
|
|
5138
|
+
if (entry.isDirectory()) {
|
|
5139
|
+
walk(childRel);
|
|
5140
|
+
continue;
|
|
5141
|
+
}
|
|
4950
5142
|
hash.update(childRel);
|
|
4951
5143
|
hash.update("\0");
|
|
4952
|
-
|
|
5144
|
+
if (entry.isSymbolicLink()) {
|
|
5145
|
+
hash.update(readlinkSync(childPath));
|
|
5146
|
+
hash.update("\0");
|
|
5147
|
+
try {
|
|
5148
|
+
const target = statSync(childPath);
|
|
5149
|
+
if (target.isDirectory()) walk(childRel);
|
|
5150
|
+
else if (target.isFile()) hash.update(readFileSync(childPath));
|
|
5151
|
+
else throw new Error(`Unsupported uploader symlink target: ${childRel}`);
|
|
5152
|
+
} catch (error) {
|
|
5153
|
+
if (error.code !== "ENOENT") throw error;
|
|
5154
|
+
hash.update("missing");
|
|
5155
|
+
}
|
|
5156
|
+
} else hash.update(readFileSync(childPath));
|
|
4953
5157
|
hash.update("\0");
|
|
4954
5158
|
}
|
|
5159
|
+
} finally {
|
|
5160
|
+
visiting.delete(real);
|
|
4955
5161
|
}
|
|
4956
5162
|
};
|
|
4957
5163
|
walk("");
|
|
@@ -5452,6 +5658,32 @@ function verifyGeneratedDeployConfig(root, expected) {
|
|
|
5452
5658
|
const destructiveMigration = verifyNoInjectedDestructiveMigration(generated.migrations, raw.get("migrations"));
|
|
5453
5659
|
if (!destructiveMigration.ok) return destructiveMigration;
|
|
5454
5660
|
}
|
|
5661
|
+
if (expected.expectedDurableObjectBindings) {
|
|
5662
|
+
let emittedBindings;
|
|
5663
|
+
try {
|
|
5664
|
+
emittedBindings = bindingEntriesForField("durable_objects", generated.durable_objects).map(({ entry }) => entry);
|
|
5665
|
+
} catch {
|
|
5666
|
+
return {
|
|
5667
|
+
ok: false,
|
|
5668
|
+
reason: "generated config durable_objects bindings could not be verified."
|
|
5669
|
+
};
|
|
5670
|
+
}
|
|
5671
|
+
const byName = (left, right) => String(left.name).localeCompare(String(right.name));
|
|
5672
|
+
if (!deepEqual([...emittedBindings].sort(byName), [...expected.expectedDurableObjectBindings].sort(byName))) return {
|
|
5673
|
+
ok: false,
|
|
5674
|
+
reason: "generated config durable_objects bindings differ from the pre-build binding set — refusing to deploy a binding the build added, removed, or retargeted."
|
|
5675
|
+
};
|
|
5676
|
+
}
|
|
5677
|
+
if (expected.expectedMigrations) {
|
|
5678
|
+
if (generated.migrations !== void 0 && !Array.isArray(generated.migrations)) return {
|
|
5679
|
+
ok: false,
|
|
5680
|
+
reason: "generated config migrations could not be verified."
|
|
5681
|
+
};
|
|
5682
|
+
if (!deepEqual(Array.isArray(generated.migrations) ? generated.migrations : [], expected.expectedMigrations)) return {
|
|
5683
|
+
ok: false,
|
|
5684
|
+
reason: "generated config migrations differ from the pre-build migration sequence — refusing to deploy a migration the build added, removed, or retargeted."
|
|
5685
|
+
};
|
|
5686
|
+
}
|
|
5455
5687
|
if (expected.expectedContainers) {
|
|
5456
5688
|
const emittedContainers = Array.isArray(generated.containers) ? generated.containers : [];
|
|
5457
5689
|
const expectedContainers = expected.expectedContainers;
|
|
@@ -5695,7 +5927,8 @@ async function computeDesiredCloudflareResources(root, voidConfig, configPath) {
|
|
|
5695
5927
|
const inferenceOptions = voidConfig.inference?.bindings ? { bindings: voidConfig.inference.bindings } : void 0;
|
|
5696
5928
|
const bindings = inferProjectBindings(root, {
|
|
5697
5929
|
...inferenceOptions,
|
|
5698
|
-
paths
|
|
5930
|
+
paths,
|
|
5931
|
+
environment: "prod"
|
|
5699
5932
|
}, scanDirs);
|
|
5700
5933
|
const authEnabled = bindings.needsAuth || findVoidAuthConfig(root, paths) !== null || voidConfig.auth !== void 0;
|
|
5701
5934
|
const dialect = getDatabaseDialect(voidConfig);
|
|
@@ -5714,9 +5947,10 @@ async function computeDesiredCloudflareResources(root, voidConfig, configPath) {
|
|
|
5714
5947
|
const binding = bindingNames?.d1 ?? "DB";
|
|
5715
5948
|
const storedName = readStoredResourceName(config, "d1_databases", binding, "database_name");
|
|
5716
5949
|
const storedId = readStoredResourceName(config, "d1_databases", binding, "database_id");
|
|
5950
|
+
const authoredName = voidConfig.cloudflare?.d1_databases?.find((entry) => entry.binding === binding)?.database_name;
|
|
5717
5951
|
desired.d1 = {
|
|
5718
5952
|
binding,
|
|
5719
|
-
name: storedName != null && isRealD1Id(storedId) ? storedName : suffixedResourceName(workerName, "db"),
|
|
5953
|
+
name: storedName != null && isRealD1Id(storedId) ? storedName : authoredName?.trim() || (basename(configPath) !== ".void-wrangler.jsonc" && storedName !== "default" ? storedName : void 0) || suffixedResourceName(workerName, "db"),
|
|
5720
5954
|
migrationsDir: migrationsDirRelative
|
|
5721
5955
|
};
|
|
5722
5956
|
reasons.set(binding, databaseReason);
|
|
@@ -5732,9 +5966,10 @@ async function computeDesiredCloudflareResources(root, voidConfig, configPath) {
|
|
|
5732
5966
|
if (bindings.needsR2) {
|
|
5733
5967
|
const binding = bindingNames?.r2 ?? "STORAGE";
|
|
5734
5968
|
const storedName = readStoredResourceName(config, "r2_buckets", binding, "bucket_name");
|
|
5969
|
+
const generatedDefault = storedName === "default" && basename(configPath) === ".void-wrangler.jsonc" && !voidConfig.cloudflare?.r2_buckets?.some((entry) => entry.binding === binding && entry.bucket_name === "default");
|
|
5735
5970
|
desired.r2 = {
|
|
5736
5971
|
binding,
|
|
5737
|
-
bucketName: storedName &&
|
|
5972
|
+
bucketName: storedName && !generatedDefault ? storedName : suffixedResourceName(workerName, "storage")
|
|
5738
5973
|
};
|
|
5739
5974
|
reasons.set(binding, "app uses env.STORAGE (R2)");
|
|
5740
5975
|
}
|
|
@@ -5774,7 +6009,8 @@ async function computeDesiredCloudflareResources(root, voidConfig, configPath) {
|
|
|
5774
6009
|
expectedCrons,
|
|
5775
6010
|
needsEmail: bindings.needsEmail === true || hasEmailHandlers(emailHandlers),
|
|
5776
6011
|
emailHandlers,
|
|
5777
|
-
needsSandbox: isSandboxEnabled(voidConfig) || bindings.needsSandbox
|
|
6012
|
+
needsSandbox: isSandboxEnabled(voidConfig) || bindings.needsSandbox,
|
|
6013
|
+
needsLive: bindings.needsLive === true
|
|
5778
6014
|
};
|
|
5779
6015
|
}
|
|
5780
6016
|
/**
|
|
@@ -6481,56 +6717,8 @@ async function ensureCloudflareAuthSecret(options) {
|
|
|
6481
6717
|
...workerWasMissing ? { workerWasMissing: true } : {}
|
|
6482
6718
|
};
|
|
6483
6719
|
}
|
|
6484
|
-
/**
|
|
6485
|
-
|
|
6486
|
-
*
|
|
6487
|
-
* Orchestrates the existing units — it does NOT re-implement provisioning
|
|
6488
|
-
* (`cli/provision.ts`), the config writer (`cli/wrangler.ts`), or the self-host
|
|
6489
|
-
* secret preflight (`cli/env-validation.ts`). Flow:
|
|
6490
|
-
*
|
|
6491
|
-
* app-class guard → desired set (from source, pre-build) → preflight (auth +
|
|
6492
|
-
* account pin) → automatically ensure resources → ensure worker name →
|
|
6493
|
-
* remote D1 migrate → secrets (warn + gate) → clean-env build → wrangler deploy
|
|
6494
|
-
*
|
|
6495
|
-
* ORDERING DECISION (documented): the secrets GATE runs AFTER provision + remote
|
|
6496
|
-
* migrations resolve but BEFORE build + deploy — the brief's recommended default.
|
|
6497
|
-
* Provision and D1 migrations are idempotent (read-first / tracked in wrangler's
|
|
6498
|
-
* `d1_migrations` table), so re-running them after a gate failure is safe, while
|
|
6499
|
-
* build + `wrangler deploy` (the non-idempotent worker upload) is what the gate
|
|
6500
|
-
* protects. The warning is emitted first (non-fatal); a first-deploy secret-list
|
|
6501
|
-
* failure (worker not yet created) renders actionable `wrangler secret put`
|
|
6502
|
-
* bootstrap guidance rather than dead-ending.
|
|
6503
|
-
*
|
|
6504
|
-
* Every wrangler / provisioner / secret-unit call is an injected seam
|
|
6505
|
-
* ({@link CloudflareDeployDeps}) so the whole orchestration is unit-testable with
|
|
6506
|
-
* no real wrangler, network, or Cloudflare account.
|
|
6507
|
-
*/
|
|
6508
|
-
async function runCloudflareDeploy(root, options, cliLog, deps = {}) {
|
|
6509
|
-
const initialCloudflareLink = readCloudflareLink(root);
|
|
6510
|
-
const exit = deps.exit ?? ((code) => process.exit(code));
|
|
6511
|
-
const voidConfig = readConfig(root);
|
|
6512
|
-
const detectedFramework = detectFramework(root);
|
|
6513
|
-
const frameworkPreset = detectedFramework ? FRAMEWORK_PRESETS[detectedFramework.name] : void 0;
|
|
6514
|
-
cliLog.info("cloudflare_deploy_start", { provision: options.provision === true ? true : void 0 });
|
|
6515
|
-
if (isNodeTarget(voidConfig.target)) {
|
|
6516
|
-
log.error([
|
|
6517
|
-
`deploy: --platform cloudflare is not supported for the "${voidConfig.target}" target.`,
|
|
6518
|
-
"This backend deploys Cloudflare Workers only. Deploy a node/bun/deno build with its",
|
|
6519
|
-
"own host/runtime, or use the default Cloudflare target for --platform cloudflare."
|
|
6520
|
-
].join("\n"));
|
|
6521
|
-
return exit(1);
|
|
6522
|
-
}
|
|
6523
|
-
if (detectedFramework?.class === "a" && hasConfiguredVoidWorkerRoutingRules(voidConfig.routing)) {
|
|
6524
|
-
log.error([
|
|
6525
|
-
`deploy: native Cloudflare deployment cannot apply Void routing redirects, rewrites, fallbacks, or headers to ${detectedFramework.name}.`,
|
|
6526
|
-
"This framework owns its Worker request handler, so these rules would otherwise be ignored.",
|
|
6527
|
-
"Move the rules into the framework or its Cloudflare Worker, then retry."
|
|
6528
|
-
].join("\n"));
|
|
6529
|
-
return exit(1);
|
|
6530
|
-
}
|
|
6531
|
-
const provisionModule = await loadProvisionModule();
|
|
6532
|
-
const staticPreset = resolveCloudflareStaticPreset(root, voidConfig, options) ?? await resolveCloudflareVoidStaticPreset(root, voidConfig);
|
|
6533
|
-
if (staticPreset) return runCloudflareStaticDeploy(root, options, voidConfig, staticPreset, cliLog, deps, initialCloudflareLink);
|
|
6720
|
+
/** Validate source-level native deploy inputs before account operations or project code. */
|
|
6721
|
+
async function prepareCloudflareDeploySource(root, options, voidConfig) {
|
|
6534
6722
|
if (options.skipBuild) {
|
|
6535
6723
|
log.error([
|
|
6536
6724
|
"deploy: --skip-build is not supported with --platform cloudflare.",
|
|
@@ -6540,15 +6728,16 @@ async function runCloudflareDeploy(root, options, cliLog, deps = {}) {
|
|
|
6540
6728
|
"are about to upload. Drop --skip-build, or deploy with `void deploy` (the managed",
|
|
6541
6729
|
"platform), which supports it."
|
|
6542
6730
|
].join("\n"));
|
|
6543
|
-
return
|
|
6731
|
+
return null;
|
|
6544
6732
|
}
|
|
6545
6733
|
const classification = classifyCloudflareDeployApp(root, voidConfig, options);
|
|
6546
6734
|
if (!classification.supported) {
|
|
6547
6735
|
log.error(classification.reason);
|
|
6548
|
-
return
|
|
6736
|
+
return null;
|
|
6549
6737
|
}
|
|
6550
6738
|
const configPath = discoverRootWranglerConfig(root);
|
|
6551
|
-
const
|
|
6739
|
+
const facts = await computeDesiredCloudflareResources(root, voidConfig, configPath);
|
|
6740
|
+
const { desired, dialect, migrations: preBuildMigrations, migrationsDir } = facts;
|
|
6552
6741
|
if (dialect !== "sqlite" && preBuildMigrations.length > 0 && !process.env.DATABASE_URL) {
|
|
6553
6742
|
log.error([
|
|
6554
6743
|
`deploy: ${dialect === "mysql" ? "MySQL" : "PostgreSQL"} migrations require DATABASE_URL for --platform cloudflare.`,
|
|
@@ -6556,15 +6745,204 @@ async function runCloudflareDeploy(root, options, cliLog, deps = {}) {
|
|
|
6556
6745
|
"provision Hyperdrive and apply checked-in migrations before uploading the Worker; it is",
|
|
6557
6746
|
"never written to wrangler.jsonc or the generated Worker config."
|
|
6558
6747
|
].join("\n"));
|
|
6559
|
-
return
|
|
6748
|
+
return null;
|
|
6560
6749
|
}
|
|
6561
6750
|
if (desired.d1) {
|
|
6562
6751
|
const migrationsPattern = resolveWranglerMigrationPattern(parseRootWranglerConfig(configPath), desired.d1.binding, desired.d1.migrationsDir ?? relative(dirname(configPath), migrationsDir));
|
|
6563
6752
|
if (!migrationsPattern.ok) {
|
|
6564
6753
|
log.error(migrationsPattern.reason);
|
|
6754
|
+
return null;
|
|
6755
|
+
}
|
|
6756
|
+
}
|
|
6757
|
+
return {
|
|
6758
|
+
configPath,
|
|
6759
|
+
...facts
|
|
6760
|
+
};
|
|
6761
|
+
}
|
|
6762
|
+
/** Apply remote D1 changes and prove no migrations remain pending. */
|
|
6763
|
+
async function applyAndVerifyRemoteD1Migrations(d1MigrateToken, configPath, runWrangler, assertUploaderStillPinned) {
|
|
6764
|
+
if (d1MigrateToken) {
|
|
6765
|
+
log.step("Applying D1 migrations...");
|
|
6766
|
+
if (!assertUploaderStillPinned()) return false;
|
|
6767
|
+
const migrate = await Promise.resolve(runWrangler([
|
|
6768
|
+
"d1",
|
|
6769
|
+
"migrations",
|
|
6770
|
+
"apply",
|
|
6771
|
+
d1MigrateToken,
|
|
6772
|
+
"--remote",
|
|
6773
|
+
"-c",
|
|
6774
|
+
configPath,
|
|
6775
|
+
"--env="
|
|
6776
|
+
], { capture: false }));
|
|
6777
|
+
if (!isCleanWranglerExit(migrate)) {
|
|
6778
|
+
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.`);
|
|
6779
|
+
return false;
|
|
6780
|
+
}
|
|
6781
|
+
if (!assertUploaderStillPinned()) return false;
|
|
6782
|
+
const migrateList = await Promise.resolve(runWrangler([
|
|
6783
|
+
"d1",
|
|
6784
|
+
"migrations",
|
|
6785
|
+
"list",
|
|
6786
|
+
d1MigrateToken,
|
|
6787
|
+
"--remote",
|
|
6788
|
+
"-c",
|
|
6789
|
+
configPath,
|
|
6790
|
+
"--env="
|
|
6791
|
+
], { capture: true }));
|
|
6792
|
+
if (!isCleanWranglerExit(migrateList)) {
|
|
6793
|
+
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.`);
|
|
6794
|
+
return false;
|
|
6795
|
+
}
|
|
6796
|
+
if (migrateList.stdout.includes("Migrations to be applied:")) {
|
|
6797
|
+
log.error([
|
|
6798
|
+
`deploy: remote D1 still has UNAPPLIED migrations for "${d1MigrateToken}" after apply.`,
|
|
6799
|
+
"`wrangler d1 migrations apply` exits 0 even when its confirmation is declined, so",
|
|
6800
|
+
"the schema may be un-migrated while the code that needs it is about to deploy.",
|
|
6801
|
+
"Re-run and confirm the migration (or apply it non-interactively), then rerun."
|
|
6802
|
+
].join("\n"));
|
|
6803
|
+
return false;
|
|
6804
|
+
}
|
|
6805
|
+
if (!migrateList.stdout.includes("No migrations to apply!")) {
|
|
6806
|
+
log.error([
|
|
6807
|
+
`deploy: could not confirm the remote migration state for "${d1MigrateToken}".`,
|
|
6808
|
+
"`wrangler d1 migrations list` printed neither the \"no migrations to apply\" nor the",
|
|
6809
|
+
"\"migrations to be applied\" marker (WRANGLER_LOG is pinned so they are never",
|
|
6810
|
+
"suppressed) — refusing to deploy against an unverified schema. Rerun once wrangler",
|
|
6811
|
+
"can reach your account."
|
|
6812
|
+
].join("\n"));
|
|
6813
|
+
return false;
|
|
6814
|
+
}
|
|
6815
|
+
}
|
|
6816
|
+
return true;
|
|
6817
|
+
}
|
|
6818
|
+
/** Check the built Worker against the pinned deployment target before upload. */
|
|
6819
|
+
function verifyCloudflareDeployArtifact(root, deps, options) {
|
|
6820
|
+
const verification = (deps.verifyDeployConfig ?? verifyGeneratedDeployConfig)(root, options);
|
|
6821
|
+
if (!verification.ok) {
|
|
6822
|
+
log.error([
|
|
6823
|
+
"deploy: the generated deploy config does not match the pinned target — refusing to deploy.",
|
|
6824
|
+
verification.reason,
|
|
6825
|
+
"This typically means CLOUDFLARE_ENV / CLOUDFLARE_VITE_WRANGLER_CONFIG_PATH (in the",
|
|
6826
|
+
"environment or a production `.env`) selected a different named environment or config",
|
|
6827
|
+
"at build time. This backend always deploys the canonical top-level config — remove",
|
|
6828
|
+
"them and rebuild."
|
|
6829
|
+
].filter(Boolean).join("\n"));
|
|
6830
|
+
return false;
|
|
6831
|
+
}
|
|
6832
|
+
return true;
|
|
6833
|
+
}
|
|
6834
|
+
/** Validate emitted Worker vars and required secrets against post-build ground truth. */
|
|
6835
|
+
async function validateCloudflarePostBuildEnv(root, configPath, accountId, apiBaseUrl, workerName, schemaFacts, authEnabled, existingWorker, approvedHandoffKv, deps, assertUploaderStillPinned) {
|
|
6836
|
+
const emitted = (deps.readEmittedWorkerVars ?? readEmittedWorkerVarsDefault)(root);
|
|
6837
|
+
if (existingWorker) {
|
|
6838
|
+
const generated = readGeneratedDeployConfig(root);
|
|
6839
|
+
assertExistingCloudflareConfig(existingWorker, generated.config, true, approvedHandoffKv);
|
|
6840
|
+
}
|
|
6841
|
+
if (!emitted.ok) {
|
|
6842
|
+
log.error([
|
|
6843
|
+
"deploy: could not read the worker vars the build emitted — refusing to validate secrets.",
|
|
6844
|
+
` ${emitted.reason}`,
|
|
6845
|
+
"The build must emit dist/ssr/wrangler.json for this backend. Rerun the build, or deploy",
|
|
6846
|
+
"this app with `void deploy` (the managed platform)."
|
|
6847
|
+
].join("\n"));
|
|
6848
|
+
return false;
|
|
6849
|
+
}
|
|
6850
|
+
const emittedVars = emitted.vars;
|
|
6851
|
+
if (authEnabled && Object.prototype.hasOwnProperty.call(emittedVars, BETTER_AUTH_SECRET_NAME)) {
|
|
6852
|
+
log.error([
|
|
6853
|
+
`deploy: ${BETTER_AUTH_SECRET_NAME} must be stored as a Cloudflare Worker secret, not a plaintext worker var.`,
|
|
6854
|
+
"Remove it from Worker vars and rerun. This deploy command preserves an",
|
|
6855
|
+
"existing remote value or creates a persistent one automatically when it is missing."
|
|
6856
|
+
].join("\n"));
|
|
6857
|
+
return false;
|
|
6858
|
+
}
|
|
6859
|
+
const plaintextServerKeys = schemaFacts.serverKeys.filter((key) => key in emittedVars);
|
|
6860
|
+
if (plaintextServerKeys.length > 0) {
|
|
6861
|
+
log.error([
|
|
6862
|
+
"deploy: server env keys cannot ship as plaintext Worker vars:",
|
|
6863
|
+
...plaintextServerKeys.map((key) => ` • ${key}`),
|
|
6864
|
+
"Remove them from Worker vars and set them with `void secret put <NAME>`."
|
|
6865
|
+
].join("\n"));
|
|
6866
|
+
return false;
|
|
6867
|
+
}
|
|
6868
|
+
const envContext = deriveSelfHostEnvContextFromVars(emittedVars, schemaFacts);
|
|
6869
|
+
if (schemaFacts.hasSchema) {
|
|
6870
|
+
let validateResult;
|
|
6871
|
+
try {
|
|
6872
|
+
validateResult = await (deps.validateEmittedVars ?? validateEmittedVarsDefault)({ root }, buildSchemaProbeEnv(accountId, apiBaseUrl));
|
|
6873
|
+
} catch (err) {
|
|
6874
|
+
log.error(`deploy: could not validate the emitted worker vars against the env schema — ${getErrorMessage(err)}`);
|
|
6875
|
+
return false;
|
|
6876
|
+
}
|
|
6877
|
+
if (validateResult.kind === "schema-error") {
|
|
6878
|
+
log.error(`deploy: ${selfHostSchemaFailureMessage(validateResult.reason)}`);
|
|
6879
|
+
return false;
|
|
6880
|
+
}
|
|
6881
|
+
envContext.invalidKeys = validateResult.invalidKeys;
|
|
6882
|
+
}
|
|
6883
|
+
if (authEnabled) {
|
|
6884
|
+
envContext.absentRequired = envContext.absentRequired.filter((key) => key !== BETTER_AUTH_SECRET_NAME);
|
|
6885
|
+
envContext.invalidKeys = envContext.invalidKeys.filter((key) => key !== BETTER_AUTH_SECRET_NAME);
|
|
6886
|
+
}
|
|
6887
|
+
if (!assertUploaderStillPinned()) return false;
|
|
6888
|
+
try {
|
|
6889
|
+
await (deps.dischargeSelfHostEnv ?? dischargeSelfHostEnvContext)(envContext, {
|
|
6890
|
+
root,
|
|
6891
|
+
configPath,
|
|
6892
|
+
accountId,
|
|
6893
|
+
workerName
|
|
6894
|
+
});
|
|
6895
|
+
} catch (err) {
|
|
6896
|
+
if (err instanceof SelfHostFirstDeployError || err instanceof SelfHostSecretListError || err instanceof SelfHostEnvValidationError || err instanceof SelfHostSchemaError) {
|
|
6897
|
+
log.error(err.message);
|
|
6898
|
+
return false;
|
|
6899
|
+
}
|
|
6900
|
+
throw err;
|
|
6901
|
+
}
|
|
6902
|
+
return true;
|
|
6903
|
+
}
|
|
6904
|
+
/** Deploy to the user's own Cloudflare account through the guarded native Worker flow. */
|
|
6905
|
+
async function runCloudflareDeploy(root, options, cliLog, deps = {}) {
|
|
6906
|
+
const initialCloudflareLink = readCloudflareLink(root);
|
|
6907
|
+
const initialCloudflareCandidate = readCloudflareCandidate(root);
|
|
6908
|
+
const exit = deps.exit ?? ((code) => process.exit(code));
|
|
6909
|
+
const voidConfig = readConfig(root);
|
|
6910
|
+
const atomic = options.atomic === true || voidConfig.deploy?.cloudflare?.mode === "atomic";
|
|
6911
|
+
if (atomic && (options.reuseExistingWorker || initialCloudflareLink)) {
|
|
6912
|
+
log.error("deploy: atomic deployment is unavailable during the existing Worker handoff. Complete the handoff first.");
|
|
6913
|
+
return exit(1);
|
|
6914
|
+
}
|
|
6915
|
+
const detectedFramework = detectFramework(root);
|
|
6916
|
+
const frameworkPreset = detectedFramework ? FRAMEWORK_PRESETS[detectedFramework.name] : void 0;
|
|
6917
|
+
cliLog.info("cloudflare_deploy_start", { provision: options.provision === true ? true : void 0 });
|
|
6918
|
+
if (isNodeTarget(voidConfig.target)) {
|
|
6919
|
+
log.error([
|
|
6920
|
+
`deploy: --platform cloudflare is not supported for the "${voidConfig.target}" target.`,
|
|
6921
|
+
"This backend deploys Cloudflare Workers only. Deploy a node/bun/deno build with its",
|
|
6922
|
+
"own host/runtime, or use the default Cloudflare target for --platform cloudflare."
|
|
6923
|
+
].join("\n"));
|
|
6924
|
+
return exit(1);
|
|
6925
|
+
}
|
|
6926
|
+
if (detectedFramework?.class === "a" && hasConfiguredVoidWorkerRoutingRules(voidConfig.routing)) {
|
|
6927
|
+
log.error([
|
|
6928
|
+
`deploy: native Cloudflare deployment cannot apply Void routing redirects, rewrites, fallbacks, or headers to ${detectedFramework.name}.`,
|
|
6929
|
+
"This framework owns its Worker request handler, so these rules would otherwise be ignored.",
|
|
6930
|
+
"Move the rules into the framework or its Cloudflare Worker, then retry."
|
|
6931
|
+
].join("\n"));
|
|
6932
|
+
return exit(1);
|
|
6933
|
+
}
|
|
6934
|
+
const provisionModule = await loadProvisionModule();
|
|
6935
|
+
const staticPreset = resolveCloudflareStaticPreset(root, voidConfig, options) ?? await resolveCloudflareVoidStaticPreset(root, voidConfig);
|
|
6936
|
+
if (staticPreset) {
|
|
6937
|
+
if (atomic) {
|
|
6938
|
+
log.error("deploy: atomic deployment is only for Workers with Durable Objects.");
|
|
6565
6939
|
return exit(1);
|
|
6566
6940
|
}
|
|
6941
|
+
return runCloudflareStaticDeploy(root, options, voidConfig, staticPreset, cliLog, deps, initialCloudflareLink, initialCloudflareCandidate);
|
|
6567
6942
|
}
|
|
6943
|
+
const source = await prepareCloudflareDeploySource(root, options, voidConfig);
|
|
6944
|
+
if (!source) return exit(1);
|
|
6945
|
+
const { configPath, desired, reasons, authEnabled, dialect, migrationsDir, migrations: preBuildMigrations, needsAI, aiBindingName, needsSandbox, needsLive, expectedCrons, needsEmail, emailHandlers } = source;
|
|
6568
6946
|
let rootConfig = parseRootWranglerConfig(configPath);
|
|
6569
6947
|
let apiBaseUrl;
|
|
6570
6948
|
try {
|
|
@@ -6862,6 +7240,10 @@ async function runCloudflareDeploy(root, options, cliLog, deps = {}) {
|
|
|
6862
7240
|
const passthroughIdentitySnapshot = snapshotPassthroughIdentities(preBuildRootConfig);
|
|
6863
7241
|
const passthroughRawFields = snapshotPassthroughRawFields(preBuildRootConfig);
|
|
6864
7242
|
const expectedContainers = reconstructExpectedContainers(voidConfig, root, preBuildRootConfig, needsSandbox);
|
|
7243
|
+
const expectedDurableObjectState = reconstructExpectedDurableObjectState(voidConfig, root, preBuildRootConfig, {
|
|
7244
|
+
needsSandbox,
|
|
7245
|
+
needsLive
|
|
7246
|
+
});
|
|
6865
7247
|
removeDeployPointer(root);
|
|
6866
7248
|
const buildChildEnv = scrubManagedDeployBuildMarkers(scrubWranglerAuthCredentials(deployChildEnv(accountId, apiBaseUrl)));
|
|
6867
7249
|
requireProvisionModule().deleteEnvVarCaseAware(buildChildEnv, CLOUDFLARE_DEPLOY_BUILD_ENV);
|
|
@@ -6897,6 +7279,10 @@ async function runCloudflareDeploy(root, options, cliLog, deps = {}) {
|
|
|
6897
7279
|
return exit(1);
|
|
6898
7280
|
}
|
|
6899
7281
|
const lifecycleConfigPath = (deps.resolveGeneratedConfigPath ?? ((projectRoot) => readGeneratedDeployConfig(projectRoot).path))(root);
|
|
7282
|
+
if (atomic && !Array.isArray(parseRootWranglerConfig(lifecycleConfigPath).migrations)) {
|
|
7283
|
+
log.error("deploy: atomic deployment is only for Workers with Durable Object migration history.");
|
|
7284
|
+
return exit(1);
|
|
7285
|
+
}
|
|
6900
7286
|
try {
|
|
6901
7287
|
deduplicateGeneratedCompatibilityFlags(lifecycleConfigPath, configPath);
|
|
6902
7288
|
const lifecycleOptions = {
|
|
@@ -6906,77 +7292,15 @@ async function runCloudflareDeploy(root, options, cliLog, deps = {}) {
|
|
|
6906
7292
|
accountId,
|
|
6907
7293
|
apiBaseUrl
|
|
6908
7294
|
};
|
|
6909
|
-
await (deps.assertDurableObjectLifecycle ?? assertCloudflareDurableObjectLifecycleSupported)(
|
|
7295
|
+
await (deps.assertDurableObjectLifecycle ?? assertCloudflareDurableObjectLifecycleSupported)({
|
|
7296
|
+
...lifecycleOptions,
|
|
7297
|
+
allowPendingAtomicMigration: atomic
|
|
7298
|
+
});
|
|
6910
7299
|
} catch (error) {
|
|
6911
7300
|
log.error(getErrorMessage(error));
|
|
6912
7301
|
return exit(1);
|
|
6913
7302
|
}
|
|
6914
|
-
|
|
6915
|
-
if (existingWorker) {
|
|
6916
|
-
const generated = readGeneratedDeployConfig(root);
|
|
6917
|
-
assertExistingCloudflareConfig(existingWorker, generated.config, true, approvedHandoffKv);
|
|
6918
|
-
}
|
|
6919
|
-
if (!emitted.ok) {
|
|
6920
|
-
log.error([
|
|
6921
|
-
"deploy: could not read the worker vars the build emitted — refusing to validate secrets.",
|
|
6922
|
-
` ${emitted.reason}`,
|
|
6923
|
-
"The build must emit dist/ssr/wrangler.json for this backend. Rerun the build, or deploy",
|
|
6924
|
-
"this app with `void deploy` (the managed platform)."
|
|
6925
|
-
].join("\n"));
|
|
6926
|
-
return exit(1);
|
|
6927
|
-
}
|
|
6928
|
-
const emittedVars = emitted.vars;
|
|
6929
|
-
if (authEnabled && Object.prototype.hasOwnProperty.call(emittedVars, BETTER_AUTH_SECRET_NAME)) {
|
|
6930
|
-
log.error([
|
|
6931
|
-
`deploy: ${BETTER_AUTH_SECRET_NAME} must be stored as a Cloudflare Worker secret, not a plaintext worker var.`,
|
|
6932
|
-
"Remove it from Worker vars and rerun. This deploy command preserves an",
|
|
6933
|
-
"existing remote value or creates a persistent one automatically when it is missing."
|
|
6934
|
-
].join("\n"));
|
|
6935
|
-
return exit(1);
|
|
6936
|
-
}
|
|
6937
|
-
const plaintextServerKeys = schemaFacts.serverKeys.filter((key) => key in emittedVars);
|
|
6938
|
-
if (plaintextServerKeys.length > 0) {
|
|
6939
|
-
log.error([
|
|
6940
|
-
"deploy: server env keys cannot ship as plaintext Worker vars:",
|
|
6941
|
-
...plaintextServerKeys.map((key) => ` • ${key}`),
|
|
6942
|
-
"Remove them from Worker vars and set them with `void secret put <NAME>`."
|
|
6943
|
-
].join("\n"));
|
|
6944
|
-
return exit(1);
|
|
6945
|
-
}
|
|
6946
|
-
const envContext = deriveSelfHostEnvContextFromVars(emittedVars, schemaFacts);
|
|
6947
|
-
if (schemaFacts.hasSchema) {
|
|
6948
|
-
let validateResult;
|
|
6949
|
-
try {
|
|
6950
|
-
validateResult = await (deps.validateEmittedVars ?? validateEmittedVarsDefault)({ root }, buildSchemaProbeEnv(accountId, apiBaseUrl));
|
|
6951
|
-
} catch (err) {
|
|
6952
|
-
log.error(`deploy: could not validate the emitted worker vars against the env schema — ${getErrorMessage(err)}`);
|
|
6953
|
-
return exit(1);
|
|
6954
|
-
}
|
|
6955
|
-
if (validateResult.kind === "schema-error") {
|
|
6956
|
-
log.error(`deploy: ${selfHostSchemaFailureMessage(validateResult.reason)}`);
|
|
6957
|
-
return exit(1);
|
|
6958
|
-
}
|
|
6959
|
-
envContext.invalidKeys = validateResult.invalidKeys;
|
|
6960
|
-
}
|
|
6961
|
-
if (authEnabled) {
|
|
6962
|
-
envContext.absentRequired = envContext.absentRequired.filter((key) => key !== BETTER_AUTH_SECRET_NAME);
|
|
6963
|
-
envContext.invalidKeys = envContext.invalidKeys.filter((key) => key !== BETTER_AUTH_SECRET_NAME);
|
|
6964
|
-
}
|
|
6965
|
-
if (!assertUploaderStillPinned()) return exit(1);
|
|
6966
|
-
try {
|
|
6967
|
-
await (deps.dischargeSelfHostEnv ?? dischargeSelfHostEnvContext)(envContext, {
|
|
6968
|
-
root,
|
|
6969
|
-
configPath,
|
|
6970
|
-
accountId,
|
|
6971
|
-
workerName
|
|
6972
|
-
});
|
|
6973
|
-
} catch (err) {
|
|
6974
|
-
if (err instanceof SelfHostFirstDeployError || err instanceof SelfHostSecretListError || err instanceof SelfHostEnvValidationError || err instanceof SelfHostSchemaError) {
|
|
6975
|
-
log.error(err.message);
|
|
6976
|
-
return exit(1);
|
|
6977
|
-
}
|
|
6978
|
-
throw err;
|
|
6979
|
-
}
|
|
7303
|
+
if (!await validateCloudflarePostBuildEnv(root, configPath, accountId, apiBaseUrl, workerName, schemaFacts, authEnabled, existingWorker, approvedHandoffKv, deps, assertUploaderStillPinned)) return exit(1);
|
|
6980
7304
|
if (authEnabled && dialect === "sqlite") try {
|
|
6981
7305
|
await (deps.validateAuthMigrations ?? validateAuthMigrationSchema)(root, migrations);
|
|
6982
7306
|
} catch (err) {
|
|
@@ -7071,6 +7395,8 @@ async function runCloudflareDeploy(root, options, cliLog, deps = {}) {
|
|
|
7071
7395
|
aiBindingName,
|
|
7072
7396
|
authEnabled,
|
|
7073
7397
|
expectedContainers,
|
|
7398
|
+
expectedDurableObjectBindings: expectedDurableObjectState.bindings,
|
|
7399
|
+
expectedMigrations: expectedDurableObjectState.migrations,
|
|
7074
7400
|
expectedCrons
|
|
7075
7401
|
});
|
|
7076
7402
|
if (!inheritance.ok) {
|
|
@@ -7128,59 +7454,8 @@ async function runCloudflareDeploy(root, options, cliLog, deps = {}) {
|
|
|
7128
7454
|
return exit(1);
|
|
7129
7455
|
}
|
|
7130
7456
|
}
|
|
7131
|
-
if (d1MigrateToken)
|
|
7132
|
-
|
|
7133
|
-
if (!assertUploaderStillPinned()) return exit(1);
|
|
7134
|
-
const migrate = await Promise.resolve(runWrangler([
|
|
7135
|
-
"d1",
|
|
7136
|
-
"migrations",
|
|
7137
|
-
"apply",
|
|
7138
|
-
d1MigrateToken,
|
|
7139
|
-
"--remote",
|
|
7140
|
-
"-c",
|
|
7141
|
-
configPath,
|
|
7142
|
-
"--env="
|
|
7143
|
-
], { capture: false }));
|
|
7144
|
-
if (!isCleanWranglerExit(migrate)) {
|
|
7145
|
-
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.`);
|
|
7146
|
-
return exit(1);
|
|
7147
|
-
}
|
|
7148
|
-
if (!assertUploaderStillPinned()) return exit(1);
|
|
7149
|
-
const migrateList = await Promise.resolve(runWrangler([
|
|
7150
|
-
"d1",
|
|
7151
|
-
"migrations",
|
|
7152
|
-
"list",
|
|
7153
|
-
d1MigrateToken,
|
|
7154
|
-
"--remote",
|
|
7155
|
-
"-c",
|
|
7156
|
-
configPath,
|
|
7157
|
-
"--env="
|
|
7158
|
-
], { capture: true }));
|
|
7159
|
-
if (!isCleanWranglerExit(migrateList)) {
|
|
7160
|
-
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.`);
|
|
7161
|
-
return exit(1);
|
|
7162
|
-
}
|
|
7163
|
-
if (migrateList.stdout.includes("Migrations to be applied:")) {
|
|
7164
|
-
log.error([
|
|
7165
|
-
`deploy: remote D1 still has UNAPPLIED migrations for "${d1MigrateToken}" after apply.`,
|
|
7166
|
-
"`wrangler d1 migrations apply` exits 0 even when its confirmation is declined, so",
|
|
7167
|
-
"the schema may be un-migrated while the code that needs it is about to deploy.",
|
|
7168
|
-
"Re-run and confirm the migration (or apply it non-interactively), then rerun."
|
|
7169
|
-
].join("\n"));
|
|
7170
|
-
return exit(1);
|
|
7171
|
-
}
|
|
7172
|
-
if (!migrateList.stdout.includes("No migrations to apply!")) {
|
|
7173
|
-
log.error([
|
|
7174
|
-
`deploy: could not confirm the remote migration state for "${d1MigrateToken}".`,
|
|
7175
|
-
"`wrangler d1 migrations list` printed neither the \"no migrations to apply\" nor the",
|
|
7176
|
-
"\"migrations to be applied\" marker (WRANGLER_LOG is pinned so they are never",
|
|
7177
|
-
"suppressed) — refusing to deploy against an unverified schema. Rerun once wrangler",
|
|
7178
|
-
"can reach your account."
|
|
7179
|
-
].join("\n"));
|
|
7180
|
-
return exit(1);
|
|
7181
|
-
}
|
|
7182
|
-
}
|
|
7183
|
-
const verification = (deps.verifyDeployConfig ?? verifyGeneratedDeployConfig)(root, {
|
|
7457
|
+
if (!await applyAndVerifyRemoteD1Migrations(d1MigrateToken, configPath, runWrangler, assertUploaderStillPinned)) return exit(1);
|
|
7458
|
+
if (!verifyCloudflareDeployArtifact(root, deps, {
|
|
7184
7459
|
accountId,
|
|
7185
7460
|
workerName,
|
|
7186
7461
|
desired,
|
|
@@ -7192,21 +7467,14 @@ async function runCloudflareDeploy(root, options, cliLog, deps = {}) {
|
|
|
7192
7467
|
authEnabled,
|
|
7193
7468
|
requiredSecretNames: schemaFacts.requiredKeys,
|
|
7194
7469
|
expectedContainers,
|
|
7470
|
+
expectedDurableObjectBindings: expectedDurableObjectState.bindings,
|
|
7471
|
+
expectedMigrations: expectedDurableObjectState.migrations,
|
|
7195
7472
|
expectedCrons
|
|
7196
|
-
});
|
|
7197
|
-
if (!verification.ok) {
|
|
7198
|
-
log.error([
|
|
7199
|
-
"deploy: the generated deploy config does not match the pinned target — refusing to deploy.",
|
|
7200
|
-
verification.reason,
|
|
7201
|
-
"This typically means CLOUDFLARE_ENV / CLOUDFLARE_VITE_WRANGLER_CONFIG_PATH (in the",
|
|
7202
|
-
"environment or a production `.env`) selected a different named environment or config",
|
|
7203
|
-
"at build time. This backend always deploys the canonical top-level config — remove",
|
|
7204
|
-
"them and rebuild."
|
|
7205
|
-
].filter(Boolean).join("\n"));
|
|
7206
|
-
return exit(1);
|
|
7207
|
-
}
|
|
7473
|
+
})) return exit(1);
|
|
7208
7474
|
const queueConsumerCleanup = readWranglerManagedQueueCleanupCandidates(configPath);
|
|
7209
7475
|
if (existingWorker) assertCloudflareLinkUnchanged(root, pinnedHandoffLink);
|
|
7476
|
+
assertCloudflareCandidateUnchanged(root, initialCloudflareCandidate);
|
|
7477
|
+
if (initialCloudflareCandidate && (initialCloudflareCandidate.accountId !== accountId || initialCloudflareCandidate.workerName !== workerName)) throw new Error("The saved Cloudflare candidate belongs to a different account or Worker. Inspect its receipt before retrying.");
|
|
7210
7478
|
const candidateReceipt = pinnedHandoffLink?.candidateReceipt;
|
|
7211
7479
|
if (!deps.activateVersion && !deps.runWrangler && !cfUploaderIsPinned()) return exit(1);
|
|
7212
7480
|
const cfOutput = deps.activateVersion || deps.runWrangler ? null : await prepareBuildOutput();
|
|
@@ -7238,7 +7506,7 @@ async function runCloudflareDeploy(root, options, cliLog, deps = {}) {
|
|
|
7238
7506
|
configPath: generatedConfigPath,
|
|
7239
7507
|
preserveTriggers: existingWorker !== null,
|
|
7240
7508
|
expectedPreviousVersionId: existingWorker?.versionId,
|
|
7241
|
-
trustedInheritanceVersionIds: existingWorker
|
|
7509
|
+
trustedInheritanceVersionIds: existingWorker ? candidateReceipt?.parentVersionId === existingWorker.versionId ? candidateReceipt.versionIds : void 0 : initialCloudflareCandidate?.versionIds,
|
|
7242
7510
|
validateUploadedVersion: existingWorker ? async (versionId) => {
|
|
7243
7511
|
if (!assertUploaderStillPinned()) throw new Error("The deployment uploader changed.");
|
|
7244
7512
|
const uploaded = await (deps.readExistingWorker ?? readExistingCloudflareWorker)({
|
|
@@ -7249,7 +7517,9 @@ async function runCloudflareDeploy(root, options, cliLog, deps = {}) {
|
|
|
7249
7517
|
});
|
|
7250
7518
|
assertCloudflareBindingsPreserved(existingWorker, uploaded, approvedHandoffKv);
|
|
7251
7519
|
} : void 0,
|
|
7252
|
-
recordVerifiedCandidate: existingWorker ? (versionId) => recordCloudflareCandidate(root, pinnedHandoffLink, existingWorker.versionId, versionId) :
|
|
7520
|
+
recordVerifiedCandidate: existingWorker ? (versionId) => recordCloudflareCandidate(root, pinnedHandoffLink, existingWorker.versionId, versionId) : (versionId, parentVersionId) => {
|
|
7521
|
+
if (parentVersionId) recordCloudflareCandidateUpload(root, initialCloudflareCandidate, accountId, workerName, parentVersionId, versionId);
|
|
7522
|
+
},
|
|
7253
7523
|
message: encodeCloudflareVersionMessage(migrations.map((migration) => migration.name), {
|
|
7254
7524
|
...readCloudflareTriggerConfig(generatedConfigPath, configPath),
|
|
7255
7525
|
...existingWorker ? { preserve: true } : {}
|
|
@@ -7275,12 +7545,22 @@ async function runCloudflareDeploy(root, options, cliLog, deps = {}) {
|
|
|
7275
7545
|
previousTrafficConfig: readWranglerPublishedTrafficSnapshot(configPath),
|
|
7276
7546
|
queueConsumerCleanup,
|
|
7277
7547
|
verifyInheritedSecrets: true,
|
|
7548
|
+
...cfOutput && existingWorker && !pinnedHandoffLink ? { pinActiveSecrets: (activeVersionId, bindings) => pinActiveWorkerSecrets({
|
|
7549
|
+
output: cfOutput,
|
|
7550
|
+
activeVersionId,
|
|
7551
|
+
bindings,
|
|
7552
|
+
requiredNames: schemaFacts.requiredKeys,
|
|
7553
|
+
...initialAuthSecret ? { explicitNames: [BETTER_AUTH_SECRET_NAME] } : {}
|
|
7554
|
+
}) } : {},
|
|
7555
|
+
atomic,
|
|
7278
7556
|
...initialAuthSecret ? { candidateSecrets: { [BETTER_AUTH_SECRET_NAME]: initialAuthSecret } } : {}
|
|
7279
7557
|
}).finally(() => cfOutput?.dispose());
|
|
7280
7558
|
if (!execution.ok) {
|
|
7559
|
+
if (execution.reason === "atomic-readiness-failed" || execution.reason === "atomic-readiness-access-denied") clearCloudflareCandidate(root);
|
|
7281
7560
|
await reportCloudflareActivationFailure(cliLog, needsSandbox && execution.containersUnavailable ? formatCloudflareSandboxUnavailable() : formatCloudflareActivationError(execution));
|
|
7282
7561
|
return exit(1);
|
|
7283
7562
|
}
|
|
7563
|
+
clearCloudflareCandidate(root);
|
|
7284
7564
|
if (existingWorker) completeCloudflareLink(root);
|
|
7285
7565
|
acknowledgeWranglerManagedQueueRemovals(configPath, queueConsumerCleanup);
|
|
7286
7566
|
rememberCloudflareWorkersDevSubdomain(root, accountId, execution.previewUrl);
|
|
@@ -7319,12 +7599,16 @@ async function activateCloudflareVersionWithProgress(activate, options) {
|
|
|
7319
7599
|
const progress = createSpinner();
|
|
7320
7600
|
progress.start("Checking the current Worker deployment...");
|
|
7321
7601
|
try {
|
|
7322
|
-
|
|
7602
|
+
const result = await activate({
|
|
7323
7603
|
...options,
|
|
7324
7604
|
onProgress: (message) => progress.message(message)
|
|
7325
7605
|
});
|
|
7326
|
-
|
|
7327
|
-
progress.
|
|
7606
|
+
if (result.ok) progress.stop("Worker version is ready.");
|
|
7607
|
+
else progress.error("Worker deployment stopped.");
|
|
7608
|
+
return result;
|
|
7609
|
+
} catch (error) {
|
|
7610
|
+
progress.error("Worker deployment stopped.");
|
|
7611
|
+
throw error;
|
|
7328
7612
|
}
|
|
7329
7613
|
}
|
|
7330
7614
|
function formatCloudflareActivationError(result) {
|
|
@@ -7342,9 +7626,8 @@ function formatCloudflareActivationError(result) {
|
|
|
7342
7626
|
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.`;
|
|
7343
7627
|
case "inheritance-source-unavailable": return "deploy: could not verify which Worker Version would supply inherited secrets; production traffic is unchanged.";
|
|
7344
7628
|
case "inheritance-source-changed": return [
|
|
7345
|
-
"deploy: the active Worker Version is not the latest upload,
|
|
7346
|
-
"
|
|
7347
|
-
"non-text secret bindings, inspect its active and latest versions in Cloudflare before proceeding.",
|
|
7629
|
+
"deploy: the active Worker Version is not the latest upload, and its secrets could not be pinned safely.",
|
|
7630
|
+
"Inspect the active and latest Worker versions in Cloudflare before retrying.",
|
|
7348
7631
|
"No version was uploaded; production traffic is unchanged."
|
|
7349
7632
|
].join("\n");
|
|
7350
7633
|
case "traffic-preservation-unavailable": return ["deploy: the existing Worker has dashboard-managed routes or visibility that Void cannot safely republish.", "Add its current routes, workers_dev, and preview_urls values to the root Wrangler config, then retry; no version was uploaded."].join("\n");
|
|
@@ -7360,7 +7643,11 @@ function formatCloudflareActivationError(result) {
|
|
|
7360
7643
|
"Set CLOUDFLARE_WORKERS_SUBDOMAIN to your account subdomain (for example \"my-team\")",
|
|
7361
7644
|
"and retry. Void caches it after a successful workers.dev deployment; production traffic is unchanged."
|
|
7362
7645
|
].join("\n");
|
|
7363
|
-
case "readiness-staging-failed": return `deploy: Cloudflare could not stage the uploaded Worker Version at zero-percent traffic${status}; production traffic is unchanged
|
|
7646
|
+
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." : ""}`;
|
|
7647
|
+
case "atomic-failed": return `deploy: Cloudflare could not publish the Worker atomically${status}; inspect production status before retrying.${cloudflareCode}${diagnostic}`;
|
|
7648
|
+
case "atomic-output-invalid": return "deploy: Cloudflare published atomically but did not report a version id or URL. Inspect `void project status` immediately.";
|
|
7649
|
+
case "atomic-readiness-failed":
|
|
7650
|
+
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.";
|
|
7364
7651
|
case "readiness-failed": return ["deploy: the uploaded Worker Version did not pass /__void/ready.", formatCloudflareReadinessRestoration(result)].join("\n");
|
|
7365
7652
|
case "readiness-access-denied": return [
|
|
7366
7653
|
"deploy: Cloudflare Access blocked the uploaded Worker Version readiness probe.",
|
|
@@ -7491,7 +7778,10 @@ async function resolveCloudflareVoidStaticPreset(root, voidConfig) {
|
|
|
7491
7778
|
paths
|
|
7492
7779
|
});
|
|
7493
7780
|
if (pageScan.pages.length === 0 || !pageScan.pages.every((page) => page.shouldPrerender && (page.params.length === 0 && !page.catchAll || page.hasGetPrerenderPaths))) return null;
|
|
7494
|
-
const bindings = inferProjectBindings(root, {
|
|
7781
|
+
const bindings = inferProjectBindings(root, {
|
|
7782
|
+
paths,
|
|
7783
|
+
environment: "prod"
|
|
7784
|
+
});
|
|
7495
7785
|
const authEnabled = bindings.needsAuth || findVoidAuthConfig(root, paths) !== null || voidConfig.auth !== void 0;
|
|
7496
7786
|
if (hasNonPageBackend({
|
|
7497
7787
|
hasRoutes: routeScan.routes.length > 0,
|
|
@@ -7507,7 +7797,7 @@ async function resolveCloudflareVoidStaticPreset(root, voidConfig) {
|
|
|
7507
7797
|
appType: "static"
|
|
7508
7798
|
};
|
|
7509
7799
|
}
|
|
7510
|
-
async function runCloudflareStaticDeploy(root, options, voidConfig, preset, cliLog, deps, initialCloudflareLink) {
|
|
7800
|
+
async function runCloudflareStaticDeploy(root, options, voidConfig, preset, cliLog, deps, initialCloudflareLink, initialCloudflareCandidate) {
|
|
7511
7801
|
const exit = deps.exit ?? ((code) => process.exit(code));
|
|
7512
7802
|
const configPath = discoverRootWranglerConfig(root);
|
|
7513
7803
|
let rootConfig = parseRootWranglerConfig(configPath);
|
|
@@ -7657,6 +7947,8 @@ async function runCloudflareStaticDeploy(root, options, voidConfig, preset, cliL
|
|
|
7657
7947
|
});
|
|
7658
7948
|
const queueConsumerCleanup = readWranglerManagedQueueCleanupCandidates(configPath);
|
|
7659
7949
|
if (existingWorker) assertCloudflareLinkUnchanged(root, pinnedHandoffLink);
|
|
7950
|
+
assertCloudflareCandidateUnchanged(root, initialCloudflareCandidate);
|
|
7951
|
+
if (initialCloudflareCandidate && (initialCloudflareCandidate.accountId !== accountId || initialCloudflareCandidate.workerName !== workerName)) throw new Error("The saved Cloudflare candidate belongs to a different account or Worker. Inspect its receipt before retrying.");
|
|
7660
7952
|
const candidateReceipt = pinnedHandoffLink?.candidateReceipt;
|
|
7661
7953
|
if (!deps.activateVersion && !deps.runWrangler && !cfUploaderIsPinned()) return exit(1);
|
|
7662
7954
|
const cfOutput = deps.activateVersion || deps.runWrangler ? null : await prepareCfStaticBuildOutput({
|
|
@@ -7692,7 +7984,7 @@ async function runCloudflareStaticDeploy(root, options, voidConfig, preset, cliL
|
|
|
7692
7984
|
configPath: staticConfigPath,
|
|
7693
7985
|
preserveTriggers: existingWorker !== null,
|
|
7694
7986
|
expectedPreviousVersionId: existingWorker?.versionId,
|
|
7695
|
-
trustedInheritanceVersionIds: existingWorker
|
|
7987
|
+
trustedInheritanceVersionIds: existingWorker ? candidateReceipt?.parentVersionId === existingWorker.versionId ? candidateReceipt.versionIds : void 0 : initialCloudflareCandidate?.versionIds,
|
|
7696
7988
|
validateUploadedVersion: existingWorker ? async (versionId) => {
|
|
7697
7989
|
if (!uploaderIsPinned()) throw new Error("The deployment uploader changed.");
|
|
7698
7990
|
const uploaded = await (deps.readExistingWorker ?? readExistingCloudflareWorker)({
|
|
@@ -7703,7 +7995,9 @@ async function runCloudflareStaticDeploy(root, options, voidConfig, preset, cliL
|
|
|
7703
7995
|
});
|
|
7704
7996
|
assertCloudflareBindingsPreserved(existingWorker, uploaded, [], { staticAssetsBinding: "ASSETS" });
|
|
7705
7997
|
} : void 0,
|
|
7706
|
-
recordVerifiedCandidate: existingWorker ? (versionId) => recordCloudflareCandidate(root, pinnedHandoffLink, existingWorker.versionId, versionId) :
|
|
7998
|
+
recordVerifiedCandidate: existingWorker ? (versionId) => recordCloudflareCandidate(root, pinnedHandoffLink, existingWorker.versionId, versionId) : (versionId, parentVersionId) => {
|
|
7999
|
+
if (parentVersionId) recordCloudflareCandidateUpload(root, initialCloudflareCandidate, accountId, workerName, parentVersionId, versionId);
|
|
8000
|
+
},
|
|
7707
8001
|
workerName,
|
|
7708
8002
|
message: encodeCloudflareVersionMessage([], {
|
|
7709
8003
|
...readCloudflareTriggerConfig(staticConfigPath, configPath),
|
|
@@ -7734,6 +8028,7 @@ async function runCloudflareStaticDeploy(root, options, voidConfig, preset, cliL
|
|
|
7734
8028
|
await reportCloudflareActivationFailure(cliLog, formatCloudflareActivationError(execution));
|
|
7735
8029
|
return exit(1);
|
|
7736
8030
|
}
|
|
8031
|
+
clearCloudflareCandidate(root);
|
|
7737
8032
|
if (existingWorker) completeCloudflareLink(root);
|
|
7738
8033
|
acknowledgeWranglerManagedQueueRemovals(configPath, queueConsumerCleanup);
|
|
7739
8034
|
rememberCloudflareWorkersDevSubdomain(root, accountId, execution.previewUrl);
|
|
@@ -7828,6 +8123,7 @@ async function runDeployInner(root, options, cliLog) {
|
|
|
7828
8123
|
reuseExistingWorker: true
|
|
7829
8124
|
};
|
|
7830
8125
|
const platform = resolveDeploymentPlatform(root, options);
|
|
8126
|
+
if (options?.atomic && platform !== "cloudflare") throw new Error("deploy: --atomic is available only for Cloudflare Workers.");
|
|
7831
8127
|
if (platform === "none") throw new Error("deploy: deployment setup was skipped during `void init`. Pass `--platform cloudflare` or `--platform void` to choose a destination.");
|
|
7832
8128
|
const targetLabel = platform === "cloudflare" ? "Cloudflare" : "Void";
|
|
7833
8129
|
log.info(`Deployment target: ${targetLabel}`);
|
|
@@ -7863,11 +8159,16 @@ async function runManagedDeploy(root, options, cliLog) {
|
|
|
7863
8159
|
cliLog
|
|
7864
8160
|
});
|
|
7865
8161
|
const requestedProjectSlug = getRequestedProjectSlug(options);
|
|
8162
|
+
const linkedProject = readProjectConfig(root);
|
|
7866
8163
|
let config = null;
|
|
7867
8164
|
if (requestedProjectSlug) {
|
|
7868
|
-
const
|
|
7869
|
-
|
|
7870
|
-
|
|
8165
|
+
const linked = linkedProject?.slug === requestedProjectSlug ? await client.getProject(linkedProject.projectId) : null;
|
|
8166
|
+
const project = linked?.slug === requestedProjectSlug ? linked : await client.findProjectBySlug(requestedProjectSlug);
|
|
8167
|
+
assertProjectDeployAccess(project ?? void 0);
|
|
8168
|
+
config = project ? {
|
|
8169
|
+
projectId: project.id,
|
|
8170
|
+
slug: project.slug
|
|
8171
|
+
} : null;
|
|
7871
8172
|
if (!config) {
|
|
7872
8173
|
if (!process.stdin.isTTY) config = await createProjectFromSlug(root, client, requestedProjectSlug, cliLog);
|
|
7873
8174
|
else {
|
|
@@ -7880,11 +8181,10 @@ async function runManagedDeploy(root, options, cliLog) {
|
|
|
7880
8181
|
}
|
|
7881
8182
|
}
|
|
7882
8183
|
} else {
|
|
7883
|
-
config =
|
|
8184
|
+
config = linkedProject;
|
|
7884
8185
|
if (config) {
|
|
7885
|
-
const projects = await client.listProjects();
|
|
7886
8186
|
const { projectId, slug } = config;
|
|
7887
|
-
const project =
|
|
8187
|
+
const project = await client.getProject(projectId);
|
|
7888
8188
|
if (!project) throw new Error(`deploy: The linked project "${slug}" is unavailable or you no longer have access. Ask a project admin or owner to restore access, or choose another project with \`--project <slug>\`.`);
|
|
7889
8189
|
assertProjectDeployAccess(project);
|
|
7890
8190
|
}
|
|
@@ -7956,7 +8256,7 @@ function assertProjectDeployAccess(project) {
|
|
|
7956
8256
|
if (project?.role === "reader") throw new Error(`deploy: You have reader access to "${project.slug}" and cannot deploy. Ask a project admin or owner to grant collaborator access, or choose another project with \`--project <slug>\`.`);
|
|
7957
8257
|
}
|
|
7958
8258
|
async function promptDeployProjectConfig(root, client, cliLog) {
|
|
7959
|
-
const projects = await client.
|
|
8259
|
+
const projects = await client.listProjectChoices();
|
|
7960
8260
|
const deployableProjects = projects.filter((project) => project.role !== "reader");
|
|
7961
8261
|
if (deployableProjects.length !== projects.length) log.warn("Projects with reader access are hidden from deploy selection. Ask a project admin or owner to grant collaborator access to deploy to them.");
|
|
7962
8262
|
if (await promptProjectSetupAction("Set up a Void project for deploy:", { includeLink: deployableProjects.length > 0 }) === "create") return promptAndCreateProject(root, client);
|
|
@@ -8475,7 +8775,8 @@ async function runFrameworkDeploy(root, config, client, detected, fwPreset, void
|
|
|
8475
8775
|
const scanDirs = voidConfig.inference?.scanDirs ?? FRAMEWORK_SCAN_DIRS;
|
|
8476
8776
|
const bindings = inferProjectBindings(root, {
|
|
8477
8777
|
...inferenceOptions,
|
|
8478
|
-
paths
|
|
8778
|
+
paths,
|
|
8779
|
+
environment: "prod"
|
|
8479
8780
|
}, scanDirs);
|
|
8480
8781
|
if (bindings.needsAuth || findVoidAuthConfig(root, paths) !== null || voidConfig.auth !== void 0) {
|
|
8481
8782
|
log.error("deploy: Void-managed Better Auth is only supported in Void apps. Use Better Auth's official integration for this framework instead.");
|
|
@@ -8696,7 +8997,10 @@ async function runFullDeploy(root, config, client, voidConfig, fwPreset, skipBui
|
|
|
8696
8997
|
const paths = resolveProjectPaths(root, deployConfig);
|
|
8697
8998
|
const dialect = getDatabaseDialect(deployConfig);
|
|
8698
8999
|
const deployScanDirs = deployConfig.inference?.scanDirs ?? (isFrameworkMode ? FRAMEWORK_SCAN_DIRS : void 0);
|
|
8699
|
-
const bindings = inferProjectBindings(root, {
|
|
9000
|
+
const bindings = inferProjectBindings(root, {
|
|
9001
|
+
paths,
|
|
9002
|
+
environment: "prod"
|
|
9003
|
+
}, deployScanDirs);
|
|
8700
9004
|
if (isSandboxEnabled(deployConfig)) bindings.needsSandbox = true;
|
|
8701
9005
|
const authEnabled = bindings.needsAuth || findVoidAuthConfig(root, paths) !== null || deployConfig.auth !== void 0;
|
|
8702
9006
|
const effectiveBindings = authEnabled ? {
|
|
@@ -9202,4 +9506,4 @@ function resolveWorkerDirName(distDir, fwPreset, buildCommand) {
|
|
|
9202
9506
|
throw new Error("deploy: Worker output not found. Expected dist/ssr/ or dist/rsc/.");
|
|
9203
9507
|
}
|
|
9204
9508
|
//#endregion
|
|
9205
|
-
export {
|
|
9509
|
+
export { snapshotPassthroughRawFields as $, parseRootWranglerConfig$1 as A, resolveDeploymentPlatform as B, generateDeployWrapperIfNeeded as C, resolveAssetConfig 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, hasDocumentRoutes as St, hasNonPageBackend as T, resolveStaticBuildCommand as U, resolveDistDir as V, resolveStaticDeployPreset as W, runWranglerAuthToken as X, runStaticDeploy as Y, snapshotBindingIdentities as Z, deriveWorkerName as _, findEmailConfigConflicts as _t, applyDeployEvent as a, warnUnpublishedRouting as at, ensurePreviouslyDeployedLiveBindingConfig as b, renderEmailChecklist as bt, assertMigrationsProduceAuthSchema as c, prerenderPagesNode as ct, assertWranglerUploaderUnchanged as d, collectRevalidate as dt, streamDeployEvents as et, checkWranglerMigrationApplySet as f, hasRevalidate as ft, deployChildEnv as g, createNodeEmailDns as gt, createDeployWranglerRunner as h, applyEmailSetup as ht, DEPLOY_WHOLE_OBJECT_PINNED_FIELDS as i, warnRedundantForceOn3xx as it, prepareCloudflareFrameworkArtifact as j, loadProvisionModule as k, assertNoConfigOverrideInProjectDotenv as l, buildEnv as lt, computeDesiredCloudflareResources as m, SEND_EMAIL_BINDING as mt, DEPLOY_PASSTHROUGH_ASSERT_FIELDS as n, verifyGeneratedDeployConfig as nt, assembleVoidManifest as o, generateQueueResolverSource as ot, compareWranglerMigrationPaths as p, scanDurableObjectModules as pt, runCloudflareDeploy as q, DEPLOY_PASSTHROUGH_EXCLUDE_FIELDS as r, warnIgnoredNotFoundForFramework as rt, assertManagedDurableStateSupported as s, prerenderPages as st, CloudflareAuthSecretError as t, validateAuthMigrationSchema as tt, assertRemoteMigrationsDeployable as u, collectPages as ut, discoverRootWranglerConfig as v, preflightEmail as vt, hasDeploySchemaDrift as w, resolveAssetRoutingPolicy as wt, formatCloudflareActivationError as x, hasApiRoutes as xt, ensureCloudflareAuthSecret as y, renderAddressMap as yt, resolveDeployWranglerCompat as z };
|