void 1.1.11 → 1.1.12

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 (152) hide show
  1. package/dist/{account-cmd-R35a4Oa8.mjs → account-cmd-Cj6sCMTk.mjs} +4 -4
  2. package/dist/{auth-link-VHmiKZmP.mjs → auth-link-Dj7lAC_K.mjs} +4 -4
  3. package/dist/{auth-router-O_Wrs5kg.mjs → auth-router-CNsMOFCa.mjs} +2 -2
  4. package/dist/{build-cmd-CMZiMn46.mjs → build-cmd-ByhegwRC.mjs} +2 -2
  5. package/dist/{cache-TZ5Ab3d7.mjs → cache-CEFb5ban.mjs} +2 -2
  6. package/dist/{cancel-deploy-DXoR6oC3.mjs → cancel-deploy-CaARY26n.mjs} +2 -2
  7. package/dist/{cf-build-output-Bc8i3dzE.mjs → cf-build-output-ChEKWan2.mjs} +71 -7
  8. package/dist/cf-build-output-Dcmxa-Zm.mjs +1 -0
  9. package/dist/{cf-user-agent-ChjQp2MU.mjs → cf-command-values-b8OqDoo9.mjs} +5 -16
  10. package/dist/cf-user-agent-BkEHPDLA.mjs +16 -0
  11. package/dist/cli/cli.mjs +135 -31
  12. package/dist/cli/cloudflare-operation-process.mjs +46 -9
  13. package/dist/{client-GuSO3v_x.mjs → client-BdzxubTS.mjs} +57 -12
  14. package/dist/client-DAnfyMe9.mjs +1 -0
  15. package/dist/{cloudflare-cmd-ZSErUl6Y.mjs → cloudflare-cmd-D_2-Q-_i.mjs} +1 -1
  16. package/dist/{cloudflare-operations-Cm8lVx7W.mjs → cloudflare-operations-BFLCpUCV.mjs} +1 -1
  17. package/dist/{cloudflare-operations-DH3GedbV.mjs → cloudflare-operations-D5PLrOqD.mjs} +14 -4
  18. package/dist/{connect-yQuLbuiJ.mjs → connect-C4_m2moF.mjs} +4 -4
  19. package/dist/{create-project-CGOo_OL_.mjs → create-project-CvuYDD-l.mjs} +1 -1
  20. package/dist/{create-project-DEEWJX_M.mjs → create-project-D8jQTwVQ.mjs} +2 -2
  21. package/dist/{db-COI-yTJE.mjs → db-BsiOAa0A.mjs} +58 -8
  22. package/dist/{delete-PgN6L_9N.mjs → delete-CAma7nFi.mjs} +2 -2
  23. package/dist/{deploy-DsW-PrRQ.mjs → deploy-D1gIPiAq.mjs} +118 -36
  24. package/dist/deploy-Dc0XsCQj.mjs +2 -0
  25. package/dist/{deploy-managed-static-Dqz06S2u.mjs → deploy-managed-static-B9KVxY3X.mjs} +64 -18
  26. package/dist/{deploy-transport-nY3vLXPL.mjs → deploy-transport-B3mtEi_q.mjs} +1 -1
  27. package/dist/deploy.d.mts +22 -1
  28. package/dist/deploy.mjs +45 -4
  29. package/dist/{domain-DKlNI0SR.mjs → domain-BAdwm-QS.mjs} +3 -3
  30. package/dist/{email-C0s3OvJk.mjs → email-MwjA7kaL.mjs} +4 -4
  31. package/dist/{env-BX2JFsgF.mjs → env-B163-G1s.mjs} +3 -3
  32. package/dist/{fetch-DHLOuPyk.d.mts → fetch-CUX0tB78.d.mts} +14 -1
  33. package/dist/fetch-CtESUYWd.mjs +26 -0
  34. package/dist/{fetch-error-Dj3crt0e.mjs → fetch-error-Bw0n-IY-.mjs} +1 -1
  35. package/dist/{fetch-stream-PGgz4uGz.mjs → fetch-stream-BspOeTAI.mjs} +1 -1
  36. package/dist/{fetch-stream-CNxOrBdP.d.mts → fetch-stream-DfkAzZf-.d.mts} +1 -1
  37. package/dist/{gen-Bj6ZkOcI.mjs → gen-CYN3wiov.mjs} +1 -1
  38. package/dist/gen-Cf-RBVg4.mjs +1 -0
  39. package/dist/{github-cmd-DQDryS-5.mjs → github-cmd-C8QsnJQs.mjs} +2 -2
  40. package/dist/{handler-_PqY82xe.d.mts → handler-D5K_yP6T.d.mts} +1 -1
  41. package/dist/{help-D49SL_lN.mjs → help-B2sFwn9b.mjs} +44 -3
  42. package/dist/help-w-xlx_kq.mjs +1 -0
  43. package/dist/index.d.mts +1 -1
  44. package/dist/index.mjs +38 -71
  45. package/dist/{init-DyTEY04s.mjs → init-DGFQMnbk.mjs} +6 -6
  46. package/dist/{link-CgOVn9EC.mjs → link-CwrfpjIM.mjs} +3 -3
  47. package/dist/{list-CUfD9RSb.mjs → list-hKoW5z-b.mjs} +3 -3
  48. package/dist/{live-DJONVlQK.d.mts → live-JheIDZKc.d.mts} +1 -1
  49. package/dist/login-08mBwZfI.mjs +1 -0
  50. package/dist/{login-BJvGW5Eu.mjs → login-f2eu2TQh.mjs} +3 -3
  51. package/dist/{logs-DeizBI4j.mjs → logs-CEWqD-_B.mjs} +3 -3
  52. package/dist/{migrate-8rk56vV8.mjs → migrate-DYfdWBXt.mjs} +1 -1
  53. package/dist/migrate-Di-4EuoE.mjs +1 -0
  54. package/dist/nitro.mjs +1 -1
  55. package/dist/operator-cmd-Bv20yLu2.mjs +1 -0
  56. package/dist/{operator-cmd-CA5QQyvE.mjs → operator-cmd-DCr_QGMH.mjs} +4 -4
  57. package/dist/{output-Ba6ZbrzY.mjs → output-CKguMgr7.mjs} +13 -1
  58. package/dist/pages/client.d.mts +2 -2
  59. package/dist/pages/client.mjs +18 -5
  60. package/dist/pages/index.d.mts +1 -1
  61. package/dist/pages/index.mjs +1 -1
  62. package/dist/pages/islands-plugin.d.mts +43 -5
  63. package/dist/pages/islands-plugin.mjs +98 -27
  64. package/dist/pages/protocol.d.mts +2 -2
  65. package/dist/pages/protocol.mjs +1 -1
  66. package/dist/pages/serialize.d.mts +2 -2
  67. package/dist/pages/serialize.mjs +1 -1
  68. package/dist/{platform-auth-config-CZaY812e.mjs → platform-auth-config-qGvEuns3.mjs} +5 -5
  69. package/dist/{platform-auth-protection-U9HCqoXv.mjs → platform-auth-protection-CyLcD6ot.mjs} +3 -3
  70. package/dist/{platform-auth-recovery-B0BV2hfV.mjs → platform-auth-recovery-B2LKI8V2.mjs} +3 -3
  71. package/dist/{platform-cmd-D9lwFpcl.mjs → platform-cmd-B2ec5eFg.mjs} +1 -1
  72. package/dist/{platform-cmd-CXrjk4fb.mjs → platform-cmd-CX7phm7V.mjs} +5 -5
  73. package/dist/{platform-domain-CXyq-68_.mjs → platform-domain-DDNK2y-4.mjs} +3 -3
  74. package/dist/{platform-lifecycle-D0TdyXbN.mjs → platform-lifecycle-3CR98Tg2.mjs} +386 -36
  75. package/dist/{platform-lifecycle-Dz2cJsLX.mjs → platform-lifecycle-CWc5gr6c.mjs} +1 -1
  76. package/dist/{platform-management-BvgbusqL.mjs → platform-management-DAE6g2QU.mjs} +1 -1
  77. package/dist/{platform-management-CnXhgxTM.mjs → platform-management-o3LCCeE4.mjs} +40 -2
  78. package/dist/{platform-plans-config-BWn1S2Rv.mjs → platform-plans-config-CBMZxCep.mjs} +1 -1
  79. package/dist/{platform-recovery-CH_fThW6.mjs → platform-recovery-Dmsg7lWA.mjs} +2 -2
  80. package/dist/{platform-setup-YvN9VQXV.mjs → platform-setup-hFbnWAVQ.mjs} +1 -1
  81. package/dist/{prepare-2XD6kh77.mjs → prepare-HKo7Rh5V.mjs} +1 -1
  82. package/dist/{project-cmd-CpLYflCH.mjs → project-cmd-8ylYGx-O.mjs} +17 -17
  83. package/dist/{project-team-CTSY7W7Q.mjs → project-team-Bvpl78we.mjs} +2 -2
  84. package/dist/{project-token-Cybtlfbl.mjs → project-token-QWHoJH2t.mjs} +2 -2
  85. package/dist/{project-zero-trust-DKOtqyvu.mjs → project-zero-trust-8tJ-RFvu.mjs} +2 -2
  86. package/dist/{protocol-B8sI8dRD.d.mts → protocol-Ssc_LhHj.d.mts} +1 -1
  87. package/dist/{protocol-RNP0u7UY.mjs → protocol-bAUUkx70.mjs} +1 -1
  88. package/dist/{provision-UcYjpTRh.mjs → provision-BgXFDv0d.mjs} +1 -1
  89. package/dist/{provision-BuifYvLc.mjs → provision-DZKYCEJg.mjs} +3 -2
  90. package/dist/{requests-Ryiazz9i.mjs → requests-Vk5Zyhcy.mjs} +2 -2
  91. package/dist/{rollback-Or0EV3rP.mjs → rollback-CH4yMQys.mjs} +9 -8
  92. package/dist/runtime/client-react.d.mts +2 -2
  93. package/dist/runtime/client-react.mjs +3 -3
  94. package/dist/runtime/client-solid.d.mts +2 -2
  95. package/dist/runtime/client-solid.mjs +3 -3
  96. package/dist/runtime/client-svelte.d.mts +2 -2
  97. package/dist/runtime/client-svelte.mjs +3 -3
  98. package/dist/runtime/client-vue.d.mts +2 -2
  99. package/dist/runtime/client-vue.mjs +3 -3
  100. package/dist/runtime/client.d.mts +2 -2
  101. package/dist/runtime/client.mjs +3 -3
  102. package/dist/runtime/fetch-server.d.mts +8 -0
  103. package/dist/runtime/fetch-server.mjs +30 -0
  104. package/dist/runtime/fetch-stream.d.mts +2 -2
  105. package/dist/runtime/fetch-stream.mjs +2 -2
  106. package/dist/runtime/fetch.d.mts +2 -2
  107. package/dist/runtime/fetch.mjs +3 -3
  108. package/dist/runtime/handler.d.mts +1 -1
  109. package/dist/runtime/live-client.d.mts +1 -1
  110. package/dist/runtime/live.d.mts +1 -1
  111. package/dist/runtime/routing.d.mts +1 -1
  112. package/dist/runtime/routing.mjs +1 -1
  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/{secret-CClHaFxm.mjs → secret-wr6Sn4Xa.mjs} +3 -3
  117. package/dist/serialize-DtR8Vwa_.d.mts +18 -0
  118. package/dist/serialize-YHvlcG3Q.mjs +31 -0
  119. package/dist/{subcommand-prompt-Bm3ZlYgA.mjs → subcommand-prompt-CNZc4XUd.mjs} +1 -1
  120. package/dist/{wrapper-BOigE1xJ.mjs → wrapper-DGsYwNi6.mjs} +2 -0
  121. package/dist/{ws-CsBNxv86.d.mts → ws-nnFnAyQb.d.mts} +1 -1
  122. package/docs/guide/deployment.md +2 -0
  123. package/docs/guide/edge/headers.md +1 -1
  124. package/docs/guide/email/receiving.md +1 -1
  125. package/docs/guide/email/sending.md +3 -3
  126. package/docs/guide/pages-routing/markdown.md +3 -1
  127. package/docs/guide/platform/administration/email.md +7 -1
  128. package/docs/guide/platform/installation/ci.md +2 -0
  129. package/docs/guide/platform/installation/credentials.md +23 -5
  130. package/docs/guide/platform/installation/maintenance.md +32 -2
  131. package/docs/guide/platform/installation/setup.md +1 -1
  132. package/docs/guide/typed-fetch.md +1 -1
  133. package/docs/integrations/cloudflare.md +1 -1
  134. package/docs/integrations/frameworks/tanstack-start.md +25 -0
  135. package/docs/reference/api/deploy.md +35 -3
  136. package/docs/reference/cli/database.md +15 -0
  137. package/docs/reference/cli/platform-installation.md +2 -0
  138. package/docs/reference/cli/project.md +4 -2
  139. package/docs/reference/cli.md +1 -0
  140. package/docs/reference/config.md +1 -1
  141. package/package.json +8 -7
  142. package/dist/cf-build-output-BU3hqdHu.mjs +0 -1
  143. package/dist/client-DrdeJgHR.mjs +0 -1
  144. package/dist/deploy-CxNgEYr4.mjs +0 -2
  145. package/dist/fetch-sAcwjzLO.mjs +0 -18
  146. package/dist/gen-DsCukhuw.mjs +0 -1
  147. package/dist/help-DOFygYi4.mjs +0 -1
  148. package/dist/login-alAlxw4S.mjs +0 -1
  149. package/dist/migrate-D2odrAmh.mjs +0 -1
  150. package/dist/operator-cmd-D7toMPJ9.mjs +0 -1
  151. package/dist/serialize-BtQyaYoC.mjs +0 -20
  152. package/dist/serialize-CfSwWfF2.d.mts +0 -10
