void 0.23.0 → 0.24.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 (126) hide show
  1. package/AGENTS_TEMPLATE.md +1 -1
  2. package/dist/{account-cmd-C84Ee8cO.mjs → account-cmd-vJhh5lrb.mjs} +5 -5
  3. package/dist/{auth-CSkdO2Bb.mjs → auth-CQkSDS50.mjs} +22 -49
  4. package/dist/auth-DX3JURcX.mjs +2 -0
  5. package/dist/{auth-link-CioEg6uY.mjs → auth-link-D75t9wO2.mjs} +5 -5
  6. package/dist/{auth-router-BsR981d4.mjs → auth-router-ClfhL1J7.mjs} +7 -7
  7. package/dist/{build-cmd-LzvNJORH.mjs → build-cmd-zMi1iFnS.mjs} +6 -6
  8. package/dist/{cache-C4MvnrMH.mjs → cache-ZtQmyxVV.mjs} +5 -5
  9. package/dist/{cancel-deploy-abUxpP2n.mjs → cancel-deploy-Box0kkEV.mjs} +5 -5
  10. package/dist/{cf-access-P0iZnu0q.mjs → cf-access-BGe5sWXF.mjs} +4 -48
  11. package/dist/{cf-access-DRsQRe6k.mjs → cf-access-TWNzXltp.mjs} +3 -11
  12. package/dist/cli/cli.mjs +47 -44
  13. package/dist/cli/cloudflare-operation-process.mjs +14 -5
  14. package/dist/cli/env-schema-probe.mjs +3 -3
  15. package/dist/client-B9UBI03V.mjs +2 -0
  16. package/dist/{client-RV8NVeB8.mjs → client-DKAsFA4X.mjs} +33 -15
  17. package/dist/{cloudflare-cmd-BcrVyTmJ.mjs → cloudflare-cmd-CmY8dGkd.mjs} +1 -1
  18. package/dist/{cloudflare-connect-B8uPZ4nx.mjs → cloudflare-connect-IiR3ZieC.mjs} +1 -1
  19. package/dist/{cloudflare-operations-AiWashgg.mjs → cloudflare-operations-BCdXSsmo.mjs} +1 -1
  20. package/dist/{cloudflare-operations-fxHb-byx.mjs → cloudflare-operations-DzH-A966.mjs} +1 -1
  21. package/dist/{connect-Bd4kJd9U.mjs → connect-B-usTnlF.mjs} +9 -9
  22. package/dist/{create-project-bMf6ffLZ.mjs → create-project-CYOOAYcn.mjs} +12 -12
  23. package/dist/{create-project-Boczwj5r.mjs → create-project-FWbf5Olo.mjs} +1 -1
  24. package/dist/{db-8uG64XLl.mjs → db-Ck2eZ2iB.mjs} +15 -15
  25. package/dist/{delete-NvbiyeJf.mjs → delete-sK56qtzZ.mjs} +5 -5
  26. package/dist/{deploy-DzAIwqNU.mjs → deploy-gCVaiJbS.mjs} +86 -44
  27. package/dist/{deploy-bjXdFCtn.mjs → deploy-irP5q0-x.mjs} +1 -1
  28. package/dist/{domain-y5Tvydvo.mjs → domain-DFfQE8jg.mjs} +6 -6
  29. package/dist/{email-B3umsW75.mjs → email-CdnhUHvJ.mjs} +7 -7
  30. package/dist/{env-BS6qYHDb.mjs → env-DmGdHi5i.mjs} +8 -8
  31. package/dist/{env-types-C2_bIk_b.mjs → env-types-D5kds_OZ.mjs} +1 -1
  32. package/dist/{env-validation-BPn7vk-V.mjs → env-validation-C_8tPdhs.mjs} +2 -2
  33. package/dist/{env-validation-DbTg7-ar.mjs → env-validation-zZOCcQVZ.mjs} +1 -1
  34. package/dist/{gen-B580--vC.mjs → gen-CshAkukR.mjs} +2 -2
  35. package/dist/gen-DvQTWzDU.mjs +2 -0
  36. package/dist/{github-cmd-v45BdfKX.mjs → github-cmd-DftuEvIt.mjs} +13 -13
  37. package/dist/{headers-DWi2IXWx.mjs → headers-2rKda9Y6.mjs} +1 -1
  38. package/dist/{help-daGKjXGk.mjs → help-Dotbf6iz.mjs} +8 -4
  39. package/dist/help-mabuIV98.mjs +2 -0
  40. package/dist/{inbound-aVHEUhKo.mjs → inbound-fRkqcXaC.mjs} +1 -1
  41. package/dist/index.mjs +16 -20
  42. package/dist/{init-Bvy7zrBo.mjs → init-BTQEZZGJ.mjs} +25 -22
  43. package/dist/{link-CDqqCjFl.mjs → link-B46sYH0K.mjs} +6 -6
  44. package/dist/{list-CZj0dzKY.mjs → list-BnPrIsU_.mjs} +6 -6
  45. package/dist/log-vqY3pqwI.mjs +29 -0
  46. package/dist/{login-UZKFM_u7.mjs → login-BuiMyUrx.mjs} +8 -8
  47. package/dist/login-DIy9Sb-U.mjs +2 -0
  48. package/dist/{logs-CUZ6t9t3.mjs → logs-CZG9d-ic.mjs} +10 -11
  49. package/dist/migrate-BCiJ8w0f.mjs +2 -0
  50. package/dist/{migrate-DHul7PRV.mjs → migrate-q4_njtaW.mjs} +2 -2
  51. package/dist/{operator-args-CLgKGlwU.mjs → operator-args-B3BTmSoi.mjs} +12 -5
  52. package/dist/{operator-auth-8KnOVXVd.mjs → operator-auth-7erYc6Lt.mjs} +2 -2
  53. package/dist/{operator-client-DUwumHpQ.mjs → operator-client-CpHjTd0t.mjs} +3 -3
  54. package/dist/{operator-cmd-DBA6dl0m.mjs → operator-cmd-DGqPJUD3.mjs} +6 -6
  55. package/dist/{output-Dm_A4Tbv.mjs → output-CbM85T4k.mjs} +18 -10
  56. package/dist/pages/index.mjs +1 -1
  57. package/dist/{platform-args-BJdRtlLq.mjs → platform-args-3k8X9-H_.mjs} +11 -3
  58. package/dist/platform-args-DdnM6WIf.mjs +2 -0
  59. package/dist/{platform-auth-config-B56E9YP1.mjs → platform-auth-config-DDrxUy4m.mjs} +6 -6
  60. package/dist/{platform-auth-protection-BDWO_aER.mjs → platform-auth-protection-BLadnnct.mjs} +8 -8
  61. package/dist/{platform-auth-recovery-1gg4CSRe.mjs → platform-auth-recovery-CmCzX2Fl.mjs} +6 -6
  62. package/dist/{platform-cmd-DMcQStSc.mjs → platform-cmd-DMDEc9uS.mjs} +10 -10
  63. package/dist/{platform-cmd-Bt-1w6pY.mjs → platform-cmd-pMTRhvYs.mjs} +1 -1
  64. package/dist/{platform-domain-BNkcz0OB.mjs → platform-domain-Di6EYrQl.mjs} +5 -5
  65. package/dist/{platform-lifecycle-9OyBALhH.mjs → platform-lifecycle-BBoNzojY.mjs} +1264 -407
  66. package/dist/{platform-lifecycle-BE6C_jxh.mjs → platform-lifecycle-BFdSi9Qt.mjs} +1 -1
  67. package/dist/{platform-management-CjwLVQwN.mjs → platform-management-CWOQOWXm.mjs} +5 -5
  68. package/dist/{platform-management-CnyTdcWX.mjs → platform-management-DG47jys8.mjs} +1 -1
  69. package/dist/{platform-plans-config-BNGKGr4P.mjs → platform-plans-config-Vl9BP3H4.mjs} +3 -3
  70. package/dist/{platform-recovery-D6KSpuFm.mjs → platform-recovery-BJnQJEtQ.mjs} +4 -4
  71. package/dist/{platform-registry-QBa4DK32.mjs → platform-registry-DkPPXfp_.mjs} +2 -2
  72. package/dist/{prepare-B5Mkic5u.mjs → prepare-CBLT3CHH.mjs} +3 -3
  73. package/dist/prepare-CnjcTV2s.mjs +2 -0
  74. package/dist/{prepare-DOsL0CC9.mjs → prepare-DnaKBi--.mjs} +1 -1
  75. package/dist/{project-C0Fqu05O.mjs → project-DKG5Ra8p.mjs} +15 -82
  76. package/dist/project-DsblYifa.mjs +2 -0
  77. package/dist/{project-cmd-CNzrqvBv.mjs → project-cmd-DxnXstAq.mjs} +19 -19
  78. package/dist/{project-team-DQOWPfQT.mjs → project-team-BmHcaALJ.mjs} +5 -5
  79. package/dist/{project-token-CTDYU0Cc.mjs → project-token-GionZlBI.mjs} +5 -5
  80. package/dist/{project-zero-trust-BNAkW-_0.mjs → project-zero-trust-JLCjVQA7.mjs} +5 -5
  81. package/dist/prompts-2TGE6oXx.mjs +2 -0
  82. package/dist/prompts-BNUoTiaf.mjs +2044 -0
  83. package/dist/{provision-C4ORE7G7.mjs → provision-CVku1JFU.mjs} +1 -1
  84. package/dist/{provision-CJFgTZY8.mjs → provision-CaoxO_U7.mjs} +1 -1
  85. package/dist/{requests-MhxYnau8.mjs → requests-BOjIVAeF.mjs} +5 -5
  86. package/dist/{rollback-CJ6iSDoU.mjs → rollback-CwR3pLj3.mjs} +6 -6
  87. package/dist/runtime/ai.mjs +3 -5
  88. package/dist/runtime/email/testing.mjs +1 -1
  89. package/dist/runtime/email.mjs +1 -1
  90. package/dist/runtime/remote/index.mjs +2 -2
  91. package/dist/{secret-Dli5fP0B.mjs → secret-ByWJWBUG.mjs} +7 -7
  92. package/dist/{skills-D1II1Juz.mjs → skills-C1PlclPt.mjs} +1 -1
  93. package/dist/{subcommand-prompt-CY1C4fvl.mjs → subcommand-prompt-klFCfcor.mjs} +40 -32
  94. package/package.json +8 -9
  95. package/skills/void/SKILL.md +6 -1
  96. package/skills/void/docs/guide/deployment.md +22 -0
  97. package/skills/void/docs/guide/edge/headers.md +1 -1
  98. package/skills/void/docs/guide/email/domains.md +5 -1
  99. package/skills/void/docs/guide/email/sending.md +1 -1
  100. package/skills/void/docs/guide/platform/administration/zero-trust.md +27 -9
  101. package/skills/void/docs/guide/platform/installation/ci.md +1 -1
  102. package/skills/void/docs/guide/platform/installation/credentials.md +10 -3
  103. package/skills/void/docs/guide/platform/installation/domains.md +8 -3
  104. package/skills/void/docs/guide/platform/installation/first-deployment.md +2 -2
  105. package/skills/void/docs/guide/platform/installation/maintenance.md +12 -0
  106. package/skills/void/docs/guide/platform/installation/prerequisites.md +8 -7
  107. package/skills/void/docs/guide/platform/installation/setup.md +80 -10
  108. package/skills/void/docs/guide/remote-dev.md +1 -1
  109. package/skills/void/docs/reference/cli/auth.md +4 -3
  110. package/skills/void/docs/reference/cli/database.md +1 -1
  111. package/skills/void/docs/reference/cli/deploy.md +20 -0
  112. package/skills/void/docs/reference/cli/platform-installation.md +42 -27
  113. package/skills/void/docs/reference/cli/platform-zero-trust.md +14 -0
  114. package/skills/void/docs/reference/config.md +1 -1
  115. package/dist/auth-CCjt0hcq.mjs +0 -2
  116. package/dist/client-Cu7jWiF1.mjs +0 -2
  117. package/dist/dist-BuDuKZJv.mjs +0 -2
  118. package/dist/dist-CTBk70IR.mjs +0 -1310
  119. package/dist/gen-BVaUUumi.mjs +0 -2
  120. package/dist/help-DofyZuY7.mjs +0 -2
  121. package/dist/log-ChfPKsVd.mjs +0 -26
  122. package/dist/login-DYt_An22.mjs +0 -2
  123. package/dist/migrate-8_2u55MD.mjs +0 -2
  124. package/dist/platform-args-D3RXyR6h.mjs +0 -2
  125. package/dist/prepare-cgvDMtSb.mjs +0 -2
  126. package/dist/project-BuUwfj6f.mjs +0 -2
