void 1.2.1 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (200) hide show
  1. package/dist/{account-cmd-CdUll_35.mjs → account-cmd-HP8bixYo.mjs} +3 -3
  2. package/dist/{application-analysis-fEqoSeMp.mjs → application-analysis-DDOQwiXk.mjs} +18 -12
  3. package/dist/{application-routing-DAhNP4u3.mjs → application-routing-4719u_kf.mjs} +3 -1
  4. package/dist/auth-g2TQbDLD.d.mts +70 -0
  5. package/dist/{auth-link-C87vGXM-.mjs → auth-link-CedYpDCy.mjs} +3 -3
  6. package/dist/{auth-router-6I81r-ix.mjs → auth-router-vafo7x8w.mjs} +11 -6
  7. package/dist/{better-auth-shared-D-6z0q0f.mjs → better-auth-shared-7FM3Uk2N.mjs} +48 -2
  8. package/dist/{better-auth-shared-DVk2DkTW.d.mts → better-auth-shared-BHB8kiTE.d.mts} +1 -1
  9. package/dist/{build-cmd-ex1g-j_e.mjs → build-cmd-9vUAQ1_V.mjs} +1 -1
  10. package/dist/{cache-oHzrnY3z.mjs → cache-jvwLNb0h.mjs} +1 -1
  11. package/dist/{cancel-deploy-viAMD0Q_.mjs → cancel-deploy-Dw0UmWKO.mjs} +1 -1
  12. package/dist/{cf-build-output-BhVxldCw.mjs → cf-build-output-XpNR9zoh.mjs} +122 -5
  13. package/dist/cf-build-output-bd8Uwv1P.mjs +1 -0
  14. package/dist/{cf-worker-settings-BECvvTVd.mjs → cf-worker-settings-Dg27RzyT.mjs} +11 -5
  15. package/dist/cli/cli.mjs +41 -32
  16. package/dist/cli/cloudflare-operation-process.mjs +35 -8
  17. package/dist/cli/env-schema-probe.mjs +2 -2
  18. package/dist/{client-BEkdj1kx.mjs → client-B3LnB_bE.mjs} +8 -1
  19. package/dist/client-BZb9j66F.mjs +1 -0
  20. package/dist/{cloudflare-auth-Byo_0_N9.mjs → cloudflare-auth-DyD_kVFr.mjs} +1 -1
  21. package/dist/{cloudflare-cmd-DMzCv12s.mjs → cloudflare-cmd-D-b_u3T4.mjs} +2 -2
  22. package/dist/{cloudflare-config-DchHxPTo.mjs → cloudflare-config-CH1AylZT.mjs} +14 -3
  23. package/dist/{cloudflare-connect-CCRTVg-I.mjs → cloudflare-connect-zTJh8UnN.mjs} +2 -2
  24. package/dist/{cloudflare-operations-Dh9dEHJj.mjs → cloudflare-operations-Bc-7fN44.mjs} +4 -4
  25. package/dist/{cloudflare-operations-DsSaw2BT.mjs → cloudflare-operations-BtulCNOg.mjs} +1 -1
  26. package/dist/{config-BU6hMu1W.mjs → config-BV2ASlpn.mjs} +1 -1
  27. package/dist/{config-DQfHOKh9.d.mts → config-CAdZVTLN.d.mts} +4 -1
  28. package/dist/config-D-6q7EBH.mjs +87 -0
  29. package/dist/{config-DHgSEWT7.mjs → config-OFOAimzt.mjs} +5 -3
  30. package/dist/config-entry.d.mts +1 -1
  31. package/dist/{config-BIaXIkkv.mjs → config-tqMM6DwY.mjs} +1 -1
  32. package/dist/{connect-k7R2rPVA.mjs → connect-BOM6zvFX.mjs} +4 -4
  33. package/dist/{create-project-DV71ol5d.mjs → create-project-Bxd02EHN.mjs} +1 -1
  34. package/dist/{create-project-DTuy-l0z.mjs → create-project-C2K0DN2O.mjs} +1 -1
  35. package/dist/{db-DVOkLH5X.mjs → db-Cdvr3zwG.mjs} +18 -18
  36. package/dist/{db-types-NGxPwnlt.mjs → db-types-0eCiqYb1.mjs} +1 -1
  37. package/dist/{delete-BbP5eopu.mjs → delete-lETE6Tpt.mjs} +1 -1
  38. package/dist/deploy-CX94CmKa.mjs +2 -0
  39. package/dist/{deploy-7H32EnUs.mjs → deploy-CdM-LAxX.mjs} +473 -148
  40. package/dist/{deploy-managed-static-DlvcvnQT.mjs → deploy-managed-static-DjeBFG2c.mjs} +43 -20
  41. package/dist/{deploy-transport-BzGEj0Ge.mjs → deploy-transport-DIq_gFTP.mjs} +14 -13
  42. package/dist/deploy.d.mts +2 -0
  43. package/dist/deploy.mjs +8 -5
  44. package/dist/{dispatch-DoUnxTNo.mjs → dispatch-CLa2LThw.mjs} +76 -7
  45. package/dist/{domain-CA2wBgra.mjs → domain-DyhNtdYf.mjs} +2 -2
  46. package/dist/{email-DXpCc77w.mjs → email-DM2wDcBN.mjs} +59 -10
  47. package/dist/{email-cloudflare-D03g2TkS.mjs → email-cloudflare-PMbAev9Q.mjs} +124 -10
  48. package/dist/{env-DgOQ9_8S.mjs → env-78hbN-oI.mjs} +3 -3
  49. package/dist/{env-BJjULvL0.mjs → env-BaMz0j7H.mjs} +6 -1
  50. package/dist/{env-validation-Dwq3PJzK.mjs → env-validation-B3VobvXm.mjs} +2 -1
  51. package/dist/{env-validation-BmsdCZEk.mjs → env-validation-BUfFZ6bt.mjs} +1 -1
  52. package/dist/error-pages-CLIJ7aYq.mjs +37 -0
  53. package/dist/gen-BhWBT4iu.mjs +1 -0
  54. package/dist/{gen-BfmcIi2g.mjs → gen-CFmsUsW1.mjs} +3 -3
  55. package/dist/{github-cmd-CY9LUqLh.mjs → github-cmd-De-_IWbM.mjs} +1 -1
  56. package/dist/{handler-BbkSPzGF.d.mts → handler-BHktmuTL.d.mts} +4 -2
  57. package/dist/{headers-D522zd0A.mjs → headers--vaK_chu.mjs} +1 -1
  58. package/dist/{help-CxSlPpzJ.mjs → help-CKbrhZha.mjs} +16 -1
  59. package/dist/help-qOZr3wng.mjs +1 -0
  60. package/dist/index.d.mts +3 -5
  61. package/dist/index.mjs +370 -140
  62. package/dist/{info-7VDlhtyy.mjs → info-Yg0-V5Rs.mjs} +4 -4
  63. package/dist/{init-DxYyOs4-.mjs → init-CDiJQycf.mjs} +241 -206
  64. package/dist/{link-Ddmod1dZ.mjs → link-Dllip08S.mjs} +2 -2
  65. package/dist/{list-MogaugiO.mjs → list-BYRP6am0.mjs} +2 -2
  66. package/dist/{live-Bt8Y_0bg.d.mts → live-BllfDuzA.d.mts} +2 -2
  67. package/dist/{local-d1-BHBnKWRb.mjs → local-d1-CAwAs9GH.mjs} +1 -1
  68. package/dist/login-BAPmYnb7.mjs +1 -0
  69. package/dist/{login-Cttnagmm.mjs → login-PcFy5mlC.mjs} +2 -2
  70. package/dist/{logs-CAszUWZI.mjs → logs-DmJTBhed.mjs} +2 -2
  71. package/dist/{migrate-DyT2jJ8y.mjs → migrate-B8S2xTcb.mjs} +5 -66
  72. package/dist/migrate-BIYTPQE6.mjs +1 -0
  73. package/dist/nitro.mjs +4 -4
  74. package/dist/{node-WB7c2N4L.mjs → node-CDOPrGSl.mjs} +5 -5
  75. package/dist/{operator-args-UnE8Y2eK.mjs → operator-args-BsJIYXaT.mjs} +8 -1
  76. package/dist/operator-cmd-CjazwOyb.mjs +1 -0
  77. package/dist/{operator-cmd-skshjMGl.mjs → operator-cmd-DmkmS2wL.mjs} +4 -3
  78. package/dist/pages/client.d.mts +32 -4
  79. package/dist/pages/client.mjs +186 -29
  80. package/dist/pages/index.d.mts +34 -2
  81. package/dist/pages/index.mjs +96 -55
  82. package/dist/pages/islands-plugin.d.mts +1 -1
  83. package/dist/pages/islands-plugin.mjs +9 -3
  84. package/dist/pages/protocol.d.mts +2 -2
  85. package/dist/platform-args-BC8_hsDj.mjs +1 -0
  86. package/dist/{platform-args-DVbVClZl.mjs → platform-args-BMD2gjc_.mjs} +1 -1
  87. package/dist/{platform-auth-config-C-pm5Qzx.mjs → platform-auth-config-CImnfohz.mjs} +3 -3
  88. package/dist/{platform-auth-protection-SHhvim1L.mjs → platform-auth-protection-BogLhtHi.mjs} +2 -2
  89. package/dist/{platform-auth-recovery-DXVWs-wA.mjs → platform-auth-recovery-B-mEaWEi.mjs} +2 -2
  90. package/dist/{platform-cmd-PiNRkopU.mjs → platform-cmd-CV8NxIIn.mjs} +1 -1
  91. package/dist/{platform-cmd-D5I1beUX.mjs → platform-cmd-DZK2ixMl.mjs} +4 -4
  92. package/dist/{platform-domain-jpmBfZeb.mjs → platform-domain-CRvelPGE.mjs} +2 -2
  93. package/dist/{platform-lifecycle-DyKmuNY6.mjs → platform-lifecycle-CPYY7E9B.mjs} +103 -41
  94. package/dist/{platform-lifecycle-DH3Yr1qQ.mjs → platform-lifecycle-DwXq7kZt.mjs} +1 -1
  95. package/dist/{platform-management--vDwSn35.mjs → platform-management-BOnGbMSM.mjs} +1 -1
  96. package/dist/{platform-management-7m-PLaPJ.mjs → platform-management-lXdgGgAM.mjs} +1 -1
  97. package/dist/{platform-recovery-BiNpZZab.mjs → platform-recovery-noaALXnE.mjs} +2 -2
  98. package/dist/{plugin-inference-DUjCd55H.mjs → plugin-inference-CeiB6BG5.mjs} +53 -18
  99. package/dist/{prepare-BcAE5Sdj.mjs → prepare-BuOS18AM.mjs} +1 -1
  100. package/dist/{prepare-DA-17DhO.mjs → prepare-D604Yiyr.mjs} +12 -8
  101. package/dist/prepare-DU-tOpS5.mjs +1 -0
  102. package/dist/{prerender-render-Cijv7UFo.mjs → prerender-render-CaShbHJ3.mjs} +13 -1
  103. package/dist/prerender-render.d.mts +1 -0
  104. package/dist/prerender-render.mjs +1 -1
  105. package/dist/{project-cmd-DA4K5faU.mjs → project-cmd-DBYqAIbe.mjs} +15 -15
  106. package/dist/{project-team-CQBNveX3.mjs → project-team-BjCLgTRC.mjs} +1 -1
  107. package/dist/{project-token-CCalFyQf.mjs → project-token-BB6PwaA9.mjs} +1 -1
  108. package/dist/{project-tsconfig-Itv1f4WC.mjs → project-tsconfig-CVvk6Z_e.mjs} +24 -2
  109. package/dist/{project-zero-trust-DPnkiEuT.mjs → project-zero-trust-CWDh1P_t.mjs} +1 -1
  110. package/dist/{protocol-BBDpJz3G.d.mts → protocol-D5XDySYu.d.mts} +2 -2
  111. package/dist/{provision-BFLCrnUp.mjs → provision-DfxLCg-d.mjs} +1 -1
  112. package/dist/{provision-DtROpNNI.mjs → provision-DztLJ97X.mjs} +24 -8
  113. package/dist/{requests-BpH0kImL.mjs → requests-D_pbzDyz.mjs} +1 -1
  114. package/dist/{rollback-CXS1tAa-.mjs → rollback-CjfIYsJx.mjs} +2 -2
  115. package/dist/{route-types-BZi26DVS.mjs → route-types-DvEGmPif.mjs} +109 -30
  116. package/dist/routes-stub.d.mts +22 -13
  117. package/dist/runtime/auth.d.mts +2 -2
  118. package/dist/runtime/better-auth-mysql.d.mts +1 -1
  119. package/dist/runtime/better-auth-mysql.mjs +1 -1
  120. package/dist/runtime/better-auth-pg.d.mts +1 -1
  121. package/dist/runtime/better-auth-pg.mjs +1 -1
  122. package/dist/runtime/better-auth.d.mts +1 -1
  123. package/dist/runtime/better-auth.mjs +1 -1
  124. package/dist/runtime/client-react.d.mts +1 -1
  125. package/dist/runtime/client-solid.d.mts +1 -1
  126. package/dist/runtime/client-svelte.d.mts +1 -1
  127. package/dist/runtime/client-vue.d.mts +1 -1
  128. package/dist/runtime/client.d.mts +1 -1
  129. package/dist/runtime/handler.d.mts +1 -1
  130. package/dist/runtime/live-client.d.mts +1 -1
  131. package/dist/runtime/live.d.mts +1 -1
  132. package/dist/runtime/log.mjs +19 -1
  133. package/dist/runtime/routing.d.mts +5 -4
  134. package/dist/runtime/routing.mjs +14 -73
  135. package/dist/runtime/validator.d.mts +1 -1
  136. package/dist/runtime/ws-server.d.mts +3 -3
  137. package/dist/runtime/ws.d.mts +1 -1
  138. package/dist/runtime/ws.mjs +4 -2
  139. package/dist/{scan-8IzYXiU_.mjs → scan-N9WzdcAl.mjs} +302 -23
  140. package/dist/{secret-BbXHfLAt.mjs → secret-3X0PxmuX.mjs} +9 -12
  141. package/dist/static-asset-marker-Btf-6oCD.mjs +32 -0
  142. package/dist/{types-7AIz0OZu.d.mts → types-w72dljaA.d.mts} +6 -1
  143. package/dist/{version-metadata-tS39iW09.mjs → version-metadata-D2vfMQzv.mjs} +2 -1
  144. package/dist/worker-conditions-AWFRcFxR.mjs +11 -0
  145. package/dist/{wrangler-F96NnLyb.mjs → wrangler-I-scB_1t.mjs} +82 -13
  146. package/dist/wrangler-UnwdISay.mjs +1 -0
  147. package/dist/{wrapper-D3sZyh2C.mjs → wrapper-BBl1rC32.mjs} +8 -12
  148. package/dist/{ws-BH-im_tX.d.mts → ws-B3ClMVDh.d.mts} +3 -2
  149. package/docs/guide/auth.md +4 -2
  150. package/docs/guide/edge/redirects.md +22 -0
  151. package/docs/guide/edge/static-assets.md +10 -0
  152. package/docs/guide/email/domains.md +1 -1
  153. package/docs/guide/email/receiving.md +2 -0
  154. package/docs/guide/email/sending.md +1 -1
  155. package/docs/guide/pages-routing/actions-and-forms.md +43 -13
  156. package/docs/guide/pages-routing/markdown.md +2 -0
  157. package/docs/guide/pages-routing/overview.md +33 -2
  158. package/docs/guide/platform/administration/email.md +18 -0
  159. package/docs/guide/platform/installation/maintenance.md +3 -1
  160. package/docs/guide/platform/installation/prerequisites.md +9 -4
  161. package/docs/guide/platform/installation/uninstall.md +2 -0
  162. package/docs/guide/queues.md +13 -1
  163. package/docs/guide/server-routing.md +40 -2
  164. package/docs/guide/ssg.md +8 -0
  165. package/docs/guide/type-safety.md +7 -7
  166. package/docs/guide/websockets.md +4 -2
  167. package/docs/integrations/cloudflare.md +16 -7
  168. package/docs/reference/api/auth.md +6 -2
  169. package/docs/reference/api/deploy.md +9 -5
  170. package/docs/reference/api/pages.md +6 -4
  171. package/docs/reference/cli/deploy.md +10 -9
  172. package/docs/reference/cli/email.md +13 -0
  173. package/docs/reference/cli/platform-email.md +2 -2
  174. package/docs/reference/cli.md +1 -0
  175. package/docs/reference/config.md +11 -1
  176. package/docs/reference/structure.md +3 -1
  177. package/package.json +9 -7
  178. package/schema.json +4 -0
  179. package/skills/void/SKILL.md +1 -1
  180. package/templates/assets/icons.svg +49 -0
  181. package/templates/assets/react.svg +1 -0
  182. package/templates/assets/solid.svg +1 -0
  183. package/templates/assets/stack.svg +35 -0
  184. package/templates/assets/svelte.svg +1 -0
  185. package/templates/assets/void.svg +5 -0
  186. package/templates/assets/vue.svg +1 -0
  187. package/dist/auth-DkcFflXV.d.mts +0 -42
  188. package/dist/cf-build-output-BJHuSsVN.mjs +0 -1
  189. package/dist/client-BiRDZTSd.mjs +0 -1
  190. package/dist/config-CyUJzi3q.mjs +0 -32
  191. package/dist/deploy-CE0Ev0Ob.mjs +0 -2
  192. package/dist/gen-NrOlWZaG.mjs +0 -1
  193. package/dist/help-BeAFFE5C.mjs +0 -1
  194. package/dist/login-DgDwlKc_.mjs +0 -1
  195. package/dist/migrate-n49ZeS1X.mjs +0 -1
  196. package/dist/operator-cmd-d2MvJOrl.mjs +0 -1
  197. package/dist/parse-filename-DioPHiR9.mjs +0 -77
  198. package/dist/platform-args-kQrgxScY.mjs +0 -1
  199. package/dist/prepare-C4I0f--h.mjs +0 -1
  200. package/dist/wrangler-BLb3_luP.mjs +0 -1
