void 1.2.1 → 1.3.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 (166) hide show
  1. package/dist/{account-cmd-CdUll_35.mjs → account-cmd-B4i71m7k.mjs} +3 -3
  2. package/dist/{application-analysis-fEqoSeMp.mjs → application-analysis-DYdVoMAY.mjs} +8 -6
  3. package/dist/{application-routing-DAhNP4u3.mjs → application-routing-C8EqRDfv.mjs} +3 -1
  4. package/dist/{auth-link-C87vGXM-.mjs → auth-link-BKwHPbdv.mjs} +3 -3
  5. package/dist/{auth-router-6I81r-ix.mjs → auth-router-DqLx8E0F.mjs} +2 -2
  6. package/dist/{better-auth-shared-D-6z0q0f.mjs → better-auth-shared-7FM3Uk2N.mjs} +48 -2
  7. package/dist/{build-cmd-ex1g-j_e.mjs → build-cmd-Dy4psnt1.mjs} +1 -1
  8. package/dist/{cache-oHzrnY3z.mjs → cache-DV37S6dl.mjs} +1 -1
  9. package/dist/{cancel-deploy-viAMD0Q_.mjs → cancel-deploy-DMPyu1Vt.mjs} +1 -1
  10. package/dist/{cf-build-output-BhVxldCw.mjs → cf-build-output-Bapzc_8Z.mjs} +102 -1
  11. package/dist/cf-build-output-DlBkWdNU.mjs +1 -0
  12. package/dist/cli/cli.mjs +41 -32
  13. package/dist/cli/cloudflare-operation-process.mjs +27 -6
  14. package/dist/cli/env-schema-probe.mjs +2 -2
  15. package/dist/{client-BEkdj1kx.mjs → client-BEMtySaV.mjs} +8 -1
  16. package/dist/client-DyxPQnF_.mjs +1 -0
  17. package/dist/{cloudflare-cmd-DMzCv12s.mjs → cloudflare-cmd-BaqIigwI.mjs} +1 -1
  18. package/dist/{cloudflare-connect-CCRTVg-I.mjs → cloudflare-connect-pNLQmr_e.mjs} +1 -1
  19. package/dist/{cloudflare-operations-DsSaw2BT.mjs → cloudflare-operations-PCM4wucv.mjs} +1 -1
  20. package/dist/{cloudflare-operations-Dh9dEHJj.mjs → cloudflare-operations-vP3b5CQf.mjs} +3 -3
  21. package/dist/config-BTu1o3Dc.mjs +49 -0
  22. package/dist/{config-DQfHOKh9.d.mts → config-Du88-7Y8.d.mts} +2 -1
  23. package/dist/config-entry.d.mts +1 -1
  24. package/dist/{connect-k7R2rPVA.mjs → connect-DwVsBvVh.mjs} +4 -4
  25. package/dist/{create-project-DTuy-l0z.mjs → create-project-CgrnvzyA.mjs} +1 -1
  26. package/dist/{create-project-DV71ol5d.mjs → create-project-CjzbBlTv.mjs} +1 -1
  27. package/dist/{db-DVOkLH5X.mjs → db-rvo64snS.mjs} +13 -13
  28. package/dist/{delete-BbP5eopu.mjs → delete-DWX6dP4M.mjs} +1 -1
  29. package/dist/deploy-CtHE2A3R.mjs +2 -0
  30. package/dist/{deploy-7H32EnUs.mjs → deploy-hRPvw8ci.mjs} +229 -69
  31. package/dist/{deploy-managed-static-DlvcvnQT.mjs → deploy-managed-static-CDYA2p3L.mjs} +30 -14
  32. package/dist/{deploy-transport-BzGEj0Ge.mjs → deploy-transport-JCxw7QDi.mjs} +3 -3
  33. package/dist/deploy.mjs +4 -3
  34. package/dist/{dispatch-DoUnxTNo.mjs → dispatch-OVLeWW8K.mjs} +71 -2
  35. package/dist/{domain-CA2wBgra.mjs → domain-CH5iBD9Y.mjs} +2 -2
  36. package/dist/{email-DXpCc77w.mjs → email-CbTO1l78.mjs} +58 -9
  37. package/dist/{email-cloudflare-D03g2TkS.mjs → email-cloudflare-B8-pq_-W.mjs} +106 -5
  38. package/dist/{env-DgOQ9_8S.mjs → env-BBdw236G.mjs} +3 -3
  39. package/dist/{env-BJjULvL0.mjs → env-BaMz0j7H.mjs} +6 -1
  40. package/dist/{env-validation-BmsdCZEk.mjs → env-validation-BfBVvBNe.mjs} +1 -1
  41. package/dist/{env-validation-Dwq3PJzK.mjs → env-validation-XcukUlFM.mjs} +1 -1
  42. package/dist/{gen-BfmcIi2g.mjs → gen-CCx3t2Ju.mjs} +1 -1
  43. package/dist/gen-TgXy93Rr.mjs +1 -0
  44. package/dist/{github-cmd-CY9LUqLh.mjs → github-cmd-BzkRLkbg.mjs} +1 -1
  45. package/dist/{handler-BbkSPzGF.d.mts → handler-CQv5YDS0.d.mts} +1 -1
  46. package/dist/{help-CxSlPpzJ.mjs → help-CKbrhZha.mjs} +16 -1
  47. package/dist/help-qOZr3wng.mjs +1 -0
  48. package/dist/index.d.mts +2 -4
  49. package/dist/index.mjs +317 -122
  50. package/dist/{info-7VDlhtyy.mjs → info-oBm8yK8J.mjs} +2 -2
  51. package/dist/{init-DxYyOs4-.mjs → init-CBp_uMve.mjs} +217 -197
  52. package/dist/{link-Ddmod1dZ.mjs → link-Dt_QXmM4.mjs} +2 -2
  53. package/dist/{list-MogaugiO.mjs → list-DF6asTdt.mjs} +2 -2
  54. package/dist/{live-Bt8Y_0bg.d.mts → live-CXJ9yC98.d.mts} +1 -1
  55. package/dist/{local-d1-BHBnKWRb.mjs → local-d1-CUhH3qtj.mjs} +1 -1
  56. package/dist/{login-Cttnagmm.mjs → login-BjSyhXlT.mjs} +2 -2
  57. package/dist/login-Cdo8Aco1.mjs +1 -0
  58. package/dist/{logs-CAszUWZI.mjs → logs-DmvBl6xA.mjs} +2 -2
  59. package/dist/{migrate-DyT2jJ8y.mjs → migrate-BXRHpYwR.mjs} +1 -1
  60. package/dist/migrate-COPncCGx.mjs +1 -0
  61. package/dist/nitro.mjs +2 -2
  62. package/dist/{node-WB7c2N4L.mjs → node-DtD7ZiPf.mjs} +4 -4
  63. package/dist/{operator-args-UnE8Y2eK.mjs → operator-args-BsJIYXaT.mjs} +8 -1
  64. package/dist/operator-cmd-DDiX7Y3f.mjs +1 -0
  65. package/dist/{operator-cmd-skshjMGl.mjs → operator-cmd-DjZKGGgN.mjs} +4 -3
  66. package/dist/pages/client.d.mts +17 -4
  67. package/dist/pages/client.mjs +161 -29
  68. package/dist/pages/index.d.mts +18 -2
  69. package/dist/pages/index.mjs +2 -52
  70. package/dist/pages/islands-plugin.d.mts +1 -1
  71. package/dist/pages/islands-plugin.mjs +9 -3
  72. package/dist/pages/protocol.d.mts +2 -2
  73. package/dist/platform-args-BC8_hsDj.mjs +1 -0
  74. package/dist/{platform-args-DVbVClZl.mjs → platform-args-BMD2gjc_.mjs} +1 -1
  75. package/dist/{platform-auth-config-C-pm5Qzx.mjs → platform-auth-config-BgnuMbml.mjs} +3 -3
  76. package/dist/{platform-auth-protection-SHhvim1L.mjs → platform-auth-protection-NjRejttU.mjs} +2 -2
  77. package/dist/{platform-auth-recovery-DXVWs-wA.mjs → platform-auth-recovery-Ug12d9W5.mjs} +2 -2
  78. package/dist/{platform-cmd-PiNRkopU.mjs → platform-cmd-BYKLMPCn.mjs} +1 -1
  79. package/dist/{platform-cmd-D5I1beUX.mjs → platform-cmd-HByuZAO7.mjs} +4 -4
  80. package/dist/{platform-domain-jpmBfZeb.mjs → platform-domain-DLSQ8GF8.mjs} +2 -2
  81. package/dist/{platform-lifecycle-DyKmuNY6.mjs → platform-lifecycle-3dwFJmnq.mjs} +102 -40
  82. package/dist/{platform-lifecycle-DH3Yr1qQ.mjs → platform-lifecycle-BRqcxerG.mjs} +1 -1
  83. package/dist/{platform-management-7m-PLaPJ.mjs → platform-management-ZK6XcbCo.mjs} +1 -1
  84. package/dist/{platform-management--vDwSn35.mjs → platform-management-ZZ6bQM5j.mjs} +1 -1
  85. package/dist/{platform-recovery-BiNpZZab.mjs → platform-recovery-8vNE5dNN.mjs} +2 -2
  86. package/dist/{plugin-inference-DUjCd55H.mjs → plugin-inference-CeiB6BG5.mjs} +53 -18
  87. package/dist/{prepare-BcAE5Sdj.mjs → prepare-5BR7Splm.mjs} +1 -1
  88. package/dist/prepare-B3VrSF1Z.mjs +1 -0
  89. package/dist/{prepare-DA-17DhO.mjs → prepare-Dseww74N.mjs} +4 -4
  90. package/dist/{prerender-render-Cijv7UFo.mjs → prerender-render-CaShbHJ3.mjs} +13 -1
  91. package/dist/prerender-render.d.mts +1 -0
  92. package/dist/prerender-render.mjs +1 -1
  93. package/dist/{project-cmd-DA4K5faU.mjs → project-cmd-CjLNNxwe.mjs} +15 -15
  94. package/dist/{project-team-CQBNveX3.mjs → project-team-DE5drjcl.mjs} +1 -1
  95. package/dist/{project-token-CCalFyQf.mjs → project-token-XEYEXfiJ.mjs} +1 -1
  96. package/dist/{project-zero-trust-DPnkiEuT.mjs → project-zero-trust-6VPU8zmV.mjs} +1 -1
  97. package/dist/{protocol-BBDpJz3G.d.mts → protocol-BekmFxCI.d.mts} +2 -2
  98. package/dist/{provision-DtROpNNI.mjs → provision-B7UFrBH7.mjs} +1 -1
  99. package/dist/{provision-BFLCrnUp.mjs → provision-Chq0NRAV.mjs} +1 -1
  100. package/dist/{requests-BpH0kImL.mjs → requests-CG-Pj8ze.mjs} +1 -1
  101. package/dist/{rollback-CXS1tAa-.mjs → rollback-CIrm2txZ.mjs} +2 -2
  102. package/dist/{route-types-BZi26DVS.mjs → route-types--PAOzHlH.mjs} +49 -28
  103. package/dist/routes-stub.d.mts +22 -13
  104. package/dist/runtime/better-auth-mysql.mjs +1 -1
  105. package/dist/runtime/better-auth-pg.mjs +1 -1
  106. package/dist/runtime/better-auth.mjs +1 -1
  107. package/dist/runtime/handler.d.mts +1 -1
  108. package/dist/runtime/live-client.d.mts +1 -1
  109. package/dist/runtime/live.d.mts +1 -1
  110. package/dist/runtime/log.mjs +19 -1
  111. package/dist/runtime/routing.d.mts +2 -2
  112. package/dist/runtime/routing.mjs +4 -3
  113. package/dist/runtime/validator.d.mts +1 -1
  114. package/dist/runtime/ws-server.d.mts +1 -1
  115. package/dist/runtime/ws.d.mts +1 -1
  116. package/dist/{scan-8IzYXiU_.mjs → scan-N9WzdcAl.mjs} +302 -23
  117. package/dist/{secret-BbXHfLAt.mjs → secret-BL6g7mF5.mjs} +3 -3
  118. package/dist/static-asset-marker-Btf-6oCD.mjs +32 -0
  119. package/dist/{types-7AIz0OZu.d.mts → types-w72dljaA.d.mts} +6 -1
  120. package/dist/{version-metadata-tS39iW09.mjs → version-metadata-DmaZNTYW.mjs} +1 -1
  121. package/dist/worker-conditions-AWFRcFxR.mjs +11 -0
  122. package/dist/{wrangler-F96NnLyb.mjs → wrangler-CDiEBCdS.mjs} +2 -1
  123. package/dist/wrangler-DOPr4jyI.mjs +1 -0
  124. package/dist/{wrapper-D3sZyh2C.mjs → wrapper-CEiDeCqD.mjs} +6 -10
  125. package/dist/{ws-BH-im_tX.d.mts → ws-D1zWiB_P.d.mts} +1 -1
  126. package/docs/guide/auth.md +3 -1
  127. package/docs/guide/edge/static-assets.md +10 -0
  128. package/docs/guide/email/domains.md +1 -1
  129. package/docs/guide/email/receiving.md +2 -0
  130. package/docs/guide/email/sending.md +1 -1
  131. package/docs/guide/pages-routing/actions-and-forms.md +19 -13
  132. package/docs/guide/pages-routing/markdown.md +2 -0
  133. package/docs/guide/pages-routing/overview.md +33 -2
  134. package/docs/guide/platform/administration/email.md +18 -0
  135. package/docs/guide/platform/installation/prerequisites.md +9 -4
  136. package/docs/guide/platform/installation/uninstall.md +2 -0
  137. package/docs/guide/queues.md +13 -1
  138. package/docs/guide/server-routing.md +38 -2
  139. package/docs/guide/type-safety.md +7 -7
  140. package/docs/guide/websockets.md +4 -2
  141. package/docs/reference/api/pages.md +4 -4
  142. package/docs/reference/cli/email.md +13 -0
  143. package/docs/reference/cli/platform-email.md +2 -2
  144. package/docs/reference/cli.md +1 -0
  145. package/docs/reference/structure.md +3 -1
  146. package/package.json +8 -7
  147. package/templates/assets/icons.svg +49 -0
  148. package/templates/assets/react.svg +1 -0
  149. package/templates/assets/solid.svg +1 -0
  150. package/templates/assets/stack.svg +35 -0
  151. package/templates/assets/svelte.svg +1 -0
  152. package/templates/assets/void.svg +5 -0
  153. package/templates/assets/vue.svg +1 -0
  154. package/dist/cf-build-output-BJHuSsVN.mjs +0 -1
  155. package/dist/client-BiRDZTSd.mjs +0 -1
  156. package/dist/config-CyUJzi3q.mjs +0 -32
  157. package/dist/deploy-CE0Ev0Ob.mjs +0 -2
  158. package/dist/gen-NrOlWZaG.mjs +0 -1
  159. package/dist/help-BeAFFE5C.mjs +0 -1
  160. package/dist/login-DgDwlKc_.mjs +0 -1
  161. package/dist/migrate-n49ZeS1X.mjs +0 -1
  162. package/dist/operator-cmd-d2MvJOrl.mjs +0 -1
  163. package/dist/parse-filename-DioPHiR9.mjs +0 -77
  164. package/dist/platform-args-kQrgxScY.mjs +0 -1
  165. package/dist/prepare-C4I0f--h.mjs +0 -1
  166. package/dist/wrangler-BLb3_luP.mjs +0 -1