@@ -2,8 +2,9 @@
2
2
  import { n as __toESM } from "../rolldown-runtime-DXIUcv95.mjs";
3
3
  import { a as join, c as resolve, n as dirname } from "../dist-ipQi0Q8y.mjs";
4
4
  import { t as require_picocolors } from "../picocolors-BTps1_gs.mjs";
5
- import { l as formatUrl } from "../output-Ba6ZbrzY.mjs";
6
- import { i as safePositional, n as getVoidUserAgent, r as readCfUploadOutput, t as getCfCliVersion } from "../cf-user-agent-ChjQp2MU.mjs";
5
+ import { l as formatUrl } from "../output-CKguMgr7.mjs";
6
+ import { n as readCfUploadOutput, r as safePositional, t as isD1Bookmark } from "../cf-command-values-b8OqDoo9.mjs";
7
+ import { n as getVoidUserAgent, t as getCfCliVersion } from "../cf-user-agent-BkEHPDLA.mjs";
7
8
  import { t as sanitizeTerminalLogText } from "../terminal-log-text-D9ACPOuG.mjs";
8
9
  import { copyFileSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
9
10
  import { fileURLToPath } from "node:url";
@@ -148,7 +149,7 @@ function result(status, stdout = "", stderr = "", data) {
148
149
  ].includes(errorCode ?? 0) ? { failure: "not-found" } : {}
149
150
  };