@@ -1,49 +1,50 @@
1
1
  import { n as __toESM, t as __commonJSMin } from "./rolldown-runtime-3h0WiCiA.mjs";
2
2
  import { a as join, c as resolve, n as dirname, o as normalize, r as extname, s as relative, t as basename } from "./dist-ipQi0Q8y.mjs";
3
3
  import { t as require_picocolors } from "./picocolors-BsDfhxIw.mjs";
4
- import { r as detectFramework } from "./plugin-inference-DUjCd55H.mjs";
4
+ import { r as detectFramework } from "./plugin-inference-CeiB6BG5.mjs";
5
5
  import { n as readProjectPaths, t as assertNoRootSourceConventionConflicts } from "./project-paths-DGu_QZ_Q.mjs";
6
- import { m as resolveBindingNames, p as readConfig, u as isNodeTarget } from "./config-DHgSEWT7.mjs";
7
- import { a as hasSandboxSqliteMigration, c as sandboxContainerConfig, i as assertSandboxNamespaceConfig, o as requiresSandboxPlatformImage, r as SANDBOX_MIGRATION_TAG, s as resolveSandboxConfig, t as analyzeApplicationSync } from "./application-analysis-fEqoSeMp.mjs";
6
+ import { m as resolveBindingNames, p as readConfig, u as isNodeTarget } from "./config-OFOAimzt.mjs";
7
+ import { a as hasSandboxSqliteMigration, c as sandboxContainerConfig, i as assertSandboxNamespaceConfig, o as requiresSandboxPlatformImage, r as SANDBOX_MIGRATION_TAG, s as resolveSandboxConfig, t as analyzeApplicationSync } from "./application-analysis-DDOQwiXk.mjs";
8
8
  import { t as collectMigrations } from "./collect-Dew86qce.mjs";
9
9
  import { o as validateSsrEntry } from "./entry-BEM8ZuGP.mjs";
10
10
  import { r as hasEmailHandlers } from "./email-B9ayYQEG.mjs";
11
- import { i as voidWarn } from "./log-BMwmN5Ae.mjs";
12
11
  import { a as resolveDistDir, c as hasDocumentRoutes, l as resolveAssetConfig, n as collectRevalidate, o as resolveWorkerDirName, r as hasRevalidate, s as hasApiRoutes } from "./isr-config-fZaJJ8t7.mjs";
13
12
  import { t as writeFileAtomic } from "./atomic-write-Dq6R0BPN.mjs";
14
13
  import { s as listPlatformConnections } from "./platform-registry-B9mWX9LO.mjs";
15
14
  import { c as writeDeploymentPlatform, n as readDeploymentPlatform, r as readProjectConfig } from "./project-rqDnVsJN.mjs";
16
15
  import { n as readGeneratedWranglerConfigFile } from "./generated-wrangler-config-DeWj5F9Y.mjs";
17
- import { i as persistCloudflareConfig, r as materializeCloudflareConfig, s as stashCloudflareDeployPointer } from "./cloudflare-config-DchHxPTo.mjs";
18
- import { A as syncWranglerWebSockets, C as readWranglerManagedQueueCleanupCandidates, D as sameMigrationsDir, E as resolveLiveBindingConfig, M as writeProvisionedWranglerConfig, N as writeWranglerPublishedTrafficSnapshot, a as LIVE_MIGRATION_TAG, c as bindingEntriesForField, h as nextDurableObjectMigrationTag, k as syncWranglerDurableObjects, m as hasDurableObjectSqliteMigration, o as acknowledgeWranglerManagedQueueRemovals, r as FRIENDLY_BINDING_NAMES, v as readExistingLiveBindingConfig, w as readWranglerPublishedTrafficSnapshot } from "./wrangler-F96NnLyb.mjs";
16
+ import { a as persistCloudflareConfig, c as stashCloudflareDeployPointer, i as materializeCloudflareConfig } from "./cloudflare-config-CH1AylZT.mjs";
17
+ import { A as syncWranglerWebSockets, C as readWranglerManagedQueueCleanupCandidates, D as sameMigrationsDir, E as resolveLiveBindingConfig, L as writeVoidProjectConfig, M as writeProvisionedWranglerConfig, N as writeWranglerPublishedTrafficSnapshot, a as LIVE_MIGRATION_TAG, c as bindingEntriesForField, h as nextDurableObjectMigrationTag, k as syncWranglerDurableObjects, m as hasDurableObjectSqliteMigration, o as acknowledgeWranglerManagedQueueRemovals, r as FRIENDLY_BINDING_NAMES, v as readExistingLiveBindingConfig, w as readWranglerPublishedTrafficSnapshot } from "./wrangler-I-scB_1t.mjs";
19
18
  import { r as trustedCloudflareWorkerAccessHeaders, t as cfAccessHeaders } from "./cf-access-BM9G0lhO.mjs";
20
19
  import { t as ensurePlatformAccessToken } from "./cf-access-CWP4avfP.mjs";
21
20
  import { a as getApiUrl, c as getToken, l as getTokenSource } from "./auth-B6iOCjKI.mjs";