@@ -114,7 +114,7 @@ function result(status, stdout = "", stderr = "", data) {
114
114
  ].includes(errorCode ?? 0) ? { failure: "not-found" } : {}
115
115
  };
116
116
  }
117
- function runCf(command, cwd = process.cwd()) {
117
+ function runCf(command, cwd = process.cwd(), bounds) {
118
118
  const env = cfEnvironment();
119
119
  env.CF_QUIET = "1";
120
120
  const child = spawnSync(process.execPath, [cf, ...command], {
@@ -123,7 +123,8 @@ function runCf(command, cwd = process.cwd()) {
123
123
  encoding: "utf8",
124
124
  shell: false,
125
125
  windowsHide: true,
126
- maxBuffer: 33554432,
126
+ maxBuffer: bounds?.maxOutputBytes ?? 33554432,
127
+ ...bounds ? { timeout: bounds.timeoutMs } : {},
127
128
  stdio: [
128
129
  "ignore",
129
130
  "pipe",
@@ -207,7 +208,10 @@ async function withBuildOutput(raw, sourceMain, action) {
207
208
  try {
208
209
  const main = "index.js";
209
210
  if (sourceMain) copyFileSync(sourceMain, join(scratch, main));
210
- else writeFileSync(join(scratch, main), "export default { fetch() { return new Response(\"\"); } };\n");
211
+ else {
212
+ const { VOID_SECRET_DRAFT_SOURCE } = await import("@void/deploy-cloudflare");
213
+ writeFileSync(join(scratch, main), VOID_SECRET_DRAFT_SOURCE);
214
+ }
211
215
  writeFileSync(join(scratch, "wrangler.json"), JSON.stringify({
212
216
  ...raw,
213
217
  main,
@@ -845,11 +849,16 @@ async function workerHistory() {
845
849
  "get",
846
850
  versionId,
847
851
  "--worker-id",
848
- worker
849
- ]);
852
+ worker,
853
+ ...operation.includeSource ? ["--include", "modules"] : []
854
+ ], process.cwd(), operation.includeSource ? {
855
+ timeoutMs: 3e4,
856
+ maxOutputBytes: 1048576
857
+ } : void 0);
850
858
  if (called.status !== 0) return called;
851
859
  const version = object(parsedJson(called.stdout));
852
860
  if (version.id !== versionId || !Array.isArray(version.bindings)) throw new Error("Worker version bindings were malformed.");
861
+ if (operation.includeSource) return result(0, "", called.stderr, version);
853
862
  const resources = await readVersionResources(worker, versionId);
854
863
  return result(0, "", called.stderr, {
855
864
  ...version,
@@ -1,4 +1,4 @@
1
- import { t as findEnvFile } from "../env-types-C2_bIk_b.mjs";
1
+ import { t as findEnvFile } from "../env-types-D5kds_OZ.mjs";
2
2
  import { writeSync } from "node:fs";
3
3
  import { fileURLToPath } from "node:url";
4
4
  import { spawnSync } from "node:child_process";
@@ -169,7 +169,7 @@ function emitResult(result) {
169
169
  * facts. The import stays isolated because env.ts is arbitrary project code.
170
170
  */
171
171
  async function runFactsChild(root) {
172
- const { deriveSelfHostSchemaFacts, SelfHostSchemaError } = await import("../env-validation-DbTg7-ar.mjs");
172
+ const { deriveSelfHostSchemaFacts, SelfHostSchemaError } = await import("../env-validation-zZOCcQVZ.mjs");
173
173
  try {
174
174
  emitResult({
175
175
  kind: "ok",
@@ -194,7 +194,7 @@ async function runFactsChild(root) {
194
194
  * fault → fail closed as a values-free schema error.
195
195
  */
196
196
  async function runValidateEmittedChild(root) {
197
- const { computeInvalidEmittedKeys, readEmittedWorkerVars, SelfHostSchemaError } = await import("../env-validation-DbTg7-ar.mjs");
197
+ const { computeInvalidEmittedKeys, readEmittedWorkerVars, SelfHostSchemaError } = await import("../env-validation-zZOCcQVZ.mjs");
198
198
  const emitted = readEmittedWorkerVars(root);
199
199
  if (!emitted.ok) {
200
200
  emitResult({
@@ -0,0 +1,2 @@
1
+ import { n as PlatformClient } from "./client-DKAsFA4X.mjs";
2
+ export { PlatformClient };
@@ -1,8 +1,8 @@
1
1
  import { a as join } from "./dist-BVqXeR_h.mjs";
2
- import { t as cfAccessHeaders } from "./cf-access-DRsQRe6k.mjs";
3
- import { a as getApiUrl } from "./auth-CSkdO2Bb.mjs";
4
- import { s as normalizePlatformApiUrl } from "./platform-registry-QBa4DK32.mjs";
5
- import { i as isCloudflareAccessChallenge, n as ensurePlatformAccessToken, t as ensureCloudflaredToken } from "./cf-access-P0iZnu0q.mjs";
2
+ import { t as cfAccessHeaders } from "./cf-access-TWNzXltp.mjs";
3
+ import { s as normalizePlatformApiUrl } from "./platform-registry-DkPPXfp_.mjs";
4
+ import { i as isCloudflareAccessChallenge, n as ensurePlatformAccessToken, t as ensureCloudflaredToken } from "./cf-access-BGe5sWXF.mjs";
5
+ import { a as getApiUrl } from "./auth-CQkSDS50.mjs";
6
6
  import { n as getPackageDir } from "./agents-B_pX_HmQ.mjs";
7
7
  import { readFileSync } from "node:fs";
8
8
  import { stripVTControlCharacters } from "node:util";
@@ -175,11 +175,20 @@ const DEPLOY_OBSERVATION_BACKOFF_MS = [
175
175
  ];
176
176
  const DEPLOY_EVENT_MAX_BYTES = 1048576;
177
177
  var DeploymentProtocolError = class extends Error {};
178
+ var DeploymentObservationTimeoutError = class extends Error {
179
+ constructor(deploymentId) {
180
+ super(`Timed out observing deployment ${deploymentId}. Inspect with \`void project status\`.`);
181
+ }
182
+ };
178
183
  function parseDeployEvent(value) {
179
184
  if (!value || typeof value !== "object" || !("event" in value) || typeof value.event !== "string") throw new DeploymentProtocolError("Invalid deployment event from platform.");
180
185
  const event = value;
181
186
  if (event.seq !== void 0 && (!Number.isSafeInteger(event.seq) || event.seq < 1)) throw new DeploymentProtocolError("Invalid deployment event sequence from platform.");
182
- if (event.event === "start" && typeof event.deploymentId !== "string" || event.event === "done" && (typeof event.deployment !== "string" || typeof event.url !== "string" || !Array.isArray(event.urls) || !event.urls.every((url) => typeof url === "string") || !Number.isSafeInteger(event.assets) || event.assets < 0 || !Number.isSafeInteger(event.workers) || event.workers < 0 || event.published !== void 0 && typeof event.published !== "boolean") || event.event === "error" && (typeof event.message !== "string" || typeof event.step !== "string")) throw new DeploymentProtocolError("Invalid deployment result from platform.");
187
+ if (event.event === "start" && typeof event.deploymentId !== "string" || event.event === "heartbeat" && (typeof event.step !== "string" || event.status !== void 0 && ![
188
+ "queued",
189
+ "running",
190
+ "recovering"
191
+ ].includes(event.status) || event.recoveryAt !== void 0 && (typeof event.recoveryAt !== "string" || !Number.isFinite(Date.parse(event.recoveryAt)))) || event.event === "done" && (typeof event.deployment !== "string" || typeof event.url !== "string" || !Array.isArray(event.urls) || !event.urls.every((url) => typeof url === "string") || !Number.isSafeInteger(event.assets) || event.assets < 0 || !Number.isSafeInteger(event.workers) || event.workers < 0 || event.published !== void 0 && typeof event.published !== "boolean") || event.event === "error" && (typeof event.message !== "string" || typeof event.step !== "string")) throw new DeploymentProtocolError("Invalid deployment result from platform.");
183
192
  return event;
184
193
  }
185
194
  /**
@@ -589,6 +598,7 @@ var PlatformClient = class {
589
598
  throw new PlatformApiError("Deploy failed", res.status, body, isCloudflareAccessChallenge(res) ? void 0 : "deploy");
590
599
  }
591
600
  const receipt = res.headers.get("x-void-deployment-id");
601
+ const observationDeadline = Date.now() + DEPLOY_OBSERVATION_DEADLINE_MS;
592
602
  if (receipt !== null && !/^[A-Za-z0-9_-]{1,128}$/.test(receipt)) {
593
603
  res.body?.cancel().catch(() => {});
594
604
  throw new Error("Invalid deployment receipt from platform.");
@@ -601,7 +611,7 @@ var PlatformClient = class {
601
611
  event: "start",
602
612
  deploymentId: receipt
603
613
  };
604
- yield* this.followDeploymentEvents(projectId, receipt, cursor);
614
+ yield* this.followDeploymentEvents(projectId, receipt, cursor, observationDeadline);
605
615
  return;
606
616
  }
607
617
  throw new Error("Platform returned no deployment event stream.");
@@ -618,9 +628,11 @@ var PlatformClient = class {
618
628
  let readTimer;
619
629
  const read = async () => {
620
630
  if (!receipt) return reader.read();
631
+ const remaining = observationDeadline - Date.now();
632
+ if (remaining <= 0) throw new DeploymentObservationTimeoutError(receipt);
621
633
  try {
622
634
  return await Promise.race([reader.read(), new Promise((_, reject) => {
623
- readTimer = setTimeout(() => reject(/* @__PURE__ */ new TypeError("Deployment event stream timed out.")), DEPLOY_OBSERVATION_TIMEOUT_MS);
635
+ readTimer = setTimeout(() => reject(Date.now() >= observationDeadline ? new DeploymentObservationTimeoutError(receipt) : /* @__PURE__ */ new TypeError("Deployment event stream timed out.")), Math.min(DEPLOY_OBSERVATION_TIMEOUT_MS, remaining));
624
636
  })]);
625
637
  } finally {
626
638
  clearTimeout(readTimer);
@@ -652,6 +664,7 @@ var PlatformClient = class {
652
664
  };
653
665
  while (true) {
654
666
  const { done, value } = await read();
667
+ if (receipt && Date.now() >= observationDeadline) throw new DeploymentObservationTimeoutError(receipt);
655
668
  if (done) {
656
669
  streamFinished = true;
657
670
  buffer += decoder.decode();
@@ -688,28 +701,28 @@ var PlatformClient = class {
688
701
  eventCount,
689
702
  lastEvent: lastEventName
690
703
  });
691
- if (!receipt || err instanceof DeploymentProtocolError || err instanceof SyntaxError || err instanceof DOMException && err.name === "AbortError") throw err;
704
+ if (!receipt || err instanceof DeploymentObservationTimeoutError || err instanceof DeploymentProtocolError || err instanceof SyntaxError || err instanceof DOMException && err.name === "AbortError") throw err;
692
705
  } finally {
693
706
  clearTimeout(readTimer);
694
707
  if (!streamFinished) reader.cancel().catch(() => {});
695
708
  reader.releaseLock();
696
709
  }
697
- if (receipt && !terminal) yield* this.followDeploymentEvents(projectId, receipt, cursor);
710
+ if (receipt && !terminal) yield* this.followDeploymentEvents(projectId, receipt, cursor, observationDeadline);
698
711
  }
699
- async *followDeploymentEvents(projectId, deploymentId, since) {
712
+ async *followDeploymentEvents(projectId, deploymentId, since, deadline) {
700
713
  let cursor = since;
701
714
  let failures = 0;
702
- const deadline = Date.now() + DEPLOY_OBSERVATION_DEADLINE_MS;
703
715
  while (Date.now() < deadline) {
704
716
  const url = `${this.baseUrl}/projects/${encodeURIComponent(projectId)}/deployments/${encodeURIComponent(deploymentId)}/events?since=${cursor}`;
705
717
  let page;
706
718
  try {
707
719
  const response = await this.request(url, {
708
720
  headers: { ...this.authHeaders },
709
- signal: AbortSignal.timeout(DEPLOY_OBSERVATION_TIMEOUT_MS)
721
+ signal: AbortSignal.timeout(Math.max(1, Math.min(DEPLOY_OBSERVATION_TIMEOUT_MS, deadline - Date.now())))
710
722
  });
711
723
  if (!response.ok) await throwPlatformApiError("Failed to observe deployment", response, "read");
712
724
  page = await response.json();
725
+ if (Date.now() >= deadline) throw new DeploymentObservationTimeoutError(deploymentId);
713
726
  } catch (err) {
714
727
  if (!(err instanceof TypeError || err instanceof DOMException && err.name === "TimeoutError" || err instanceof PlatformApiError && (err.status === 429 || err.status >= 500)) || failures >= DEPLOY_OBSERVATION_BACKOFF_MS.length) throw err;
715
728
  const delayMs = DEPLOY_OBSERVATION_BACKOFF_MS[failures++];
@@ -718,7 +731,7 @@ var PlatformClient = class {
718
731
  cursor,
719
732
  delayMs
720
733
  });
721
- await sleep(delayMs);
734
+ await sleep(Math.min(delayMs, Math.max(0, deadline - Date.now())));
722
735
  continue;
723
736
  }
724
737
  failures = 0;
@@ -734,9 +747,14 @@ var PlatformClient = class {
734
747
  if (event.event === "done" || event.event === "error") return;
735
748
  }
736
749
  if (page.terminal) throw new Error("Platform finished deployment without a terminal result.");
737
- await sleep(1e3);
750
+ if (page.heartbeat !== void 0) {
751
+ const heartbeat = parseDeployEvent(page.heartbeat);
752
+ if (heartbeat.event !== "heartbeat" || heartbeat.deploymentId !== void 0 && heartbeat.deploymentId !== deploymentId) throw new DeploymentProtocolError("Invalid deployment observation heartbeat.");
753
+ yield heartbeat;
754
+ }
755
+ await sleep(Math.min(1e3, Math.max(0, deadline - Date.now())));
738
756
  }
739
- throw new Error(`Timed out observing deployment ${deploymentId}. Inspect with \`void project status\`.`);
757
+ throw new DeploymentObservationTimeoutError(deploymentId);
740
758
  }
741
759
  async listSecrets(projectId) {
742
760
  const res = await this.request(`${this.baseUrl}/projects/${projectId}/secrets`, { headers: { ...this.authHeaders } });
@@ -1,6 +1,6 @@
1
1
  import { t as basename } from "./dist-BVqXeR_h.mjs";
2
2
  import { y as readRootWranglerConfig } from "./wrangler-7K-bW_DL.mjs";
3
- import { j as log } from "./dist-CTBk70IR.mjs";
3
+ import { L as log } from "./prompts-BNUoTiaf.mjs";
4
4
  import { a as parseCloudflareAuthSession, i as ensureCloudflareAuthentication, n as cloudflareCredentialOverrides, r as createBundledCloudflareAuthRunner } from "./cloudflare-auth-Qdc7tw8F.mjs";
5
5
  //#region src/cli/cloudflare-cmd.ts
6
6
  async function runCloudflareCommand(root, args) {
@@ -1,6 +1,6 @@
1
1
  import { a as join, t as basename } from "./dist-BVqXeR_h.mjs";
2
2
  import { A as writeProvisionedWranglerConfig, i as LATEST_KNOWN_COMPAT_DATE, y as readRootWranglerConfig } from "./wrangler-7K-bW_DL.mjs";
3
- import { I as select, W as isCancel, j as log } from "./dist-CTBk70IR.mjs";
3
+ import { K as select, L as log, tt as isCancel } from "./prompts-BNUoTiaf.mjs";
4
4
  import { i as ensureCloudflareAuthentication, r as createBundledCloudflareAuthRunner } from "./cloudflare-auth-Qdc7tw8F.mjs";
5
5
  import { existsSync } from "node:fs";
6
6
  //#region src/cli/cloudflare-connect.ts
@@ -1,2 +1,2 @@
1
- import { _ as resolveCloudflareD1Context, b as tailCloudflareWorker, c as listCloudflareDomains, g as readCloudflareWorkerStatus, h as readCloudflareD1Migrations, l as listCloudflareSecrets, m as putCloudflareSecret, n as applyCloudflareD1Migrations, o as deleteCloudflareSecret, r as changeCloudflareDomain, s as executeCloudflareD1Sql, t as activateCloudflareExistingVersion, v as resolveCloudflareOperationContext, y as syncCloudflareSecrets } from "./cloudflare-operations-fxHb-byx.mjs";
1
+ import { _ as resolveCloudflareD1Context, b as tailCloudflareWorker, c as listCloudflareDomains, g as readCloudflareWorkerStatus, h as readCloudflareD1Migrations, l as listCloudflareSecrets, m as putCloudflareSecret, n as applyCloudflareD1Migrations, o as deleteCloudflareSecret, r as changeCloudflareDomain, s as executeCloudflareD1Sql, t as activateCloudflareExistingVersion, v as resolveCloudflareOperationContext, y as syncCloudflareSecrets } from "./cloudflare-operations-DzH-A966.mjs";
2
2
  export { activateCloudflareExistingVersion, applyCloudflareD1Migrations, changeCloudflareDomain, deleteCloudflareSecret, executeCloudflareD1Sql, listCloudflareDomains, listCloudflareSecrets, putCloudflareSecret, readCloudflareD1Migrations, readCloudflareWorkerStatus, resolveCloudflareD1Context, resolveCloudflareOperationContext, syncCloudflareSecrets, tailCloudflareWorker };
@@ -3,7 +3,7 @@ import { i as persistCloudflareConfig, r as materializeCloudflareConfig } from "
3
3
  import { C as readWranglerPublishedTrafficSnapshot, j as writeWranglerPublishedTrafficSnapshot, k as updateWranglerCustomDomain, x as readWranglerCustomDomains } from "./wrangler-7K-bW_DL.mjs";
4
4
  import { r as scanWranglerDotenvKeys } from "./dotenv-VQxupEUv.mjs";
5
5
  import { t as createCloudflareProcessRunner } from "./cloudflare-process-B-wekeR6.mjs";
6
- import { _ as resolvePinnedApiBaseUrl, g as provisionEnv, r as assertNoTransportRedirectInProjectDotenv, s as deleteEnvVarCaseAware } from "./provision-CJFgTZY8.mjs";
6
+ import { _ as resolvePinnedApiBaseUrl, g as provisionEnv, r as assertNoTransportRedirectInProjectDotenv, s as deleteEnvVarCaseAware } from "./provision-CaoxO_U7.mjs";
7
7
  import { existsSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
8
8
  import { tmpdir } from "node:os";
9
9
  import { deployCloudflareVersionTraffic, encodeCloudflareVersionMessage, parseCloudflareVersionMessage, parseRootWranglerConfig, readBindingFieldPresence, readCloudflareTriggerConfig, readWranglerTopLevelString, resolveD1MigrateTarget, stabilizeCloudflareVersionTriggers } from "@void/deploy-cloudflare";
@@ -1,11 +1,11 @@
1
- import { f as readPlatformToken } from "./auth-CSkdO2Bb.mjs";
2
- import { o as listPlatformConnections, s as normalizePlatformApiUrl } from "./platform-registry-QBa4DK32.mjs";
3
- import { i as readDeploymentPlatform, l as writeDeploymentPlatform, u as writePlatformSelection } from "./project-C0Fqu05O.mjs";
4
- import { I as select, W as isCancel, j as log } from "./dist-CTBk70IR.mjs";
5
- import { i as isExpiredTokenError, n as PlatformClient } from "./client-RV8NVeB8.mjs";
6
- import { t as promptForLoginToken } from "./login-UZKFM_u7.mjs";
7
- import { i as saveDiscoveredPlatform, n as promptPlatformUrl, t as discoverPlatform } from "./platform-cmd-DMcQStSc.mjs";
8
- import { t as connectCloudflare } from "./cloudflare-connect-B8uPZ4nx.mjs";
1
+ import { o as listPlatformConnections, s as normalizePlatformApiUrl } from "./platform-registry-DkPPXfp_.mjs";
2
+ import { c as writePlatformSelection, n as readDeploymentPlatform, s as writeDeploymentPlatform } from "./project-DKG5Ra8p.mjs";
3
+ import { d as readPlatformToken } from "./auth-CQkSDS50.mjs";
4
+ import { K as select, L as log, tt as isCancel } from "./prompts-BNUoTiaf.mjs";
5
+ import { i as isExpiredTokenError, n as PlatformClient } from "./client-DKAsFA4X.mjs";
6
+ import { t as promptForLoginToken } from "./login-BuiMyUrx.mjs";
7
+ import { i as saveDiscoveredPlatform, n as promptPlatformUrl, t as discoverPlatform } from "./platform-cmd-DMDEc9uS.mjs";
8
+ import { t as connectCloudflare } from "./cloudflare-connect-IiR3ZieC.mjs";
9
9
  //#region src/cli/connect.ts
10
10
  async function selectVoidPlatform(interactive) {
11
11
  if (!interactive) throw new Error("connect: Supply a Void platform URL in non-interactive mode.");
@@ -71,7 +71,7 @@ async function runConnectCommand(root, args, interactive = Boolean(process.stdin
71
71
  if (!args.noLogin) await authenticateConnection(root, discovery, interactive);
72
72
  saveDiscoveredPlatform(discovery);
73
73
  const envUrl = process.env.VOID_API_URL;
74
- const selected = Boolean(envUrl && normalizePlatformApiUrl(envUrl) !== discovery.apiUrl || process.env.VOID_TOKEN && !envUrl) ? false : writePlatformSelection(root, discovery);
74
+ const selected = Boolean(envUrl && normalizePlatformApiUrl(envUrl) !== discovery.apiUrl) ? false : writePlatformSelection(root, discovery);
75
75
  log.success(`Connected to ${discovery.displayName} at ${discovery.apiUrl}.`);
76
76
  if (!selected) log.info("Saved the connection. The current project link or environment still selects its existing destination.");
77
77
  if (args.noLogin) log.info("Connection saved without login. Run `void account login` in a project using this platform when ready.");
@@ -1,8 +1,8 @@
1
- import { s as getSiteDomain } from "./auth-CSkdO2Bb.mjs";
2
- import { d as writeProjectConfig, t as attachSelectedPlatform } from "./project-C0Fqu05O.mjs";
3
- import { B as text, E as confirm, I as select, T as cancel, W as isCancel, j as log } from "./dist-CTBk70IR.mjs";
4
- import { t as PlatformApiError } from "./client-RV8NVeB8.mjs";
5
- import { c as import_picocolors, l as sanitizeTerminalText } from "./output-Dm_A4Tbv.mjs";
1
+ import { l as writeProjectConfig, t as attachSelectedPlatform } from "./project-DKG5Ra8p.mjs";
2
+ import { s as getSiteDomain } from "./auth-CQkSDS50.mjs";
3
+ import { A as confirm, K as select, L as log, O as cancel, X as text, tt as isCancel } from "./prompts-BNUoTiaf.mjs";
4
+ import { t as PlatformApiError } from "./client-DKAsFA4X.mjs";
5
+ import { c as import_picocolors, l as sanitizeTerminalText } from "./output-CbM85T4k.mjs";
6
6
  import { t as validateProjectSlug } from "./project-slug-23TpquG4.mjs";
7
7
  import { n as inferDefaultSlug } from "./resolve-project-BG5ORGID.mjs";
8
8
  //#region src/cli/prompt.ts
@@ -14,7 +14,7 @@ async function promptProjectSetupAction(message = "Set up a Void project:", opti
14
14
  label: "Create a new project"
15
15
  }, ...options.includeLink === false ? [] : [{
16
16
  value: "link",
17
- label: "Link an existing project"
17
+ label: options.link === false ? "Use an existing project" : "Link an existing project"
18
18
  }]]
19
19
  });
20
20
  if (isCancel(result) || typeof result === "symbol") {
@@ -43,7 +43,7 @@ async function promptProjectSelection(projects, message = "Select a project:", r
43
43
  if (result === "__create__") return { action: "create" };
44
44
  const project = projects.find((p) => p.id === result);
45
45
  if (options.confirmExisting) {
46
- const confirmed = await confirm({ message: project.role === "reader" ? `Link to ${project.slug} with read-only access? Deploying requires collaborator access or higher.` : `Linking to an existing project. Running \`void deploy\` will overwrite the current deployment of ${project.url ?? `${project.slug}.${getSiteDomain(root)}`}. Continue?` });
46
+ const confirmed = await confirm({ message: project.role === "reader" ? `Link to ${project.slug} with read-only access? Deploying requires collaborator access or higher.` : (options.link === false ? "This deployment will overwrite the current deployment of " : `Linking to an existing project. Running \`void deploy\` will overwrite the current deployment of `) + `${project.url ?? `${project.slug}.${getSiteDomain(root)}`}. Continue?` });
47
47
  if (isCancel(confirmed) || !confirmed) {
48
48
  cancel("Project link cancelled.");
49
49
  process.exit(0);
@@ -57,9 +57,9 @@ async function promptProjectSelection(projects, message = "Select a project:", r
57
57
  async function promptProjectSlug(defaultSlug) {
58
58
  const result = await text({
59
59
  message: "Choose a slug for your new Void project:",
60
- placeholder: "my-app",
61
- initialValue: defaultSlug,
62
- validate: validateProjectSlug
60
+ placeholder: defaultSlug,
61
+ defaultValue: defaultSlug,
62
+ validate: (value) => validateProjectSlug(value || defaultSlug)
63
63
  });
64
64
  if (isCancel(result) || typeof result === "symbol") {
65
65
  cancel("Deploy cancelled.");
@@ -102,14 +102,14 @@ async function createProjectWithSlugRetry(client, initialDefaultSlug, promptSlug
102
102
  function reportProjectCreationWarnings(project) {
103
103
  for (const warning of project.warnings ?? []) log.warn(sanitizeTerminalText(warning));
104
104
  }
105
- async function promptAndCreateProject(root, client) {
105
+ async function promptAndCreateProject(root, client, options = {}) {
106
106
  const project = await createProjectWithSlugRetry(client, inferDefaultSlug(root), async (defaultSlug) => promptProjectSlug(defaultSlug));
107
107
  if (!project) throw new Error("Project creation cancelled.");
108
108
  const config = {
109
109
  projectId: project.id,
110
110
  slug: project.slug
111
111
  };
112
- writeProjectConfig(root, attachSelectedPlatform(root, config, client.apiUrl));
112
+ if (options.link !== false) writeProjectConfig(root, attachSelectedPlatform(root, config, client.apiUrl));
113
113
  if (project.owner_email_destination) {
114
114
  const { address } = project.owner_email_destination;
115
115
  log.info(`Registering ${address} as a recipient for this project. Cloudflare emails it a verification link unless it is already verified — \`void email destinations\` shows the state.`);
@@ -1,2 +1,2 @@
1
- import { t as createProjectWithSlugRetry } from "./create-project-bMf6ffLZ.mjs";
1
+ import { t as createProjectWithSlugRetry } from "./create-project-CYOOAYcn.mjs";
2
2
  export { createProjectWithSlugRetry };
@@ -3,17 +3,17 @@ import { r as detectFramework } from "./plugin-inference-CXWnn79A.mjs";
3
3
  import { n as readProjectPaths } from "./project-paths-GgcMozYz.mjs";
4
4
  import { h as resolveBindingNames, m as readConfig, u as getDatabaseDialect } from "./config-Br_JZD6u.mjs";
5
5
  import { i as writeJournal, n as readJournal, r as stripSqlExt, t as collectMigrations } from "./collect-DiTn9yr6.mjs";
6
- import { t as cfAccessHeaders } from "./cf-access-DRsQRe6k.mjs";
7
- import { c as getToken, o as getProxyUrl } from "./auth-CSkdO2Bb.mjs";
8
- import { i as isCloudflareAccessChallenge, n as ensurePlatformAccessToken, r as ensurePlatformProxyAccess } from "./cf-access-P0iZnu0q.mjs";
9
- import { i as readDeploymentPlatform, o as readProjectConfig } from "./project-C0Fqu05O.mjs";
6
+ import { t as cfAccessHeaders } from "./cf-access-TWNzXltp.mjs";
7
+ import { i as isCloudflareAccessChallenge, n as ensurePlatformAccessToken, r as ensurePlatformProxyAccess } from "./cf-access-BGe5sWXF.mjs";
8
+ import { n as readDeploymentPlatform, r as readProjectConfig } from "./project-DKG5Ra8p.mjs";
9
+ import { c as getToken, o as getProxyUrl } from "./auth-CQkSDS50.mjs";
10
10
  import { t as resolveLocalD1Target } from "./local-d1-2CMnpuW_.mjs";
11
11
  import { a as loadLocalEnv } from "./env-_v349JBd.mjs";
12
- import { E as confirm, O as intro, P as outro, W as isCancel, j as log } from "./dist-CTBk70IR.mjs";
12
+ import { A as confirm, H as outro, L as log, N as intro, tt as isCancel } from "./prompts-BNUoTiaf.mjs";
13
13
  import { i as validateMigrations, r as listDrizzleArtifacts, t as assertJournalCoherence } from "./validate-ctOrgiS3.mjs";
14
- import { n as PlatformClient, t as PlatformApiError } from "./client-RV8NVeB8.mjs";
15
- import { a as dim, c as import_picocolors, r as cliTitle } from "./output-Dm_A4Tbv.mjs";
16
- import { n as formatTimestamp } from "./gen-B580--vC.mjs";
14
+ import { n as PlatformClient, t as PlatformApiError } from "./client-DKAsFA4X.mjs";
15
+ import { a as dim, c as import_picocolors, r as cliTitle } from "./output-CbM85T4k.mjs";
16
+ import { n as formatTimestamp } from "./gen-CshAkukR.mjs";
17
17
  import { createRequire } from "node:module";
18
18
  import { existsSync, readFileSync, readdirSync, renameSync, rmSync, writeFileSync } from "node:fs";
19
19
  import { fileURLToPath, pathToFileURL } from "node:url";
@@ -273,7 +273,7 @@ async function runConnect(root, dialect, args) {
273
273
  if (result.dashboardUrl) log.info(`Dashboard: ${result.dashboardUrl}`);
274
274
  }
275
275
  if (!connectionString) {
276
- const { text: promptText, isCancel: isCancelCheck } = await import("./dist-BuDuKZJv.mjs");
276
+ const { text: promptText, isCancel: isCancelCheck } = await import("./prompts-2TGE6oXx.mjs");
277
277
  const answer = await promptText({
278
278
  message: `Enter your ${dialect === "mysql" ? "MySQL" : "PostgreSQL"} connection string:`,
279
279
  placeholder: dialect === "mysql" ? "mysql://user:pass@host:3306/database" : "postgresql://user:pass@host:5432/database"
@@ -318,7 +318,7 @@ async function runPush(root, dialect) {
318
318
  outro("Done.");
319
319
  }
320
320
  async function runGenerate(root, dialect) {
321
- const { prepareProject } = await import("./prepare-cgvDMtSb.mjs");
321
+ const { prepareProject } = await import("./prepare-CnjcTV2s.mjs");
322
322
  const { writeDrizzleConfig } = await import("./config-0acf1oys.mjs");
323
323
  await prepareProject(root);
324
324
  const authSchemaPath = join(root, ".void", "better-auth-schema.ts");
@@ -399,7 +399,7 @@ async function runStatus(root, dialect) {
399
399
  applied_at: ""
400
400
  }));
401
401
  } else {
402
- const { readCloudflareD1Migrations, resolveCloudflareD1Context } = await import("./cloudflare-operations-AiWashgg.mjs");
402
+ const { readCloudflareD1Migrations, resolveCloudflareD1Context } = await import("./cloudflare-operations-BCdXSsmo.mjs");
403
403
  remoteApplied = (await readCloudflareD1Migrations(resolveCloudflareD1Context(root, resolveBindingNames(readConfig(root).inference?.bindings)?.d1 ?? "DB"))).map((name) => ({
404
404
  name,
405
405
  applied_at: ""
@@ -641,7 +641,7 @@ async function runExecute(root, command, file, dialect, remote) {
641
641
  process.exit(0);
642
642
  }
643
643
  if (dialect === "sqlite") {
644
- const { executeCloudflareD1Sql, resolveCloudflareD1Context } = await import("./cloudflare-operations-AiWashgg.mjs");
644
+ const { executeCloudflareD1Sql, resolveCloudflareD1Context } = await import("./cloudflare-operations-BCdXSsmo.mjs");
645
645
  const rows = await executeCloudflareD1Sql(resolveCloudflareD1Context(root, resolveBindingNames(readConfig(root).inference?.bindings)?.d1 ?? "DB"), sql);
646
646
  if (rows.length > 0) printTable(rows);
647
647
  else log.success("Executed successfully.");
@@ -846,7 +846,7 @@ async function runMigrate(root, dialect, remote) {
846
846
  outro("Done.");
847
847
  return;
848
848
  }
849
- const { applyCloudflareD1Migrations, readCloudflareD1Migrations, resolveCloudflareD1Context } = await import("./cloudflare-operations-AiWashgg.mjs");
849
+ const { applyCloudflareD1Migrations, readCloudflareD1Migrations, resolveCloudflareD1Context } = await import("./cloudflare-operations-BCdXSsmo.mjs");
850
850
  const binding = resolveBindingNames(readConfig(root).inference?.bindings)?.d1 ?? "DB";
851
851
  const context = resolveCloudflareD1Context(root, binding);
852
852
  const remoteBefore = new Set(await readCloudflareD1Migrations(context));
@@ -862,7 +862,7 @@ async function runMigrate(root, dialect, remote) {
862
862
  log.error(getErrorMessage(error));
863
863
  process.exit(1);
864
864
  }
865
- const { checkWranglerMigrationApplySet, parseRootWranglerConfig } = await import("./deploy-bjXdFCtn.mjs");
865
+ const { checkWranglerMigrationApplySet, parseRootWranglerConfig } = await import("./deploy-irP5q0-x.mjs");
866
866
  const applySet = await checkWranglerMigrationApplySet(context.operation.configPath, parseRootWranglerConfig(context.operation.configPath), binding, context.migrationsDir, rawMigrations);
867
867
  if (!applySet.ok) {
868
868
  log.error(applySet.reason);
@@ -1524,7 +1524,7 @@ async function runSetUrl(root) {
1524
1524
  log.error("No project linked. Run `void deploy` first or link a project.");
1525
1525
  process.exit(1);
1526
1526
  }
1527
- const { text: promptText, isCancel: isCancelCheck } = await import("./dist-BuDuKZJv.mjs");
1527
+ const { text: promptText, isCancel: isCancelCheck } = await import("./prompts-2TGE6oXx.mjs");
1528
1528
  const connectionString = await promptText({
1529
1529
  message: `Enter your ${dialect === "mysql" ? "MySQL" : "PostgreSQL"} connection string:`,
1530
1530
  placeholder: dialect === "mysql" ? "mysql://user:pass@host:3306/dbname" : "postgresql://user:pass@host:5432/dbname",
@@ -1,8 +1,8 @@
1
- import { c as getToken } from "./auth-CSkdO2Bb.mjs";
2
- import { c as removeProjectConfig, o as readProjectConfig } from "./project-C0Fqu05O.mjs";
3
- import { B as text, N as note, O as intro, P as outro, T as cancel, W as isCancel, j as log } from "./dist-CTBk70IR.mjs";
4
- import { n as PlatformClient } from "./client-RV8NVeB8.mjs";
5
- import { i as createSpinner, r as cliTitle } from "./output-Dm_A4Tbv.mjs";
1
+ import { a as removeProjectConfig, r as readProjectConfig } from "./project-DKG5Ra8p.mjs";
2
+ import { c as getToken } from "./auth-CQkSDS50.mjs";
3
+ import { B as note, H as outro, L as log, N as intro, O as cancel, X as text, tt as isCancel } from "./prompts-BNUoTiaf.mjs";
4
+ import { n as PlatformClient } from "./client-DKAsFA4X.mjs";
5
+ import { i as createSpinner, r as cliTitle } from "./output-CbM85T4k.mjs";
6
6
  import { r as resolveProjectBySlug } from "./resolve-project-BG5ORGID.mjs";
7
7
  //#region src/cli/delete.ts
8
8
  async function runDeleteCommand(root, slug, options) {