@@ -3,8 +3,8 @@ import { u as openBrowser } from "./auth-B6iOCjKI.mjs";
3
3
  import { A as confirm, tt as isCancel } from "./dist-Cor9XGoz.mjs";
4
4
  import { l as formatUrl, m as printSuccess } from "./output-BpgYODYx.mjs";
5
5
  import { a as resolveOperatorOrigin } from "./operator-auth-Cr2zCc-J.mjs";
6
- import { H as resolvePlatformCloudflareCredential, Y as PlatformCloudflareClient, g as platformDatabaseClientUrl, h as acquirePlatformDatabaseLifecycleLockConnection, n as resolvePlatformInstallDatabaseUrl } from "./platform-lifecycle-DyKmuNY6.mjs";
7
- import { d as verifyPlatformInstallationOwnership, l as selectAuthoritativePlatformManifest } from "./platform-management--vDwSn35.mjs";
6
+ import { H as resolvePlatformCloudflareCredential, Y as PlatformCloudflareClient, g as platformDatabaseClientUrl, h as acquirePlatformDatabaseLifecycleLockConnection, n as resolvePlatformInstallDatabaseUrl } from "./platform-lifecycle-3dwFJmnq.mjs";
7
+ import { d as verifyPlatformInstallationOwnership, l as selectAuthoritativePlatformManifest } from "./platform-management-ZZ6bQM5j.mjs";
8
8
  import { parsePlatformAccessProtection, parsePlatformAdmissionPolicy, parsePlatformLoginConfiguration, platformAuthenticationRecoveryMessage, validatePlatformAdmissionPolicy } from "@void/platform";
9
9
  import { createCipheriv, createDecipheriv, createHash, createHmac, hkdfSync, randomBytes, randomUUID } from "node:crypto";
10
10
  import { setTimeout } from "node:timers/promises";
@@ -1 +1 @@
1
- export { t as discoverPlatform, r as runPlatformCommand } from "./platform-cmd-D5I1beUX.mjs";
1
+ export { t as discoverPlatform, r as runPlatformCommand } from "./platform-cmd-HByuZAO7.mjs";
@@ -96,19 +96,19 @@ async function runPlatformCommand(_root, args) {
96
96
  }]
97
97
  });
98
98
  if (isCancel(group)) return;