150
151
  }
151
- function runCf(command, cwd = process.cwd(), bounds) {
152
+ function runCf(command, cwd = process.cwd(), bounds, interactive = false) {
152
153
  const env = cfEnvironment();
153
154
  env.CF_QUIET = "1";
154
155
  const child = spawnSync(process.execPath, [cf, ...command], {
@@ -159,7 +160,7 @@ function runCf(command, cwd = process.cwd(), bounds) {
159
160
  windowsHide: true,
160
161
  maxBuffer: bounds?.maxOutputBytes ?? 33554432,
161
162
  ...bounds ? { timeout: bounds.timeoutMs } : {},
162
- stdio: [
163
+ stdio: interactive ? "inherit" : [
163
164
  "ignore",
164
165
  "pipe",
165
166
  "pipe"
@@ -253,7 +254,7 @@ async function withBuildOutput(raw, sourceMain, action) {
253
254
  }), { mode: 384 });
254
255
  const accountId = process.env.CLOUDFLARE_ACCOUNT_ID ?? raw.account_id;
255
256
  if (typeof accountId !== "string" || !accountId) throw new Error("Cloudflare account is not pinned for Worker deployment.");
256
- const { prepareCfBuildOutput } = await import("../cf-build-output-BU3hqdHu.mjs");
257
+ const { prepareCfBuildOutput } = await import("../cf-build-output-Dcmxa-Zm.mjs");
257
258
  const output = await prepareCfBuildOutput(scratch, accountId);
258
259
  if (!output) throw new Error("Could not prepare the Cloudflare Worker build output.");
259
260
  try {
@@ -314,6 +315,14 @@ function d1Database(token) {
314
315
  table: typeof selected.migrations_table === "string" ? selected.migrations_table : "d1_migrations"
315
316
  };
316
317
  }
318
+ function previousD1Bookmark(stdout) {
319
+ try {
320
+ const previous = object(parsedJson(stdout)).previous_bookmark;
321
+ return isD1Bookmark(previous) ? previous : void 0;
322
+ } catch {
323
+ return;
324
+ }
325
+ }
317
326
  function cleanJson(command, transform) {
318
327
  const called = runCf(command);
319
328
  if (called.status !== 0 || !transform) return called;
@@ -568,6 +577,33 @@ async function resources() {
568
577
  if (!Array.isArray(pending) || pending.some((item) => typeof object(item).Name !== "string")) throw new Error("D1 migration list was malformed.");
569
578
  return result(0, "", called.stderr, { pending: pending.map((item) => object(item).Name) });
570
579
  }
580
+ case "d1.time-travel.bookmark": {
581
+ const called = runCf([
582
+ "d1",
583
+ "time-travel",
584
+ "get-bookmark",
585
+ d1Database(operation.database).id
586
+ ]);
587
+ if (called.status !== 0) return called;
588
+ const bookmark = object(parsedJson(called.stdout)).bookmark;
589
+ if (!isD1Bookmark(bookmark)) throw new Error("D1 Time Travel bookmark was malformed.");
590
+ return result(0, "", called.stderr, { bookmark });
591
+ }
592
+ case "d1.time-travel.restore": {
593
+ const database = d1Database(operation.database);
594
+ if ("bookmark" in operation.target && !isD1Bookmark(operation.target.bookmark)) throw new Error("D1 Time Travel bookmark was malformed.");
595
+ const target = "bookmark" in operation.target ? `--bookmark=${operation.target.bookmark}` : `--timestamp=${operation.target.timestamp}`;
596
+ const called = runCf([
597
+ "d1",
598
+ "time-travel",
599
+ "restore",
600
+ database.id,
601
+ target,
602
+ "--force"
603
+ ]);
604
+ if (called.status !== 0) return called;
605
+ return result(0, "", called.stderr, { previousBookmark: previousD1Bookmark(called.stdout) });
606
+ }
571
607
  case "containers.list": return runCf([
572
608
  "containers",
573
609
  "applications",
@@ -979,8 +1015,8 @@ async function workerChanges() {
979
1015
  "--prebuilt",
980
1016
  ...request.message ? ["--message", request.message] : [],
981
1017
  ...request.secretsFilePath ? ["--secrets-file", request.secretsFilePath] : []
982
- ], directory));
983
- if (called.status !== 0) return called;
1018
+ ], directory, void 0, request.interactive === true));
1019
+ if (called.status !== 0 || request.interactive === true) return called;
984
1020
  let uploaded = {};
985
1021
  try {
986
1022
  uploaded = object(parsedJson(called.stdout));
@@ -1099,9 +1135,10 @@ async function main() {
1099
1135
  if (operation.type.startsWith("triggers.") || operation.type === "worker.deploy" || operation.type === "versions.upload" || operation.type === "queues.consumer.remove") return workerChanges();
1100
1136
  return resources();
1101
1137
  }
1138
+ const terminalOperation = operation?.type === "auth.login" || operation?.type === "tail" || (operation?.type === "versions.upload" || operation?.type === "worker.deploy") && operation.interactive === true;
1102
1139
  try {
1103
1140
  const output = await main();
1104
- if (operation.type !== "auth.login" && operation.type !== "tail") {
1141
+ if (!terminalOperation) {
1105
1142
  let data = output.data;
1106
1143
  let humanOutput = "";
1107
1144
  if (data === void 0 && output.stdout.trim()) try {
@@ -1127,7 +1164,7 @@ try {
1127
1164
  process.exitCode = output.status;
1128
1165
  } catch (error) {
1129
1166
  const message = error instanceof Error ? error.message : "Cloudflare operation failed.";
1130
- if (operation?.type !== "auth.login" && operation?.type !== "tail") process.stdout.write(JSON.stringify({
1167
+ if (!terminalOperation) process.stdout.write(JSON.stringify({
1131
1168
  operationResult: 1,
1132
1169
  errors: [{ message }]
1133
1170
  }) + "\n");
@@ -98,11 +98,11 @@ const VOID_CLI_VERSION = readCliVersion();
98
98
  const MIN_PLATFORM_VERSION = "1.1.11";
99
99
  const RELEASE_VERSION = /^(\d+)\.(\d+)\.(\d+)(-[0-9A-Za-z.-]+)?(\+[0-9A-Za-z.-]+)?$/;
100
100
  /**
101
- * Version checks keyed by platform base URL. Every outcome (pass, inconclusive,
102
- * or too old) is kept for the rest of the process, so polling commands probe
103
- * discovery once.
101
+ * Discovery probes keyed by platform base URL. Every outcome (pass,
102
+ * inconclusive, or too old) is kept for the rest of the process, so polling
103
+ * commands probe discovery once.
104
104
  */
105
- const platformVersionChecks = /* @__PURE__ */ new Map();
105
+ const platformVersionProbes = /* @__PURE__ */ new Map();
106
106
  /**
107
107
  * Returns whether `version` is older than MIN_PLATFORM_VERSION, or null when
108
108
  * it is not a release version. A prerelease sorts before its release.
@@ -244,15 +244,26 @@ var PlatformClient = class {
244
244
  }
245
245
  /**
246
246
  * Checks the platform version once per process and base URL. Concurrent
247
- * first requests share one check, and its outcome is kept for later requests.
247
+ * first requests share one probe, and its outcome is kept for later requests.
248
248
  */
249
- ensureSupportedPlatform() {
250
- const apiUrl = this.baseUrl;
251
- const cached = platformVersionChecks.get(apiUrl);
249
+ async ensureSupportedPlatform() {
250
+ assertSupportedPlatform(this.baseUrl, await this.platformProbe());
251
+ }
252
+ platformProbe() {
253
+ const cached = platformVersionProbes.get(this.baseUrl);
252
254
  if (cached) return cached;
253
- const check = this.probePlatformVersion().then((probe) => assertSupportedPlatform(apiUrl, probe));
254
- platformVersionChecks.set(apiUrl, check);
255
- return check;
255
+ const probe = this.probePlatformVersion();
256
+ platformVersionProbes.set(this.baseUrl, probe);
257
+ return probe;
258
+ }
259
+ /**
260
+ * Whether discovery says the platform accepts Worker modules uploaded to R2.
261
+ * False when discovery omits the field or gave no usable answer.
262
+ */
263
+ async supportsDirectWorkerUpload() {
264
+ let probe = await this.platformProbe();
265
+ if (probe.kind === "unknown") probe = await this.probePlatformVersion();
266
+ return probe.kind === "version" && probe.directWorkerUpload;
256
267
  }
257
268
  /** Reads the platform version from public discovery, without credentials. */
258
269
  async probePlatformVersion() {
@@ -270,9 +281,11 @@ var PlatformClient = class {
270
281
  return { kind: "missing" };
271
282
  }
272
283
  try {
284
+ const discovery = await readPlatformDiscoveryResponse(this.baseUrl, response);
273
285
  return {
274
286
  kind: "version",
275
- version: (await readPlatformDiscoveryResponse(this.baseUrl, response)).platformVersion
287
+ version: discovery.platformVersion,
288
+ directWorkerUpload: discovery.directWorkerUpload === true
276
289
  };
277
290
  } catch {
278
291
  return { kind: "unknown" };
@@ -518,6 +531,38 @@ var PlatformClient = class {
518
531
  if (!res.ok) await throwPlatformApiError("Failed to request upload URLs", res, "deploy");
519
532
  return (await res.json()).urls;
520
533
  }
534
+ /**
535
+ * Requests one presigned R2 PUT per Worker module, in `modules` order. The
536
+ * platform refuses a Worker over Cloudflare's size limit here (413
537
+ * `worker_too_large`), before any bytes are uploaded.
538
+ */
539
+ async requestWorkerUploadUrls(projectId, modules) {
540
+ const url = `${this.baseUrl}/projects/${projectId}/deploy/worker-upload-urls`;
541
+ this.cliLog?.info("worker_upload_urls_post", {
542
+ url,
543
+ moduleCount: modules.length
544
+ });
545
+ const request = { modules };
546
+ const res = await this.request(url, {
547
+ method: "POST",
548
+ headers: {
549
+ "Content-Type": "application/json",
550
+ ...this.authHeaders
551
+ },
552
+ body: JSON.stringify(request)
553
+ });
554
+ this.cliLog?.info("worker_upload_urls_response", {
555
+ status: res.status,
556
+ cfRay: res.headers.get("cf-ray")
557
+ });
558
+ if (!res.ok) await throwPlatformApiError("Failed to request worker upload URLs", res, "deploy");
559
+ const json = await res.json();
560
+ if (typeof json?.id !== "string" || !json.id || !Array.isArray(json.urls) || json.urls.length !== modules.length || !json.urls.every((entry) => typeof entry?.url === "string" && typeof entry.headers === "object" && !!entry.headers)) throw new Error("Invalid worker upload URLs from platform.");
561
+ return {
562
+ id: json.id,
563
+ urls: json.urls
564
+ };
565
+ }
521
566
  async *finalizeDeploy(projectId, payload) {
522
567
  const url = `${this.baseUrl}/projects/${projectId}/deploy`;
523
568
  yield* this.streamDeployRequest(url, projectId, {
@@ -0,0 +1 @@
1
+ export { r as PlatformClient } from "./client-BdzxubTS.mjs";
@@ -1,7 +1,7 @@
1
1
  import { t as basename } from "./dist-ipQi0Q8y.mjs";
2
2
  import { b as readRootWranglerConfig } from "./wrangler-C9XSzrju.mjs";
3
3
  import { L as log } from "./dist-BVdsO7Py.mjs";
4
- import { m as printSuccess } from "./output-Ba6ZbrzY.mjs";
4
+ import { m as printSuccess } from "./output-CKguMgr7.mjs";
5
5
  import { i as isCleanCloudflareExit } from "./cloudflare-process-CZJ4viYl.mjs";
6
6
  import { a as parseCloudflareAuthSession, i as ensureCloudflareAuthentication, n as cloudflareCredentialOverrides, r as createBundledCloudflareAuthRunner } from "./cloudflare-auth-DSvBc1Gu.mjs";
7
7
  //#region src/cli/cloudflare-cmd.ts
@@ -1 +1 @@
1
- export { t as activateCloudflareExistingVersion, n as applyCloudflareD1Migrations, r as changeCloudflareDomain, o as deleteCloudflareSecret, s as executeCloudflareD1Sql, c as listCloudflareDomains, l as listCloudflareSecrets, m as putCloudflareSecret, h as readCloudflareD1Migrations, g as readCloudflareWorkerStatus, _ as resolveCloudflareD1Context, v as resolveCloudflareOperationContext, y as syncCloudflareSecrets, b as tailCloudflareWorker } from "./cloudflare-operations-DH3GedbV.mjs";
1
+ export { t as activateCloudflareExistingVersion, n as applyCloudflareD1Migrations, r as changeCloudflareDomain, o as deleteCloudflareSecret, s as executeCloudflareD1Sql, c as listCloudflareDomains, l as listCloudflareSecrets, m as putCloudflareSecret, h as readCloudflareD1Migrations, g as readCloudflareWorkerStatus, _ as resolveCloudflareD1Context, v as resolveCloudflareOperationContext, y as restoreCloudflareD1Database, b as syncCloudflareSecrets, x as tailCloudflareWorker } from "./cloudflare-operations-D5PLrOqD.mjs";
@@ -1,10 +1,10 @@
1
1
  import { a as join } from "./dist-ipQi0Q8y.mjs";
2
2
  import { i as persistCloudflareConfig, r as materializeCloudflareConfig } from "./cloudflare-config-rdFOys4X.mjs";
3
3
  import { A as updateWranglerCustomDomain, M as writeWranglerPublishedTrafficSnapshot, S as readWranglerCustomDomains, w as readWranglerPublishedTrafficSnapshot } from "./wrangler-C9XSzrju.mjs";
4
- import { u as getErrorMessage } from "./output-Ba6ZbrzY.mjs";
4
+ import { u as getErrorMessage } from "./output-CKguMgr7.mjs";
5
5
  import { t as createCloudflareProcessRunner } from "./cloudflare-process-CZJ4viYl.mjs";
6
- import { _ as provisionEnv, r as assertNoTransportRedirectInProjectDotenv, s as deleteEnvVarCaseAware, v as resolvePinnedApiBaseUrl } from "./provision-BuifYvLc.mjs";
7
- import { a as findWranglerCiOverrideDotenvFile, i as findAmbientConfigOverride } from "./deploy-transport-nY3vLXPL.mjs";
6
+ import { _ as provisionEnv, r as assertNoTransportRedirectInProjectDotenv, s as deleteEnvVarCaseAware, v as resolvePinnedApiBaseUrl } from "./provision-DZKYCEJg.mjs";
7
+ import { a as findWranglerCiOverrideDotenvFile, i as findAmbientConfigOverride } from "./deploy-transport-B3mtEi_q.mjs";
8
8
  import { existsSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
9
9
  import { tmpdir } from "node:os";
10
10
  import { deployCloudflareVersionTraffic, encodeCloudflareVersionMessage, parseCloudflareVersionMessage, parseRootWranglerConfig, readBindingFieldPresence, readCloudflareTriggerConfig, readWranglerTopLevelString, resolveD1MigrateTarget, stabilizeCloudflareVersionTriggers } from "@void/deploy-cloudflare";
@@ -115,6 +115,16 @@ async function applyCloudflareD1Migrations(context) {
115
115
  configPath: context.operation.configPath
116
116
  }, { capture: false });
117
117
  }
118
+ /** Restore the D1 database with Time Travel. Returns the bookmark that undoes the restore. */
119
+ async function restoreCloudflareD1Database(context, target) {
120
+ const previous = (await run(context.operation, {
121
+ type: "d1.time-travel.restore",
122
+ database: context.migrateToken,
123
+ target,
124
+ configPath: context.operation.configPath
125
+ })).data?.previousBookmark;
126
+ return typeof previous === "string" ? previous : void 0;
127
+ }
118
128
  async function readCloudflareWorkerStatus(context) {
119
129
  const [deployment, deployments, versions] = await Promise.all([
120
130
  run(context, {
@@ -439,4 +449,4 @@ function failedOperationResult(error) {
439
449
  };
440
450
  }
441
451
  //#endregion
442
- export { resolveCloudflareD1Context as _, createCloudflareEmptyDomainPublisher as a, tailCloudflareWorker as b, listCloudflareDomains as c, parseCloudflareDeployedVersionIds as d, parseCloudflareVersions as f, readCloudflareWorkerStatus as g, readCloudflareD1Migrations as h, createCloudflareEmptyCronPublisher as i, listCloudflareSecrets as l, putCloudflareSecret as m, applyCloudflareD1Migrations as n, deleteCloudflareSecret as o, publishEmptyCloudflareCustomDomainSet as p, changeCloudflareDomain as r, executeCloudflareD1Sql as s, activateCloudflareExistingVersion as t, parseActiveVersionId as u, resolveCloudflareOperationContext as v, syncCloudflareSecrets as y };
452
+ export { resolveCloudflareD1Context as _, createCloudflareEmptyDomainPublisher as a, syncCloudflareSecrets as b, listCloudflareDomains as c, parseCloudflareDeployedVersionIds as d, parseCloudflareVersions as f, readCloudflareWorkerStatus as g, readCloudflareD1Migrations as h, createCloudflareEmptyCronPublisher as i, listCloudflareSecrets as l, putCloudflareSecret as m, applyCloudflareD1Migrations as n, deleteCloudflareSecret as o, publishEmptyCloudflareCustomDomainSet as p, changeCloudflareDomain as r, executeCloudflareD1Sql as s, activateCloudflareExistingVersion as t, parseActiveVersionId as u, resolveCloudflareOperationContext as v, tailCloudflareWorker as x, restoreCloudflareD1Database as y };
@@ -2,10 +2,10 @@ import { c as normalizePlatformApiUrl, s as listPlatformConnections } from "./pl
2
2
  import { c as writeDeploymentPlatform, l as writePlatformSelection, n as readDeploymentPlatform } from "./project-rqDnVsJN.mjs";
3
3
  import { d as readPlatformToken } from "./auth-B6iOCjKI.mjs";
4
4
  import { K as select, L as log, tt as isCancel } from "./dist-BVdsO7Py.mjs";
5
- import { m as printSuccess } from "./output-Ba6ZbrzY.mjs";
6
- import { a as isExpiredTokenError, r as PlatformClient } from "./client-GuSO3v_x.mjs";
7
- import { t as promptForLoginToken } from "./login-BJvGW5Eu.mjs";
8
- import { i as saveDiscoveredPlatform, n as promptPlatformUrl, t as discoverPlatform } from "./platform-cmd-CXrjk4fb.mjs";
5
+ import { m as printSuccess } from "./output-CKguMgr7.mjs";
6
+ import { a as isExpiredTokenError, r as PlatformClient } from "./client-BdzxubTS.mjs";
7
+ import { t as promptForLoginToken } from "./login-f2eu2TQh.mjs";
8
+ import { i as saveDiscoveredPlatform, n as promptPlatformUrl, t as discoverPlatform } from "./platform-cmd-CX7phm7V.mjs";
9
9
  import { t as connectCloudflare } from "./cloudflare-connect-BN-k2kD-.mjs";
10
10
  //#region src/cli/connect.ts
11
11
  async function selectVoidPlatform(interactive) {
@@ -1 +1 @@
1
- export { t as createProjectWithSlugRetry } from "./create-project-DEEWJX_M.mjs";
1
+ export { t as createProjectWithSlugRetry } from "./create-project-D8jQTwVQ.mjs";
@@ -1,8 +1,8 @@
1
1
  import { t as attachSelectedPlatform, u as writeProjectConfig } from "./project-rqDnVsJN.mjs";
2
2
  import { s as getSiteDomain } from "./auth-B6iOCjKI.mjs";
3
3
  import { A as confirm, K as select, L as log, O as cancel, X as text, tt as isCancel } from "./dist-BVdsO7Py.mjs";
4
- import { f as import_picocolors, h as sanitizeTerminalText } from "./output-Ba6ZbrzY.mjs";
5
- import { n as PlatformApiError } from "./client-GuSO3v_x.mjs";
4
+ import { f as import_picocolors, h as sanitizeTerminalText } from "./output-CKguMgr7.mjs";
5
+ import { n as PlatformApiError } from "./client-BdzxubTS.mjs";
6
6
  import { t as validateProjectSlug } from "./project-slug-23TpquG4.mjs";
7
7
  import { n as inferDefaultSlug } from "./resolve-project-WpwkCB_c.mjs";
8
8
  //#region src/cli/prompt.ts
@@ -9,12 +9,12 @@ import { t as cfAccessHeaders } from "./cf-access-BM9G0lhO.mjs";
9
9
  import { n as ensurePlatformProxyAccess, r as isCloudflareAccessChallenge, t as ensurePlatformAccessToken } from "./cf-access-CWP4avfP.mjs";
10
10
  import { c as getToken, o as getProxyUrl } from "./auth-B6iOCjKI.mjs";
11
11
  import { A as confirm, H as outro, L as log, X as text, tt as isCancel } from "./dist-BVdsO7Py.mjs";
12
- import { f as import_picocolors, i as dim, l as formatUrl, m as printSuccess, o as formatCount, u as getErrorMessage } from "./output-Ba6ZbrzY.mjs";
12
+ import { f as import_picocolors, i as dim, l as formatUrl, m as printSuccess, o as formatCount, u as getErrorMessage } from "./output-CKguMgr7.mjs";
13
13
  import { o as loadLocalEnv } from "./env-BJjULvL0.mjs";
14
14
  import { i as validateMigrations, t as assertJournalCoherence } from "./validate-CnZPMq4q.mjs";
15
- import { n as PlatformApiError, r as PlatformClient } from "./client-GuSO3v_x.mjs";
15
+ import { n as PlatformApiError, r as PlatformClient } from "./client-BdzxubTS.mjs";
16
16
  import { n as drizzleKitBin } from "./yarn-pnp-DLbEFMT0.mjs";
17
- import { n as formatTimestamp } from "./gen-Bj6ZkOcI.mjs";
17
+ import { n as formatTimestamp } from "./gen-CYN3wiov.mjs";
18
18
  import { createRequire } from "node:module";
19
19
  import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, writeFileSync } from "node:fs";
20
20
  import { pathToFileURL } from "node:url";
@@ -223,6 +223,7 @@ async function runDbCommand(root, args) {
223
223
  else if (args.action === "studio") await runStudio(root, dialect, args.remote);
224
224
  else if (args.action === "set-url") await runSetUrl(root, dialect);
225
225
  else if (args.action === "connect") await runConnect(root, dialect, args);
226
+ else if (args.action === "restore") await runRestore(root, dialect, args);
226
227
  else if (args.action === "rename-migrations") await runRenameMigrations(root, dialect);
227
228
  else await runExport(root, args, dialect);
228
229
  }
@@ -398,7 +399,7 @@ async function runStatus(root, dialect) {
398
399
  applied_at: ""
399
400
  }));
400
401
  } else {
401
- const { readCloudflareD1Migrations, resolveCloudflareD1Context } = await import("./cloudflare-operations-Cm8lVx7W.mjs");
402
+ const { readCloudflareD1Migrations, resolveCloudflareD1Context } = await import("./cloudflare-operations-BFLCpUCV.mjs");
402
403
  remoteApplied = (await readCloudflareD1Migrations(resolveCloudflareD1Context(root, configuredD1Binding(root)))).map((name) => ({
403
404
  name,
404
405
  applied_at: ""
@@ -710,7 +711,7 @@ async function runExecute(root, command, file, dialect, remote) {
710
711
  process.exit(0);
711
712
  }
712
713
  if (dialect === "sqlite") {
713
- const { executeCloudflareD1Sql, resolveCloudflareD1Context } = await import("./cloudflare-operations-Cm8lVx7W.mjs");
714
+ const { executeCloudflareD1Sql, resolveCloudflareD1Context } = await import("./cloudflare-operations-BFLCpUCV.mjs");
714
715
  const rows = await executeCloudflareD1Sql(resolveCloudflareD1Context(root, configuredD1Binding(root)), sql);
715
716
  if (rows.length > 0) printTable(rows);
716
717
  } else {
@@ -904,7 +905,7 @@ async function runMigrate(root, dialect, remote) {
904
905
  log.info(`No migration files found in ${paths.sourceRelative("db/migrations")}/`);
905
906
  return;
906
907
  }
907
- const { applyCloudflareD1Migrations, readCloudflareD1Migrations, resolveCloudflareD1Context } = await import("./cloudflare-operations-Cm8lVx7W.mjs");
908
+ const { applyCloudflareD1Migrations, readCloudflareD1Migrations, resolveCloudflareD1Context } = await import("./cloudflare-operations-BFLCpUCV.mjs");
908
909
  const binding = configuredD1Binding(root);
909
910
  const context = resolveCloudflareD1Context(root, binding);
910
911
  const remoteBefore = new Set(await readCloudflareD1Migrations(context));
@@ -924,7 +925,7 @@ async function runMigrate(root, dialect, remote) {
924
925
  log.error(`db: D1 binding ${binding} has no "migrations_dir", so Cloudflare would apply ./migrations instead of ${dir}/. Add "migrations_dir": "./${dir}" to that D1 binding in your Cloudflare config, then run the command again.`);
925
926
  process.exit(1);
926
927
  }
927
- const { checkWranglerMigrationApplySet, parseRootWranglerConfig } = await import("./deploy-CxNgEYr4.mjs");
928
+ const { checkWranglerMigrationApplySet, parseRootWranglerConfig } = await import("./deploy-Dc0XsCQj.mjs");
928
929
  const applySet = await checkWranglerMigrationApplySet(context.operation.configPath, parseRootWranglerConfig(context.operation.configPath), binding, context.migrationsDir, rawMigrations, paths.sourceRelative("db/migrations"));
929
930
  if (!applySet.ok) {
930
931
  log.error(applySet.reason);
@@ -1040,6 +1041,55 @@ async function runMigrate(root, dialect, remote) {
1040
1041
  printSuccess(`Applied ${formatCount(applied.length, "migration")}.`);
1041
1042
  }
1042
1043
  }
1044
+ async function runRestore(root, dialect, { target, platform: explicitPlatform, yes }) {
1045
+ const platform = readDeploymentPlatform(root);
1046
+ const directCloudflare = explicitPlatform === "cloudflare" || platform === "cloudflare" || platform === null && !readProjectConfig(root) && await hasDeployedCloudflareDatabase(root);
1047
+ if (dialect !== "sqlite") {
1048
+ log.error("db: `void db restore` restores D1 databases only.");
1049
+ process.exit(1);
1050
+ }
1051
+ if (!directCloudflare) {
1052
+ log.error("db: `void db restore` restores the D1 database of a direct Cloudflare deploy. After a one-off `void deploy --platform cloudflare`, run it with `--platform cloudflare`.");
1053
+ process.exit(1);
1054
+ }
1055
+ const { readCloudflareD1Migrations, resolveCloudflareD1Context, restoreCloudflareD1Database } = await import("./cloudflare-operations-BFLCpUCV.mjs");
1056
+ const binding = configuredD1Binding(root);
1057
+ const context = resolveCloudflareD1Context(root, binding);
1058
+ const database = `D1 database ${context.migrateToken} (${binding})`;
1059
+ const point = "bookmark" in target ? `bookmark ${target.bookmark}` : target.timestamp;
1060
+ if (!yes) {
1061
+ if (!process.stdin.isTTY) {
1062
+ log.error(`db: Refusing to restore ${database} without confirmation. Re-run with --yes.`);
1063
+ process.exit(1);
1064
+ }
1065
+ const ok = await confirm({
1066
+ message: `This restores ${database} to ${point} and discards every write made after it. Continue?`,
1067
+ initialValue: false
1068
+ });
1069
+ if (isCancel(ok) || !ok) {
1070
+ log.info("Cancelled.");
1071
+ process.exit(0);
1072
+ }
1073
+ }
1074
+ let previousBookmark;
1075
+ try {
1076
+ previousBookmark = await restoreCloudflareD1Database(context, target);
1077
+ } catch (error) {
1078
+ log.error(`db: Could not restore ${database} to ${point}: ${getErrorMessage(error)}\nRestore points expire after 7 days on Workers Free and 30 days on Workers Paid. To undo an older migration, write a new migration that reverses it.`);
1079
+ process.exit(1);
1080
+ }
1081
+ const platformFlag = platform === "cloudflare" ? "" : " --platform cloudflare";
1082
+ if (previousBookmark) log.info(`To undo this restore, run \`void db restore${platformFlag} --bookmark=${previousBookmark}\`.`);
1083
+ const paths = readProjectPaths(root);
1084
+ try {
1085
+ const applied = new Set(await readCloudflareD1Migrations(context));
1086
+ const unapplied = collectMigrations(paths.migrationsDir).filter((migration) => !applied.has(migration.name));
1087
+ if (unapplied.length > 0) log.warn(`The remote database does not have these migrations applied: ${unapplied.map((migration) => migration.name).join(", ")}. The next \`void deploy${platformFlag}\` applies them. Fix or remove a migration that caused the problem before you deploy.`);
1088
+ } catch (error) {
1089
+ log.warn(`Could not read the applied migrations after the restore: ${getErrorMessage(error)}. ` + (platformFlag ? `The next \`void deploy${platformFlag}\` applies any migration the restore rewound.` : "Run `void db status` to check them."));
1090
+ }
1091
+ printSuccess(`Restored ${database} to ${point}.`);
1092
+ }
1043
1093
  async function runStudio(root, dialect, remote) {
1044
1094
  if (remote) {
1045
1095
  if (dialect === "sqlite") {
@@ -1097,7 +1147,7 @@ async function runStudio(root, dialect, remote) {
1097
1147
  /** A direct Cloudflare deploy records its D1 or Hyperdrive id in the checked-in Cloudflare config. */
1098
1148
  async function hasDeployedCloudflareDatabase(root) {
1099
1149
  const { readRootWranglerConfig } = await import("./wrangler-DAdxHEzh.mjs");
1100
- const { isRealD1Id, isRealHyperdriveId } = await import("./provision-UcYjpTRh.mjs");
1150
+ const { isRealD1Id, isRealHyperdriveId } = await import("./provision-BgXFDv0d.mjs");
1101
1151
  const config = readRootWranglerConfig(root)?.config;
1102
1152
  const entries = (key) => {
1103
1153
  const value = config?.[key];
@@ -1,8 +1,8 @@
1
1
  import { o as removeProjectConfig, r as readProjectConfig } from "./project-rqDnVsJN.mjs";
2
2
  import { c as getToken } from "./auth-B6iOCjKI.mjs";
3
3
  import { L as log, O as cancel, X as text, tt as isCancel } from "./dist-BVdsO7Py.mjs";
4
- import { m as printSuccess, p as note, r as createSpinner } from "./output-Ba6ZbrzY.mjs";
5
- import { r as PlatformClient } from "./client-GuSO3v_x.mjs";
4
+ import { m as printSuccess, p as note, r as createSpinner } from "./output-CKguMgr7.mjs";
5
+ import { r as PlatformClient } from "./client-BdzxubTS.mjs";
6
6
  import { a as resolveProjectBySlug } from "./resolve-project-WpwkCB_c.mjs";
7
7
  //#region src/cli/delete.ts
8
8
  async function runDeleteCommand(root, slug, options) {