22
- import { c as resolveRemoteMode, t as CLOUDFLARE_DEPLOY_BUILD_ENV } from "./env-BJjULvL0.mjs";
23
- import { a as buildEnv, n as readVersionMetadataBinding, r as selectNativeVersionMetadataBinding, t as CLOUDFLARE_PRESERVE_BINDINGS_BUILD_ENV } from "./version-metadata-tS39iW09.mjs";
24
- import { a as emailConfigInputs, c as renderAddressMap, d as collectPrerenderPathsNode, f as prerenderPages, i as createNodeEmailDns, l as renderEmailChecklist, n as SEND_EMAIL_BINDING, o as preflightEmail, p as prerenderPagesNode, r as applyEmailSetup, t as EMAIL_FROM_VAR, u as collectPrerenderPaths } from "./email-cloudflare-D03g2TkS.mjs";
25
- import { n as completeApplicationAnalysis, t as analyzeApplication } from "./application-routing-DAhNP4u3.mjs";
26
- import { a as record, i as migrateBuiltWranglerConfig, n as prepareCfFrameworkBuildOutput, r as prepareCfStaticBuildOutput, t as prepareCfBuildOutput } from "./cf-build-output-BhVxldCw.mjs";
21
+ import { i as otherQueueConsumers, n as chooseCloudflareQueueName, o as scopedCloudflareQueueName, r as cloudflareQueueName } from "./dispatch-CLa2LThw.mjs";
22
+ import { l as resolveRemoteMode, n as CLOUDFLARE_QUEUE_NAMES_BUILD_ENV, t as CLOUDFLARE_DEPLOY_BUILD_ENV } from "./env-BaMz0j7H.mjs";
23
+ import { t as assertNoPrerenderFailures } from "./prerender-render-CaShbHJ3.mjs";
24
+ import { a as buildEnv, n as readVersionMetadataBinding, r as selectNativeVersionMetadataBinding, t as CLOUDFLARE_PRESERVE_BINDINGS_BUILD_ENV } from "./version-metadata-D2vfMQzv.mjs";
25
+ import { a as emailConfigInputs, c as renderAddressMap, d as isGeneratedAssetHeaders, g as prerenderPagesNode, h as prerenderPages, i as createNodeEmailDns, l as renderEmailChecklist, m as collectPrerenderPathsNode, n as SEND_EMAIL_BINDING, o as preflightEmail, p as collectPrerenderPaths, r as applyEmailSetup, t as EMAIL_FROM_VAR } from "./email-cloudflare-PMbAev9Q.mjs";
26
+ import { n as completeApplicationAnalysis, t as analyzeApplication } from "./application-routing-4719u_kf.mjs";
27
+ import { a as record, i as migrateBuiltWranglerConfig, n as prepareCfFrameworkBuildOutput, r as prepareCfStaticBuildOutput, t as prepareCfBuildOutput } from "./cf-build-output-XpNR9zoh.mjs";
27
28
  import { i as validateMigrations, t as assertJournalCoherence } from "./validate-CnZPMq4q.mjs";
28
29
  import { A as confirm, K as select, L as log, tt as isCancel } from "./dist-Cor9XGoz.mjs";
29
30
  import { r as getPackageDir } from "./agents-CuNtT0D_.mjs";
30
- import { a as isExpiredTokenError, r as PlatformClient } from "./client-BEkdj1kx.mjs";
31
+ import { a as isExpiredTokenError, r as PlatformClient } from "./client-B3LnB_bE.mjs";
31
32
  import { o as formatCount, p as note, r as createSpinner, u as getErrorMessage } from "./output-BpgYODYx.mjs";
32
33
  import { t as getRequestedProjectSlug } from "./resolve-project-Xoi6eTWY.mjs";
33
34
  import { i as safePositional, r as readCfUploadOutput, t as CF_VERSION_SOURCE_MAX_OUTPUT_BYTES } from "./cf-command-values-ByHk0xg4.mjs";
34
35
  import { a as FRAMEWORK_PRESETS, c as hasBackendFiles, i as isCleanCloudflareExit, l as resolveCloudflareOperationArgv, o as detectPreset, s as formatProjectCommand, t as createCloudflareProcessRunner, u as resolveProjectCommand } from "./cloudflare-process-8jEYIeim.mjs";
35
- import { f as listSelfHostSecretNames, h as selfHostSchemaFailureMessage, i as SelfHostSecretListError, l as dischargeSelfHostEnvContext, n as SelfHostFirstDeployError, p as readEmittedWorkerVars, r as SelfHostSchemaError, s as deriveSelfHostEnvContextFromVars, t as SelfHostEnvValidationError } from "./env-validation-Dwq3PJzK.mjs";
36
- import { a as needsWrapper, r as cleanupWrapper, t as bundleEntry } from "./wrapper-D3sZyh2C.mjs";
37
- import { A as resolveDeployLiveBindingConfig, C as generateDeployWrapperIfNeeded, D as hasPrerenderSources, E as hasNonPageBackend, F as resolveStaticDeployPreset, I as toManifestSchedulesAndQueues, L as validateDeployMigrations, M as resolveDeployWranglerCompat, N as resolveFullDeployBuildCommand, O as log$1, P as resolveStaticBuildCommand, S as ensureManagedHyperdrive, T as getGitCommit, _ as hasDeploySchemaDrift, a as collectAndHashAssets, b as assertWorkerMainUploaded, c as formatDeploySummary, d as mergeAndLintRoutingRules, f as streamDirectR2Deploy, g as getDeploySchemaDriftMessage, h as assertDeploySchemaDriftFree, i as buildStaticManifest, j as resolveDeployWorkerMain, k as promptDeployProjectConfig, l as printDeployContext, m as warnUnpublishedRouting, n as runStaticDeploy, o as collectWorkerFiles, p as warnIgnoredNotFoundForFramework, r as buildFrameworkManifest, s as detectNonSpaFallbackWarning, t as assembleVoidManifest, u as printDeploySuccess, v as assertEnvSchemaValid, w as getExitCode, x as createProjectFromSlug, y as assertProjectDeployAccess } from "./deploy-managed-static-DlvcvnQT.mjs";
38
- import { a as checkCloudflareProvisionDrift, d as isQueueConfirmedAbsent, f as isRealD1Id, g as provisionCloudflareResources, i as assertValidResourceName, m as isRealKvId, s as deleteEnvVarCaseAware } from "./provision-DtROpNNI.mjs";
39
- import { c as scrubWranglerAuthCredentials, n as buildSchemaProbeEnv, o as resolveDeployTransport, r as deployChildEnv, s as scrubManagedDeployBuildMarkers, t as MANAGED_DEPLOY_BUILD_ENV } from "./deploy-transport-BzGEj0Ge.mjs";
40
- import { n as getCfCliVersion, r as getVoidUserAgent, t as publishCloudflareObservability } from "./cf-worker-settings-BECvvTVd.mjs";
36
+ import { f as listSelfHostSecretNames, h as selfHostSchemaFailureMessage, i as SelfHostSecretListError, l as dischargeSelfHostEnvContext, n as SelfHostFirstDeployError, p as readEmittedWorkerVars, r as SelfHostSchemaError, s as deriveSelfHostEnvContextFromVars, t as SelfHostEnvValidationError } from "./env-validation-B3VobvXm.mjs";
37
+ import { a as needsWrapper, r as cleanupWrapper, t as bundleEntry } from "./wrapper-BBl1rC32.mjs";
38
+ import { A as promptDeployProjectConfig, C as ensureManagedHyperdrive, D as hasNonPageBackend, E as getGitCommit, F as resolveStaticBuildCommand, I as resolveStaticDeployPreset, L as toManifestSchedulesAndQueues, M as resolveDeployWorkerMain, N as resolveDeployWranglerCompat, O as hasPrerenderSources, P as resolveFullDeployBuildCommand, R as validateDeployMigrations, S as createProjectFromSlug, T as getExitCode, _ as getDeploySchemaDriftMessage, a as collectAndHashAssets, b as assertProjectDeployAccess, c as readWranglerHtmlHandling, d as printDeploySuccess, f as mergeAndLintRoutingRules, g as assertDeploySchemaDriftFree, h as warnUnpublishedRouting, i as buildStaticManifest, j as resolveDeployLiveBindingConfig, k as log$1, l as formatDeploySummary, m as warnIgnoredNotFoundForFramework, n as runStaticDeploy, o as collectWorkerFiles, p as streamDirectR2Deploy, r as buildFrameworkManifest, s as detectNonSpaFallbackWarning, t as assembleVoidManifest, u as printDeployContext, v as hasDeploySchemaDrift, w as generateDeployWrapperIfNeeded, x as assertWorkerMainUploaded, y as assertEnvSchemaValid } from "./deploy-managed-static-DjeBFG2c.mjs";
39
+ import { a as checkCloudflareProvisionDrift, b as resolveWorkersDevComplianceRegion, d as isQueueConfirmedAbsent, f as isRealD1Id, g as provisionCloudflareResources, i as assertValidResourceName, m as isRealKvId, s as deleteEnvVarCaseAware } from "./provision-DztLJ97X.mjs";
40
+ import { c as scrubWranglerAuthCredentials, n as buildSchemaProbeEnv, o as resolveDeployTransport, r as deployChildEnv, s as scrubManagedDeployBuildMarkers, t as MANAGED_DEPLOY_BUILD_ENV } from "./deploy-transport-DIq_gFTP.mjs";
41
+ import { n as getCfCliVersion, r as getVoidUserAgent, t as publishCloudflareWorkerSettings } from "./cf-worker-settings-Dg27RzyT.mjs";
41
42
  import { t as sanitizeTerminalLogText } from "./terminal-log-text-D9ACPOuG.mjs";
42
- import { t as promptForLoginToken } from "./login-Cttnagmm.mjs";
43
- import { a as parseCloudflareAuthSession, i as ensureCloudflareAuthentication, n as cloudflareCredentialOverrides, t as CloudflareAuthenticationError } from "./cloudflare-auth-Byo_0_N9.mjs";
44
- import { a as createCloudflareEmptyDomainPublisher, i as createCloudflareEmptyCronPublisher } from "./cloudflare-operations-Dh9dEHJj.mjs";
43
+ import { t as promptForLoginToken } from "./login-PcFy5mlC.mjs";
44
+ import { a as parseCloudflareAuthSession, i as ensureCloudflareAuthentication, n as cloudflareCredentialOverrides, t as CloudflareAuthenticationError } from "./cloudflare-auth-DyD_kVFr.mjs";
45
+ import { a as createCloudflareEmptyDomainPublisher, i as createCloudflareEmptyCronPublisher } from "./cloudflare-operations-Bc-7fN44.mjs";
45
46
  import { n as openMigrationValidationDatabase, t as SqliteMigrationError } from "./sqlite-validation-BzKMWnO4.mjs";
46
- import { a as discoverFrameworkWranglerFiles, i as writeVoidProjectConfig, t as migrateLegacyVoidConfig } from "./migrate-DyT2jJ8y.mjs";
47
+ import { r as discoverFrameworkWranglerFiles, t as migrateLegacyVoidConfig } from "./migrate-B8S2xTcb.mjs";
47
48
  import { a as runMySqlMigrations } from "./runner-mysql-BWmbk5IE.mjs";
48
49
  import { i as runPgMigrations } from "./runner-pg-Cr3qrqi4.mjs";
49
50
  import { t as collectGitDeployMetadata } from "./git-metadata-D-gurjzG.mjs";
@@ -59,9 +60,10 @@ import { execFile, execSync, spawn } from "node:child_process";
59
60
  import { getWorkerAssetsDir, getWorkerBundleDir, getWorkerConfigPath, readBuildOutput } from "@cloudflare/build-output-utils";
60
61
  import { convertToWranglerConfig } from "@cloudflare/config";
61
62
  import ignore from "ignore";
62
- import { CloudflareWorkerInspectionError, activateCloudflareVersion, assertCloudflareBindingsPreserved, assertCloudflareDurableObjectLifecycleSupported, assertExistingCloudflareConfig, cloudflareCommandDiagnostic, encodeCloudflareVersionMessage, extractWorkersDevSubdomain, normalizeWorkersDevSubdomain, parseRootWranglerConfig, parseRootWranglerConfig as parseRootWranglerConfig$1, readBindingFieldPresence, readCloudflareTriggerConfig, readConfigEntryString, readExistingCloudflareWorker, readStoredResourceName, readWranglerTopLevelString, renderCloudflareStaticEntry, resolveD1MigrateTarget, stageCloudflareStaticAssets, writeCloudflareFrameworkDeployConfig, writeCloudflareStaticDeployConfig } from "@void/deploy-cloudflare";
63
+ import { CloudflareWorkerInspectionError, activateCloudflareVersion, assertCloudflareBindingsPreserved, assertCloudflareDurableObjectLifecycleSupported, assertExistingCloudflareConfig, cloudflareCommandDiagnostic, encodeCloudflareVersionMessage, extractWorkersDevSubdomain, normalizeReadinessAccessOrigin, normalizeWorkersDevSubdomain, parseRootWranglerConfig, parseRootWranglerConfig as parseRootWranglerConfig$1, readBindingFieldPresence, readCloudflareTriggerConfig, readConfigEntryString, readExistingCloudflareWorker, readStoredResourceName, readWranglerTopLevelString, renderCloudflareStaticEntry, resolveD1MigrateTarget, stageCloudflareStaticAssets, writeCloudflareFrameworkDeployConfig, writeCloudflareStaticDeployConfig } from "@void/deploy-cloudflare";
63
64
  import { setTimeout as setTimeout$1 } from "node:timers/promises";