99
- const { parsePlatformArgs } = await import("./platform-args-kQrgxScY.mjs");
99
+ const { parsePlatformArgs } = await import("./platform-args-BC8_hsDj.mjs");
100
100
  return runPlatformCommand(_root, parsePlatformArgs(["config", group]));
101
101
  }
102
102
  const { runPlatformPlansConfig } = await import("./platform-plans-config-CeydDSj0.mjs");
103
103
  await runPlatformPlansConfig(args);
104
104
  return;
105
105
  }
106
- const { runPlatformAuthConfig } = await import("./platform-auth-config-C-pm5Qzx.mjs");
106
+ const { runPlatformAuthConfig } = await import("./platform-auth-config-BgnuMbml.mjs");
107
107
  await runPlatformAuthConfig(args);
108
108
  return;
109
109
  }
110
110
  if (args.subcommand === "operator") {
111
- const { runOperatorCommand } = await import("./operator-cmd-d2MvJOrl.mjs");
111
+ const { runOperatorCommand } = await import("./operator-cmd-DDiX7Y3f.mjs");
112
112
  await runOperatorCommand(args);
113
113
  return;
114
114
  }
@@ -176,7 +176,7 @@ async function runPlatformCommand(_root, args) {
176
176
  console.log(`Capabilities: ${Object.entries(discovery.capabilities).filter(([, enabled]) => enabled).map(([name]) => name).join(", ")}`);
177
177
  return;
178
178
  }
179
- const { runPlatformLifecycleCommand } = await import("./platform-lifecycle-DH3Yr1qQ.mjs");
179
+ const { runPlatformLifecycleCommand } = await import("./platform-lifecycle-BRqcxerG.mjs");
180
180
  await runPlatformLifecycleCommand(args);
181
181
  }
182
182
  function showSavedInstallationStatus(manifest) {
@@ -2,8 +2,8 @@ import { m as readInstallationRecoverySecrets, t as acquirePlatformLifecycleLock
2
2
  import { t as cfAccessHeaders } from "./cf-access-BM9G0lhO.mjs";
3
3
  import { A as confirm, X as text, tt as isCancel } from "./dist-Cor9XGoz.mjs";
4
4
  import { m as printSuccess, p as note } from "./output-BpgYODYx.mjs";
5
- import { C as createPlatformHealthProbeToken, E as recordResource, H as resolvePlatformCloudflareCredential, O as recordPlatformWorkerTraffic, V as assertPlatformOperatorCredentialCanApplyPlan, Y as PlatformCloudflareClient, k as createPlatformInstallPlan, m as acquirePlatformDatabaseLifecycleLock, n as resolvePlatformInstallDatabaseUrl, t as assertNoninteractivePlatformMutationAcknowledged } from "./platform-lifecycle-DyKmuNY6.mjs";
6
- import { d as verifyPlatformInstallationOwnership, l as selectAuthoritativePlatformManifest, o as resolveInstalledPlatformManifest } from "./platform-management--vDwSn35.mjs";
5
+ import { C as createPlatformHealthProbeToken, E as recordResource, H as resolvePlatformCloudflareCredential, O as recordPlatformWorkerTraffic, V as assertPlatformOperatorCredentialCanApplyPlan, Y as PlatformCloudflareClient, k as createPlatformInstallPlan, m as acquirePlatformDatabaseLifecycleLock, n as resolvePlatformInstallDatabaseUrl, t as assertNoninteractivePlatformMutationAcknowledged } from "./platform-lifecycle-3dwFJmnq.mjs";
6
+ import { d as verifyPlatformInstallationOwnership, l as selectAuthoritativePlatformManifest, o as resolveInstalledPlatformManifest } from "./platform-management-ZZ6bQM5j.mjs";
7
7
  import { PLATFORM_HEALTH_HOSTNAME_LABEL, PLATFORM_REMOTE_INSTALLATION_MANIFEST_KEY, createApplicationRoutes, createPlatformDeploymentManifest, normalizeApplicationDomain } from "@void/platform";
8
8
  //#region src/cli/platform-domain.ts
9
9
  function platformDomainTarget(manifest, domain, zone, dedicatedZone) {
@@ -6,8 +6,8 @@ import { t as ensurePlatformAccessToken } from "./cf-access-CWP4avfP.mjs";
6
6
  import { A as confirm, H as outro, K as select, L as log, U as password, X as text$1, tt as isCancel, z as multiselect } from "./dist-Cor9XGoz.mjs";
7
7
  import { f as import_picocolors, l as formatUrl, m as printSuccess, n as cliCommandName, p as note, r as createSpinner, u as getErrorMessage } from "./output-BpgYODYx.mjs";
8
8
  import { l as resolveCloudflareOperationArgv } from "./cloudflare-process-8jEYIeim.mjs";
9
- import { o as createDefaultRunWrangler, v as resolvePinnedApiBaseUrl } from "./provision-DtROpNNI.mjs";
10
- import { t as parsePlatformArgs } from "./platform-args-DVbVClZl.mjs";
9
+ import { o as createDefaultRunWrangler, v as resolvePinnedApiBaseUrl } from "./provision-B7UFrBH7.mjs";
10
+ import { t as parsePlatformArgs } from "./platform-args-BMD2gjc_.mjs";
11
11
  import { o as runCloudflareAuthCommand } from "./cloudflare-auth-Byo_0_N9.mjs";
12
12
  import { a as platformManagementSetupPage, c as platformSetupLink, i as platformInstallCommandArguments, l as platformSetupPages, n as formatPlatformSetupPlan, o as platformPromptAnswer, r as openPlatformSetupPage, s as platformSetupFieldHelp, t as formatPlatformInstallCommand } from "./platform-setup-Ca53gtt0.mjs";
13
13
  import { copyFileSync, cpSync, existsSync, lstatSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, rmSync, writeFileSync } from "node:fs";
@@ -34,6 +34,14 @@ var PlatformCloudflareApiError = class extends Error {
34
34
  this.requestPath = requestPath;
35
35
  }
36
36
  };
37
+ var PlatformCloudflarePrerequisiteError = class extends PlatformCloudflareApiError {
38
+ cause;
39
+ constructor(message, cause) {
40
+ super(message, cause.status, cause.requestPath);
41
+ this.name = "PlatformCloudflarePrerequisiteError";
42
+ this.cause = cause;
43
+ }
44
+ };
37
45
  var PlatformWorkerCustomDomainsChangedError = class extends Error {
38
46
  constructor(message, options) {
39
47
  super(message, options);
@@ -165,7 +173,14 @@ var PlatformCloudflareClient = class PlatformCloudflareClient {
165
173
  } catch {
166
174
  throw new PlatformCloudflareApiError(`Cloudflare returned a non-JSON response (HTTP ${response.status}).`, response.status, path.split("?")[0]);
167
175
  }
168
- if (!response.ok || envelope.success !== true || envelope.result === void 0) throw new PlatformCloudflareApiError(`Cloudflare API error: ${cloudflareErrorDetails(envelope, response.status)} (HTTP ${response.status}; ${init?.method ?? "GET"} ${path.split("?")[0]}).`, response.status, path.split("?")[0]);
176
+ if (!response.ok || envelope.success !== true || envelope.result === void 0) {
177
+ const details = cloudflareErrorDetails(envelope, response.status);
178
+ const requestPath = path.split("?")[0];
179
+ const error = new PlatformCloudflareApiError(`Cloudflare API error: ${details} (HTTP ${response.status}; ${init?.method ?? "GET"} ${requestPath}).`, response.status, requestPath);
180
+ const prerequisite = cloudflarePrerequisiteHelp(envelope, response.status, requestPath);
181
+ if (prerequisite) throw new PlatformCloudflarePrerequisiteError(prerequisite, error);
182
+ throw error;
183
+ }
169
184
  return {
170
185
  result: envelope.result,
171
186
  resultInfo: envelope.result_info
@@ -804,6 +819,13 @@ function deletionPath(kind, account, encoded, zoneId) {
804
819
  default: return null;
805
820
  }
806
821
  }
822
+ function cloudflarePrerequisiteHelp(envelope, status, path) {
823
+ if (status !== 403) return;
824
+ const [, scope, accountId, service, resource] = path.split("/");
825
+ if (scope !== "accounts" || !accountId) return;
826
+ if (service === "r2" && envelope.errors?.some((error) => error.code === 10042)) return `Cloudflare R2 is not enabled for this account (code 10042). Complete R2 activation at ${formatUrl(`https://dash.cloudflare.com/${accountId}/r2/overview`)}, then retry the same command.`;
827
+ if (service === "workers" && resource === "dispatch" && envelope.errors?.some((error) => error.code === 10121)) return `Cloudflare Workers for Platforms requires a paid subscription for this account (code 10121). Enable it at ${formatUrl(`https://dash.cloudflare.com/${accountId}/workers-for-platforms`)}. Enterprise customers can contact their account team. Then retry the same command.`;
828
+ }
807
829
  function cloudflareErrorDetails(envelope, status) {
808
830
  return envelope.errors?.filter((error) => error.message).map((error) => error.code === void 0 ? error.message : `${error.message} (code ${error.code})`).join(", ") || `HTTP ${status}`;
809
831
  }
@@ -2488,19 +2510,27 @@ async function createPlatformInstallPlan(client, input, existing, options) {
2488
2510
  }
2489
2511
  throw error;
2490
2512
  });
2513
+ const prerequisites = [];
2514
+ const collectPrerequisite = (error) => {
2515
+ if (!(error instanceof PlatformCloudflarePrerequisiteError)) throw error;
2516
+ prerequisites.push(error);
2517
+ return [];
2518
+ };
2491
2519
  const [aiGateways, routingKv, isrKv, legacyKv, r2Buckets, usageQueues, cronQueues, deploymentQueues, dispatchNamespaces, hyperdrives, workers] = await Promise.all([
2492
2520
  gatewayInventory,
2493
2521
  client.listKvNamespaces(account.id, names.routingKv),
2494
2522
  client.listKvNamespaces(account.id, names.isrCacheKv),
2495
2523
  client.listKvNamespaces(account.id, names.legacyAssetsKv),
2496
- client.listR2Buckets(account.id),
2524
+ client.listR2Buckets(account.id).catch(collectPrerequisite),
2497
2525
  client.listQueues(account.id, names.usageQueue),
2498
2526
  client.listQueues(account.id, names.cronQueue),
2499
2527
  options?.deploymentExecution ?? existing?.resources.some((resource) => resource.key === "deployment-queue") ? client.listQueues(account.id, names.deploymentQueue) : Promise.resolve([]),
2500
- client.listDispatchNamespaces(account.id),
2528
+ client.listDispatchNamespaces(account.id).catch(collectPrerequisite),
2501
2529
  client.listHyperdriveConfigs(account.id),
2502
2530
  client.listWorkerNames(account.id)
2503
2531
  ]);
2532
+ if (prerequisites.length === 1) throw prerequisites[0];
2533
+ if (prerequisites.length > 1) throw new AggregateError(prerequisites, `platform: Cloudflare account prerequisites are missing:\n\n${prerequisites.map((error) => error.message).join("\n\n")}`);
2504
2534
  const dnsRecords = zone ? await listZoneDnsRecords(client, zone, wildcardHostname) : [];
2505
2535
  const remoteOwnership = existing ? await readRemoteOwnership(client, account.id, routingKv, existing) : null;
2506
2536
  const intentProofs = /* @__PURE__ */ new Set();
@@ -3739,7 +3769,7 @@ function uploadConflictMessage(result, operation) {
3739
3769
  }
3740
3770
  return `platform: The Cloudflare CLI did not ${operation}. It stopped the upload because of a conflict that it could not confirm without a terminal. Fix the conflict, then run the command again.`;
3741
3771
  }
3742
- function assertCleanPlatformWrangler(result, operation) {
3772
+ function assertCleanPlatformWrangler(result, operation, accountId) {
3743
3773
  if (result.status !== 0 || result.signal || result.error) {
3744
3774
  const conflict = uploadConflictMessage(result, operation);
3745
3775
  if (conflict) throw new Error(conflict);
@@ -3747,8 +3777,11 @@ function assertCleanPlatformWrangler(result, operation) {
3747
3777
  ...result,
3748
3778
  stderr: result.stderr.trim() || result.errors?.map((error) => error.message).join("\n") || ""
3749
3779
  });
3750
- const analyticsEngineDisabled = result.errorCode === ANALYTICS_ENGINE_NOT_ENABLED || result.errors?.some((error) => error.code === ANALYTICS_ENGINE_NOT_ENABLED) || /\b10089\b/.test(diagnostic ?? "");
3751
- throw new Error(`platform: Wrangler failed to ${operation} (${diagnostic || `exit ${result.status}`}).` + (analyticsEngineDisabled ? " If the Analytics Engine page offers no way to enable it, follow https://void.cloud/guide/platform/installation/prerequisites#if-cloudflare-rejects-analytics-engine, then retry." : ""));
3780
+ if (result.errorCode === ANALYTICS_ENGINE_NOT_ENABLED || result.errors?.some((error) => error.code === ANALYTICS_ENGINE_NOT_ENABLED) || result.errorCode === void 0 && !result.errors?.some((error) => error.code !== void 0) && (diagnostic?.includes("[code: 10089]") || diagnostic?.includes("[10089]"))) {
3781
+ const dashboard = accountId ? `https://dash.cloudflare.com/${accountId}/workers/analytics-engine` : "https://dash.cloudflare.com/";
3782
+ throw new Error(`platform: Cloudflare could not ${operation}: Analytics Engine is not enabled for this account (code 10089). Open ${formatUrl(dashboard)}${accountId ? "" : ", select your account, and open Analytics Engine"}, then select Enable. Analytics Engine is available on Workers Free. After enabling it, use the printed recovery command if one is shown; otherwise retry this command. If Enable is unavailable, see ${formatUrl("https://void.cloud/guide/platform/installation/prerequisites#if-cloudflare-rejects-analytics-engine")}.`);
3783
+ }
3784
+ throw new Error(`platform: Cloudflare failed to ${operation} (${diagnostic || `exit ${result.status}`}).`);
3752
3785
  }
3753
3786
  }
3754
3787
  function assertPlatformTriggerStabilization(result, workerName, targetVersionId, operation) {
@@ -3764,7 +3797,7 @@ async function readActivePlatformWorkerVersion(configPath, accountId, workerName
3764
3797
  configPath,
3765
3798
  workerName
3766
3799
  }, accountId, process.cwd(), true);
3767
- if (result.status !== 0) assertCleanPlatformWrangler(result, `read active version for ${workerName}`);
3800
+ if (result.status !== 0) assertCleanPlatformWrangler(result, `read active version for ${workerName}`, accountId);
3768
3801
  const value = result.data;
3769
3802
  if (!value || typeof value !== "object" || !Array.isArray(value.versions)) throw new Error(`platform: Wrangler returned malformed deployment status for ${workerName}.`);
3770
3803
  const active = value.versions.filter((entry) => entry && typeof entry === "object" && Number(entry.percentage) === 100);
@@ -3807,7 +3840,7 @@ async function readPlatformWorkerDeployments(configPath, accountId, workerName,
3807
3840
  configPath,
3808
3841
  workerName
3809
3842
  }, accountId, process.cwd(), true);
