void 0.21.1 → 0.21.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -2
- package/dist/{auth-cmd-g_ymMkUe.mjs → account-cmd-DGt9cpRe.mjs} +10 -10
- 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-DFvxIyZi.mjs → auth-link-Cl9vOuf7.mjs} +5 -5
- package/dist/auth-router-D4ZcMUSf.mjs +74 -0
- 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-wJAv808h.mjs → build-cmd-Dpt0jd-x.mjs} +5 -5
- package/dist/{cache-Be0Fu5Ka.mjs → cache-7_UeZdTk.mjs} +5 -5
- package/dist/{cancel-deploy-BgmyOwhe.mjs → cancel-deploy-D23R1RXT.mjs} +4 -4
- 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 +122 -66
- 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-LnvW4HKx.mjs → connect-4Ph5Y0QE.mjs} +8 -8
- 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-Mzv88E1C.mjs → db-DzJRn-qz.mjs} +128 -60
- package/dist/{delete-Ri6JemSU.mjs → delete-D6dZ9B6B.mjs} +5 -5
- package/dist/deploy-BH0grP4y.mjs +2 -0
- package/dist/{deploy-DEsMVrCY.mjs → deploy-CsMJrPfM.mjs} +522 -262
- 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-BA37Ye7T.mjs → domain-Dmhvb2oU.mjs} +5 -5
- package/dist/{email-C5kaZXzJ.mjs → email--tEtMoj_.mjs} +1 -1
- package/dist/{email-C5NsxrQG.mjs → email-BRKOG2RG.mjs} +10 -10
- package/dist/{entry-DdRFGK0y.mjs → entry-CF5wvH4w.mjs} +4 -21
- package/dist/{env-U_ohASB0.mjs → env-Csi-tMbT.mjs} +8 -8
- 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-DsrkweIl.mjs → github-cmd-BED3_9JD.mjs} +7 -7
- package/dist/{headers-B_HBMgi0.mjs → headers-BOg_velo.mjs} +2 -2
- package/dist/{help-sBhFH6pi.mjs → help-DC7gdz7L.mjs} +46 -11
- package/dist/help-DQMfeKMz.mjs +2 -0
- package/dist/index.mjs +134 -160
- package/dist/{init-C--Yyj1b.mjs → init-CRGDXzVC.mjs} +105 -289
- package/dist/{link-BC-mNG9-.mjs → link-CsHOinF7.mjs} +6 -6
- package/dist/{list-DHU1Wj6c.mjs → list-CDb-4bZ1.mjs} +6 -6
- package/dist/{local-d1-DzykTWY8.mjs → local-d1-CC8sKFGu.mjs} +3 -3
- package/dist/{login-jKe_0QZL.mjs → login-BQyISZuW.mjs} +4 -4
- package/dist/login-r2gL8l7B.mjs +2 -0
- package/dist/{logs-BG11f5PR.mjs → logs-BdfiOezj.mjs} +5 -5
- 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-BwAS2XZt.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-C-hv-_Ok.mjs → platform-auth-config-TSw8edHw.mjs} +5 -5
- package/dist/{platform-auth-protection-DjTE5Hj-.mjs → platform-auth-protection-Ba1XqGhn.mjs} +6 -6
- package/dist/{platform-auth-recovery-Cr0r8TEb.mjs → platform-auth-recovery-BkT3EsF2.mjs} +5 -5
- package/dist/{platform-cmd-DE6dw45v.mjs → platform-cmd-C8OqhqPt.mjs} +1 -1
- package/dist/{platform-cmd-0tEh2ZtA.mjs → platform-cmd-CRSKfu8k.mjs} +5 -5
- package/dist/{platform-domain-B_7x6Iqx.mjs → platform-domain-j9YCXRm6.mjs} +3 -3
- package/dist/{platform-lifecycle-Di0LbhPM.mjs → platform-lifecycle-78H0XQUA.mjs} +278 -230
- package/dist/{platform-lifecycle-Dhx9Pnub.mjs → platform-lifecycle-DDc9zCeJ.mjs} +1 -1
- package/dist/{platform-management-eaiaU3uM.mjs → platform-management-6w8-DUjC.mjs} +2 -2
- package/dist/{platform-management-B9LUtMt9.mjs → platform-management-DzKNsMlt.mjs} +1 -1
- package/dist/{platform-recovery-BxfA8E5C.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-DrnRJdep.mjs → project-cmd-B44I8J_W.mjs} +16 -16
- package/dist/{project-paths-CKQ-Q5JS.mjs → project-paths-GgcMozYz.mjs} +1 -1
- package/dist/{project-team-CzRbO_kA.mjs → project-team-BkbYIsXN.mjs} +6 -6
- 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-DwrqUQZ8.mjs → requests-DFyhBMaf.mjs} +4 -4
- package/dist/{resolve-project-Xvis70DG.mjs → resolve-project-BG5ORGID.mjs} +1 -1
- package/dist/resolve-project-DtbidV4y.mjs +2 -0
- package/dist/{rollback-B4tFWmkN.mjs → rollback-DHHxXZiS.mjs} +5 -5
- 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-UtrRjhEO.mjs → secret-DN9sSNiV.mjs} +7 -7
- 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/migrate-vite-cloudflare-to-void/SKILL.md +1 -1
- package/skills/void/SKILL.md +4 -2
- 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/administration/access.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/project-collaboration.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 +2 -0
- package/skills/void/docs/reference/api.md +1 -1
- package/skills/void/docs/reference/cli.md +34 -13
- package/skills/void/docs/reference/config.md +12 -1
- 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-DAH2-m_-.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-B403BLBB.mjs +0 -2
- package/dist/login-BwiopVdg.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";
|
|
@@ -2275,6 +2277,48 @@ function createCfVersionRunner(options) {
|
|
|
2275
2277
|
};
|
|
2276
2278
|
}
|
|
2277
2279
|
//#endregion
|
|
2280
|
+
//#region src/cli/cloudflare-candidate.ts
|
|
2281
|
+
const CANDIDATE_FILE = ".void/cloudflare-candidate.json";
|
|
2282
|
+
/** A failed normal deploy keeps its locally verified upload chain across retries. */
|
|
2283
|
+
function readCloudflareCandidate(root) {
|
|
2284
|
+
const path = join(root, CANDIDATE_FILE);
|
|
2285
|
+
if (!existsSync(path)) return null;
|
|
2286
|
+
let value;
|
|
2287
|
+
try {
|
|
2288
|
+
value = JSON.parse(readFileSync(path, "utf8"));
|
|
2289
|
+
} catch {
|
|
2290
|
+
throw new Error("The saved Cloudflare candidate receipt is invalid. Restore or remove .void/cloudflare-candidate.json before retrying.");
|
|
2291
|
+
}
|
|
2292
|
+
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.");
|
|
2293
|
+
return value;
|
|
2294
|
+
}
|
|
2295
|
+
function assertCloudflareCandidateUnchanged(root, expected) {
|
|
2296
|
+
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.");
|
|
2297
|
+
}
|
|
2298
|
+
function recordCloudflareCandidateUpload(root, expected, accountId, workerName, parentVersionId, versionId) {
|
|
2299
|
+
assertCloudflareCandidateUnchanged(root, expected);
|
|
2300
|
+
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.");
|
|
2301
|
+
const versionIds = [...expected?.versionIds ?? [], versionId];
|
|
2302
|
+
mkdirSync(join(root, ".void"), { recursive: true });
|
|
2303
|
+
const path = join(root, CANDIDATE_FILE);
|
|
2304
|
+
const temp = `${path}.${process.pid}.tmp`;
|
|
2305
|
+
try {
|
|
2306
|
+
writeFileSync(temp, `${JSON.stringify({
|
|
2307
|
+
accountId,
|
|
2308
|
+
workerName,
|
|
2309
|
+
parentVersionId,
|
|
2310
|
+
versionIds
|
|
2311
|
+
})}\n`, { mode: 384 });
|
|
2312
|
+
renameSync(temp, path);
|
|
2313
|
+
} finally {
|
|
2314
|
+
if (existsSync(temp)) unlinkSync(temp);
|
|
2315
|
+
}
|
|
2316
|
+
}
|
|
2317
|
+
function clearCloudflareCandidate(root) {
|
|
2318
|
+
const path = join(root, CANDIDATE_FILE);
|
|
2319
|
+
if (existsSync(path)) unlinkSync(path);
|
|
2320
|
+
}
|
|
2321
|
+
//#endregion
|
|
2278
2322
|
//#region src/cli/cloudflare-deploy/classify.ts
|
|
2279
2323
|
/**
|
|
2280
2324
|
* Narrow native Cloudflare deploys to app shapes whose emitted Worker artifact
|
|
@@ -3837,6 +3881,69 @@ function __resolveQueueIndex(queueName) {
|
|
|
3837
3881
|
}`;
|
|
3838
3882
|
}
|
|
3839
3883
|
//#endregion
|
|
3884
|
+
//#region src/cli/pg-bundle-transform.ts
|
|
3885
|
+
function nodes(root) {
|
|
3886
|
+
const found = [];
|
|
3887
|
+
const pending = [root];
|
|
3888
|
+
while (pending.length > 0) {
|
|
3889
|
+
const node = pending.pop();
|
|
3890
|
+
found.push(node);
|
|
3891
|
+
for (const value of Object.values(node)) if (Array.isArray(value)) {
|
|
3892
|
+
for (const child of value) if (child && typeof child === "object" && typeof child.type === "string") pending.push(child);
|
|
3893
|
+
} else if (value && typeof value === "object" && typeof value.type === "string") pending.push(value);
|
|
3894
|
+
}
|
|
3895
|
+
return found;
|
|
3896
|
+
}
|
|
3897
|
+
/** Rewrite the two CommonJS constructs emitted by the PG migration bundle. */
|
|
3898
|
+
function transformPgWorkerBundle(code, filename, requireShim) {
|
|
3899
|
+
if (!code.includes("createRequire") && !code.includes("pgpass")) return code;
|
|
3900
|
+
const program = parseSync(filename, code).program;
|
|
3901
|
+
const edits = [];
|
|
3902
|
+
let hasRequireBinding = false;
|
|
3903
|
+
let pgpassCalls = 0;
|
|
3904
|
+
for (const statement of program.body ?? []) {
|
|
3905
|
+
if (statement.type === "ImportDeclaration" && statement.source?.value === "node:module") {
|
|
3906
|
+
const specifiers = statement.specifiers;
|
|
3907
|
+
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}.`);
|
|
3908
|
+
edits.push({
|
|
3909
|
+
start: statement.start,
|
|
3910
|
+
end: statement.end,
|
|
3911
|
+
replacement: ""
|
|
3912
|
+
});
|
|
3913
|
+
}
|
|
3914
|
+
if (statement.type === "VariableDeclaration") {
|
|
3915
|
+
const declarations = statement.declarations;
|
|
3916
|
+
if (declarations?.some((declaration) => isIdentifier(declaration.id) && declaration.id.name === "__require")) {
|
|
3917
|
+
if (declarations.length !== 1 || hasRequireBinding) throw new Error(`deploy: Unsupported require binding in PostgreSQL bundle ${filename}.`);
|
|
3918
|
+
hasRequireBinding = true;
|
|
3919
|
+
edits.push({
|
|
3920
|
+
start: statement.start,
|
|
3921
|
+
end: statement.end,
|
|
3922
|
+
replacement: requireShim
|
|
3923
|
+
});
|
|
3924
|
+
}
|
|
3925
|
+
}
|
|
3926
|
+
}
|
|
3927
|
+
for (const node of nodes(program)) {
|
|
3928
|
+
if (node.type !== "CallExpression" || !isIdentifier(node.callee) || node.callee.name !== "__require") continue;
|
|
3929
|
+
const args = node.arguments;
|
|
3930
|
+
if (args?.length !== 1 || !isLiteral(args[0]) || args[0].value !== "pgpass") continue;
|
|
3931
|
+
pgpassCalls++;
|
|
3932
|
+
edits.push({
|
|
3933
|
+
start: node.start,
|
|
3934
|
+
end: node.end,
|
|
3935
|
+
replacement: "__voidPgpassNoop"
|
|
3936
|
+
});
|
|
3937
|
+
}
|
|
3938
|
+
if (code.includes("createRequire") && !hasRequireBinding) throw new Error(`deploy: Could not locate the generated require binding in PostgreSQL bundle ${filename}.`);
|
|
3939
|
+
if (code.includes("pgpass") && pgpassCalls === 0 && code.includes("__require")) throw new Error(`deploy: Could not locate the pgpass require in PostgreSQL bundle ${filename}.`);
|
|
3940
|
+
const ms = new MagicString(code);
|
|
3941
|
+
for (const edit of edits.sort((a, b) => b.start - a.start)) ms.overwrite(edit.start, edit.end, edit.replacement);
|
|
3942
|
+
const transformed = ms.toString();
|
|
3943
|
+
if (transformed.includes("createRequire") || transformed.includes("__require(\"pgpass\")")) throw new Error(`deploy: PostgreSQL bundle ${filename} still contains an unsupported require.`);
|
|
3944
|
+
return pgpassCalls > 0 ? `const __voidPgpassNoop = Object.assign(function pgpass(_connectionInfo, callback) { callback(undefined); }, { warnTo() {} });\n${transformed}` : transformed;
|
|
3945
|
+
}
|
|
3946
|
+
//#endregion
|
|
3840
3947
|
//#region src/cli/wrapper.ts
|
|
3841
3948
|
const BUNDLED_ENTRY_RE = /^index\.(?:m?js|cjs)$/;
|
|
3842
3949
|
const WRAPPER_MARKER = "// Generated by Void: deployment wrapper.";
|
|
@@ -3904,7 +4011,7 @@ async function generateWrapper(workerDir, workerMain, root, features) {
|
|
|
3904
4011
|
let migrations;
|
|
3905
4012
|
let migrationPlanBundle;
|
|
3906
4013
|
if (features.hasMigrations) {
|
|
3907
|
-
const { collectMigrations } = await import("./collect-
|
|
4014
|
+
const { collectMigrations } = await import("./collect-DLyFDiKW.mjs");
|
|
3908
4015
|
const { buildMigrationPlanBundle } = await import("./plan-DpuOr14e.mjs");
|
|
3909
4016
|
const migrationsDir = readProjectPaths(root).migrationsDir;
|
|
3910
4017
|
migrations = collectMigrations(migrationsDir);
|
|
@@ -4017,11 +4124,9 @@ function patchPgWorkerBundle(outDir) {
|
|
|
4017
4124
|
for (const file of readdirSync(outDir)) {
|
|
4018
4125
|
if (!file.endsWith(".mjs") && !file.endsWith(".js")) continue;
|
|
4019
4126
|
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);
|
|
4127
|
+
const code = readFileSync(path, "utf-8");
|
|
4128
|
+
const transformed = transformPgWorkerBundle(code, file, pgWorkerRequireShim());
|
|
4129
|
+
if (transformed !== code) writeFileSync(path, transformed);
|
|
4025
4130
|
}
|
|
4026
4131
|
}
|
|
4027
4132
|
function createPgPackageRequire(fromPath) {
|
|
@@ -4318,7 +4423,7 @@ let loadedProvisionModule;
|
|
|
4318
4423
|
* so a managed deploy never imports it — and thus never loads `proper-lockfile`.
|
|
4319
4424
|
*/
|
|
4320
4425
|
async function loadProvisionModule() {
|
|
4321
|
-
loadedProvisionModule ??= await import("./provision-
|
|
4426
|
+
loadedProvisionModule ??= await import("./provision-DNtrtaVD.mjs");
|
|
4322
4427
|
return loadedProvisionModule;
|
|
4323
4428
|
}
|
|
4324
4429
|
/**
|
|
@@ -4884,6 +4989,47 @@ function reconstructExpectedContainers(config, root, rootConfig, needsSandbox) {
|
|
|
4884
4989
|
}
|
|
4885
4990
|
return expected;
|
|
4886
4991
|
}
|
|
4992
|
+
/** Reconstruct the Durable Object state emitted after the pre-build root config is synced. */
|
|
4993
|
+
function reconstructExpectedDurableObjectState(config, root, rootConfig, options) {
|
|
4994
|
+
const bindings = bindingEntriesForField("durable_objects", rootConfig.durable_objects).map(({ entry }) => entry);
|
|
4995
|
+
const migrations = Array.isArray(rootConfig.migrations) ? [...rootConfig.migrations] : [];
|
|
4996
|
+
const sandbox = options.needsSandbox ? resolveSandboxConfig(config, root) : void 0;
|
|
4997
|
+
if (sandbox) {
|
|
4998
|
+
if (!bindings.some((binding) => binding.name === sandbox.binding)) bindings.push({
|
|
4999
|
+
name: sandbox.binding,
|
|
5000
|
+
class_name: sandbox.className
|
|
5001
|
+
});
|
|
5002
|
+
if (!migrations.some((migration) => migration.tag === "void-sandbox-v1" || Array.isArray(migration.new_sqlite_classes) && migration.new_sqlite_classes.includes(sandbox.className))) migrations.push({
|
|
5003
|
+
tag: SANDBOX_MIGRATION_TAG,
|
|
5004
|
+
new_sqlite_classes: [sandbox.className]
|
|
5005
|
+
});
|
|
5006
|
+
}
|
|
5007
|
+
const paths = resolveProjectPaths(root, config);
|
|
5008
|
+
const websocketRoutes = scanWebSocketRoutesSync(root, paths);
|
|
5009
|
+
const durableObjects = scanDurableObjectModules(root);
|
|
5010
|
+
const live = options.needsLive ? resolveLiveBindingConfig(root, {
|
|
5011
|
+
reservedBindings: [...websocketRoutes.map((route) => route.bindingName), ...durableObjects.map((module) => module.bindingName)],
|
|
5012
|
+
reservedClasses: [
|
|
5013
|
+
...websocketRoutes.map((route) => route.className),
|
|
5014
|
+
...durableObjects.map((module) => module.className),
|
|
5015
|
+
sandbox?.className
|
|
5016
|
+
]
|
|
5017
|
+
}) : readExistingLiveBindingConfig(root);
|
|
5018
|
+
if (live) {
|
|
5019
|
+
if (!bindings.some((binding) => binding.name === live.bindingName)) bindings.push({
|
|
5020
|
+
name: live.bindingName,
|
|
5021
|
+
class_name: live.className
|
|
5022
|
+
});
|
|
5023
|
+
if (!hasDurableObjectSqliteMigration(migrations, live.className)) migrations.push({
|
|
5024
|
+
tag: nextDurableObjectMigrationTag(migrations, LIVE_MIGRATION_TAG),
|
|
5025
|
+
new_sqlite_classes: [live.className]
|
|
5026
|
+
});
|
|
5027
|
+
}
|
|
5028
|
+
return {
|
|
5029
|
+
bindings,
|
|
5030
|
+
migrations
|
|
5031
|
+
};
|
|
5032
|
+
}
|
|
4887
5033
|
/**
|
|
4888
5034
|
* Deterministic sha256 over the wrangler uploader BUNDLE the credentialed deploy executes — the
|
|
4889
5035
|
* resolved `wrangler-dist/cli.js` PLUS every sibling file in its directory. `cli.js` loads sibling
|
|
@@ -4941,17 +5087,39 @@ function hashCfUploader() {
|
|
|
4941
5087
|
function hashDirectoryContents(dir) {
|
|
4942
5088
|
try {
|
|
4943
5089
|
const hash = createHash("sha256");
|
|
5090
|
+
const visiting = /* @__PURE__ */ new Set();
|
|
4944
5091
|
const walk = (rel) => {
|
|
4945
|
-
const
|
|
4946
|
-
|
|
4947
|
-
|
|
4948
|
-
|
|
4949
|
-
|
|
5092
|
+
const real = realpathSync(join(dir, rel));
|
|
5093
|
+
if (visiting.has(real)) throw new Error(`Cyclic symlink in uploader: ${rel}`);
|
|
5094
|
+
visiting.add(real);
|
|
5095
|
+
try {
|
|
5096
|
+
const entries = readdirSync(join(dir, rel), { withFileTypes: true }).sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0);
|
|
5097
|
+
for (const entry of entries) {
|
|
5098
|
+
const childRel = rel ? `${rel}/${entry.name}` : entry.name;
|
|
5099
|
+
const childPath = join(dir, childRel);
|
|
5100
|
+
if (entry.isDirectory()) {
|
|
5101
|
+
walk(childRel);
|
|
5102
|
+
continue;
|
|
5103
|
+
}
|
|
4950
5104
|
hash.update(childRel);
|
|
4951
5105
|
hash.update("\0");
|
|
4952
|
-
|
|
5106
|
+
if (entry.isSymbolicLink()) {
|
|
5107
|
+
hash.update(readlinkSync(childPath));
|
|
5108
|
+
hash.update("\0");
|
|
5109
|
+
try {
|
|
5110
|
+
const target = statSync(childPath);
|
|
5111
|
+
if (target.isDirectory()) walk(childRel);
|
|
5112
|
+
else if (target.isFile()) hash.update(readFileSync(childPath));
|
|
5113
|
+
else throw new Error(`Unsupported uploader symlink target: ${childRel}`);
|
|
5114
|
+
} catch (error) {
|
|
5115
|
+
if (error.code !== "ENOENT") throw error;
|
|
5116
|
+
hash.update("missing");
|
|
5117
|
+
}
|
|
5118
|
+
} else hash.update(readFileSync(childPath));
|
|
4953
5119
|
hash.update("\0");
|
|
4954
5120
|
}
|
|
5121
|
+
} finally {
|
|
5122
|
+
visiting.delete(real);
|
|
4955
5123
|
}
|
|
4956
5124
|
};
|
|
4957
5125
|
walk("");
|
|
@@ -5452,6 +5620,32 @@ function verifyGeneratedDeployConfig(root, expected) {
|
|
|
5452
5620
|
const destructiveMigration = verifyNoInjectedDestructiveMigration(generated.migrations, raw.get("migrations"));
|
|
5453
5621
|
if (!destructiveMigration.ok) return destructiveMigration;
|
|
5454
5622
|
}
|
|
5623
|
+
if (expected.expectedDurableObjectBindings) {
|
|
5624
|
+
let emittedBindings;
|
|
5625
|
+
try {
|
|
5626
|
+
emittedBindings = bindingEntriesForField("durable_objects", generated.durable_objects).map(({ entry }) => entry);
|
|
5627
|
+
} catch {
|
|
5628
|
+
return {
|
|
5629
|
+
ok: false,
|
|
5630
|
+
reason: "generated config durable_objects bindings could not be verified."
|
|
5631
|
+
};
|
|
5632
|
+
}
|
|
5633
|
+
const byName = (left, right) => String(left.name).localeCompare(String(right.name));
|
|
5634
|
+
if (!deepEqual([...emittedBindings].sort(byName), [...expected.expectedDurableObjectBindings].sort(byName))) return {
|
|
5635
|
+
ok: false,
|
|
5636
|
+
reason: "generated config durable_objects bindings differ from the pre-build binding set — refusing to deploy a binding the build added, removed, or retargeted."
|
|
5637
|
+
};
|
|
5638
|
+
}
|
|
5639
|
+
if (expected.expectedMigrations) {
|
|
5640
|
+
if (generated.migrations !== void 0 && !Array.isArray(generated.migrations)) return {
|
|
5641
|
+
ok: false,
|
|
5642
|
+
reason: "generated config migrations could not be verified."
|
|
5643
|
+
};
|
|
5644
|
+
if (!deepEqual(Array.isArray(generated.migrations) ? generated.migrations : [], expected.expectedMigrations)) return {
|
|
5645
|
+
ok: false,
|
|
5646
|
+
reason: "generated config migrations differ from the pre-build migration sequence — refusing to deploy a migration the build added, removed, or retargeted."
|
|
5647
|
+
};
|
|
5648
|
+
}
|
|
5455
5649
|
if (expected.expectedContainers) {
|
|
5456
5650
|
const emittedContainers = Array.isArray(generated.containers) ? generated.containers : [];
|
|
5457
5651
|
const expectedContainers = expected.expectedContainers;
|
|
@@ -5695,7 +5889,8 @@ async function computeDesiredCloudflareResources(root, voidConfig, configPath) {
|
|
|
5695
5889
|
const inferenceOptions = voidConfig.inference?.bindings ? { bindings: voidConfig.inference.bindings } : void 0;
|
|
5696
5890
|
const bindings = inferProjectBindings(root, {
|
|
5697
5891
|
...inferenceOptions,
|
|
5698
|
-
paths
|
|
5892
|
+
paths,
|
|
5893
|
+
environment: "prod"
|
|
5699
5894
|
}, scanDirs);
|
|
5700
5895
|
const authEnabled = bindings.needsAuth || findVoidAuthConfig(root, paths) !== null || voidConfig.auth !== void 0;
|
|
5701
5896
|
const dialect = getDatabaseDialect(voidConfig);
|
|
@@ -5714,9 +5909,10 @@ async function computeDesiredCloudflareResources(root, voidConfig, configPath) {
|
|
|
5714
5909
|
const binding = bindingNames?.d1 ?? "DB";
|
|
5715
5910
|
const storedName = readStoredResourceName(config, "d1_databases", binding, "database_name");
|
|
5716
5911
|
const storedId = readStoredResourceName(config, "d1_databases", binding, "database_id");
|
|
5912
|
+
const authoredName = voidConfig.cloudflare?.d1_databases?.find((entry) => entry.binding === binding)?.database_name;
|
|
5717
5913
|
desired.d1 = {
|
|
5718
5914
|
binding,
|
|
5719
|
-
name: storedName != null && isRealD1Id(storedId) ? storedName : suffixedResourceName(workerName, "db"),
|
|
5915
|
+
name: storedName != null && isRealD1Id(storedId) ? storedName : authoredName?.trim() || (basename(configPath) !== ".void-wrangler.jsonc" && storedName !== "default" ? storedName : void 0) || suffixedResourceName(workerName, "db"),
|
|
5720
5916
|
migrationsDir: migrationsDirRelative
|
|
5721
5917
|
};
|
|
5722
5918
|
reasons.set(binding, databaseReason);
|
|
@@ -5732,9 +5928,10 @@ async function computeDesiredCloudflareResources(root, voidConfig, configPath) {
|
|
|
5732
5928
|
if (bindings.needsR2) {
|
|
5733
5929
|
const binding = bindingNames?.r2 ?? "STORAGE";
|
|
5734
5930
|
const storedName = readStoredResourceName(config, "r2_buckets", binding, "bucket_name");
|
|
5931
|
+
const generatedDefault = storedName === "default" && basename(configPath) === ".void-wrangler.jsonc" && !voidConfig.cloudflare?.r2_buckets?.some((entry) => entry.binding === binding && entry.bucket_name === "default");
|
|
5735
5932
|
desired.r2 = {
|
|
5736
5933
|
binding,
|
|
5737
|
-
bucketName: storedName &&
|
|
5934
|
+
bucketName: storedName && !generatedDefault ? storedName : suffixedResourceName(workerName, "storage")
|
|
5738
5935
|
};
|
|
5739
5936
|
reasons.set(binding, "app uses env.STORAGE (R2)");
|
|
5740
5937
|
}
|
|
@@ -5774,7 +5971,8 @@ async function computeDesiredCloudflareResources(root, voidConfig, configPath) {
|
|
|
5774
5971
|
expectedCrons,
|
|
5775
5972
|
needsEmail: bindings.needsEmail === true || hasEmailHandlers(emailHandlers),
|
|
5776
5973
|
emailHandlers,
|
|
5777
|
-
needsSandbox: isSandboxEnabled(voidConfig) || bindings.needsSandbox
|
|
5974
|
+
needsSandbox: isSandboxEnabled(voidConfig) || bindings.needsSandbox,
|
|
5975
|
+
needsLive: bindings.needsLive === true
|
|
5778
5976
|
};
|
|
5779
5977
|
}
|
|
5780
5978
|
/**
|
|
@@ -6481,56 +6679,8 @@ async function ensureCloudflareAuthSecret(options) {
|
|
|
6481
6679
|
...workerWasMissing ? { workerWasMissing: true } : {}
|
|
6482
6680
|
};
|
|
6483
6681
|
}
|
|
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);
|
|
6682
|
+
/** Validate source-level native deploy inputs before account operations or project code. */
|
|
6683
|
+
async function prepareCloudflareDeploySource(root, options, voidConfig) {
|
|
6534
6684
|
if (options.skipBuild) {
|
|
6535
6685
|
log.error([
|
|
6536
6686
|
"deploy: --skip-build is not supported with --platform cloudflare.",
|
|
@@ -6540,15 +6690,16 @@ async function runCloudflareDeploy(root, options, cliLog, deps = {}) {
|
|
|
6540
6690
|
"are about to upload. Drop --skip-build, or deploy with `void deploy` (the managed",
|
|
6541
6691
|
"platform), which supports it."
|
|
6542
6692
|
].join("\n"));
|
|
6543
|
-
return
|
|
6693
|
+
return null;
|
|
6544
6694
|
}
|
|
6545
6695
|
const classification = classifyCloudflareDeployApp(root, voidConfig, options);
|
|
6546
6696
|
if (!classification.supported) {
|
|
6547
6697
|
log.error(classification.reason);
|
|
6548
|
-
return
|
|
6698
|
+
return null;
|
|
6549
6699
|
}
|
|
6550
6700
|
const configPath = discoverRootWranglerConfig(root);
|
|
6551
|
-
const
|
|
6701
|
+
const facts = await computeDesiredCloudflareResources(root, voidConfig, configPath);
|
|
6702
|
+
const { desired, dialect, migrations: preBuildMigrations, migrationsDir } = facts;
|
|
6552
6703
|
if (dialect !== "sqlite" && preBuildMigrations.length > 0 && !process.env.DATABASE_URL) {
|
|
6553
6704
|
log.error([
|
|
6554
6705
|
`deploy: ${dialect === "mysql" ? "MySQL" : "PostgreSQL"} migrations require DATABASE_URL for --platform cloudflare.`,
|
|
@@ -6556,15 +6707,204 @@ async function runCloudflareDeploy(root, options, cliLog, deps = {}) {
|
|
|
6556
6707
|
"provision Hyperdrive and apply checked-in migrations before uploading the Worker; it is",
|
|
6557
6708
|
"never written to wrangler.jsonc or the generated Worker config."
|
|
6558
6709
|
].join("\n"));
|
|
6559
|
-
return
|
|
6710
|
+
return null;
|
|
6560
6711
|
}
|
|
6561
6712
|
if (desired.d1) {
|
|
6562
6713
|
const migrationsPattern = resolveWranglerMigrationPattern(parseRootWranglerConfig(configPath), desired.d1.binding, desired.d1.migrationsDir ?? relative(dirname(configPath), migrationsDir));
|
|
6563
6714
|
if (!migrationsPattern.ok) {
|
|
6564
6715
|
log.error(migrationsPattern.reason);
|
|
6716
|
+
return null;
|
|
6717
|
+
}
|
|
6718
|
+
}
|
|
6719
|
+
return {
|
|
6720
|
+
configPath,
|
|
6721
|
+
...facts
|
|
6722
|
+
};
|
|
6723
|
+
}
|
|
6724
|
+
/** Apply remote D1 changes and prove no migrations remain pending. */
|
|
6725
|
+
async function applyAndVerifyRemoteD1Migrations(d1MigrateToken, configPath, runWrangler, assertUploaderStillPinned) {
|
|
6726
|
+
if (d1MigrateToken) {
|
|
6727
|
+
log.step("Applying D1 migrations...");
|
|
6728
|
+
if (!assertUploaderStillPinned()) return false;
|
|
6729
|
+
const migrate = await Promise.resolve(runWrangler([
|
|
6730
|
+
"d1",
|
|
6731
|
+
"migrations",
|
|
6732
|
+
"apply",
|
|
6733
|
+
d1MigrateToken,
|
|
6734
|
+
"--remote",
|
|
6735
|
+
"-c",
|
|
6736
|
+
configPath,
|
|
6737
|
+
"--env="
|
|
6738
|
+
], { capture: false }));
|
|
6739
|
+
if (!isCleanWranglerExit(migrate)) {
|
|
6740
|
+
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.`);
|
|
6741
|
+
return false;
|
|
6742
|
+
}
|
|
6743
|
+
if (!assertUploaderStillPinned()) return false;
|
|
6744
|
+
const migrateList = await Promise.resolve(runWrangler([
|
|
6745
|
+
"d1",
|
|
6746
|
+
"migrations",
|
|
6747
|
+
"list",
|
|
6748
|
+
d1MigrateToken,
|
|
6749
|
+
"--remote",
|
|
6750
|
+
"-c",
|
|
6751
|
+
configPath,
|
|
6752
|
+
"--env="
|
|
6753
|
+
], { capture: true }));
|
|
6754
|
+
if (!isCleanWranglerExit(migrateList)) {
|
|
6755
|
+
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.`);
|
|
6756
|
+
return false;
|
|
6757
|
+
}
|
|
6758
|
+
if (migrateList.stdout.includes("Migrations to be applied:")) {
|
|
6759
|
+
log.error([
|
|
6760
|
+
`deploy: remote D1 still has UNAPPLIED migrations for "${d1MigrateToken}" after apply.`,
|
|
6761
|
+
"`wrangler d1 migrations apply` exits 0 even when its confirmation is declined, so",
|
|
6762
|
+
"the schema may be un-migrated while the code that needs it is about to deploy.",
|
|
6763
|
+
"Re-run and confirm the migration (or apply it non-interactively), then rerun."
|
|
6764
|
+
].join("\n"));
|
|
6765
|
+
return false;
|
|
6766
|
+
}
|
|
6767
|
+
if (!migrateList.stdout.includes("No migrations to apply!")) {
|
|
6768
|
+
log.error([
|
|
6769
|
+
`deploy: could not confirm the remote migration state for "${d1MigrateToken}".`,
|
|
6770
|
+
"`wrangler d1 migrations list` printed neither the \"no migrations to apply\" nor the",
|
|
6771
|
+
"\"migrations to be applied\" marker (WRANGLER_LOG is pinned so they are never",
|
|
6772
|
+
"suppressed) — refusing to deploy against an unverified schema. Rerun once wrangler",
|
|
6773
|
+
"can reach your account."
|
|
6774
|
+
].join("\n"));
|
|
6775
|
+
return false;
|
|
6776
|
+
}
|
|
6777
|
+
}
|
|
6778
|
+
return true;
|
|
6779
|
+
}
|
|
6780
|
+
/** Check the built Worker against the pinned deployment target before upload. */
|
|
6781
|
+
function verifyCloudflareDeployArtifact(root, deps, options) {
|
|
6782
|
+
const verification = (deps.verifyDeployConfig ?? verifyGeneratedDeployConfig)(root, options);
|
|
6783
|
+
if (!verification.ok) {
|
|
6784
|
+
log.error([
|
|
6785
|
+
"deploy: the generated deploy config does not match the pinned target — refusing to deploy.",
|
|
6786
|
+
verification.reason,
|
|
6787
|
+
"This typically means CLOUDFLARE_ENV / CLOUDFLARE_VITE_WRANGLER_CONFIG_PATH (in the",
|
|
6788
|
+
"environment or a production `.env`) selected a different named environment or config",
|
|
6789
|
+
"at build time. This backend always deploys the canonical top-level config — remove",
|
|
6790
|
+
"them and rebuild."
|
|
6791
|
+
].filter(Boolean).join("\n"));
|
|
6792
|
+
return false;
|
|
6793
|
+
}
|
|
6794
|
+
return true;
|
|
6795
|
+
}
|
|
6796
|
+
/** Validate emitted Worker vars and required secrets against post-build ground truth. */
|
|
6797
|
+
async function validateCloudflarePostBuildEnv(root, configPath, accountId, apiBaseUrl, workerName, schemaFacts, authEnabled, existingWorker, approvedHandoffKv, deps, assertUploaderStillPinned) {
|
|
6798
|
+
const emitted = (deps.readEmittedWorkerVars ?? readEmittedWorkerVarsDefault)(root);
|
|
6799
|
+
if (existingWorker) {
|
|
6800
|
+
const generated = readGeneratedDeployConfig(root);
|
|
6801
|
+
assertExistingCloudflareConfig(existingWorker, generated.config, true, approvedHandoffKv);
|
|
6802
|
+
}
|
|
6803
|
+
if (!emitted.ok) {
|
|
6804
|
+
log.error([
|
|
6805
|
+
"deploy: could not read the worker vars the build emitted — refusing to validate secrets.",
|
|
6806
|
+
` ${emitted.reason}`,
|
|
6807
|
+
"The build must emit dist/ssr/wrangler.json for this backend. Rerun the build, or deploy",
|
|
6808
|
+
"this app with `void deploy` (the managed platform)."
|
|
6809
|
+
].join("\n"));
|
|
6810
|
+
return false;
|
|
6811
|
+
}
|
|
6812
|
+
const emittedVars = emitted.vars;
|
|
6813
|
+
if (authEnabled && Object.prototype.hasOwnProperty.call(emittedVars, BETTER_AUTH_SECRET_NAME)) {
|
|
6814
|
+
log.error([
|
|
6815
|
+
`deploy: ${BETTER_AUTH_SECRET_NAME} must be stored as a Cloudflare Worker secret, not a plaintext worker var.`,
|
|
6816
|
+
"Remove it from Worker vars and rerun. This deploy command preserves an",
|
|
6817
|
+
"existing remote value or creates a persistent one automatically when it is missing."
|
|
6818
|
+
].join("\n"));
|
|
6819
|
+
return false;
|
|
6820
|
+
}
|
|
6821
|
+
const plaintextServerKeys = schemaFacts.serverKeys.filter((key) => key in emittedVars);
|
|
6822
|
+
if (plaintextServerKeys.length > 0) {
|
|
6823
|
+
log.error([
|
|
6824
|
+
"deploy: server env keys cannot ship as plaintext Worker vars:",
|
|
6825
|
+
...plaintextServerKeys.map((key) => ` • ${key}`),
|
|
6826
|
+
"Remove them from Worker vars and set them with `void secret put <NAME>`."
|
|
6827
|
+
].join("\n"));
|
|
6828
|
+
return false;
|
|
6829
|
+
}
|
|
6830
|
+
const envContext = deriveSelfHostEnvContextFromVars(emittedVars, schemaFacts);
|
|
6831
|
+
if (schemaFacts.hasSchema) {
|
|
6832
|
+
let validateResult;
|
|
6833
|
+
try {
|
|
6834
|
+
validateResult = await (deps.validateEmittedVars ?? validateEmittedVarsDefault)({ root }, buildSchemaProbeEnv(accountId, apiBaseUrl));
|
|
6835
|
+
} catch (err) {
|
|
6836
|
+
log.error(`deploy: could not validate the emitted worker vars against the env schema — ${getErrorMessage(err)}`);
|
|
6837
|
+
return false;
|
|
6838
|
+
}
|
|
6839
|
+
if (validateResult.kind === "schema-error") {
|
|
6840
|
+
log.error(`deploy: ${selfHostSchemaFailureMessage(validateResult.reason)}`);
|
|
6841
|
+
return false;
|
|
6842
|
+
}
|
|
6843
|
+
envContext.invalidKeys = validateResult.invalidKeys;
|
|
6844
|
+
}
|
|
6845
|
+
if (authEnabled) {
|
|
6846
|
+
envContext.absentRequired = envContext.absentRequired.filter((key) => key !== BETTER_AUTH_SECRET_NAME);
|
|
6847
|
+
envContext.invalidKeys = envContext.invalidKeys.filter((key) => key !== BETTER_AUTH_SECRET_NAME);
|
|
6848
|
+
}
|
|
6849
|
+
if (!assertUploaderStillPinned()) return false;
|
|
6850
|
+
try {
|
|
6851
|
+
await (deps.dischargeSelfHostEnv ?? dischargeSelfHostEnvContext)(envContext, {
|
|
6852
|
+
root,
|
|
6853
|
+
configPath,
|
|
6854
|
+
accountId,
|
|
6855
|
+
workerName
|
|
6856
|
+
});
|
|
6857
|
+
} catch (err) {
|
|
6858
|
+
if (err instanceof SelfHostFirstDeployError || err instanceof SelfHostSecretListError || err instanceof SelfHostEnvValidationError || err instanceof SelfHostSchemaError) {
|
|
6859
|
+
log.error(err.message);
|
|
6860
|
+
return false;
|
|
6861
|
+
}
|
|
6862
|
+
throw err;
|
|
6863
|
+
}
|
|
6864
|
+
return true;
|
|
6865
|
+
}
|
|
6866
|
+
/** Deploy to the user's own Cloudflare account through the guarded native Worker flow. */
|
|
6867
|
+
async function runCloudflareDeploy(root, options, cliLog, deps = {}) {
|
|
6868
|
+
const initialCloudflareLink = readCloudflareLink(root);
|
|
6869
|
+
const initialCloudflareCandidate = readCloudflareCandidate(root);
|
|
6870
|
+
const exit = deps.exit ?? ((code) => process.exit(code));
|
|
6871
|
+
const voidConfig = readConfig(root);
|
|
6872
|
+
const atomic = options.atomic === true || voidConfig.deploy?.cloudflare?.mode === "atomic";
|
|
6873
|
+
if (atomic && (options.reuseExistingWorker || initialCloudflareLink)) {
|
|
6874
|
+
log.error("deploy: atomic deployment is unavailable during the existing Worker handoff. Complete the handoff first.");
|
|
6875
|
+
return exit(1);
|
|
6876
|
+
}
|
|
6877
|
+
const detectedFramework = detectFramework(root);
|
|
6878
|
+
const frameworkPreset = detectedFramework ? FRAMEWORK_PRESETS[detectedFramework.name] : void 0;
|
|
6879
|
+
cliLog.info("cloudflare_deploy_start", { provision: options.provision === true ? true : void 0 });
|
|
6880
|
+
if (isNodeTarget(voidConfig.target)) {
|
|
6881
|
+
log.error([
|
|
6882
|
+
`deploy: --platform cloudflare is not supported for the "${voidConfig.target}" target.`,
|
|
6883
|
+
"This backend deploys Cloudflare Workers only. Deploy a node/bun/deno build with its",
|
|
6884
|
+
"own host/runtime, or use the default Cloudflare target for --platform cloudflare."
|
|
6885
|
+
].join("\n"));
|
|
6886
|
+
return exit(1);
|
|
6887
|
+
}
|
|
6888
|
+
if (detectedFramework?.class === "a" && hasConfiguredVoidWorkerRoutingRules(voidConfig.routing)) {
|
|
6889
|
+
log.error([
|
|
6890
|
+
`deploy: native Cloudflare deployment cannot apply Void routing redirects, rewrites, fallbacks, or headers to ${detectedFramework.name}.`,
|
|
6891
|
+
"This framework owns its Worker request handler, so these rules would otherwise be ignored.",
|
|
6892
|
+
"Move the rules into the framework or its Cloudflare Worker, then retry."
|
|
6893
|
+
].join("\n"));
|
|
6894
|
+
return exit(1);
|
|
6895
|
+
}
|
|
6896
|
+
const provisionModule = await loadProvisionModule();
|
|
6897
|
+
const staticPreset = resolveCloudflareStaticPreset(root, voidConfig, options) ?? await resolveCloudflareVoidStaticPreset(root, voidConfig);
|
|
6898
|
+
if (staticPreset) {
|
|
6899
|
+
if (atomic) {
|
|
6900
|
+
log.error("deploy: atomic deployment is only for Workers with Durable Objects.");
|
|
6565
6901
|
return exit(1);
|
|
6566
6902
|
}
|
|
6903
|
+
return runCloudflareStaticDeploy(root, options, voidConfig, staticPreset, cliLog, deps, initialCloudflareLink, initialCloudflareCandidate);
|
|
6567
6904
|
}
|
|
6905
|
+
const source = await prepareCloudflareDeploySource(root, options, voidConfig);
|
|
6906
|
+
if (!source) return exit(1);
|
|
6907
|
+
const { configPath, desired, reasons, authEnabled, dialect, migrationsDir, migrations: preBuildMigrations, needsAI, aiBindingName, needsSandbox, needsLive, expectedCrons, needsEmail, emailHandlers } = source;
|
|
6568
6908
|
let rootConfig = parseRootWranglerConfig(configPath);
|
|
6569
6909
|
let apiBaseUrl;
|
|
6570
6910
|
try {
|
|
@@ -6862,6 +7202,10 @@ async function runCloudflareDeploy(root, options, cliLog, deps = {}) {
|
|
|
6862
7202
|
const passthroughIdentitySnapshot = snapshotPassthroughIdentities(preBuildRootConfig);
|
|
6863
7203
|
const passthroughRawFields = snapshotPassthroughRawFields(preBuildRootConfig);
|
|
6864
7204
|
const expectedContainers = reconstructExpectedContainers(voidConfig, root, preBuildRootConfig, needsSandbox);
|
|
7205
|
+
const expectedDurableObjectState = reconstructExpectedDurableObjectState(voidConfig, root, preBuildRootConfig, {
|
|
7206
|
+
needsSandbox,
|
|
7207
|
+
needsLive
|
|
7208
|
+
});
|
|
6865
7209
|
removeDeployPointer(root);
|
|
6866
7210
|
const buildChildEnv = scrubManagedDeployBuildMarkers(scrubWranglerAuthCredentials(deployChildEnv(accountId, apiBaseUrl)));
|
|
6867
7211
|
requireProvisionModule().deleteEnvVarCaseAware(buildChildEnv, CLOUDFLARE_DEPLOY_BUILD_ENV);
|
|
@@ -6897,6 +7241,10 @@ async function runCloudflareDeploy(root, options, cliLog, deps = {}) {
|
|
|
6897
7241
|
return exit(1);
|
|
6898
7242
|
}
|
|
6899
7243
|
const lifecycleConfigPath = (deps.resolveGeneratedConfigPath ?? ((projectRoot) => readGeneratedDeployConfig(projectRoot).path))(root);
|
|
7244
|
+
if (atomic && !Array.isArray(parseRootWranglerConfig(lifecycleConfigPath).migrations)) {
|
|
7245
|
+
log.error("deploy: atomic deployment is only for Workers with Durable Object migration history.");
|
|
7246
|
+
return exit(1);
|
|
7247
|
+
}
|
|
6900
7248
|
try {
|
|
6901
7249
|
deduplicateGeneratedCompatibilityFlags(lifecycleConfigPath, configPath);
|
|
6902
7250
|
const lifecycleOptions = {
|
|
@@ -6906,77 +7254,15 @@ async function runCloudflareDeploy(root, options, cliLog, deps = {}) {
|
|
|
6906
7254
|
accountId,
|
|
6907
7255
|
apiBaseUrl
|
|
6908
7256
|
};
|
|
6909
|
-
await (deps.assertDurableObjectLifecycle ?? assertCloudflareDurableObjectLifecycleSupported)(
|
|
7257
|
+
await (deps.assertDurableObjectLifecycle ?? assertCloudflareDurableObjectLifecycleSupported)({
|
|
7258
|
+
...lifecycleOptions,
|
|
7259
|
+
allowPendingAtomicMigration: atomic
|
|
7260
|
+
});
|
|
6910
7261
|
} catch (error) {
|
|
6911
7262
|
log.error(getErrorMessage(error));
|
|
6912
7263
|
return exit(1);
|
|
6913
7264
|
}
|
|
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
|
-
}
|
|
7265
|
+
if (!await validateCloudflarePostBuildEnv(root, configPath, accountId, apiBaseUrl, workerName, schemaFacts, authEnabled, existingWorker, approvedHandoffKv, deps, assertUploaderStillPinned)) return exit(1);
|
|
6980
7266
|
if (authEnabled && dialect === "sqlite") try {
|
|
6981
7267
|
await (deps.validateAuthMigrations ?? validateAuthMigrationSchema)(root, migrations);
|
|
6982
7268
|
} catch (err) {
|
|
@@ -7071,6 +7357,8 @@ async function runCloudflareDeploy(root, options, cliLog, deps = {}) {
|
|
|
7071
7357
|
aiBindingName,
|
|
7072
7358
|
authEnabled,
|
|
7073
7359
|
expectedContainers,
|
|
7360
|
+
expectedDurableObjectBindings: expectedDurableObjectState.bindings,
|
|
7361
|
+
expectedMigrations: expectedDurableObjectState.migrations,
|
|
7074
7362
|
expectedCrons
|
|
7075
7363
|
});
|
|
7076
7364
|
if (!inheritance.ok) {
|
|
@@ -7128,59 +7416,8 @@ async function runCloudflareDeploy(root, options, cliLog, deps = {}) {
|
|
|
7128
7416
|
return exit(1);
|
|
7129
7417
|
}
|
|
7130
7418
|
}
|
|
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, {
|
|
7419
|
+
if (!await applyAndVerifyRemoteD1Migrations(d1MigrateToken, configPath, runWrangler, assertUploaderStillPinned)) return exit(1);
|
|
7420
|
+
if (!verifyCloudflareDeployArtifact(root, deps, {
|
|
7184
7421
|
accountId,
|
|
7185
7422
|
workerName,
|
|
7186
7423
|
desired,
|
|
@@ -7192,21 +7429,14 @@ async function runCloudflareDeploy(root, options, cliLog, deps = {}) {
|
|
|
7192
7429
|
authEnabled,
|
|
7193
7430
|
requiredSecretNames: schemaFacts.requiredKeys,
|
|
7194
7431
|
expectedContainers,
|
|
7432
|
+
expectedDurableObjectBindings: expectedDurableObjectState.bindings,
|
|
7433
|
+
expectedMigrations: expectedDurableObjectState.migrations,
|
|
7195
7434
|
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
|
-
}
|
|
7435
|
+
})) return exit(1);
|
|
7208
7436
|
const queueConsumerCleanup = readWranglerManagedQueueCleanupCandidates(configPath);
|
|
7209
7437
|
if (existingWorker) assertCloudflareLinkUnchanged(root, pinnedHandoffLink);
|
|
7438
|
+
assertCloudflareCandidateUnchanged(root, initialCloudflareCandidate);
|
|
7439
|
+
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
7440
|
const candidateReceipt = pinnedHandoffLink?.candidateReceipt;
|
|
7211
7441
|
if (!deps.activateVersion && !deps.runWrangler && !cfUploaderIsPinned()) return exit(1);
|
|
7212
7442
|
const cfOutput = deps.activateVersion || deps.runWrangler ? null : await prepareBuildOutput();
|
|
@@ -7238,7 +7468,7 @@ async function runCloudflareDeploy(root, options, cliLog, deps = {}) {
|
|
|
7238
7468
|
configPath: generatedConfigPath,
|
|
7239
7469
|
preserveTriggers: existingWorker !== null,
|
|
7240
7470
|
expectedPreviousVersionId: existingWorker?.versionId,
|
|
7241
|
-
trustedInheritanceVersionIds: existingWorker
|
|
7471
|
+
trustedInheritanceVersionIds: existingWorker ? candidateReceipt?.parentVersionId === existingWorker.versionId ? candidateReceipt.versionIds : void 0 : initialCloudflareCandidate?.versionIds,
|
|
7242
7472
|
validateUploadedVersion: existingWorker ? async (versionId) => {
|
|
7243
7473
|
if (!assertUploaderStillPinned()) throw new Error("The deployment uploader changed.");
|
|
7244
7474
|
const uploaded = await (deps.readExistingWorker ?? readExistingCloudflareWorker)({
|
|
@@ -7249,7 +7479,9 @@ async function runCloudflareDeploy(root, options, cliLog, deps = {}) {
|
|
|
7249
7479
|
});
|
|
7250
7480
|
assertCloudflareBindingsPreserved(existingWorker, uploaded, approvedHandoffKv);
|
|
7251
7481
|
} : void 0,
|
|
7252
|
-
recordVerifiedCandidate: existingWorker ? (versionId) => recordCloudflareCandidate(root, pinnedHandoffLink, existingWorker.versionId, versionId) :
|
|
7482
|
+
recordVerifiedCandidate: existingWorker ? (versionId) => recordCloudflareCandidate(root, pinnedHandoffLink, existingWorker.versionId, versionId) : (versionId, parentVersionId) => {
|
|
7483
|
+
if (parentVersionId) recordCloudflareCandidateUpload(root, initialCloudflareCandidate, accountId, workerName, parentVersionId, versionId);
|
|
7484
|
+
},
|
|
7253
7485
|
message: encodeCloudflareVersionMessage(migrations.map((migration) => migration.name), {
|
|
7254
7486
|
...readCloudflareTriggerConfig(generatedConfigPath, configPath),
|
|
7255
7487
|
...existingWorker ? { preserve: true } : {}
|
|
@@ -7275,12 +7507,15 @@ async function runCloudflareDeploy(root, options, cliLog, deps = {}) {
|
|
|
7275
7507
|
previousTrafficConfig: readWranglerPublishedTrafficSnapshot(configPath),
|
|
7276
7508
|
queueConsumerCleanup,
|
|
7277
7509
|
verifyInheritedSecrets: true,
|
|
7510
|
+
atomic,
|
|
7278
7511
|
...initialAuthSecret ? { candidateSecrets: { [BETTER_AUTH_SECRET_NAME]: initialAuthSecret } } : {}
|
|
7279
7512
|
}).finally(() => cfOutput?.dispose());
|
|
7280
7513
|
if (!execution.ok) {
|
|
7514
|
+
if (execution.reason === "atomic-readiness-failed" || execution.reason === "atomic-readiness-access-denied") clearCloudflareCandidate(root);
|
|
7281
7515
|
await reportCloudflareActivationFailure(cliLog, needsSandbox && execution.containersUnavailable ? formatCloudflareSandboxUnavailable() : formatCloudflareActivationError(execution));
|
|
7282
7516
|
return exit(1);
|
|
7283
7517
|
}
|
|
7518
|
+
clearCloudflareCandidate(root);
|
|
7284
7519
|
if (existingWorker) completeCloudflareLink(root);
|
|
7285
7520
|
acknowledgeWranglerManagedQueueRemovals(configPath, queueConsumerCleanup);
|
|
7286
7521
|
rememberCloudflareWorkersDevSubdomain(root, accountId, execution.previewUrl);
|
|
@@ -7319,12 +7554,16 @@ async function activateCloudflareVersionWithProgress(activate, options) {
|
|
|
7319
7554
|
const progress = createSpinner();
|
|
7320
7555
|
progress.start("Checking the current Worker deployment...");
|
|
7321
7556
|
try {
|
|
7322
|
-
|
|
7557
|
+
const result = await activate({
|
|
7323
7558
|
...options,
|
|
7324
7559
|
onProgress: (message) => progress.message(message)
|
|
7325
7560
|
});
|
|
7326
|
-
|
|
7327
|
-
progress.
|
|
7561
|
+
if (result.ok) progress.stop("Worker version is ready.");
|
|
7562
|
+
else progress.error("Worker deployment stopped.");
|
|
7563
|
+
return result;
|
|
7564
|
+
} catch (error) {
|
|
7565
|
+
progress.error("Worker deployment stopped.");
|
|
7566
|
+
throw error;
|
|
7328
7567
|
}
|
|
7329
7568
|
}
|
|
7330
7569
|
function formatCloudflareActivationError(result) {
|
|
@@ -7360,7 +7599,11 @@ function formatCloudflareActivationError(result) {
|
|
|
7360
7599
|
"Set CLOUDFLARE_WORKERS_SUBDOMAIN to your account subdomain (for example \"my-team\")",
|
|
7361
7600
|
"and retry. Void caches it after a successful workers.dev deployment; production traffic is unchanged."
|
|
7362
7601
|
].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
|
|
7602
|
+
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." : ""}`;
|
|
7603
|
+
case "atomic-failed": return `deploy: Cloudflare could not publish the Worker atomically${status}; inspect production status before retrying.${cloudflareCode}${diagnostic}`;
|
|
7604
|
+
case "atomic-output-invalid": return "deploy: Cloudflare published atomically but did not report a version id or URL. Inspect `void project status` immediately.";
|
|
7605
|
+
case "atomic-readiness-failed":
|
|
7606
|
+
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
7607
|
case "readiness-failed": return ["deploy: the uploaded Worker Version did not pass /__void/ready.", formatCloudflareReadinessRestoration(result)].join("\n");
|
|
7365
7608
|
case "readiness-access-denied": return [
|
|
7366
7609
|
"deploy: Cloudflare Access blocked the uploaded Worker Version readiness probe.",
|
|
@@ -7491,7 +7734,10 @@ async function resolveCloudflareVoidStaticPreset(root, voidConfig) {
|
|
|
7491
7734
|
paths
|
|
7492
7735
|
});
|
|
7493
7736
|
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, {
|
|
7737
|
+
const bindings = inferProjectBindings(root, {
|
|
7738
|
+
paths,
|
|
7739
|
+
environment: "prod"
|
|
7740
|
+
});
|
|
7495
7741
|
const authEnabled = bindings.needsAuth || findVoidAuthConfig(root, paths) !== null || voidConfig.auth !== void 0;
|
|
7496
7742
|
if (hasNonPageBackend({
|
|
7497
7743
|
hasRoutes: routeScan.routes.length > 0,
|
|
@@ -7507,7 +7753,7 @@ async function resolveCloudflareVoidStaticPreset(root, voidConfig) {
|
|
|
7507
7753
|
appType: "static"
|
|
7508
7754
|
};
|
|
7509
7755
|
}
|
|
7510
|
-
async function runCloudflareStaticDeploy(root, options, voidConfig, preset, cliLog, deps, initialCloudflareLink) {
|
|
7756
|
+
async function runCloudflareStaticDeploy(root, options, voidConfig, preset, cliLog, deps, initialCloudflareLink, initialCloudflareCandidate) {
|
|
7511
7757
|
const exit = deps.exit ?? ((code) => process.exit(code));
|
|
7512
7758
|
const configPath = discoverRootWranglerConfig(root);
|
|
7513
7759
|
let rootConfig = parseRootWranglerConfig(configPath);
|
|
@@ -7657,6 +7903,8 @@ async function runCloudflareStaticDeploy(root, options, voidConfig, preset, cliL
|
|
|
7657
7903
|
});
|
|
7658
7904
|
const queueConsumerCleanup = readWranglerManagedQueueCleanupCandidates(configPath);
|
|
7659
7905
|
if (existingWorker) assertCloudflareLinkUnchanged(root, pinnedHandoffLink);
|
|
7906
|
+
assertCloudflareCandidateUnchanged(root, initialCloudflareCandidate);
|
|
7907
|
+
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
7908
|
const candidateReceipt = pinnedHandoffLink?.candidateReceipt;
|
|
7661
7909
|
if (!deps.activateVersion && !deps.runWrangler && !cfUploaderIsPinned()) return exit(1);
|
|
7662
7910
|
const cfOutput = deps.activateVersion || deps.runWrangler ? null : await prepareCfStaticBuildOutput({
|
|
@@ -7692,7 +7940,7 @@ async function runCloudflareStaticDeploy(root, options, voidConfig, preset, cliL
|
|
|
7692
7940
|
configPath: staticConfigPath,
|
|
7693
7941
|
preserveTriggers: existingWorker !== null,
|
|
7694
7942
|
expectedPreviousVersionId: existingWorker?.versionId,
|
|
7695
|
-
trustedInheritanceVersionIds: existingWorker
|
|
7943
|
+
trustedInheritanceVersionIds: existingWorker ? candidateReceipt?.parentVersionId === existingWorker.versionId ? candidateReceipt.versionIds : void 0 : initialCloudflareCandidate?.versionIds,
|
|
7696
7944
|
validateUploadedVersion: existingWorker ? async (versionId) => {
|
|
7697
7945
|
if (!uploaderIsPinned()) throw new Error("The deployment uploader changed.");
|
|
7698
7946
|
const uploaded = await (deps.readExistingWorker ?? readExistingCloudflareWorker)({
|
|
@@ -7703,7 +7951,9 @@ async function runCloudflareStaticDeploy(root, options, voidConfig, preset, cliL
|
|
|
7703
7951
|
});
|
|
7704
7952
|
assertCloudflareBindingsPreserved(existingWorker, uploaded, [], { staticAssetsBinding: "ASSETS" });
|
|
7705
7953
|
} : void 0,
|
|
7706
|
-
recordVerifiedCandidate: existingWorker ? (versionId) => recordCloudflareCandidate(root, pinnedHandoffLink, existingWorker.versionId, versionId) :
|
|
7954
|
+
recordVerifiedCandidate: existingWorker ? (versionId) => recordCloudflareCandidate(root, pinnedHandoffLink, existingWorker.versionId, versionId) : (versionId, parentVersionId) => {
|
|
7955
|
+
if (parentVersionId) recordCloudflareCandidateUpload(root, initialCloudflareCandidate, accountId, workerName, parentVersionId, versionId);
|
|
7956
|
+
},
|
|
7707
7957
|
workerName,
|
|
7708
7958
|
message: encodeCloudflareVersionMessage([], {
|
|
7709
7959
|
...readCloudflareTriggerConfig(staticConfigPath, configPath),
|
|
@@ -7734,6 +7984,7 @@ async function runCloudflareStaticDeploy(root, options, voidConfig, preset, cliL
|
|
|
7734
7984
|
await reportCloudflareActivationFailure(cliLog, formatCloudflareActivationError(execution));
|
|
7735
7985
|
return exit(1);
|
|
7736
7986
|
}
|
|
7987
|
+
clearCloudflareCandidate(root);
|
|
7737
7988
|
if (existingWorker) completeCloudflareLink(root);
|
|
7738
7989
|
acknowledgeWranglerManagedQueueRemovals(configPath, queueConsumerCleanup);
|
|
7739
7990
|
rememberCloudflareWorkersDevSubdomain(root, accountId, execution.previewUrl);
|
|
@@ -7828,6 +8079,7 @@ async function runDeployInner(root, options, cliLog) {
|
|
|
7828
8079
|
reuseExistingWorker: true
|
|
7829
8080
|
};
|
|
7830
8081
|
const platform = resolveDeploymentPlatform(root, options);
|
|
8082
|
+
if (options?.atomic && platform !== "cloudflare") throw new Error("deploy: --atomic is available only for Cloudflare Workers.");
|
|
7831
8083
|
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
8084
|
const targetLabel = platform === "cloudflare" ? "Cloudflare" : "Void";
|
|
7833
8085
|
log.info(`Deployment target: ${targetLabel}`);
|
|
@@ -7855,7 +8107,7 @@ async function runManagedDeploy(root, options, cliLog) {
|
|
|
7855
8107
|
}
|
|
7856
8108
|
token ??= getToken(root);
|
|
7857
8109
|
if (!token) {
|
|
7858
|
-
log.error("No auth token found. Run `void
|
|
8110
|
+
log.error("No auth token found. Run `void account login` first.");
|
|
7859
8111
|
process.exit(1);
|
|
7860
8112
|
}
|
|
7861
8113
|
const client = new PlatformClient(token, {
|
|
@@ -7863,11 +8115,16 @@ async function runManagedDeploy(root, options, cliLog) {
|
|
|
7863
8115
|
cliLog
|
|
7864
8116
|
});
|
|
7865
8117
|
const requestedProjectSlug = getRequestedProjectSlug(options);
|
|
8118
|
+
const linkedProject = readProjectConfig(root);
|
|
7866
8119
|
let config = null;
|
|
7867
8120
|
if (requestedProjectSlug) {
|
|
7868
|
-
const
|
|
7869
|
-
|
|
7870
|
-
|
|
8121
|
+
const linked = linkedProject?.slug === requestedProjectSlug ? await client.getProject(linkedProject.projectId) : null;
|
|
8122
|
+
const project = linked?.slug === requestedProjectSlug ? linked : await client.findProjectBySlug(requestedProjectSlug);
|
|
8123
|
+
assertProjectDeployAccess(project ?? void 0);
|
|
8124
|
+
config = project ? {
|
|
8125
|
+
projectId: project.id,
|
|
8126
|
+
slug: project.slug
|
|
8127
|
+
} : null;
|
|
7871
8128
|
if (!config) {
|
|
7872
8129
|
if (!process.stdin.isTTY) config = await createProjectFromSlug(root, client, requestedProjectSlug, cliLog);
|
|
7873
8130
|
else {
|
|
@@ -7880,11 +8137,10 @@ async function runManagedDeploy(root, options, cliLog) {
|
|
|
7880
8137
|
}
|
|
7881
8138
|
}
|
|
7882
8139
|
} else {
|
|
7883
|
-
config =
|
|
8140
|
+
config = linkedProject;
|
|
7884
8141
|
if (config) {
|
|
7885
|
-
const projects = await client.listProjects();
|
|
7886
8142
|
const { projectId, slug } = config;
|
|
7887
|
-
const project =
|
|
8143
|
+
const project = await client.getProject(projectId);
|
|
7888
8144
|
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
8145
|
assertProjectDeployAccess(project);
|
|
7890
8146
|
}
|
|
@@ -7942,7 +8198,7 @@ async function runManagedDeploy(root, options, cliLog) {
|
|
|
7942
8198
|
} catch (error) {
|
|
7943
8199
|
if (isExpiredTokenError(error)) {
|
|
7944
8200
|
if (getTokenSource() === "ci") throw new Error("`VOID_TOKEN` is invalid or expired. Generate a new token and try again.");
|
|
7945
|
-
if (!process.stdin.isTTY || reauthenticated) throw new Error("Auth token expired. Run `void
|
|
8201
|
+
if (!process.stdin.isTTY || reauthenticated) throw new Error("Auth token expired. Run `void account login` and try again.");
|
|
7946
8202
|
log.warn("Auth token expired. Re-authenticating...");
|
|
7947
8203
|
await promptForLoginToken(root);
|
|
7948
8204
|
log.success("Re-authenticated. Retrying deploy...");
|
|
@@ -7956,7 +8212,7 @@ function assertProjectDeployAccess(project) {
|
|
|
7956
8212
|
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
8213
|
}
|
|
7958
8214
|
async function promptDeployProjectConfig(root, client, cliLog) {
|
|
7959
|
-
const projects = await client.
|
|
8215
|
+
const projects = await client.listProjectChoices();
|
|
7960
8216
|
const deployableProjects = projects.filter((project) => project.role !== "reader");
|
|
7961
8217
|
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
8218
|
if (await promptProjectSetupAction("Set up a Void project for deploy:", { includeLink: deployableProjects.length > 0 }) === "create") return promptAndCreateProject(root, client);
|
|
@@ -8475,7 +8731,8 @@ async function runFrameworkDeploy(root, config, client, detected, fwPreset, void
|
|
|
8475
8731
|
const scanDirs = voidConfig.inference?.scanDirs ?? FRAMEWORK_SCAN_DIRS;
|
|
8476
8732
|
const bindings = inferProjectBindings(root, {
|
|
8477
8733
|
...inferenceOptions,
|
|
8478
|
-
paths
|
|
8734
|
+
paths,
|
|
8735
|
+
environment: "prod"
|
|
8479
8736
|
}, scanDirs);
|
|
8480
8737
|
if (bindings.needsAuth || findVoidAuthConfig(root, paths) !== null || voidConfig.auth !== void 0) {
|
|
8481
8738
|
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 +8953,10 @@ async function runFullDeploy(root, config, client, voidConfig, fwPreset, skipBui
|
|
|
8696
8953
|
const paths = resolveProjectPaths(root, deployConfig);
|
|
8697
8954
|
const dialect = getDatabaseDialect(deployConfig);
|
|
8698
8955
|
const deployScanDirs = deployConfig.inference?.scanDirs ?? (isFrameworkMode ? FRAMEWORK_SCAN_DIRS : void 0);
|
|
8699
|
-
const bindings = inferProjectBindings(root, {
|
|
8956
|
+
const bindings = inferProjectBindings(root, {
|
|
8957
|
+
paths,
|
|
8958
|
+
environment: "prod"
|
|
8959
|
+
}, deployScanDirs);
|
|
8700
8960
|
if (isSandboxEnabled(deployConfig)) bindings.needsSandbox = true;
|
|
8701
8961
|
const authEnabled = bindings.needsAuth || findVoidAuthConfig(root, paths) !== null || deployConfig.auth !== void 0;
|
|
8702
8962
|
const effectiveBindings = authEnabled ? {
|
|
@@ -9202,4 +9462,4 @@ function resolveWorkerDirName(distDir, fwPreset, buildCommand) {
|
|
|
9202
9462
|
throw new Error("deploy: Worker output not found. Expected dist/ssr/ or dist/rsc/.");
|
|
9203
9463
|
}
|
|
9204
9464
|
//#endregion
|
|
9205
|
-
export {
|
|
9465
|
+
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 };
|