64
65
  import mime from "mime";
66
+ import { Buffer as Buffer$1 } from "node:buffer";
65
67
  import { Minimatch } from "minimatch";
66
68
  //#region src/cli/cloudflare-candidate.ts
67
69
  const CANDIDATE_FILE = ".void/cloudflare-candidate.json";
@@ -217,6 +219,112 @@ async function maybeLinkCloudflareDeploy(root, options = {}, deps = {}) {
217
219
  return isCancel(accepted) || accepted !== true ? "cancelled" : "existing";
218
220
  }
219
221
  //#endregion
222
+ //#region src/cli/cloudflare-readiness.ts
223
+ const STATE_FILE = join(".void", "cloudflare.json");
224
+ /** Resolve the account subdomain without exposing Cloudflare credentials to project code. */
225
+ function resolveCloudflareWorkersDevSubdomain(root, accountId, env = process.env) {
226
+ const configured = env.CLOUDFLARE_WORKERS_SUBDOMAIN;
227
+ if (configured !== void 0 && configured.trim().length > 0) {
228
+ const normalized = normalizeWorkersDevSubdomain(configured);
229
+ if (!normalized) throw new Error("deploy: CLOUDFLARE_WORKERS_SUBDOMAIN must be the account subdomain, for example \"my-team\" or \"my-team.workers.dev\".");
230
+ return normalized;
231
+ }
232
+ const cached = subdomainsByAccount(readCloudflareLocalState(root))[accountId];
233
+ return typeof cached === "string" ? normalizeWorkersDevSubdomain(cached) : void 0;
234
+ }
235
+ /**
236
+ * Record `CF_ACCESS_READINESS_ORIGIN` before project code runs. `void.config.ts` is evaluated in
237
+ * this process, so a later read of `process.env` could see a value that the project assigned,
238
+ * for example through a dotenv import. `null` means unset. An already recorded value is kept.
239
+ */
240
+ function withRecordedReadinessAccessOrigin(options, env = process.env) {
241
+ return options.readinessAccessOrigin !== void 0 ? options : {
242
+ ...options,
243
+ readinessAccessOrigin: env.CF_ACCESS_READINESS_ORIGIN ?? null
244
+ };
245
+ }
246
+ /**
247
+ * Validate the operator-selected origin that may receive readiness Access credentials when the
248
+ * probe uses a route or Custom Domain. Pass the value that `withRecordedReadinessAccessOrigin`
249
+ * recorded, not the current `process.env`.
250
+ */
251
+ function resolveCloudflareReadinessAccessOrigin(env) {
252
+ const configured = env.CF_ACCESS_READINESS_ORIGIN?.trim();
253
+ if (!configured) return;
254
+ const origin = normalizeReadinessAccessOrigin(configured);
255
+ if (!origin) throw new Error("deploy: CF_ACCESS_READINESS_ORIGIN must be one exact https origin, without a wildcard, path, query, fragment, or credentials, for example \"https://app.example.com\".");
256
+ return origin;
257
+ }
258
+ /**
259
+ * Read the account subdomain from the Cloudflare API when a first publish reports no URL and
260
+ * no subdomain is configured or cached. The API returns only the account label, so this adds
261
+ * `.fed` for FedRAMP High, as Wrangler does. A failed lookup resolves `unavailable`.
262
+ */
263
+ async function readCloudflareWorkersDevSubdomain(options) {
264
+ if (!options.verifyUploader()) return {
265
+ ok: false,
266
+ reason: "uploader-changed"
267
+ };
268
+ let label;
269
+ try {
270
+ const result = await options.runWrangler({
271
+ type: "workers.subdomain.get",
272
+ configPath: options.configPath
273
+ }, { capture: true });
274
+ if (!isCleanCloudflareExit(result) || !result.data || typeof result.data !== "object" || !("subdomain" in result.data) || typeof result.data.subdomain !== "string") return {
275
+ ok: false,
276
+ reason: "unavailable"
277
+ };
278
+ label = result.data.subdomain;
279
+ } catch {
280
+ return {
281
+ ok: false,
282
+ reason: "unavailable"
283
+ };
284
+ }
285
+ const subdomain = normalizeWorkersDevSubdomain(options.complianceRegion === "fedramp_high" ? `${label}.fed` : label);
286
+ return subdomain ? {
287
+ ok: true,
288
+ subdomain
289
+ } : {
290
+ ok: false,
291
+ reason: "unavailable"
292
+ };
293
+ }
294
+ /** Cache a Wrangler-reported account subdomain for later no-preview version probes. */
295
+ function rememberCloudflareWorkersDevSubdomain(root, accountId, url) {
296
+ const workersDevSubdomain = extractWorkersDevSubdomain(url);
297
+ if (!workersDevSubdomain) return false;
298
+ const current = readCloudflareLocalState(root);
299
+ const currentByAccount = subdomainsByAccount(current);
300
+ if (currentByAccount[accountId] === workersDevSubdomain) return false;
301
+ const { workersDevSubdomain: _legacy, ...state } = current;
302
+ const filePath = join(root, STATE_FILE);
303
+ mkdirSync(dirname(filePath), { recursive: true });
304
+ writeFileSync(filePath, JSON.stringify({
305
+ ...state,
306
+ workersDevSubdomains: {
307
+ ...currentByAccount,
308
+ [accountId]: workersDevSubdomain
309
+ }
310
+ }, null, 2) + "\n");
311
+ return true;
312
+ }
313
+ function subdomainsByAccount(state) {
314
+ const value = state.workersDevSubdomains;
315
+ return value && typeof value === "object" && !Array.isArray(value) ? value : {};
316
+ }
317
+ function readCloudflareLocalState(root) {
318
+ const filePath = join(root, STATE_FILE);
319
+ if (!existsSync(filePath)) return {};
320
+ try {
321
+ const parsed = JSON.parse(readFileSync(filePath, "utf-8"));
322
+ return typeof parsed === "object" && parsed !== null && !Array.isArray(parsed) ? parsed : {};
323
+ } catch {
324
+ return {};
325
+ }
326
+ }
327
+ //#endregion
220
328
  //#region src/cli/deploy-binding-snapshot.ts
221
329
  /** The id-bearing binding fields whose identity must survive the build unchanged. */
222
330
  const DEPLOY_BINDING_IDENTITY_FIELDS = {
@@ -786,7 +894,10 @@ async function computeDesiredCloudflareResources(root, voidConfig, configPath, a
786
894
  };
787
895
  reasons.set(binding, analysis.reasons.r2[0]);
788
896
  }
789
- desired.queues = analysis.queues.map((q) => q.name);
897
+ if (analysis.queues.length > 0) {
898
+ desired.queueNames = Object.fromEntries(analysis.queues.map((q) => [q.name, scopedCloudflareQueueName(toValidWorkerName(workerName), q.name)]));
899
+ desired.queues = Object.values(desired.queueNames);
900
+ }
790
901
  if (needsDatabase && dialect !== "sqlite") {
791
902
  const binding = "HYPERDRIVE";
792
903
  desired.hyperdrive = {
@@ -1772,6 +1883,9 @@ async function ensureCloudflareAuthSecret(options) {
1772
1883
  return { created: true };
1773
1884
  }
1774
1885
  //#endregion
1886
+ //#region src/cli/node-buffer.ts
1887
+ const Buffer$2 = Buffer$1;
1888
+ //#endregion
1775
1889
  //#region src/cli/cf-version-api.ts
1776
1890
  var CloudflareApiError = class extends Error {
1777
1891
  status;
@@ -1797,6 +1911,31 @@ function textValue(value, label) {
1797
1911
  if (typeof value !== "string") throw new Error(`The Cloudflare ${label} is missing from the verified Worker output.`);
1798
1912
  return value;
1799
1913
  }
1914
+ /** Match cf's package collection for uploads that preserve secrets through the JSON API. */
1915
+ async function readPackageDependencies(directory) {
1916
+ try {
1917
+ const pkg = record(JSON.parse(readFileSync(join(directory, "package.json"), "utf8")));
1918
+ const declared = {
1919
+ ...record(pkg?.dependencies),
1920
+ ...record(pkg?.devDependencies)
1921
+ };
1922
+ const { getInstalledPackageVersion } = await import("@cloudflare/workers-utils");
1923
+ const dependencies = [];
1924
+ for (const [name, packageJsonVersion] of Object.entries(declared)) {
1925
+ if (dependencies.length >= 200) break;
1926
+ if (typeof packageJsonVersion !== "string" || /^(workspace|catalog|file|link):/.test(packageJsonVersion)) continue;
1927
+ const installedVersion = getInstalledPackageVersion(name, directory);
1928
+ if (installedVersion) dependencies.push({
1929
+ name,
1930
+ packageJsonVersion,
1931
+ installedVersion
1932
+ });
1933
+ }
1934
+ return dependencies.length ? dependencies : void 0;
1935
+ } catch {
1936
+ return;
1937
+ }
1938
+ }
1800
1939
  const moduleContentTypes = {
1801
1940
  esm: "application/javascript+module",
1802
1941
  cjs: "application/javascript",
@@ -2090,11 +2229,22 @@ function assetConfigFromOutput(value) {
2090
2229
  ...config.runWorkerFirst === void 0 ? {} : { run_worker_first: config.runWorkerFirst }
2091
2230
  };
2092
2231
  }
2093
- /**
2094
- * The version API placement. Smart placement is normalized the same way as cf's own version
2095
- * uploads. Targeted placement is rejected: the Workers beta version endpoint can drop its
2096
- * target, and an atomic upload is live before a read-back could catch that.
2097
- */
2232
+ /** The region, host or hostname of a targeted placement. */
2233
+ function placementTarget(placement) {
2234
+ if (!placement) return;
2235
+ for (const kind of [
2236
+ "region",
2237
+ "host",
2238
+ "hostname"
2239
+ ]) {
2240
+ const value = placement[kind];
2241
+ if (typeof value === "string" && value) return {
2242
+ kind,
2243
+ value
2244
+ };
2245
+ }
2246
+ }
2247
+ /** The version API placement, in the shape cf's own version uploads send. */
2098
2248
  function placementFromOutput(placement) {
2099
2249
  if (!placement) return;
2100
2250
  const hint = "hint" in placement ? placement.hint : void 0;
@@ -2102,8 +2252,22 @@ function placementFromOutput(placement) {
2102
2252
  mode: "smart",
2103
2253
  ...hint ? { hint } : {}
2104
2254
  };
2105
- const target = "region" in placement && placement.region && "region" || "host" in placement && placement.host && "host" || "hostname" in placement && placement.hostname && "hostname";
2106
- if (target) throw new Error(`Cloudflare placement.${target} cannot be deployed while the Worker has secrets. Remove cloudflare.placement from void.config.ts, or set it to { mode: 'smart' }.`);
2255
+ const target = placementTarget(placement);
2256
+ return target ? {
2257
+ mode: "targeted",
2258
+ [target.kind]: target.value
2259
+ } : void 0;
2260
+ }
2261
+ /**
2262
+ * Whether the upload reply still names the requested target. The Workers beta version
2263
+ * endpoint has replied `placement: {}` after dropping one (terraform-provider-cloudflare#7273).
2264
+ * It now replies with the target alone, e.g. `{ region }`.
2265
+ */
2266
+ function keepsPlacementTarget(placement, target) {
2267
+ const reply = record(placement);
2268
+ if (!reply) return false;
2269
+ const targets = reply.target === void 0 ? [reply] : reply.target;
2270
+ return Array.isArray(targets) && targets.length === 1 && record(targets[0])?.[target.kind] === target.value;
2107
2271
  }
2108
2272
  async function apiResult(url, token, method, body, verifyUploader, timeout = 12e4) {
2109
2273
  assertUploaderUnchanged(verifyUploader);
@@ -2333,6 +2497,22 @@ async function ensureContainerApplications(options) {
2333
2497
  assertContainerApplicationSettings(confirmed, plan);
2334
2498
  }
2335
2499
  }
2500
+ /**
2501
+ * The `_headers` file a native build generated for its fingerprinted files.
2502
+ * This API takes it as a `_headers` module, as cf does on its JSON version
2503
+ * uploads. A user-authored `_headers` is not sent on this path.
2504
+ */
2505
+ function readGeneratedAssetHeaders(output) {
2506
+ if (!output.assetsDirectory) return;
2507
+ let text;
2508
+ try {
2509
+ text = readFileSync(join(getWorkerAssetsDir(output.directory), "_headers"), "utf8");
2510
+ } catch (cause) {
2511
+ if (cause instanceof Error && "code" in cause && cause.code === "ENOENT") return;
2512
+ throw cause;
2513
+ }
2514
+ return isGeneratedAssetHeaders(text) ? text : void 0;
2515
+ }
2336
2516
  async function uploadAssets(options) {
2337
2517
  if (!options.output.assetsDirectory) return;
2338
2518
  const directory = getWorkerAssetsDir(options.output.directory);
@@ -2460,6 +2640,12 @@ async function uploadPinnedCloudflareVersion(options) {
2460
2640
  content_base64: readFileSync(join(getWorkerBundleDir(options.output.directory), name)).toString("base64")
2461
2641
  });
2462
2642
  }
2643
+ const generatedHeaders = readGeneratedAssetHeaders(options.output);
2644
+ if (generatedHeaders !== void 0) modules.push({
2645
+ name: "_headers",
2646
+ content_type: "text/plain",
2647
+ content_base64: Buffer$2.from(generatedHeaders).toString("base64")
2648
+ });
2463
2649
  await preflightWorkflowExports({
2464
2650
  exports,
2465
2651
  accountUrl,
@@ -2489,6 +2675,7 @@ async function uploadPinnedCloudflareVersion(options) {
2489
2675
  modules,
2490
2676
  compatibility_date: config.compatibilityDate,
2491
2677
  compatibility_flags: config.compatibilityFlags,
2678
+ package_dependencies: await readPackageDependencies(options.output.directory),
2492
2679
  bindings,
2493
2680
  ...config.limits ? { limits: {
2494
2681
  cpu_ms: config.limits.cpuMs,
@@ -2522,6 +2709,8 @@ async function uploadPinnedCloudflareVersion(options) {
2522
2709
  } catch {
2523
2710
  throw new Error(`Cloudflare Worker version ${versionId} was uploaded${options.atomic ? " and may already be published" : ""}, but its Container applications could not be verified. Read back the Worker deployment and Container identities before retrying.`);
2524
2711
  }
2712
+ const target = placementTarget(config.placement);
2713
+ if (target && !keepsPlacementTarget(uploaded.placement, target)) throw new Error(`Cloudflare did not keep placement.${target.kind} "${target.value}" on Worker version ${versionId}${options.atomic ? ", which is already live" : ", so it was not deployed"}. Deploy again, or set cloudflare.placement to { mode: 'smart' } in void.config.ts.`);
2525
2714
  return {
2526
2715
  id: versionId,
2527
2716
  urls: Array.isArray(uploaded.urls) ? uploaded.urls.filter((url) => typeof url === "string") : []
@@ -2952,7 +3141,7 @@ function createCfVersionRunner(options) {
2952
3141
  "versions",
2953
3142
  "create",
2954
3143
  "--prebuilt",
2955
- ...operation.message ? ["--message", operation.message] : [],
3144
+ ...operation.message ? [`--message=${operation.message}`] : [],
2956
3145
  ...operation.secretsFilePath ? ["--secrets-file", operation.secretsFilePath] : [],
2957
3146
  ...operation.previewAlias ? ["--preview-alias", operation.previewAlias] : []
2958
3147
  ], command.capture));
@@ -2979,7 +3168,8 @@ function createCfVersionRunner(options) {
2979
3168
  strategy: "percentage",
2980
3169
  versions: parsed,
2981
3170
  annotations: { "workers/message": operation.message }
2982
- })] : []
3171
+ })] : [],
3172
+ ...operation.bypassDeploymentChecks ? ["--bypass-deployment-checks"] : []
2983
3173
  ], command.capture);