3810
- if (result.status !== 0) assertCleanPlatformWrangler(result, `read deployment lineage for ${workerName}`);
3843
+ if (result.status !== 0) assertCleanPlatformWrangler(result, `read deployment lineage for ${workerName}`, accountId);
3811
3844
  const value = result.data;
3812
3845
  if (!Array.isArray(value)) throw new Error(`platform: Wrangler returned malformed deployment history for ${workerName}.`);
3813
3846
  return value.map((entry, index) => {
@@ -3894,7 +3927,7 @@ async function readPlatformWorkerVersionSnapshot(configPath, accountId, workerNa
3894
3927
  configPath,
3895
3928
  workerName
3896
3929
  }, accountId, process.cwd(), true);
3897
- assertCleanPlatformWrangler(result, `read rollback metadata for ${workerName}`);
3930
+ assertCleanPlatformWrangler(result, `read rollback metadata for ${workerName}`, accountId);
3898
3931
  const value = result.data;
3899
3932
  if (!value || typeof value !== "object") throw new Error(`platform: Wrangler returned malformed version metadata for ${workerName}.`);
3900
3933
  const resources = value.resources;
@@ -3957,6 +3990,9 @@ function recordWorkerSecretUpdateState(manifest, generation, state, intentId, co
3957
3990
  resultHash: intentId
3958
3991
  }, completedAt);
3959
3992
  }
3993
+ function workerCutoverUpdatesSecrets(manifest, generation) {
3994
+ return manifest.steps.some((step) => step.key === `worker-secret-updates:${generation}:pending`);
3995
+ }
3960
3996
  function recordWorkerCutoverStage(manifest, generation, key, previousVersionId, stagedVersionId, workerName, previousTriggers, completedAt) {
3961
3997
  return recordInstallationStep(manifest, {
3962
3998
  completedAt,
@@ -4219,6 +4255,7 @@ async function recoverInterruptedPlatformWorkerCutover(input) {
4219
4255
  const { interruptedCutover, configs, previousConfigs, plan, dependencies, ids, previousPublicEndpoints, hasEmailGatewayArtifact, runPinnedPlatformWrangler, now, writeRemoteInstallationCheckpoint, onManifestChange } = input;
4220
4256
  let { manifest, workerActions } = input;
4221
4257
  if (interruptedCutover) {
4258
+ const retainUpdatedCredentials = workerCutoverUpdatesSecrets(manifest, interruptedCutover.generation);
4222
4259
  for (const key of [
4223
4260
  "dispatch",
4224
4261
  "tail",
@@ -4236,7 +4273,20 @@ async function recoverInterruptedPlatformWorkerCutover(input) {
4236
4273
  ...previousConfigs[key],
4237
4274
  name: snapshot.workerName
4238
4275
  }, preservedRoutes);
4239
- if (dependencies.recoverWorkerCutover) await dependencies.recoverWorkerCutover({
4276
+ if (retainUpdatedCredentials) {
4277
+ const directory = mkdtempSync(join(tmpdir(), "void-platform-resume-"));
4278
+ try {
4279
+ const configPath = join(directory, "wrangler.json");
4280
+ writeFileSync(configPath, JSON.stringify(recoveryConfig), { mode: 384 });
4281
+ const currentVersionId = await readActivePlatformWorkerVersion(configPath, plan.account.id, snapshot.workerName, runPinnedPlatformWrangler);
4282
+ if (currentVersionId !== snapshot.stagedVersionId && (snapshot.previousVersionId === null || currentVersionId !== snapshot.previousVersionId)) throw new Error(`Worker ${snapshot.workerName} changed concurrently after the credential update; refusing to overwrite it.`);
4283
+ } finally {
4284
+ rmSync(directory, {
4285
+ force: true,
4286
+ recursive: true
4287
+ });
4288
+ }
4289
+ } else if (dependencies.recoverWorkerCutover) await dependencies.recoverWorkerCutover({
4240
4290
  key,
4241
4291
  preserveCustomDomains: interruptedCutover.unsafeTraffic.has(key),
4242
4292
  previousVersionId: snapshot.previousVersionId,
@@ -4272,8 +4322,8 @@ async function recoverInterruptedPlatformWorkerCutover(input) {
4272
4322
  });
4273
4323
  }
4274
4324
  }
4275
- manifest = recordWorkerCutoverResolution(manifest, interruptedCutover.generation, "restored", now());
4276
- manifest = recordWorkerTrafficState(manifest, interruptedCutover.generation, previousPublicEndpoints && interruptedCutover.unsafeTraffic.size === 0, now());
4325
+ manifest = recordWorkerCutoverResolution(manifest, interruptedCutover.generation, retainUpdatedCredentials ? "committed" : "restored", now());
4326
+ manifest = recordWorkerTrafficState(manifest, interruptedCutover.generation, !retainUpdatedCredentials && previousPublicEndpoints && interruptedCutover.unsafeTraffic.size === 0, now());
4277
4327
  onManifestChange(manifest);
4278
4328
  writeInstallationManifest(manifest);
4279
4329
  await writeRemoteInstallationCheckpoint(dependencies.client, plan, manifest);
@@ -4555,7 +4605,7 @@ async function deployPlatformWorker(config, secrets, options) {
4555
4605
  let uploadError;
4556
4606
  try {
4557
4607
  uploaded = options.workerExisted ? await options.runner(operation, accountId, directory, true) : await runPlatformWranglerForConditionalCreate(operation, accountId, directory, true, workerName, options.apiBaseUrl, options.operatorApiToken);
4558
- assertCleanPlatformWrangler(uploaded, `${options.workerExisted ? "upload" : "bootstrap"} ${workerName}`);
4608
+ assertCleanPlatformWrangler(uploaded, `${options.workerExisted ? "upload" : "bootstrap"} ${workerName}`, accountId);
4559
4609
  } catch (error) {
4560
4610
  uploadError = error;
4561
4611
  throw error;
@@ -4581,7 +4631,7 @@ async function deployPlatformWorker(config, secrets, options) {
4581
4631
  percentage: 100
4582
4632
  }],
4583
4633
  message: `Void platform activation ${uploadedVersionId}`
4584
- }, accountId, directory, true), `activate ${workerName}`);
4634
+ }, accountId, directory, true), `activate ${workerName}`, accountId);
4585
4635
  }
4586
4636
  const deploymentsAfterActivation = await readPlatformWorkerDeployments(configPath, accountId, workerName, readRunner);
4587
4637
  const lineage = classifyPlatformWorkerDeploymentLineage(deploymentsAfterActivation, uploadedVersionId, previousDeploymentId);
@@ -4808,7 +4858,7 @@ async function restorePlatformWorkerDeployment(input) {
4808
4858
  percentage: version.percentage
4809
4859
  })),
4810
4860
  message: `Void platform restoration ${input.restoration.id}`
4811
- }, input.accountId, input.directory, true), `restore deployment ${input.restoration.id}`);
4861
+ }, input.accountId, input.directory, true), `restore deployment ${input.restoration.id}`, input.accountId);
4812
4862
  const after = await readPlatformWorkerDeployments(input.configPath, input.accountId, input.workerName, input.runner);
4813
4863
  if (!samePlatformWorkerTraffic(after[0], input.restoration) || after[1]?.id !== input.expectedActiveDeploymentId) throw new Error(`Worker ${input.workerName} deployment restoration was superseded or did not restore deployment ${input.restoration.id}.`);
4814
4864
  }
@@ -5032,14 +5082,21 @@ async function platformProbeFailure(label, url, response, context) {
5032
5082
  return new Error(message);
5033
5083
  }