2984
3174
  }
2985
3175
  if (operation.type === "worker.deploy") {
@@ -2989,7 +3179,7 @@ function createCfVersionRunner(options) {
2989
3179
  return uploadedResult(await run([
2990
3180
  "deploy",
2991
3181
  "--prebuilt",
2992
- ...operation.message ? ["--message", operation.message] : [],
3182
+ ...operation.message ? [`--message=${operation.message}`] : [],
2993
3183
  ...operation.secretsFilePath ? ["--secrets-file", operation.secretsFilePath] : []
2994
3184
  ], command.capture));
2995
3185
  }
@@ -3038,17 +3228,18 @@ function createCfVersionRunner(options) {
3038
3228
  "deploy",
3039
3229
  "--prebuilt"
3040
3230
  ], command.capture, directory);
3041
- if (isCleanCloudflareExit(deployed) && raw.observability !== void 0) {
3231
+ if (isCleanCloudflareExit(deployed) && (raw.observability !== void 0 || raw.logpush !== void 0)) {
3042
3232
  const credentials = options.pinnedUpload;
3043
3233
  if (!credentials || !credentials.verifyUploader()) return failed("The Cloudflare settings publisher is unavailable.");
3044
3234
  try {
3045
3235
  const token = await credentials.getToken();
3046
3236
  if (!token || !credentials.verifyUploader()) return failed("Cloudflare session is unavailable for publishing Worker settings.");
3047
- await publishCloudflareObservability({
3237
+ await publishCloudflareWorkerSettings({
3048
3238
  apiBaseUrl: credentials.apiBaseUrl,
3049
3239
  accountId: credentials.accountId,
3050
3240
  workerName,
3051
3241
  observability: raw.observability,
3242
+ logpush: raw.logpush,
3052
3243
  headers: { Authorization: `Bearer ${token}` }
3053
3244
  });
3054
3245
  } catch (cause) {
@@ -3109,53 +3300,6 @@ function createCfVersionRunner(options) {
3109
3300
  };
3110
3301
  }
3111
3302
  //#endregion
3112
- //#region src/cli/cloudflare-readiness.ts
3113
- const STATE_FILE = join(".void", "cloudflare.json");
3114
- /** Resolve the account subdomain without exposing Cloudflare credentials to project code. */
3115
- function resolveCloudflareWorkersDevSubdomain(root, accountId, env = process.env) {
3116
- const configured = env.CLOUDFLARE_WORKERS_SUBDOMAIN;
3117
- if (configured !== void 0 && configured.trim().length > 0) {
3118
- const normalized = normalizeWorkersDevSubdomain(configured);
3119
- if (!normalized) throw new Error("deploy: CLOUDFLARE_WORKERS_SUBDOMAIN must be the account subdomain, for example \"my-team\" or \"my-team.workers.dev\".");
3120
- return normalized;
3121
- }
3122
- const cached = subdomainsByAccount(readCloudflareLocalState(root))[accountId];
3123
- return typeof cached === "string" ? normalizeWorkersDevSubdomain(cached) : void 0;
3124
- }
3125
- /** Cache a Wrangler-reported account subdomain for later no-preview version probes. */
3126
- function rememberCloudflareWorkersDevSubdomain(root, accountId, url) {
3127
- const workersDevSubdomain = extractWorkersDevSubdomain(url);
3128
- if (!workersDevSubdomain) return false;
3129
- const current = readCloudflareLocalState(root);
3130
- const currentByAccount = subdomainsByAccount(current);
3131
- if (currentByAccount[accountId] === workersDevSubdomain) return false;
3132
- const { workersDevSubdomain: _legacy, ...state } = current;
3133
- const filePath = join(root, STATE_FILE);
3134
- mkdirSync(dirname(filePath), { recursive: true });
3135
- writeFileSync(filePath, JSON.stringify({
3136
- ...state,
3137
- workersDevSubdomains: {
3138
- ...currentByAccount,
3139
- [accountId]: workersDevSubdomain
3140
- }
3141
- }, null, 2) + "\n");
3142
- return true;
3143
- }
3144
- function subdomainsByAccount(state) {
3145
- const value = state.workersDevSubdomains;
3146
- return value && typeof value === "object" && !Array.isArray(value) ? value : {};
3147
- }
3148
- function readCloudflareLocalState(root) {
3149
- const filePath = join(root, STATE_FILE);
3150
- if (!existsSync(filePath)) return {};
3151
- try {
3152
- const parsed = JSON.parse(readFileSync(filePath, "utf-8"));
3153
- return typeof parsed === "object" && parsed !== null && !Array.isArray(parsed) ? parsed : {};
3154
- } catch {
3155
- return {};
3156
- }
3157
- }
3158
- //#endregion
3159
3303
  //#region src/cli/deploy-cloudflare-helpers.ts
3160
3304
  /**
3161
3305
  * Discover the root wrangler config path the same way the build / bindings
@@ -3208,6 +3352,7 @@ async function connectCloudflareDeployAccount(options) {
3208
3352
  log$1.error(`deploy: ${getErrorMessage(error)}`);
3209
3353
  return null;
3210
3354
  }
3355
+ const complianceRegion = resolveWorkersDevComplianceRegion(process.env, readWranglerTopLevelString(rootConfig, "compliance_region"));
3211
3356
  const pins = createCloudflareUploaderPins(root, deps);
3212
3357
  let accountId = readWranglerTopLevelString(rootConfig, "account_id") ?? (process.env.CLOUDFLARE_ACCOUNT_ID?.trim() || void 0);
3213
3358
  if (!accountId) {
@@ -3227,8 +3372,10 @@ async function connectCloudflareDeployAccount(options) {
3227
3372
  }
3228
3373
  }
3229
3374
  let workersDevSubdomain;
3375
+ let readinessAccessOrigin;
3230
3376
  try {
3231
3377
  workersDevSubdomain = resolveCloudflareWorkersDevSubdomain(root, accountId);
3378
+ readinessAccessOrigin = resolveCloudflareReadinessAccessOrigin({ CF_ACCESS_READINESS_ORIGIN: options.readinessAccessOrigin ?? void 0 });
3232
3379
  } catch (error) {
3233
3380
  log$1.error(getErrorMessage(error));
3234
3381
  return null;
@@ -3236,8 +3383,10 @@ async function connectCloudflareDeployAccount(options) {
3236
3383
  return {
3237
3384
  ...pins,
3238
3385
  apiBaseUrl,
3386
+ complianceRegion,
3239
3387
  accountId,
3240
3388
  workersDevSubdomain,
3389
+ readinessAccessOrigin,
3241
3390
  runWrangler: deps.runWrangler ?? createDeployWranglerRunner(root, accountId, apiBaseUrl),
3242
3391
  rootConfig
3243
3392
  };
@@ -3323,7 +3472,21 @@ function cloudflareCandidateActivationOptions(options) {
3323
3472
  },
3324
3473
  readinessHeaders: cloudflareWorkerReadinessHeaders(),
3325
3474
  workersDevSubdomain,
3475
+ resolveWorkersDevSubdomain: async () => {
3476
+ const { complianceRegion } = options;
3477
+ if (complianceRegion === void 0) return {
3478
+ ok: false,
3479
+ reason: "unavailable"
3480
+ };
3481
+ return readCloudflareWorkersDevSubdomain({
3482
+ configPath,
3483
+ complianceRegion,
3484
+ runWrangler,
3485
+ verifyUploader: options.assertUploaderStillPinned
3486
+ });
3487
+ },
3326
3488
  readinessHeadersWorkersDevSubdomain: process.env.CLOUDFLARE_WORKERS_SUBDOMAIN?.trim() ? workersDevSubdomain : void 0,
3489
+ readinessHeadersOrigin: options.readinessAccessOrigin,
3327
3490
  ...createCloudflareEmptyTriggerPublishers({
3328
3491
  accountId,
3329
3492
  apiBaseUrl: options.apiBaseUrl,
@@ -3383,6 +3546,10 @@ async function activateCloudflareVersionWithProgress(activate, options) {
3383
3546
  }
3384
3547
  }
3385
3548
  function formatCloudflareActivationError(result) {
3549
+ const message = formatCloudflareActivationFailure(result);
3550
+ return result.restoredOlderSecrets ? `${message}\nCloudflare refused to restore the previous version because this deploy changed a secret, so Void forced the restore. The previous version runs with its old secret values; deploy again to apply the new ones.` : message;
3551
+ }
3552
+ function formatCloudflareActivationFailure(result) {
3386
3553
  const status = result.status === void 0 ? "" : ` (exit ${String(result.status)})`;
3387
3554
  const cloudflareCode = result.cloudflareErrorCode === void 0 ? "" : ` Cloudflare error code: ${String(result.cloudflareErrorCode)}.`;
3388
3555
  const diagnostic = result.diagnostic ? `\n\n${result.diagnostic}` : "";
@@ -3420,36 +3587,64 @@ function formatCloudflareActivationError(result) {
3420
3587
  ].join("\n");
3421
3588
  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 && (result.diagnostic ?? "").toLowerCase().includes("durable object migration") ? "\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." : result.cloudflareErrorCode === 100405 ? "\n\nThe new version declares different exports from the live version (for example a Durable Object or Workflow class), so Cloudflare cannot split traffic between them. Run `void deploy --platform cloudflare --atomic` once to publish it at 100% directly; it receives traffic before readiness is checked." : ""}`;
3422
3589
  case "atomic-failed": return `deploy: Cloudflare could not publish the Worker atomically${status}; inspect production status before retrying.${cloudflareCode}${diagnostic}`;
3423
- case "atomic-output-invalid": return "deploy: Cloudflare published atomically but did not report a version id or URL. Inspect `void project status` immediately.";
3590
+ case "atomic-output-invalid":
3591
+ if (result.versionId) return formatCloudflarePublishWithoutUrl(`Cloudflare published Worker version ${result.versionId} atomically`, `If the app uses workers.dev, set CLOUDFLARE_WORKERS_SUBDOMAIN to your account subdomain ${WORKERS_SUBDOMAIN_EXAMPLE}.`);
3592
+ return "deploy: Cloudflare published atomically but did not report its version id. Inspect `void project status` immediately.";
3424
3593
  case "atomic-readiness-failed":
3425
- case "atomic-readiness-access-denied": return `deploy: the atomic Worker deployment is live, but /__void/ready could not be verified. Inspect \`void project status\` and Worker logs immediately.${diagnostic}`;
3594
+ case "atomic-readiness-access-denied": return `deploy: the atomic Worker deployment is live, but /__void/ready could not be verified. Inspect \`void project status\` and Worker logs immediately.${diagnostic}${result.customRouteReadinessOrigin ? `\n\n${customRouteAccessHint(result.customRouteReadinessOrigin).join("\n")}` : ""}`;
3426
3595
  case "readiness-failed": return ["deploy: the uploaded Worker Version did not pass /__void/ready.", formatCloudflareReadinessRestoration(result)].join("\n");
3427
- case "readiness-access-denied": return [
3428
- "deploy: Cloudflare Access blocked the uploaded Worker Version readiness probe.",
3429
- "For CI, set CF_ACCESS_CLIENT_ID and CF_ACCESS_CLIENT_SECRET to an admitted service token.",
3430
- "For a local deploy, set CF_ACCESS_TOKEN to a short-lived user JWT from cloudflared.",
3431
- "If the response is error 1050, create an Access application for this hostname; a token alone cannot bypass account default-deny.",
3432
- `Then retry. ${formatCloudflareReadinessRestoration(result)}`
3433
- ].join("\n");
3596
+ case "readiness-access-denied":
3597
+ if (result.customRouteReadinessOrigin) return [
3598
+ "deploy: Cloudflare Access blocked the uploaded Worker Version readiness probe.",
3599
+ ...customRouteAccessHint(result.customRouteReadinessOrigin),
3600
+ ATOMIC_ACCESS_ALTERNATIVE,
3601
+ formatCloudflareReadinessRestoration(result)
3602
+ ].join("\n");
3603
+ return [
3604
+ "deploy: Cloudflare Access blocked the uploaded Worker Version readiness probe.",
3605
+ "For CI, set CF_ACCESS_CLIENT_ID and CF_ACCESS_CLIENT_SECRET to an admitted service token.",
3606
+ "For a local deploy, set CF_ACCESS_TOKEN to a short-lived user JWT from cloudflared.",
3607
+ "If the response is error 1050, create an Access application for this hostname; a token alone cannot bypass account default-deny.",
3608
+ `Then retry. ${formatCloudflareReadinessRestoration(result)}`
3609
+ ].join("\n");
3434
3610
  case "bootstrap-failed": return `deploy: Cloudflare could not bootstrap the first Worker deployment${status}.${cloudflareCode}${diagnostic}`;
3435
- case "bootstrap-output-invalid": return ["deploy: Cloudflare bootstrapped the first Worker deployment, but Wrangler", "did not report its version id and workers.dev URL. Inspect `void project status` before retrying."].join("\n");
3611
+ case "bootstrap-output-invalid":
3612
+ if (result.versionId) return formatCloudflarePublishWithoutUrl(`Cloudflare published the first Worker deployment as version ${result.versionId}`, `If the app uses workers.dev, enable workers.dev for this Worker in the Cloudflare dashboard. Then set CLOUDFLARE_WORKERS_SUBDOMAIN to your account subdomain ${WORKERS_SUBDOMAIN_EXAMPLE}.`);
3613
+ return ["deploy: Cloudflare bootstrapped the first Worker deployment, but Wrangler", "did not report its version id. Inspect `void project status` before retrying."].join("\n");
3436
3614
  case "bootstrap-readiness-failed": return [
3437
3615
  "deploy: the first Worker deployment did not pass /__void/ready.",
3438
3616
  "Cloudflare requires this bootstrap to be non-versioned, so the new Worker is already active;",
3439
3617
  "inspect its logs and `void project status` before retrying."
3440
3618
  ].join("\n") + diagnostic;
3441
- case "bootstrap-readiness-access-denied": return [
3442
- "deploy: Cloudflare Access blocked the first Worker deployment readiness probe.",
3443
- "For CI, set CF_ACCESS_CLIENT_ID and CF_ACCESS_CLIENT_SECRET to an admitted service token;",
3444
- "for a local deploy, set CF_ACCESS_TOKEN to a short-lived user JWT from cloudflared.",
3445
- "If the response is error 1050, create an Access application for this hostname; a token alone cannot bypass account default-deny.",
3446
- "Then retry. Cloudflare requires the first deployment to be non-versioned, so the new",
3447
- "Worker is already active behind Access."
3448
- ].join("\n");
3619
+ case "bootstrap-readiness-access-denied":
3620
+ if (result.customRouteReadinessOrigin) return [
3621
+ "deploy: Cloudflare Access blocked the first Worker deployment readiness probe.",
3622
+ "Cloudflare requires the first deployment to be non-versioned, so the new Worker is already active behind Access.",
3623
+ ...customRouteAccessHint(result.customRouteReadinessOrigin),
3624
+ "Later deploys check readiness before traffic moves, so they need the same setting.",
3625
+ ATOMIC_ACCESS_ALTERNATIVE
3626
+ ].join("\n");
3627
+ return [
3628
+ "deploy: Cloudflare Access blocked the first Worker deployment readiness probe.",
3629
+ "For CI, set CF_ACCESS_CLIENT_ID and CF_ACCESS_CLIENT_SECRET to an admitted service token;",
3630
+ "for a local deploy, set CF_ACCESS_TOKEN to a short-lived user JWT from cloudflared.",
3631
+ "If the response is error 1050, create an Access application for this hostname; a token alone cannot bypass account default-deny.",
3632
+ "Then retry. Cloudflare requires the first deployment to be non-versioned, so the new",
3633
+ "Worker is already active behind Access."
3634
+ ].join("\n");
3449
3635
  case "activation-failed": return `deploy: the ready Worker Version could not be activated${status}; production traffic is unchanged.`;
3450
3636
  case "triggers-failed": return `deploy: the Worker activated, but Cloudflare trigger synchronization failed${status}. ${result.rollback === "succeeded" ? "Traffic was restored to the previous version." : result.rollback === "unavailable" ? result.previousVersionId === null ? "This was the first deployment, so no previous version was available to restore." : "Traffic or trigger restoration could not be completed. Inspect its routes, schedules, queues, and workflows in Cloudflare before retrying." : "Automatic traffic restoration failed; inspect `void project status` immediately."}`;
3451
3637
  }
3452
3638
  }
3639
+ /** Explain why a custom-route readiness probe carried no Access credentials. */
3640
+ function customRouteAccessHint(origin) {
3641
+ return [
3642
+ `Void did not send Access credentials to ${origin}. A route or Custom Domain receives them only when CF_ACCESS_READINESS_ORIGIN names its origin.`,
3643
+ `If Access protects ${origin} and admits your credentials, set CF_ACCESS_READINESS_ORIGIN=${origin} with CF_ACCESS_CLIENT_ID and CF_ACCESS_CLIENT_SECRET, or CF_ACCESS_TOKEN. Then retry.`,
3644
+ "Set it only if you control this hostname and it serves this Worker, because Void sends your Access credentials to it."
3645
+ ];
3646
+ }
3647
+ const ATOMIC_ACCESS_ALTERNATIVE = "For a Worker with Durable Object migration history, `void deploy --platform cloudflare --atomic` publishes without the zero-traffic check. The new version receives traffic first, and the command still exits with an error because Void cannot verify readiness through Access.";
3453
3648
  function formatCloudflareReadinessRestoration(result) {
3454
3649
  switch (result.rollback) {
3455
3650
  case "succeeded": return "The failed version remains inactive, and traffic was restored to the previous version.";
@@ -3459,6 +3654,16 @@ function formatCloudflareReadinessRestoration(result) {
3459
3654
  default: return "The failed version remains inactive for inspection; production traffic is unchanged.";
3460
3655
  }
3461
3656
  }
3657
+ const WORKERS_SUBDOMAIN_EXAMPLE = "(for example \"my-team\", or \"my-team.fed\" for FedRAMP High)";
3658
+ /** Explain a live version whose readiness URL Void could not determine. */
3659
+ function formatCloudflarePublishWithoutUrl(published, recovery) {
3660
+ return [
3661
+ `deploy: ${published}, but Void could not determine its URL.`,
3662
+ "Void did not update its routes, workers.dev setting, or other triggers, and did not check /__void/ready.",
3663
+ recovery,
3664
+ "Then inspect `void project status` before you deploy again."
3665
+ ].join("\n");
3666
+ }
3462
3667
  /** Capture the Access credential used only by the guarded Worker readiness probe. */
3463
3668
  function cloudflareWorkerReadinessHeaders() {
3464
3669
  return trustedCloudflareWorkerAccessHeaders({
@@ -3494,6 +3699,7 @@ async function prepareCloudflareFrameworkArtifact(options) {
3494
3699
  await generateDeployWrapperIfNeeded(root, join(root, preset.workerDir), preset.workerMain, {
3495
3700
  crons,
3496
3701
  queues,
3702
+ cloudflareQueueNames: options.cloudflareQueueNames,
3497
3703
  hasMigrations: false,
3498
3704
  migrationDialect: analysis.dialect,
3499
3705
  readiness: true,
@@ -3585,10 +3791,11 @@ async function runCloudflareStaticDeploy(root, options, voidConfig, preset, cliL
3585
3791
  configPath,
3586
3792
  rootConfig: parseRootWranglerConfig(configPath),
3587
3793
  deps,
3588
- persistAccount: !(options.reuseExistingWorker || initialCloudflareLink)
3794
+ persistAccount: !(options.reuseExistingWorker || initialCloudflareLink),
3795
+ readinessAccessOrigin: options.readinessAccessOrigin
3589
3796
  });
3590
3797
  if (!connection || !await confirmCloudflareDeployAuthentication(connection, configPath)) return exit(1);
3591
- const { apiBaseUrl, usesCf, cfUploaderIsPinned, assertUploaderStillPinned, accountId, workersDevSubdomain, runWrangler } = connection;
3798
+ const { apiBaseUrl, complianceRegion, usesCf, cfUploaderIsPinned, assertUploaderStillPinned, accountId, workersDevSubdomain, readinessAccessOrigin, runWrangler } = connection;
3592
3799
  const existingWorker = await prepareExistingCloudflareDeployWithAuth({
3593
3800
  root,
3594
3801
  configPath,
@@ -3636,11 +3843,13 @@ async function runCloudflareStaticDeploy(root, options, voidConfig, preset, cliL
3636
3843
  const merged = mergeAndLintRoutingRules(preset.outputDir, voidConfig.routing);
3637
3844
  const manifest = buildStaticManifest({
3638
3845
  appType: preset.appType,
3846
+ alwaysUseHttps: voidConfig.routing?.alwaysUseHttps,
3639
3847
  hashedAssetsPrefix: "assets",
3640
3848
  headerRules: merged.headerRules,
3641
3849
  redirectRules: merged.redirectRules,
3642
3850
  fallbackRules: merged.fallbackRules,
3643
- notFound: voidConfig.routing?.notFound
3851
+ notFound: voidConfig.routing?.notFound,
3852
+ html_handling: readWranglerHtmlHandling(rootConfig)
3644
3853
  });
3645
3854
  const entryPath = join(root, ".void", "deploy", "cloudflare", "static-edge.mjs");
3646
3855
  mkdirSync(dirname(entryPath), { recursive: true });
@@ -3667,6 +3876,7 @@ async function runCloudflareStaticDeploy(root, options, voidConfig, preset, cliL
3667
3876
  }, null, 2)}\n`, { mode: 384 });
3668
3877
  writeFileSync(entryPath, renderCloudflareStaticEntry({
3669
3878
  runtimeImport: "void/edge",
3879
+ alwaysUseHttps: manifest.alwaysUseHttps,
3670
3880
  headerRules: manifest.headerRules,
3671
3881
  redirectRules: manifest.redirectRules,
3672
3882
  fallbackRules: manifest.fallbackRules,
@@ -3715,8 +3925,10 @@ async function runCloudflareStaticDeploy(root, options, voidConfig, preset, cliL
3715
3925
  uploadConfigPath: staticConfigPath,
3716
3926
  accountId,
3717
3927
  apiBaseUrl,
3928
+ complianceRegion,
3718
3929
  workerName,
3719
3930
  workersDevSubdomain,
3931
+ readinessAccessOrigin,
3720
3932
  runWrangler,
3721
3933
  readExistingWorker: deps.readExistingWorker,
3722
3934
  existingWorker,
@@ -4155,12 +4367,14 @@ async function buildCloudflareWorker(input) {
4155
4367
  const buildChildEnv = scrubManagedDeployBuildMarkers(scrubWranglerAuthCredentials(deployChildEnv(accountId, apiBaseUrl)));
4156
4368
  deleteEnvVarCaseAware(buildChildEnv, CLOUDFLARE_DEPLOY_BUILD_ENV);
4157
4369
  buildChildEnv[CLOUDFLARE_DEPLOY_BUILD_ENV] = "1";
4370
+ deleteEnvVarCaseAware(buildChildEnv, CLOUDFLARE_QUEUE_NAMES_BUILD_ENV);
4371
+ if (desired.queueNames) buildChildEnv[CLOUDFLARE_QUEUE_NAMES_BUILD_ENV] = JSON.stringify(desired.queueNames);
4158
4372
  deleteEnvVarCaseAware(buildChildEnv, CLOUDFLARE_PRESERVE_BINDINGS_BUILD_ENV);
4159
4373
  if (existingWorker) buildChildEnv[CLOUDFLARE_PRESERVE_BINDINGS_BUILD_ENV] = "1";
4160
4374
  deleteEnvVarCaseAware(buildChildEnv, "NODE_ENV");
4161
4375
  buildChildEnv.NODE_ENV = "production";
4162
4376
  const runBuild = deps.runBuild ?? ((env) => {
4163
- const command = frameworkPreset ? voidConfig.inference?.build ?? resolveProjectCommand(root, frameworkPreset.buildCommand) : resolveProjectCommand(root, "vite build");
4377
+ const command = resolveFullDeployBuildCommand(root, voidConfig.inference?.build, frameworkPreset?.buildCommand).command;
4164
4378
  execSync(command, {
4165
4379
  cwd: root,
4166
4380
  stdio: "inherit",
@@ -4185,7 +4399,8 @@ async function buildCloudflareWorker(input) {
4185
4399
  preset: frameworkPreset,
4186
4400
  requiredSecretNames: schemaFacts.requiredKeys,
4187
4401
  ai: needsAI ? { binding: aiBindingName } : void 0,
4188
- preserveBindings: existingWorker !== null
4402
+ preserveBindings: existingWorker !== null,
4403
+ cloudflareQueueNames: desired.queueNames
4189
4404
  });
4190
4405
  } catch (error) {
4191
4406
  log$1.error(`deploy: could not prepare ${detectedFramework.name} for Cloudflare — ${getErrorMessage(error)}`);
@@ -4301,7 +4516,7 @@ async function buildCloudflareWorker(input) {
4301
4516
  projectRoot: root,
4302
4517
  configPath: generatedConfigPath,
4303
4518
  accountId
4304
- }) : prepareCfBuildOutput(dirname(generatedConfigPath), accountId);
4519
+ }) : prepareCfBuildOutput(dirname(generatedConfigPath), accountId, void 0, root);
4305
4520
  if (usesCf) {
4306
4521
  const preflight = await prepareBuildOutput();
4307
4522
  if (!preflight) {
@@ -4639,6 +4854,114 @@ function existingAddresses(rootConfig, pre) {
4639
4854
  return Array.isArray(rootConfig.addresses) ? rootConfig.addresses.map((a) => typeof a === "string" ? a.toLowerCase() : "").filter((a) => pre.addresses.includes(a)) : [];
4640
4855
  }
4641
4856
  //#endregion
4857
+ //#region src/cli/deploy-cloudflare-queues.ts
4858
+ function isValidQueueName(name) {
4859
+ try {
4860
+ assertValidResourceName("queue", name);
4861
+ return true;
4862
+ } catch {
4863
+ return false;
4864
+ }
4865
+ }
4866
+ /**
4867
+ * Pick each queue's Cloudflare name from the account's queues and write it into `desired`.
4868
+ * Returns the chosen names that do not exist yet, or a message that blocks the deploy.
4869
+ */
4870
+ async function chooseCloudflareQueueNames(input) {
4871
+ const { desired, workerName, configPath, runWrangler } = input;
4872
+ if (!desired.queueNames) return {
4873
+ ok: true,
4874
+ absent: []
4875
+ };
4876
+ const lookup = async (name) => {
4877
+ const info = await Promise.resolve(runWrangler({
4878
+ type: "queues.info",
4879
+ name,
4880
+ configPath
4881
+ }, { capture: true }));
4882
+ if (isQueueConfirmedAbsent(info)) return null;
4883
+ const data = info.data;
4884
+ if (!isCleanCloudflareExit(info) || !isRecord(data) || data.name !== name || !Array.isArray(data.consumers)) throw new Error(`deploy: could not read Cloudflare queue ${name} and its consumers. Retry \`void deploy --platform cloudflare\`.`);
4885
+ return { consumers: data.consumers };
4886
+ };
4887
+ const invalid = Object.keys(desired.queueNames).filter((queueName) => !isValidQueueName(queueName)).map((queueName) => ` • ${queueName} (queue)`);
4888
+ if (invalid.length > 0) return {
4889
+ ok: false,
4890
+ message: [
4891
+ "Deploy blocked — these queue names are not valid Cloudflare queue names:",
4892
+ ...invalid,
4893
+ "",
4894
+ "A queue takes its name from its path in queues/; nested segments are joined with \"-\".",
4895
+ "A queue name must be 1–63 characters, contain only letters, digits and \"-\", and",
4896
+ "begin and end with a letter or digit.",
4897
+ "",
4898
+ "Rename the offending file(s) in queues/ and retry."
4899
+ ].join("\n")
4900
+ };
4901
+ const queueNames = desired.queueNames;
4902
+ const clashes = Object.keys(queueNames).filter((queueName) => Object.hasOwn(queueNames, queueNames[queueName])).map((queueName) => ` • ${queueName} uses the Cloudflare queue ${queueNames[queueName]}, which is also a queue in queues/`);
4903
+ if (clashes.length > 0) return {
4904
+ ok: false,
4905
+ message: [
4906
+ "Deploy blocked — these queues would share a Cloudflare queue:",
4907
+ ...clashes,
4908
+ "",
4909
+ `A queue's Cloudflare name is the Worker name, "-", then its name from queues/.`,
4910
+ "Rename one of the files in queues/, then retry."
4911
+ ].join("\n")
4912
+ };
4913
+ const names = {};
4914
+ const absent = [];
4915
+ const tooLong = [];
4916
+ const taken = [];
4917
+ for (const queueName of Object.keys(desired.queueNames)) {
4918
+ const scopedName = desired.queueNames[queueName];
4919
+ const scoped = isValidQueueName(scopedName) ? await lookup(scopedName) : null;
4920
+ const plain = scoped?.consumers.includes(workerName) ? void 0 : await lookup(queueName);
4921
+ const choice = chooseCloudflareQueueName({
4922
+ workerName,
4923
+ queueName,
4924
+ scopedName,
4925
+ scoped,
4926
+ plain
4927
+ });
4928
+ names[queueName] = choice.name;
4929
+ if (!isValidQueueName(choice.name)) {
4930
+ tooLong.push(` • ${choice.name} (${choice.name.length} characters)`);
4931
+ continue;
4932
+ }
4933
+ const state = choice.kept ? plain : scoped;
4934
+ if (state === null) absent.push(choice.name);
4935
+ for (const consumer of otherQueueConsumers(state, workerName)) taken.push(` • ${choice.name} is consumed by ${consumer === null ? "a non-Worker (HTTP pull) consumer" : `Worker ${consumer}`}`);
4936
+ if (choice.kept) input.info(`Queue ${queueName} keeps its Cloudflare name ${choice.name}, because this Worker already consumes it.`);
4937
+ }
4938
+ if (tooLong.length > 0) return {
4939
+ ok: false,
4940
+ message: [
4941
+ "Deploy blocked — these Cloudflare queue names are longer than 63 characters:",
4942
+ ...tooLong,
4943
+ "",
4944
+ `A queue's Cloudflare name is the Worker name, "-", then its name from queues/.`,
4945
+ "Shorten the Worker name or rename the file(s) in queues/, then retry."
4946
+ ].join("\n")
4947
+ };
4948
+ if (taken.length > 0) return {
4949
+ ok: false,
4950
+ message: [
4951
+ `Deploy blocked — Worker ${workerName} cannot consume these queues:`,
4952
+ ...taken,
4953
+ "",
4954
+ "A Cloudflare queue has one consumer. Rename the file in queues/ or the Worker, then retry."
4955
+ ].join("\n")
4956
+ };
4957
+ desired.queueNames = names;
4958
+ desired.queues = Object.values(names);
4959
+ return {
4960
+ ok: true,
4961
+ absent
4962
+ };
4963
+ }
4964
+ //#endregion
4642
4965
  //#region src/cli/deploy-cloudflare-preflight.ts
4643
4966
  /** Validate source-level native deploy inputs before account operations or project code. */
4644
4967
  async function prepareCloudflareDeploySource(root, options, voidConfig) {
@@ -4716,10 +5039,11 @@ async function preflightCloudflareWorker(input) {
4716
5039
  configPath,
4717
5040
  rootConfig,
4718
5041
  deps,
4719
- persistAccount: !(options.reuseExistingWorker || initialCloudflareLink)
5042
+ persistAccount: !(options.reuseExistingWorker || initialCloudflareLink),
5043
+ readinessAccessOrigin: options.readinessAccessOrigin
4720
5044
  });
4721
5045
  if (!connection) return exit(1);
4722
- const { apiBaseUrl, usesCf, cfUploaderIsPinned, assertUploaderStillPinned, accountId, workersDevSubdomain, runWrangler } = connection;
5046
+ const { apiBaseUrl, complianceRegion, usesCf, cfUploaderIsPinned, assertUploaderStillPinned, accountId, workersDevSubdomain, readinessAccessOrigin, runWrangler } = connection;
4723
5047
  rootConfig = connection.rootConfig;
4724
5048
  const workerName = readWranglerTopLevelString(rootConfig, "name") ?? deriveWorkerName(root);
4725
5049
  printDeployContext(workerName, "Cloudflare");
@@ -4895,53 +5219,38 @@ async function preflightCloudflareWorker(input) {
4895
5219
  return exit(1);
4896
5220
  }
4897
5221
  };
4898
- const { missing: initiallyMissing } = checkCloudflareProvisionDrift(configPath, desired);
4899
- const d1NeedsConfigReconciliation = !existingWorker && d1MigrationsDirMissing();
4900
- if (options.provision || initiallyMissing.length > 0 || d1NeedsConfigReconciliation) await provisionAndVerify();
4901
- else {
4902
- const invalidQueues = desired.queues.filter((name) => {
4903
- try {
4904
- assertValidResourceName("queue", name);
4905
- return false;
4906
- } catch {
4907
- return true;
4908
- }
5222
+ let queueNames;
5223
+ try {
5224
+ queueNames = await chooseCloudflareQueueNames({
5225
+ desired,
5226
+ workerName,
5227
+ configPath,
5228
+ runWrangler,
5229
+ info: (message) => log$1.info(message)
4909
5230
  });
4910
- if (invalidQueues.length > 0) {
4911
- log$1.error([
4912
- "Deploy blocked — these queue names are not valid Cloudflare queue names:",
4913
- ...invalidQueues.map((name) => ` • ${name} (queue)`),
4914
- "",
4915
- "A queue takes its name from its path in queues/; nested segments are joined with \"-\".",
4916
- "A queue name must be 1–63 characters, contain only letters, digits and \"-\", and",
4917
- "begin and end with a letter or digit.",
4918
- "",
4919
- "Rename the offending file(s) in queues/ and retry."
4920
- ].join("\n"));
4921
- return exit(1);
4922
- }
4923
- const absentQueues = [];
4924
- for (const name of desired.queues) {
4925
- const info = await Promise.resolve(runWrangler({
4926
- type: "queues.info",
4927
- name,
4928
- configPath
4929
- }, { capture: true }));
4930
- if (isQueueConfirmedAbsent(info)) absentQueues.push(name);
4931
- }
4932
- if (absentQueues.length > 0) await provisionAndVerify();
5231
+ } catch (error) {
5232
+ log$1.error(getErrorMessage(error));
5233
+ return exit(1);
5234
+ }
5235
+ if (!queueNames.ok) {
5236
+ log$1.error(queueNames.message);
5237
+ return exit(1);
4933
5238
  }
5239
+ const absentQueues = queueNames.absent;
5240
+ const { missing: initiallyMissing } = checkCloudflareProvisionDrift(configPath, desired);
5241
+ const d1NeedsConfigReconciliation = !existingWorker && d1MigrationsDirMissing();
5242
+ if (options.provision || initiallyMissing.length > 0 || d1NeedsConfigReconciliation || absentQueues.length > 0) await provisionAndVerify();
4934
5243
  const frameworkQueues = detectedFramework ? source.analysis.queues : [];
4935
5244
  writeProvisionedWranglerConfig(root, {
4936
5245
  name: workerName,
4937
5246
  accountId,
4938
5247
  ...detectedFramework ? { queues: {
4939
5248
  producers: frameworkQueues.map((queue) => ({
4940
- queue: queue.name,
5249
+ queue: cloudflareQueueName(queue.name, desired.queueNames),
4941
5250
  binding: queue.bindingName
4942
5251
  })),
4943
5252
  consumers: frameworkQueues.map((queue) => ({
4944
- queue: queue.name,
5253
+ queue: cloudflareQueueName(queue.name, desired.queueNames),
4945
5254
  ...queue.maxBatchSize != null && { max_batch_size: queue.maxBatchSize },
4946
5255
  ...queue.maxBatchTimeout != null && { max_batch_timeout: queue.maxBatchTimeout },
4947
5256
  ...queue.maxRetries != null && { max_retries: queue.maxRetries },
@@ -4962,11 +5271,13 @@ async function preflightCloudflareWorker(input) {
4962
5271
  });
4963
5272
  return {
4964
5273
  apiBaseUrl,
5274
+ complianceRegion,
4965
5275
  usesCf,
4966
5276
  cfUploaderIsPinned,
4967
5277
  assertUploaderStillPinned,
4968
5278
  accountId,
4969
5279
  workersDevSubdomain,
5280
+ readinessAccessOrigin,
4970
5281
  runWrangler,
4971
5282
  workerName,
4972
5283
  emailMap,
@@ -4987,7 +5298,7 @@ async function preflightCloudflareWorker(input) {
4987
5298
  async function publishCloudflareWorker(input) {
4988
5299
  const { root, deps, exit, cliLog, atomic, detectedFramework, initialCloudflareCandidate } = input;
4989
5300
  const { configPath, needsSandbox, desired, analysis } = input.source;
4990
- const { usesCf, existingWorker, pinnedHandoffLink, accountId, workerName, cfUploaderIsPinned, apiBaseUrl, runWrangler, assertUploaderStillPinned, schemaFacts, approvedHandoffKv, workersDevSubdomain } = input.preflight;
5301
+ const { usesCf, existingWorker, pinnedHandoffLink, accountId, workerName, cfUploaderIsPinned, apiBaseUrl, complianceRegion, runWrangler, assertUploaderStillPinned, schemaFacts, approvedHandoffKv, workersDevSubdomain, readinessAccessOrigin } = input.preflight;
4991
5302
  const { migrations, d1MigrateToken, generatedConfigPath, prepareBuildOutput } = input.build;
4992
5303
  const { workerWasMissingBeforeSecretProvisioning, initialAuthSecret, appliedMigrations } = input.migration;
4993
5304
  const queueConsumerCleanup = readWranglerManagedQueueCleanupCandidates(configPath);
@@ -5029,8 +5340,10 @@ async function publishCloudflareWorker(input) {
5029
5340
  uploadConfigPath: generatedConfigPath,
5030
5341
  accountId,
5031
5342
  apiBaseUrl,
5343
+ complianceRegion,
5032
5344
  workerName,
5033
5345
  workersDevSubdomain,
5346
+ readinessAccessOrigin,
5034
5347
  runWrangler,
5035
5348
  readExistingWorker: deps.readExistingWorker,
5036
5349
  existingWorker,
@@ -5081,6 +5394,7 @@ async function publishCloudflareWorker(input) {
5081
5394
  //#region src/cli/deploy-cloudflare.ts
5082
5395
  /** Deploy to the user's own Cloudflare account through the guarded native Worker flow. */
5083
5396
  async function runCloudflareDeploy(root, options, cliLog, deps = {}) {
5397
+ options = withRecordedReadinessAccessOrigin(options);
5084
5398
  const initialCloudflareLink = readCloudflareLink(root);
5085
5399
  const initialCloudflareCandidate = readCloudflareCandidate(root);
5086
5400
  const exit = deps.exit ?? ((code) => process.exit(code));
@@ -5117,6 +5431,14 @@ async function runCloudflareDeploy(root, options, cliLog, deps = {}) {
5117
5431
  }
5118
5432
  return runCloudflareStaticDeploy(root, options, voidConfig, staticPreset, cliLog, deps, initialCloudflareLink, initialCloudflareCandidate);
5119
5433
  }
5434
+ if (detectedFramework && voidConfig.routing?.alwaysUseHttps === true) {
5435
+ log$1.error([
5436
+ `deploy: native Cloudflare deployment cannot apply Void routing.alwaysUseHttps to ${detectedFramework.name}.`,
5437
+ "This framework owns its Worker request handler, so the HTTPS redirect would otherwise be ignored.",
5438
+ "Redirect HTTP to HTTPS in the framework, or turn on Cloudflare's Always Use HTTPS setting for your zone, then remove routing.alwaysUseHttps and retry."
5439
+ ].join("\n"));
5440
+ return exit(1);
5441
+ }
5120
5442
  const source = await prepareCloudflareDeploySource(root, options, voidConfig);
5121
5443
  if (!source) return exit(1);
5122
5444
  const preflight = await preflightCloudflareWorker({
@@ -5286,6 +5608,7 @@ async function runFrameworkDeploy(root, config, client, detected, fwPreset, void
5286
5608
  };
5287
5609
  const manifest = buildFrameworkManifest({
5288
5610
  frameworkName: detected.name,
5611
+ alwaysUseHttps: voidConfig.routing?.alwaysUseHttps,
5289
5612
  workerMain: actualWorkerMain,
5290
5613
  bindings,
5291
5614
  migrations: validatedMigrations,
@@ -5392,7 +5715,7 @@ async function runFullDeploy(root, config, client, voidConfig, fwPreset, skipBui
5392
5715
  voidToken: await client.createPrerenderToken(config.projectId)
5393
5716
  });
5394
5717
  if (result.paths.length === 0) log$1.info("No pages to prerender");
5395
- else if (result.failed.length > 0) voidWarn(`${formatCount(result.failed.length, "page")} failed to prerender`);
5718
+ else assertNoPrerenderFailures(result.failed);
5396
5719
  }
5397
5720
  const analysis = await analyzeApplication(root, {
5398
5721
  config: voidConfig,
@@ -5459,7 +5782,7 @@ async function runFullDeploy(root, config, client, voidConfig, fwPreset, skipBui
5459
5782
  buildCommand: null,
5460
5783
  outputDir: clientDir,
5461
5784
  appType: "static"
5462
- }, true, gitMetadata, assetsPrefix, headerRules, redirectRules, fallbackRules, void 0, cliLog, voidConfig.routing?.notFound);
5785
+ }, true, gitMetadata, assetsPrefix, headerRules, redirectRules, fallbackRules, void 0, cliLog, voidConfig.routing?.notFound, voidConfig.routing?.alwaysUseHttps);
5463
5786
  }
5464
5787
  }
5465
5788
  const prerenderSourcesPresent = hasPrerenderSources({
@@ -5542,6 +5865,7 @@ async function runFullDeploy(root, config, client, voidConfig, fwPreset, skipBui
5542
5865
  ...bindings,
5543
5866
  needsLive: true
5544
5867
  } : bindings,
5868
+ alwaysUseHttps: voidConfig.routing?.alwaysUseHttps,
5545
5869
  hasEmailHandlers: !isFrameworkMode && routeScan.email !== void 0 && hasEmailHandlers(routeScan.email),
5546
5870
  migrations: validatedMigrations,
5547
5871
  schedules,
@@ -6044,6 +6368,7 @@ function resolveDeploymentPlatform(root, options) {
6044
6368
  }
6045
6369
  /** Run `void deploy`; a failure carries a summary of the deploy log in its message. */
6046
6370
  async function runDeploy(root, options) {
6371
+ options = withRecordedReadinessAccessOrigin(options ?? {});
6047
6372
  console.log();
6048
6373
  const cliLog = openDeployLog({ mirrorToStderr: options?.debug === true || process.env.VOID_DEPLOY_DEBUG === "1" });
6049
6374
  cliLog.info("deploy_start", {