5034
5084
  async function verifyPlatformHealth(apiUrl, installationId, proxyUrl, applicationBaseDomain, platformVersion, usageProtocolVersion, healthProbeToken, fetcher = fetch, dispatchOrigin, context) {
5035
- const request = (url) => fetcher(url, {
5036
- headers: {
5037
- "X-Void-Platform-Probe": healthProbeToken,
5038
- ...cfAccessHeaders(process.env, url)
5039
- },
5040
- redirect: "manual",
5041
- signal: AbortSignal.timeout(3e4)
5042
- });
5085
+ const request = async (url) => {
5086
+ for (let attempt = 0;; attempt++) try {
5087
+ return await fetcher(url, {
5088
+ headers: {
5089
+ "X-Void-Platform-Probe": healthProbeToken,
5090
+ ...cfAccessHeaders(process.env, url)
5091
+ },
5092
+ redirect: "manual",
5093
+ signal: AbortSignal.timeout(3e4)
5094
+ });
5095
+ } catch (error) {
5096
+ if (attempt === 2) throw new Error(`platform: Health check could not reach ${url} after 3 attempts.`, { cause: error });
5097
+ await setTimeout$1(250 * (attempt + 1));
5098
+ }
5099
+ };
5043
5100
  const dispatchUrl = dispatchOrigin ?? `https://${PLATFORM_HEALTH_HOSTNAME_LABEL}.${applicationBaseDomain}`;
5044
5101
  const [health, discovery, proxy, dispatch, emailGateway] = await Promise.all([
5045
5102
  request(`${apiUrl}/health`),
@@ -5459,7 +5516,7 @@ async function verifyInstalledPlatformAccessProtection(input) {
5459
5516
  }
5460
5517
  const existingWorkers = input.plan.actions.filter((action) => action.kind === "worker" && action.action === "update").map((action) => action.name);
5461
5518
  if (existingWorkers.length) {
5462
- const { verifyProtectionWorkerOrigins } = await import("./platform-auth-protection-SHhvim1L.mjs");
5519
+ const { verifyProtectionWorkerOrigins } = await import("./platform-auth-protection-NjRejttU.mjs");
5463
5520
  await verifyProtectionWorkerOrigins({
5464
5521
  request: input.client.request.bind(input.client),
5465
5522
  listWorkerDomains: input.client.listWorkerDomains.bind(input.client),
@@ -6577,7 +6634,7 @@ async function recoverFailedPlatformInstallation(error, state) {
6577
6634
  } catch (guardError) {
6578
6635
  failure = new Error(`platform: ${getErrorMessage(error)} The installation also failed to retain its routing safety gate: ${getErrorMessage(guardError)}`, { cause: error });
6579
6636
  }
6580
- if (!workerDeploymentCommitted && workerRollbacks.length > 0 && !(authenticationEnforcementActive && authenticationProtocolTransition)) {
6637
+ if (!workerDeploymentCommitted && workerRollbacks.length > 0 && !state.workerSecretUpdateIntent && !(authenticationEnforcementActive && authenticationProtocolTransition)) {
6581
6638
  const rollbackFailures = [];
6582
6639
  for (const rollback of workerRollbacks.reverse()) try {
6583
6640
  await rollback();
@@ -6689,9 +6746,9 @@ async function installPlatform(plan, secrets, existing, dependencies) {
6689
6746
  const hasExplicitWorkerSecretUpdates = Object.keys(explicitWorkerSecretUpdates).length > 0;
6690
6747
  const resumedWorkerSecretUpdateIntent = secrets.pendingWorkerSecretUpdateIntent && platformWorkerSecretUpdateIntentState(manifest, secrets.pendingWorkerSecretUpdateIntent) === "active" ? secrets.pendingWorkerSecretUpdateIntent : null;
6691
6748
  const workerSecretUpdateIntent = hasExplicitWorkerSecretUpdates ? {
6692
- baselineGeneration: latestPlatformWorkerCutoverGeneration(manifest),
6693
- generation: null,
6694
- id: randomUUID(),
6749
+ baselineGeneration: resumedWorkerSecretUpdateIntent?.baselineGeneration ?? latestPlatformWorkerCutoverGeneration(manifest),
6750
+ generation: resumedWorkerSecretUpdateIntent?.generation ?? null,
6751
+ id: resumedWorkerSecretUpdateIntent?.id ?? randomUUID(),
6695
6752
  schema: 1,
6696
6753
  updates: {
6697
6754
  ...resumedWorkerSecretUpdateIntent?.updates,
@@ -6830,7 +6887,7 @@ async function installPlatform(plan, secrets, existing, dependencies) {
6830
6887
  const createsWorker = state.plan.actions.some((action) => action.kind === "worker" && action.action === "create" && (hasEmailGatewayArtifact || action.key !== "email-gateway-worker"));
6831
6888
  const recoveringCreatedWorker = interruptedCutover !== null && [...interruptedCutover.staged.values()].some((snapshot) => snapshot.previousVersionId === null);
6832
6889
  const requiresSandboxDrain = !preserveDisabled && targetSandboxDrainProtocol >= 1 && sandboxDrainState === "pending";
6833
- const requiresTrafficGuard = !previousPublicEndpoints || recoveringUnsafeTraffic || createsWorker || recoveringCreatedWorker || state.manifest.usageProtocolVersion !== targetUsageProtocolVersion || runtime.privatePreviews === 1 && !state.manifest.steps.some((step) => step.key === "private-previews-initialized:v1") || authenticationProtocolTransition || shouldBootstrapSharedEmail || requiresSandboxDrain || !!state.plan.deployment.appAccess && !state.manifest.steps.some((step) => step.key === "app-access-initialized:v1");
6890
+ const requiresTrafficGuard = !previousPublicEndpoints || hadPriorWorkers && !!state.workerSecretUpdateIntent || !!interruptedCutover && workerCutoverUpdatesSecrets(state.manifest, interruptedCutover.generation) || recoveringUnsafeTraffic || createsWorker || recoveringCreatedWorker || state.manifest.usageProtocolVersion !== targetUsageProtocolVersion || runtime.privatePreviews === 1 && !state.manifest.steps.some((step) => step.key === "private-previews-initialized:v1") || authenticationProtocolTransition || shouldBootstrapSharedEmail || requiresSandboxDrain || !!state.plan.deployment.appAccess && !state.manifest.steps.some((step) => step.key === "app-access-initialized:v1");
6834
6891
  const configInput = {
6835
6892
  authenticationDatabaseUncached: true,
6836
6893
  proxyHealthBinding: true,
@@ -6916,6 +6973,11 @@ async function installPlatform(plan, secrets, existing, dependencies) {
6916
6973
  }));
6917
6974
  state.workerCutoverGeneration = nextWorkerCutoverGeneration(state.manifest);
6918
6975
  if (state.workerSecretUpdateIntent) {
6976
+ state.workerSecretUpdateIntent = {
6977
+ ...state.workerSecretUpdateIntent,
6978
+ generation: null
6979
+ };
6980
+ writePendingInstallationSecrets(state.manifest, secretCheckpoint(state.secrets, state.workerSecretUpdateIntent));
6919
6981
  state.manifest = recordWorkerSecretUpdateState(state.manifest, state.workerCutoverGeneration, "pending", state.workerSecretUpdateIntent.id, now());
6920
6982
  writeInstallationManifest(state.manifest);
6921
6983
  await writeRemoteInstallationCheckpoint(dependencies.client, state.plan, state.manifest);
@@ -7535,13 +7597,13 @@ function needsReviewUpload(change) {
7535
7597
  * The earlier version of each Worker that the installer makes active again
7536
7598
  * before it deploys. A run that stopped during a Worker cutover left Void's
7537
7599
  * version active, and the next run first restores the earlier one. Like the
7538
- * installer, keep Void's version while the platform changes to configurable
7539
- * sign-in and already requires sign-in. Every Worker that this check reads
7540
- * exists, so the installation had Workers before.
7600
+ * installer, retain rotated credentials or a configurable sign-in transition
7601
+ * that already requires sign-in. Every Worker that this check reads exists,
7602
+ * so the installation had Workers before.
7541
7603
  */
7542
7604
  async function restoredPlatformWorkerVersions(installation, runtime) {
7543
7605
  const cutover = interruptedWorkerCutover(installation.manifest);
7544
- if (!cutover || installation.manifest.deployment.authentication.configurable !== true && runtime.manifest.authenticationProtocolVersion === 1 && (await installation.readAuthenticationState?.())?.sessionsRequired === true) return /* @__PURE__ */ new Map();
7606
+ if (!cutover || workerCutoverUpdatesSecrets(installation.manifest, cutover.generation) || installation.manifest.deployment.authentication.configurable !== true && runtime.manifest.authenticationProtocolVersion === 1 && (await installation.readAuthenticationState?.())?.sessionsRequired === true) return /* @__PURE__ */ new Map();
7545
7607
  return new Map([...cutover.staged.values()].flatMap((snapshot) => snapshot.previousVersionId === null ? [] : [[snapshot.workerName, snapshot.previousVersionId]]));
7546
7608
  }
7547
7609
  /** Find the existing platform Workers that a run uploads and that were changed outside Void. */
@@ -7776,14 +7838,14 @@ function resolvePlatformInstallDatabaseUrl(checkpoint, manifest = null) {
7776
7838
  }
7777
7839
  async function runPlatformLifecycleCommand(commandArgs) {
7778
7840
  if (commandArgs.subcommand === "domain") {
7779
- const { runPlatformDomainCommand } = await import("./platform-domain-jpmBfZeb.mjs");
7841
+ const { runPlatformDomainCommand } = await import("./platform-domain-DLSQ8GF8.mjs");
7780
7842
  await runPlatformDomainCommand(commandArgs);
7781
7843
  return;
7782
7844
  }
7783
7845
  if (commandArgs.subcommand === "discover") {
7784
7846
  const client = new PlatformCloudflareClient((await resolvePlatformCloudflareCredential()).token);
7785
7847
  const accountId = await selectAccount(await readAccounts(client), commandArgs.account);
7786
- const { recoverPlatformInstallations } = await import("./platform-recovery-BiNpZZab.mjs");
7848
+ const { recoverPlatformInstallations } = await import("./platform-recovery-8vNE5dNN.mjs");
7787
7849
  const recovered = await recoverPlatformInstallations(client, accountId, void 0, commandArgs.selector);
7788
7850
  if (recovered.length === 0) {
7789
7851
  log.info(`No recoverable Void platform installations were found in ${accountId}.`);
@@ -7794,7 +7856,7 @@ async function runPlatformLifecycleCommand(commandArgs) {
7794
7856
  return;
7795
7857
  }
7796
7858
  if (commandArgs.subcommand !== "install") {
7797
- const { runInstalledPlatformCommand } = await import("./platform-management-7m-PLaPJ.mjs");
7859
+ const { runInstalledPlatformCommand } = await import("./platform-management-ZK6XcbCo.mjs");
7798
7860
  await runInstalledPlatformCommand(commandArgs);
7799
7861
  return;
7800
7862
  }
@@ -7970,7 +8032,7 @@ async function runPlatformLifecycleCommand(commandArgs) {
7970
8032
  progress?.stop("Read the saved installation.");
7971
8033
  progress = void 0;
7972
8034
  if (authoritative) {
7973
- const { selectAuthoritativePlatformManifest } = await import("./platform-management-7m-PLaPJ.mjs");
8035
+ const { selectAuthoritativePlatformManifest } = await import("./platform-management-ZK6XcbCo.mjs");
7974
8036
  const selected = selectAuthoritativePlatformManifest(existing, authoritative);
7975
8037
  authoritativeProvisionIntents = true;
7976
8038
  if (!args.plan && JSON.stringify(selected) !== JSON.stringify(existing)) writeInstallationManifest(selected);
@@ -8410,7 +8472,7 @@ async function runPlatformLifecycleCommand(commandArgs) {
8410
8472
  })).actions.filter((action) => action.kind === "worker"),
8411
8473
  revalidateBeforeWorkerDeploy: (manifest, action) => revalidatePlatformInstallAction(client, plan, manifest, action),
8412
8474
  verifyExistingOwnership: async (manifest, databaseCheckpointExists) => {
8413
- const { verifyPlatformInstallationOwnership } = await import("./platform-management-7m-PLaPJ.mjs");
8475
+ const { verifyPlatformInstallationOwnership } = await import("./platform-management-ZK6XcbCo.mjs");
8414
8476
  const retainedReplacementKeys = new Set(plan.actions.filter((action) => {
8415
8477
  const previous = manifest.resources.find((resource) => resource.key === action.key);
8416
8478
  return action.action === "create" && previous && previous.name !== action.name;
@@ -1 +1 @@
1
- export { r as runPlatformLifecycleCommand } from "./platform-lifecycle-DyKmuNY6.mjs";
1
+ export { r as runPlatformLifecycleCommand } from "./platform-lifecycle-3dwFJmnq.mjs";
@@ -1 +1 @@
1
- export { c as runInstalledPlatformCommand, l as selectAuthoritativePlatformManifest, d as verifyPlatformInstallationOwnership } from "./platform-management--vDwSn35.mjs";
1
+ export { c as runInstalledPlatformCommand, l as selectAuthoritativePlatformManifest, d as verifyPlatformInstallationOwnership } from "./platform-management-ZZ6bQM5j.mjs";
@@ -2,7 +2,7 @@ import { S as writePendingInstallationSecrets, _ as removePlatformConnectionForI
2
2
  import { t as ensurePlatformAccessToken } from "./cf-access-CWP4avfP.mjs";
3
3
  import { A as confirm, H as outro, K as select, L as log, tt as isCancel } from "./dist-Cor9XGoz.mjs";
4
4
  import { f as import_picocolors, l as formatUrl, m as printSuccess, p as note, r as createSpinner } from "./output-BpgYODYx.mjs";
5
- import { $ as hyperdriveOriginMatches, A as dnsRecordConfigHash, B as turnOffInstalledProjectZeroTrust, C as createPlatformHealthProbeToken, D as platformTrafficAttachmentWorker, F as platformAdoptionIntentHash, H as resolvePlatformCloudflareCredential, I as r2BucketConfigHash, J as PlatformCloudflareApiError, L as resourceMarkerProblem, M as hasProvisionIntentStep, N as legacyResourceConfigHash, P as matchesRecordedR2Fingerprint, Q as hyperdriveOriginFromConnectionString, R as revalidatePlatformInstallAction, S as loadPlatformRuntime, T as resolveBootstrapGitHubId, U as verifyPlatformCloudflareCredential, V as assertPlatformOperatorCredentialCanApplyPlan, W as activatePlatformAccessCredentials, X as PlatformRuntimeTokenEmailPermissionError, Y as PlatformCloudflareClient, Z as hyperdriveOriginConfigHash, _ as readPlatformProjectSlugs, a as findPlatformWorkerOutsideChanges, b as formatZeroTrustApplications, c as uploadPlatformWorkerOutsideChanges, d as replacePendingInstallationAuthentication, et as verifyPlatformRuntimeTokenEmailPermissions, f as REMOTE_INSTALLATION_MANIFEST_KEY, j as formatPlatformInstallPlan, k as createPlatformInstallPlan, l as authenticationSetupRequestHash, m as acquirePlatformDatabaseLifecycleLock, n as resolvePlatformInstallDatabaseUrl, o as formatPlatformWorkerOutsideChanges, p as installPlatform, s as reviewPlatformWorkerOutsideChanges, t as assertNoninteractivePlatformMutationAcknowledged, tt as verifyPlatformRuntimeTokenPermissions, u as readLoginReplacementFile, v as readPlatformProjectZeroTrustState, w as createPlatformInstallationSecrets, x as readPlatformDatabase, y as assertProjectZeroTrustAllowsUninstall, z as platformDatabaseNameFromOwnerUrl } from "./platform-lifecycle-DyKmuNY6.mjs";
5
+ import { $ as hyperdriveOriginMatches, A as dnsRecordConfigHash, B as turnOffInstalledProjectZeroTrust, C as createPlatformHealthProbeToken, D as platformTrafficAttachmentWorker, F as platformAdoptionIntentHash, H as resolvePlatformCloudflareCredential, I as r2BucketConfigHash, J as PlatformCloudflareApiError, L as resourceMarkerProblem, M as hasProvisionIntentStep, N as legacyResourceConfigHash, P as matchesRecordedR2Fingerprint, Q as hyperdriveOriginFromConnectionString, R as revalidatePlatformInstallAction, S as loadPlatformRuntime, T as resolveBootstrapGitHubId, U as verifyPlatformCloudflareCredential, V as assertPlatformOperatorCredentialCanApplyPlan, W as activatePlatformAccessCredentials, X as PlatformRuntimeTokenEmailPermissionError, Y as PlatformCloudflareClient, Z as hyperdriveOriginConfigHash, _ as readPlatformProjectSlugs, a as findPlatformWorkerOutsideChanges, b as formatZeroTrustApplications, c as uploadPlatformWorkerOutsideChanges, d as replacePendingInstallationAuthentication, et as verifyPlatformRuntimeTokenEmailPermissions, f as REMOTE_INSTALLATION_MANIFEST_KEY, j as formatPlatformInstallPlan, k as createPlatformInstallPlan, l as authenticationSetupRequestHash, m as acquirePlatformDatabaseLifecycleLock, n as resolvePlatformInstallDatabaseUrl, o as formatPlatformWorkerOutsideChanges, p as installPlatform, s as reviewPlatformWorkerOutsideChanges, t as assertNoninteractivePlatformMutationAcknowledged, tt as verifyPlatformRuntimeTokenPermissions, u as readLoginReplacementFile, v as readPlatformProjectZeroTrustState, w as createPlatformInstallationSecrets, x as readPlatformDatabase, y as assertProjectZeroTrustAllowsUninstall, z as platformDatabaseNameFromOwnerUrl } from "./platform-lifecycle-3dwFJmnq.mjs";
6
6
  import { PLATFORM_DISABLED_KEY, PLATFORM_DISABLED_VALUE, PLATFORM_R2_OWNERSHIP_MARKER_KEY, parsePlatformInstallationManifest, recordInstallationResource, recordInstallationStep, setInstallationDesiredState, transitionInstallation } from "@void/platform";
7
7
  import { setTimeout } from "node:timers/promises";
8
8
  //#region src/cli/platform-teardown.ts
@@ -1,7 +1,7 @@
1
1
  import { o as listInstallationManifests, t as acquirePlatformLifecycleLock, x as writeInstallationManifest, y as savePlatformConnection } from "./platform-registry-B9mWX9LO.mjs";
2
2
  import { t as cfAccessHeaders } from "./cf-access-BM9G0lhO.mjs";
3
- import { f as REMOTE_INSTALLATION_MANIFEST_KEY, k as createPlatformInstallPlan } from "./platform-lifecycle-DyKmuNY6.mjs";
4
- import { a as recoverDurablyMarkedProvisionIntents, d as verifyPlatformInstallationOwnership, r as isPlatformManifestMonotonicExtension } from "./platform-management--vDwSn35.mjs";
3
+ import { f as REMOTE_INSTALLATION_MANIFEST_KEY, k as createPlatformInstallPlan } from "./platform-lifecycle-3dwFJmnq.mjs";
4
+ import { a as recoverDurablyMarkedProvisionIntents, d as verifyPlatformInstallationOwnership, r as isPlatformManifestMonotonicExtension } from "./platform-management-ZZ6bQM5j.mjs";
5
5
  import { parsePlatformInstallationManifest, setInstallationEndpoints } from "@void/platform";
6
6
  //#region src/cli/platform-recovery.ts
7
7
  async function recoverPlatformInstallations(client, accountId, verifyEndpoint = verifyInstallationEndpoint, selector = "") {
@@ -1,10 +1,10 @@
1
1
  import { a as join, l as toSlash, s as relative } from "./dist-ipQi0Q8y.mjs";
2
2
  import { n as readProjectPaths } from "./project-paths-DGu_QZ_Q.mjs";
3
3
  import { n as globSync } from "./dist-D15hFhP0.mjs";
4
+ import { d as deriveFromSource, g as ROUTE_EXTENSIONS, h as parseWebSocketFilename, m as parseRouteFilename, p as isRouteEnabledForEnvironment, t as pageFileEnvironment } from "./scan-N9WzdcAl.mjs";
4
5
  import { a as isObjectExpression, i as isMemberExpression, n as isIdentifier, r as isLiteral, t as isCallExpression } from "./ast-CsZ_q_gc.mjs";
5
6
  import { a as staticLiteral, n as bindingResolver, o as unwrapStaticExpression, r as walk } from "./ast-bindings-C3yaPs1y.mjs";
6
7
  import { n as resourceNameWords, t as isResourceName } from "./resource-name-C7LVpcRm.mjs";
7
- import { n as parseRouteFilename, r as parseWebSocketFilename, t as isRouteEnabledForEnvironment } from "./parse-filename-DioPHiR9.mjs";
8
8
  import { r as getSsrServerEntryPath } from "./entry-BEM8ZuGP.mjs";
9
9
  import { existsSync, readFileSync } from "node:fs";
10
10
  import { parseSync } from "vite";
@@ -30,9 +30,38 @@ function needsApplicationDatabase(bindings, migrationCount) {
30
30
  }
31
31
  //#endregion
32
32
  //#region src/shared/convention-files.ts
33
+ const WELL_KNOWN_DIR = ".well-known";
34
+ /** Include the convention directory's .well-known files when it is inside the scan directory. */
35
+ function conventionFileGlobs(scanDir, pattern, conventionDir = scanDir) {
36
+ const patterns = [pattern];
37
+ const conventionRelative = relative(scanDir, conventionDir);
38
+ if (conventionRelative !== ".." && !conventionRelative.startsWith("../")) patterns.push(join(conventionRelative, WELL_KNOWN_DIR, pattern));
39
+ return patterns;
40
+ }
41
+ function isConventionPath(filePath) {
42
+ return filePath.replace(/\\/g, "/").split("/").every((segment, index) => !segment.startsWith("_") && (!segment.startsWith(".") || index === 0 && segment === WELL_KNOWN_DIR));
43
+ }
44
+ /** Whether a path relative to routes/ participates in HTTP or WebSocket routing. */
45
+ function isRouteFile(filePath) {
46
+ return isConventionPath(filePath) && ROUTE_EXTENSIONS.some((ext) => filePath.endsWith(`.${ext}`));
47
+ }
33
48
  /** Handler files under `dir`, relative to it, skipping paths with a `_`-prefixed segment. */
49
+ function listFilesWithExtensions(dir, extensions) {
50
+ const suffix = `*.{${extensions.join(",")}}`;
51
+ return globSync(conventionFileGlobs(dir, `**/${suffix}`), { cwd: dir }).filter(isConventionPath);
52
+ }
53
+ /** Cron and queue handlers with .ts, .mts, .js, or .mjs extensions. */
34
54
  function listConventionFiles(dir) {
35
- return globSync(["**/*.{ts,mts,js,mjs}", ".well-known/**/*.{ts,mts,js,mjs}"], { cwd: dir }).filter((filePath) => !filePath.split("/").some((segment) => segment.startsWith("_")));
55
+ return listFilesWithExtensions(dir, [
56
+ "ts",
57
+ "mts",
58
+ "js",
59
+ "mjs"
60
+ ]);
61
+ }
62
+ /** HTTP and WebSocket handlers, also allowing .tsx and .jsx for JSX. */
63
+ function listRouteFiles(dir) {
64
+ return listFilesWithExtensions(dir, ROUTE_EXTENSIONS);
36
65
  }
37
66
  //#endregion
38
67
  //#region src/shared/resource-definition.ts
@@ -409,7 +438,7 @@ function mergeBindings(bindings) {
409
438
  }
410
439
  //#endregion
411
440
  //#region src/router/websocket.ts
412
- const WEBSOCKET_ROUTE_RE = /(?:\.(?:dev|prod))?\.ws\.(?:ts|mts|js|mjs)$/;
441
+ const WEBSOCKET_ROUTE_RE = new RegExp(`(?:\\.(?:dev|prod))?\\.ws\\.(?:${ROUTE_EXTENSIONS.join("|")})$`);
413
442
  function isWebSocketRouteFile(filePath) {
414
443
  return WEBSOCKET_ROUTE_RE.test(filePath.replace(/\\/g, "/"));
415
444
  }
@@ -420,7 +449,10 @@ function deriveWebSocketClassNameFromName(name) {
420
449
  return resourceNameWords(name).map((part) => part[0].toUpperCase() + part.slice(1)).join("") + "Ws";
421
450
  }
422
451
  function inferWebSocketResourceName(filePath) {
423
- const parts = filePath.replace(/\\/g, "/").replace(/\.(ts|mts|js|mjs)$/, "").split("/").filter((segment) => segment.length > 0 && !(segment.startsWith("(") && segment.endsWith(")"))).flatMap(identifierWords);
452
+ let normalized = filePath.replace(/\\/g, "/");
453
+ const extension = ROUTE_EXTENSIONS.find((ext) => normalized.endsWith(`.${ext}`));
454
+ if (extension) normalized = normalized.slice(0, -(extension.length + 1));
455
+ const parts = normalized.split("/").filter((segment) => segment.length > 0 && !(segment.startsWith("(") && segment.endsWith(")"))).flatMap(identifierWords);
424
456
  return parts.length > 0 ? parts.join("-") : "WebSocket";
425
457
  }
426
458
  function deriveWebSocketClassName(filePath) {
@@ -471,7 +503,7 @@ function parseWebSocketFiles(root, files, paths = readProjectPaths(root), enviro
471
503
  return routes;
472
504
  }
473
505
  function scanWebSocketRoutesSync(root, paths = readProjectPaths(root), environment) {
474
- return parseWebSocketFiles(root, listConventionFiles(paths.routesDir), paths, environment);
506
+ return parseWebSocketFiles(root, listRouteFiles(paths.routesDir), paths, environment);
475
507
  }
476
508
  function isWebSocketPatternFile(filePath) {
477
509
  return isWebSocketRouteFile(filePath);
@@ -589,26 +621,32 @@ function inferProjectBindings(root, options, scanDirs) {
589
621
  const allBindings = [];
590
622
  const scannedFiles = /* @__PURE__ */ new Set();
591
623
  const routesPrefix = `${toSlash(paths.routesDir).replace(/\/$/, "")}/`;
624
+ const pagesDir = toSlash(paths.pagesDir);
625
+ const pagesPrefix = pagesDir.endsWith("/") ? pagesDir : `${pagesDir}/`;
626
+ const scanSourceFiles = (dirPath) => globSync(conventionFileGlobs(dirPath, SOURCE_GLOB, paths.routesDir), {
627
+ cwd: dirPath,
628
+ absolute: true
629
+ });
592
630
  const addFile = (file) => {
593
631
  const normalizedFile = toSlash(file);
594
632
  if (scannedFiles.has(normalizedFile)) return;
595
633
  scannedFiles.add(normalizedFile);
596
- if (options?.environment && normalizedFile.startsWith(routesPrefix) && /\.(?:ts|mts|js|mjs)$/.test(normalizedFile)) {
597
- const routePath = relative(paths.routesDir, normalizedFile);
634
+ const routePath = normalizedFile.startsWith(routesPrefix) ? normalizedFile.slice(routesPrefix.length) : void 0;
635
+ if (options?.environment && routePath !== void 0 && isRouteFile(routePath)) {
598
636
  const route = isWebSocketPatternFile(routePath) ? parseWebSocketFilename(routePath) : parseRouteFilename(routePath);
599
637
  if (!isRouteEnabledForEnvironment(route, options.environment)) return;
600
638
  }
601
- const code = readFileSync(file, "utf-8");
602
- allBindings.push(inferBindingsFromFile(file, code));
639
+ if (options?.environment && options.filterPages && normalizedFile.startsWith(pagesPrefix)) {
640
+ const env = pageFileEnvironment(normalizedFile.slice(pagesPrefix.length));
641
+ if (!isRouteEnabledForEnvironment({ env }, options.environment)) return;
642
+ }
643
+ allBindings.push(deriveFromSource(file, "bindings", (code) => inferBindingsFromFile(file, code)));
603
644
  };
604
645
  for (const dir of dirs) {
605
646
  const dirPath = join(root, dir);
606
647
  let files;
607
648
  try {
608
- files = globSync(SOURCE_GLOB, {
609
- cwd: dirPath,
610
- absolute: true
611
- });
649
+ files = scanSourceFiles(dirPath);
612
650
  } catch {
613
651
  continue;
614
652
  }
@@ -622,10 +660,7 @@ function inferProjectBindings(root, options, scanDirs) {
622
660
  const srcPath = paths.sourceDir ? paths.sourceRoot : join(root, "src");
623
661
  let srcFiles;
624
662
  try {
625
- srcFiles = globSync(SOURCE_GLOB, {
626
- cwd: srcPath,
627
- absolute: true
628
- });
663
+ srcFiles = scanSourceFiles(srcPath);
629
664
  } catch {
630
665
  srcFiles = [];
631
666
  }
@@ -634,4 +669,4 @@ function inferProjectBindings(root, options, scanDirs) {
634
669
  return applyBindingOverrides(mergeBindings(allBindings), options?.bindings);
635
670
  }
636
671
  //#endregion
637
- export { deriveWebSocketClassNameFromName as a, scanWebSocketRoutesSync as c, readResourceDefinition as d, listConventionFiles as f, inferProjectBindings as i, inferBindingsFromSource as l, needsApplicationDatabase as m, FRAMEWORK_SCAN_DIRS as n, inferWebSocketResourceName as o, applyBindingOverrides as p, detectFramework as r, isWebSocketPatternFile as s, DEFAULT_SCAN_DIRS as t, staticModuleReferences as u };
672
+ export { deriveWebSocketClassNameFromName as a, scanWebSocketRoutesSync as c, readResourceDefinition as d, listConventionFiles as f, needsApplicationDatabase as h, inferProjectBindings as i, inferBindingsFromSource as l, applyBindingOverrides as m, FRAMEWORK_SCAN_DIRS as n, inferWebSocketResourceName as o, listRouteFiles as p, detectFramework as r, isWebSocketPatternFile as s, DEFAULT_SCAN_DIRS as t, staticModuleReferences as u };
@@ -1,6 +1,6 @@
1
1
  import { L as log } from "./dist-Cor9XGoz.mjs";
2
2
  import { m as printSuccess, p as note } from "./output-BpgYODYx.mjs";
3
- import { t as prepareProject } from "./prepare-DA-17DhO.mjs";
3
+ import { t as prepareProject } from "./prepare-Dseww74N.mjs";
4
4
  //#region src/cli/prepare.ts
5
5
  async function runPrepareCommand(root) {
6
6
  console.log();
@@ -0,0 +1 @@
1
+ export { t as prepareProject } from "./prepare-Dseww74N.mjs";