void 0.21.9 → 0.22.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 (132) hide show
  1. package/dist/{account-cmd-DZZGK80W.mjs → account-cmd-CjyxcGkM.mjs} +4 -4
  2. package/dist/{auth-link-B_CeugBw.mjs → auth-link-BLO4ptzo.mjs} +4 -4
  3. package/dist/{auth-router-BgEFRuvZ.mjs → auth-router-ZUg9MF_U.mjs} +5 -5
  4. package/dist/{build-cmd-Dpt0jd-x.mjs → build-cmd-BxR5FROK.mjs} +3 -3
  5. package/dist/{cache-7_UeZdTk.mjs → cache-D0sWhgKI.mjs} +3 -3
  6. package/dist/{cancel-deploy-D23R1RXT.mjs → cancel-deploy-D4NUqFbi.mjs} +3 -3
  7. package/dist/{cf-build-output-CGT03qCD.mjs → cf-build-output-BJ6yGEIS.mjs} +139 -62
  8. package/dist/cli/cf-compat.mjs +164 -50
  9. package/dist/cli/cli.mjs +73 -44
  10. package/dist/cli/env-schema-probe.d.mts +1 -1
  11. package/dist/{client-QTl6ko_D.mjs → client-BTZ3XkrB.mjs} +25 -0
  12. package/dist/client-Czz8o5jP.mjs +2 -0
  13. package/dist/{cloudflare-auth-C4_GPZr0.mjs → cloudflare-auth-DQkqoMYa.mjs} +1 -6
  14. package/dist/{cloudflare-cmd-bSmZ1d5L.mjs → cloudflare-cmd-BKlfGHAy.mjs} +6 -7
  15. package/dist/{cloudflare-connect-jAwacxxP.mjs → cloudflare-connect-Ctmrw579.mjs} +3 -3
  16. package/dist/{cloudflare-operations-sMZXpk_S.mjs → cloudflare-operations-B9tzgjmf.mjs} +10 -39
  17. package/dist/{cloudflare-operations-BipGMJ5O.mjs → cloudflare-operations-BT6OWFBk.mjs} +1 -1
  18. package/dist/{config-CafTW6Cz.mjs → config-Br_JZD6u.mjs} +2 -7
  19. package/dist/{config-s7Xj7tPb.mjs → config-CyQ-wVd7.mjs} +1 -1
  20. package/dist/{config-CF69HgXc.d.mts → config-VavjpDnp.d.mts} +1 -2
  21. package/dist/config-entry.d.mts +1 -1
  22. package/dist/{config-write-BSduPMY8.mjs → config-write-B1f88wJA.mjs} +1 -1
  23. package/dist/{connect-BsUSRzln.mjs → connect-Dg-WkW-C.mjs} +5 -5
  24. package/dist/{create-project-BniEV0OW.mjs → create-project-DdoqwFLF.mjs} +1 -1
  25. package/dist/{create-project-DBfFSZKY.mjs → create-project-l9J7pbtm.mjs} +8 -4
  26. package/dist/{db-hRrvZaq_.mjs → db-gp2sCXyN.mjs} +14 -14
  27. package/dist/{delete-D6dZ9B6B.mjs → delete-TTedbH6B.mjs} +3 -3
  28. package/dist/{deploy-DDz7c8LK.mjs → deploy-B19L2Bra.mjs} +1 -1
  29. package/dist/{deploy-WaAQez1O.mjs → deploy-CH-o2CaZ.mjs} +47 -36
  30. package/dist/{dist-BR1quN_w.mjs → dist-AoCzRTJE.mjs} +226 -60
  31. package/dist/{dist-C5fND3R0.mjs → dist-BuDuKZJv.mjs} +1 -1
  32. package/dist/{dist-Dn6nn2IU.mjs → dist-CTBk70IR.mjs} +42 -42
  33. package/dist/{domain-Dmhvb2oU.mjs → domain-JRF59P_r.mjs} +4 -4
  34. package/dist/{email-DFi-s2t4.mjs → email-Bo6G9LOZ.mjs} +6 -6
  35. package/dist/{env-Csi-tMbT.mjs → env-BYOrWQnv.mjs} +4 -4
  36. package/dist/{env-public-D_6u46fX.d.mts → env-public-BxU_0yTL.d.mts} +2 -1
  37. package/dist/gen-CNJ62MM7.mjs +2 -0
  38. package/dist/{gen-Dz3X1Qab.mjs → gen-sCtlCOdA.mjs} +3 -3
  39. package/dist/{github-cmd-BED3_9JD.mjs → github-cmd-0-7PexDq.mjs} +5 -7
  40. package/dist/{handler-BXJTXd02.d.mts → handler-HEcZsaij.d.mts} +2 -1
  41. package/dist/{headers-BOg_velo.mjs → headers-DWi2IXWx.mjs} +1 -1
  42. package/dist/help-CmZzxUba.mjs +2 -0
  43. package/dist/{help-DC7gdz7L.mjs → help-GKtwl07I.mjs} +124 -4
  44. package/dist/index.d.mts +1 -1
  45. package/dist/index.mjs +53 -24
  46. package/dist/{init-WO0JlPx8.mjs → init-FZx3Elvz.mjs} +13 -13
  47. package/dist/{link-CsHOinF7.mjs → link-BrQfb_CU.mjs} +4 -4
  48. package/dist/{list-CDb-4bZ1.mjs → list-D44jmIAM.mjs} +4 -4
  49. package/dist/{live-CKiJilLr.d.mts → live-CKJlvlNp.d.mts} +1 -1
  50. package/dist/{local-d1-CC8sKFGu.mjs → local-d1-Bg9OzEEO.mjs} +1 -1
  51. package/dist/{login-DvqXsfGs.mjs → login-CAsAsQ-_.mjs} +4 -4
  52. package/dist/login-CGcRKEoi.mjs +2 -0
  53. package/dist/{logs-BdfiOezj.mjs → logs-BjKvFnVM.mjs} +4 -4
  54. package/dist/{migrate-B8KuoYsO.mjs → migrate-BPITvDJN.mjs} +4 -4
  55. package/dist/migrate-CYfbKkXh.mjs +2 -0
  56. package/dist/{node-BM43oz4G.mjs → node-Dt7z256D.mjs} +1 -1
  57. package/dist/{operator-cmd-03819ATr.mjs → operator-cmd-BK5CCiT9.mjs} +4 -4
  58. package/dist/output-Dm_A4Tbv.mjs +81 -0
  59. package/dist/pages/client.d.mts +1 -1
  60. package/dist/pages/index.d.mts +1 -1
  61. package/dist/pages/index.mjs +2 -2
  62. package/dist/pages/islands-plugin.d.mts +16 -6
  63. package/dist/pages/islands-plugin.mjs +1 -1
  64. package/dist/pages/protocol.d.mts +2 -2
  65. package/dist/{output-CCH48AMM.mjs → picocolors-BTps1_gs.mjs} +2 -76
  66. package/dist/{platform-auth-config-z92h63q5.mjs → platform-auth-config-BlN8xTdD.mjs} +3 -3
  67. package/dist/{platform-auth-protection-DeE3yr2R.mjs → platform-auth-protection-7d5aV2Jg.mjs} +3 -3
  68. package/dist/{platform-auth-recovery-o_340Ixx.mjs → platform-auth-recovery-Dxij8ZbR.mjs} +3 -3
  69. package/dist/{platform-cmd-DNl8WosH.mjs → platform-cmd-B3hwKrFK.mjs} +5 -5
  70. package/dist/{platform-cmd-C4ZV3Vpy.mjs → platform-cmd-E0FuL212.mjs} +1 -1
  71. package/dist/{platform-domain-CU1JtJkW.mjs → platform-domain-D6Xcy9ZX.mjs} +36 -9
  72. package/dist/{platform-lifecycle-Bs2qx1E3.mjs → platform-lifecycle-DMh_qrry.mjs} +1 -1
  73. package/dist/{platform-lifecycle-Bc047IeT.mjs → platform-lifecycle-k0E0xoxx.mjs} +548 -86
  74. package/dist/{platform-management-CVpGI9Y5.mjs → platform-management-Brz_BDiT.mjs} +54 -9
  75. package/dist/{platform-management-C8tt6D8h.mjs → platform-management-DOtss0BN.mjs} +1 -1
  76. package/dist/{platform-recovery-dvUaptLr.mjs → platform-recovery-BvtcXON5.mjs} +2 -2
  77. package/dist/prepare-Bm3iq-u4.mjs +2 -0
  78. package/dist/{prepare-DyZ-Yok5.mjs → prepare-C-6YZyyg.mjs} +3 -3
  79. package/dist/{prepare-C3kt3Rst.mjs → prepare-CRhJbVrG.mjs} +1 -1
  80. package/dist/{project-cmd-B44I8J_W.mjs → project-cmd-BZLCqOqw.mjs} +29 -15
  81. package/dist/{project-team-BkbYIsXN.mjs → project-team-BvgM0WoX.mjs} +3 -3
  82. package/dist/{project-token-C8xEEQnB.mjs → project-token-l5DqK6Az.mjs} +3 -3
  83. package/dist/project-zero-trust-v6Mvpp8y.mjs +63 -0
  84. package/dist/{protocol-ZH3jP4a7.d.mts → protocol-BBa6cstI.d.mts} +1 -1
  85. package/dist/{provision-BhreDAOS.mjs → provision-C4IGqkBf.mjs} +24 -19
  86. package/dist/{provision-DNtrtaVD.mjs → provision-Fr9pRqce.mjs} +1 -1
  87. package/dist/{requests-DFyhBMaf.mjs → requests-DN-BbNiM.mjs} +3 -3
  88. package/dist/{rollback-DHHxXZiS.mjs → rollback-D7rzSaZM.mjs} +4 -4
  89. package/dist/runtime/env-public.d.mts +1 -1
  90. package/dist/runtime/handler.d.mts +1 -1
  91. package/dist/runtime/live-client.d.mts +1 -1
  92. package/dist/runtime/live.d.mts +1 -1
  93. package/dist/runtime/sandbox-container.d.mts +3 -0
  94. package/dist/runtime/sandbox-container.mjs +2 -0
  95. package/dist/runtime/sandbox.d.mts +4 -32
  96. package/dist/runtime/sandbox.mjs +118 -72
  97. package/dist/runtime/validator.d.mts +1 -1
  98. package/dist/runtime/ws-server.d.mts +1 -1
  99. package/dist/runtime/ws.d.mts +1 -1
  100. package/dist/sandbox-container-4fdqLnyb.mjs +279 -0
  101. package/dist/sandbox-container-DdNEBfCc.d.mts +72 -0
  102. package/dist/sandbox-qpNBT8a3.d.mts +49 -0
  103. package/dist/{secret-DN9sSNiV.mjs → secret-BOtOl_cb.mjs} +4 -4
  104. package/dist/{skills-O6FUaizK.mjs → skills-D1II1Juz.mjs} +1 -1
  105. package/dist/{subcommand-prompt-BuGYkAkC.mjs → subcommand-prompt-CY1C4fvl.mjs} +2 -2
  106. package/dist/{wrangler-BymcxrRa.mjs → wrangler-DQF1vKyf.mjs} +37 -27
  107. package/dist/{ws-BwcqizuH.d.mts → ws-BoY7vQML.d.mts} +1 -1
  108. package/package.json +40 -32
  109. package/sandbox.Dockerfile +4 -0
  110. package/schema.json +10 -22
  111. package/skills/void/SKILL.md +2 -0
  112. package/skills/void/docs/guide/deployment.md +1 -1
  113. package/skills/void/docs/guide/edge/revalidation.md +1 -1
  114. package/skills/void/docs/guide/edge/static-assets.md +1 -0
  115. package/skills/void/docs/guide/platform/administration/zero-trust.md +318 -0
  116. package/skills/void/docs/guide/platform/development/local.md +2 -2
  117. package/skills/void/docs/guide/platform/installation/domains.md +1 -1
  118. package/skills/void/docs/guide/platform/installation/first-deployment.md +4 -0
  119. package/skills/void/docs/guide/platform/installation/prerequisites.md +1 -1
  120. package/skills/void/docs/guide/platform/installation/uninstall.md +17 -2
  121. package/skills/void/docs/guide/platform-administration.md +1 -0
  122. package/skills/void/docs/guide/sandboxes.md +70 -41
  123. package/skills/void/docs/integrations/cloudflare.md +1 -1
  124. package/skills/void/docs/reference/api.md +35 -35
  125. package/skills/void/docs/reference/cli.md +68 -6
  126. package/skills/void/docs/reference/config.md +16 -16
  127. package/dist/client-4cDVv7BO.mjs +0 -2
  128. package/dist/gen-Vnv2f65C.mjs +0 -2
  129. package/dist/help-DQMfeKMz.mjs +0 -2
  130. package/dist/login-DFQk7rbW.mjs +0 -2
  131. package/dist/migrate-TsHGBnDA.mjs +0 -2
  132. package/dist/prepare-BZXkjdNe.mjs +0 -2
@@ -1,13 +1,13 @@
1
1
  import { c as getToken, p as removeToken } from "./auth-DLNN0D3Z.mjs";
2
- import { j as log } from "./dist-Dn6nn2IU.mjs";
3
- import { n as PlatformClient } from "./client-QTl6ko_D.mjs";
4
- import { n as runLoginCommand } from "./login-DvqXsfGs.mjs";
2
+ import { j as log } from "./dist-CTBk70IR.mjs";
3
+ import { n as PlatformClient } from "./client-BTZ3XkrB.mjs";
4
+ import { n as runLoginCommand } from "./login-CAsAsQ-_.mjs";
5
5
  import { execSync } from "node:child_process";
6
6
  //#region src/cli/account-cmd.ts
7
7
  async function runAccountCommand(root, args) {
8
8
  switch (args.subcommand) {
9
9
  case "login": return runLoginCommand(root);
10
- case "link": return import("./auth-link-B_CeugBw.mjs").then(({ runAuthLink }) => runAuthLink(root, args.connectionId));
10
+ case "link": return import("./auth-link-BLO4ptzo.mjs").then(({ runAuthLink }) => runAuthLink(root, args.connectionId));
11
11
  case "logout":
12
12
  if (removeToken(root)) log.success("Logged out.");
13
13
  else log.info("Not logged in.");
@@ -1,8 +1,8 @@
1
1
  import { a as getApiUrl, c as getToken, d as openBrowser, g as savePlatformToken, h as runPlatformLogin } from "./auth-DLNN0D3Z.mjs";
2
- import { j as log } from "./dist-Dn6nn2IU.mjs";
3
- import { n as PlatformClient } from "./client-QTl6ko_D.mjs";
4
- import { r as selectPlatformLoginMethod } from "./login-DvqXsfGs.mjs";
5
- import { t as discoverPlatform } from "./platform-cmd-DNl8WosH.mjs";
2
+ import { j as log } from "./dist-CTBk70IR.mjs";
3
+ import { n as PlatformClient } from "./client-BTZ3XkrB.mjs";
4
+ import { r as selectPlatformLoginMethod } from "./login-CAsAsQ-_.mjs";
5
+ import { t as discoverPlatform } from "./platform-cmd-B3hwKrFK.mjs";
6
6
  import { execFile } from "node:child_process";
7
7
  //#region src/cli/auth-link.ts
8
8
  async function runAuthLink(root, connectionId) {
@@ -1,6 +1,6 @@
1
1
  import { o as listPlatformConnections } from "./platform-registry-QBa4DK32.mjs";
2
2
  import { i as readDeploymentPlatform } from "./project-C0Fqu05O.mjs";
3
- import { I as select, W as isCancel } from "./dist-Dn6nn2IU.mjs";
3
+ import { I as select, W as isCancel } from "./dist-CTBk70IR.mjs";
4
4
  //#region src/cli/auth-router.ts
5
5
  async function chooseDestination(root, args, interactive) {
6
6
  const saved = readDeploymentPlatform(root);
@@ -37,7 +37,7 @@ async function chooseDestination(root, args, interactive) {
37
37
  }
38
38
  async function runAuthRouter(root, args, interactive = Boolean(process.stdin.isTTY)) {
39
39
  if (args.subcommand === "link") {
40
- const { runAccountCommand } = await import("./account-cmd-DZZGK80W.mjs");
40
+ const { runAccountCommand } = await import("./account-cmd-CjyxcGkM.mjs");
41
41
  await runAccountCommand(root, {
42
42
  subcommand: "link",
43
43
  ...args.connectionId ? { connectionId: args.connectionId } : {}
@@ -45,17 +45,17 @@ async function runAuthRouter(root, args, interactive = Boolean(process.stdin.isT
45
45
  return;
46
46
  }
47
47
  if (args.subcommand === "token") {
48
- const { runAccountCommand } = await import("./account-cmd-DZZGK80W.mjs");
48
+ const { runAccountCommand } = await import("./account-cmd-CjyxcGkM.mjs");
49
49
  await runAccountCommand(root, { subcommand: "token" });
50
50
  return;
51
51
  }
52
52
  const destination = await chooseDestination(root, args, interactive);
53
53
  if (destination.platform === "cloudflare") {
54
- const { runCloudflareCommand } = await import("./cloudflare-cmd-bSmZ1d5L.mjs");
54
+ const { runCloudflareCommand } = await import("./cloudflare-cmd-BKlfGHAy.mjs");
55
55
  await runCloudflareCommand(root, { subcommand: args.subcommand === "whoami" || args.subcommand === "status" ? "status" : args.subcommand });
56
56
  return;
57
57
  }
58
- const { runAccountCommand } = await import("./account-cmd-DZZGK80W.mjs");
58
+ const { runAccountCommand } = await import("./account-cmd-CjyxcGkM.mjs");
59
59
  const subcommand = args.subcommand === "status" ? "whoami" : args.subcommand;
60
60
  if (!destination.apiUrl) {
61
61
  await runAccountCommand(root, { subcommand });
@@ -1,8 +1,8 @@
1
- import { a as dim, c as import_picocolors, r as cliTitle } from "./output-CCH48AMM.mjs";
2
1
  import { c as getToken } from "./auth-DLNN0D3Z.mjs";
3
2
  import { o as readProjectConfig } from "./project-C0Fqu05O.mjs";
4
- import { O as intro, P as outro, j as log } from "./dist-Dn6nn2IU.mjs";
5
- import { n as PlatformClient, t as PlatformApiError } from "./client-QTl6ko_D.mjs";
3
+ import { O as intro, P as outro, j as log } from "./dist-CTBk70IR.mjs";
4
+ import { n as PlatformClient, t as PlatformApiError } from "./client-BTZ3XkrB.mjs";
5
+ import { a as dim, c as import_picocolors, r as cliTitle } from "./output-Dm_A4Tbv.mjs";
6
6
  import { r as resolveProjectBySlug, t as getRequestedProjectSlug } from "./resolve-project-BG5ORGID.mjs";
7
7
  import { appendFileSync, writeFileSync } from "node:fs";
8
8
  //#region src/cli/build-cmd.ts
@@ -1,8 +1,8 @@
1
- import { a as dim, i as createSpinner, r as cliTitle } from "./output-CCH48AMM.mjs";
2
1
  import { c as getToken } from "./auth-DLNN0D3Z.mjs";
3
2
  import { o as readProjectConfig } from "./project-C0Fqu05O.mjs";
4
- import { O as intro, P as outro, j as log } from "./dist-Dn6nn2IU.mjs";
5
- import { n as PlatformClient } from "./client-QTl6ko_D.mjs";
3
+ import { O as intro, P as outro, j as log } from "./dist-CTBk70IR.mjs";
4
+ import { n as PlatformClient } from "./client-BTZ3XkrB.mjs";
5
+ import { a as dim, i as createSpinner, r as cliTitle } from "./output-Dm_A4Tbv.mjs";
6
6
  import { r as resolveProjectBySlug, t as getRequestedProjectSlug } from "./resolve-project-BG5ORGID.mjs";
7
7
  //#region src/cli/cache.ts
8
8
  async function runPurgeCacheCommand(root, projectSlug) {
@@ -1,8 +1,8 @@
1
- import { r as cliTitle } from "./output-CCH48AMM.mjs";
2
1
  import { c as getToken } from "./auth-DLNN0D3Z.mjs";
3
2
  import { o as readProjectConfig } from "./project-C0Fqu05O.mjs";
4
- import { E as confirm, O as intro, P as outro, W as isCancel, j as log } from "./dist-Dn6nn2IU.mjs";
5
- import { n as PlatformClient } from "./client-QTl6ko_D.mjs";
3
+ import { E as confirm, O as intro, P as outro, W as isCancel, j as log } from "./dist-CTBk70IR.mjs";
4
+ import { n as PlatformClient } from "./client-BTZ3XkrB.mjs";
5
+ import { r as cliTitle } from "./output-Dm_A4Tbv.mjs";
6
6
  //#region src/cli/cancel-deploy.ts
7
7
  const ACTIVE_STATUSES = /* @__PURE__ */ new Set([
8
8
  "pending",
@@ -1,9 +1,10 @@
1
1
  import { a as join, i as isAbsolute, l as relative, n as dirname, r as extname, t as basename, u as resolve } from "./dist-BVqXeR_h.mjs";
2
2
  import { copyFileSync, cpSync, existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, realpathSync, rmSync, symlinkSync, writeFileSync } from "node:fs";
3
- import { fileURLToPath, pathToFileURL } from "node:url";
3
+ import { fileURLToPath } from "node:url";
4
4
  import { build } from "vite";
5
+ import { randomUUID } from "node:crypto";
5
6
  import { tmpdir } from "node:os";
6
- import { spawnSync } from "node:child_process";
7
+ import { spawn, spawnSync } from "node:child_process";
7
8
  import { isDeepStrictEqual } from "node:util";
8
9
  import { getWorkerBundleDir, normalizeDirectoryName, readBuildOutput, writeAssets, writeContainerConfig, writeRootConfig, writeWorkerConfig } from "@cloudflare/build-output-utils";
9
10
  import { InputConfigSchema, OutputContainerSchema } from "@cloudflare/config";
@@ -111,14 +112,12 @@ function uncredentialedEnvironment() {
111
112
  env.CF_DELEGATION = "1";
112
113
  return env;
113
114
  }
114
- function migrationFollowUps(output) {
115
- return [...output.matchAll(/\[required\] ([^:\n]+): ([^\n]+)/g)].map((match) => ({
116
- path: match[1],
117
- message: match[2]
118
- }));
119
- }
120
- function assertHandledFollowUps(output) {
121
- for (const item of migrationFollowUps(output)) if (!(item.path === "assets.directory" && item.message.includes("assets directory") || /^d1_databases\.\d+$/.test(item.path) && /`migrations_(?:dir|table)`/.test(item.message) || /^durable_objects\.bindings\.\d+$/.test(item.path) || item.path === "migrations" || item.path === "containers")) throw new Error(`cf cannot migrate Cloudflare setting ${item.path}: ${item.message}`);
115
+ function assertHandledFollowUps(followUps) {
116
+ for (const item of followUps) {
117
+ if (!item.blocking) continue;
118
+ const path = item.sourcePath ?? item.code;
119
+ if (!(path === "assets.directory" && item.message.includes("assets directory") || /^d1_databases\.\d+$/.test(path) && /`migrations_(?:dir|table)`/.test(item.message) || /^durable_objects\.bindings\.\d+$/.test(path) || path === "migrations" || path === "containers")) throw new Error(`cf cannot migrate Cloudflare setting ${path}: ${item.message}`);
120
+ }
122
121
  }
123
122
  function durableObjectExports(raw) {
124
123
  const migrations = raw.migrations;
@@ -172,8 +171,14 @@ function containersFromWrangler(raw, exports) {
172
171
  if (values === void 0) return [];
173
172
  if (!Array.isArray(values) || !values.every((value) => record(value))) throw new Error("Invalid Containers in the built Cloudflare config.");
174
173
  return values.map((value) => {
175
- if (typeof value.name !== "string" || typeof value.class_name !== "string" || typeof value.image !== "string") throw new Error("cf requires a name, class_name and image for each Container.");
176
- const fields = /* @__PURE__ */ new Set([
174
+ if (typeof value.name !== "string" || typeof value.class_name !== "string") throw new Error("cf requires a name and class_name for each Container.");
175
+ const managed = value.scheduling_policy === "durable_object";
176
+ const fields = new Set(managed ? [
177
+ "name",
178
+ "class_name",
179
+ "scheduling_policy",
180
+ "images"
181
+ ] : [
177
182
  "name",
178
183
  "class_name",
179
184
  "image",
@@ -184,23 +189,59 @@ function containersFromWrangler(raw, exports) {
184
189
  const declaration = record(exports[value.class_name]);
185
190
  if (!declaration || declaration.storage !== "sqlite") throw new Error(`Container ${value.name} needs a SQLite Durable Object export.`);
186
191
  declaration.container = value.name;
192
+ if (managed) {
193
+ const images = record(value.images);
194
+ if (!images) throw new Error("A Sandbox requires a named image.");
195
+ return {
196
+ name: value.name,
197
+ schedulingPolicy: "durable-object",
198
+ images: Object.fromEntries(Object.entries(images).map(([name, image]) => {
199
+ const source = record(image);
200
+ if (!source || Object.keys(source).some((key) => ![
201
+ "dockerfile",
202
+ "build_context",
203
+ "image"
204
+ ].includes(key)) || source.dockerfile !== void 0 && source.image !== void 0 || source.build_context !== void 0 && typeof source.build_context !== "string") throw new Error("Invalid Sandbox image.");
205
+ if (typeof source.dockerfile === "string") return [name, {
206
+ dockerfile: source.dockerfile,
207
+ ...typeof source.build_context === "string" ? { buildContext: source.build_context } : {}
208
+ }];
209
+ if (typeof source.image === "string") return [name, { reference: source.image }];
210
+ throw new Error("Invalid Sandbox image source.");
211
+ }))
212
+ };
213
+ }
214
+ if (typeof value.image !== "string") throw new Error("A Container requires an image.");
187
215
  return {
188
216
  name: value.name,
189
- schedulingPolicy: "durable-object",
190
- images: { default: { reference: value.image } },
217
+ image: { reference: value.image },
191
218
  ...typeof value.max_instances === "number" ? { maxInstances: value.max_instances } : {},
192
219
  ...typeof value.instance_type === "string" ? { instanceType: value.instance_type } : {}
193
220
  };
194
221
  });
195
222
  }
196
- /**
197
- * Ask the pinned cf CLI to translate the Vite plugin's generated JSON config.
198
- * Migration runs on a disposable copy without Cloudflare credentials; its
199
- * generated module is evaluated in a second uncredentialed Node process.
200
- */
223
+ const migrationScript = String.raw`
224
+ import { readFileSync, writeFileSync } from 'node:fs';
225
+ import { dirname, join } from 'node:path';
226
+ import { pathToFileURL } from 'node:url';
227
+ const { migrateWranglerToCf } = await import(process.argv[1]);
228
+ const configPath = process.argv[2];
229
+ const migration = await migrateWranglerToCf(configPath, {
230
+ bundler: 'vite', force: true, installDependencies: false,
231
+ });
232
+ const directory = dirname(configPath);
233
+ const generated = readFileSync(join(directory, 'cloudflare.config.ts'), 'utf8');
234
+ const executable = generated.replace(/^throw new Error\("Migration incomplete\.[^\n]*\);\s*$/m, '');
235
+ if (executable === generated && migration.status !== 'complete') {
236
+ throw new Error('cf did not provide a usable Cloudflare configuration.');
237
+ }
238
+ const executablePath = join(directory, 'cloudflare.config.mjs');
239
+ writeFileSync(executablePath, executable, { mode: 0o600 });
240
+ const config = (await import(pathToFileURL(executablePath).href)).default;
241
+ process.stdout.write(JSON.stringify({ config, followUps: migration.followUps }));
242
+ `;
201
243
  function migrateBuiltWranglerConfig(raw) {
202
244
  const cfPackage = fileURLToPath(import.meta.resolve("cf/package.json"));
203
- const cfBinary = join(dirname(cfPackage), "bin", "cf");
204
245
  const directory = mkdtempSync(join(tmpdir(), "void-cf-config-"));
205
246
  try {
206
247
  mkdirSync(join(directory, "node_modules"));
@@ -216,44 +257,23 @@ function migrateBuiltWranglerConfig(raw) {
216
257
  }), { mode: 384 });
217
258
  const configPath = join(directory, "wrangler.json");
218
259
  writeFileSync(configPath, JSON.stringify(migrationInput(raw)), { mode: 384 });
219
- const env = uncredentialedEnvironment();
220
260
  const migrated = spawnSync(process.execPath, [
221
- cfBinary,
222
- "migrate",
223
- configPath,
224
- "--bundler",
225
- "vite",
226
- "--no-install",
227
- "--force"
228
- ], {
229
- cwd: directory,
230
- env,
231
- encoding: "utf8",
232
- timeout: 3e4,
233
- maxBuffer: 4194304
234
- });
235
- const generatedPath = join(directory, "cloudflare.config.ts");
236
- if (!existsSync(generatedPath) || migrated.error) throw new Error("cf could not translate the built Cloudflare configuration.");
237
- assertHandledFollowUps(migrated.stdout);
238
- const generated = readFileSync(generatedPath, "utf8");
239
- const executable = generated.replace(/^throw new Error\("Migration incomplete\.[^\n]*\);\s*$/m, "");
240
- if (executable === generated && migrated.status !== 0) throw new Error("cf did not provide a usable Cloudflare configuration.");
241
- const executablePath = join(directory, "cloudflare.config.mjs");
242
- writeFileSync(executablePath, executable, { mode: 384 });
243
- const evaluated = spawnSync(process.execPath, [
244
261
  "--input-type=module",
245
262
  "-e",
246
- "const mod = await import(process.argv[1]); process.stdout.write(JSON.stringify(mod.default));",
247
- pathToFileURL(executablePath).href
263
+ migrationScript,
264
+ import.meta.resolve("@cloudflare/codemods"),
265
+ configPath
248
266
  ], {
249
267
  cwd: directory,
250
- env,
268
+ env: uncredentialedEnvironment(),
251
269
  encoding: "utf8",
252
- timeout: 1e4,
270
+ timeout: 3e4,
253
271
  maxBuffer: 4194304
254
272
  });
255
- if (evaluated.status !== 0 || evaluated.error) throw new Error("cf generated a configuration that Void could not validate.");
256
- const result = record(JSON.parse(evaluated.stdout));
273
+ if (migrated.status !== 0 || migrated.error) throw new Error("cf could not translate the built Cloudflare configuration.");
274
+ const migration = JSON.parse(migrated.stdout);
275
+ assertHandledFollowUps(migration.followUps);
276
+ const result = record(migration.config);
257
277
  const worker = record(result?.worker);
258
278
  if (!result || !worker) throw new Error("cf did not generate a Worker configuration.");
259
279
  applyPreservationFlags(raw, worker);
@@ -288,6 +308,37 @@ function migrateBuiltWranglerConfig(raw) {
288
308
  }
289
309
  }
290
310
  //#endregion
311
+ //#region src/cli/container-image.ts
312
+ function docker(args, quiet = false) {
313
+ return new Promise((resolve, reject) => {
314
+ const child = spawn(process.env.WRANGLER_DOCKER_BIN ?? "docker", args, { stdio: quiet ? "ignore" : "inherit" });
315
+ child.once("error", reject);
316
+ child.once("exit", (code) => code === 0 ? resolve() : reject(/* @__PURE__ */ new Error("Sandbox image preparation failed. Start Docker and retry the deployment.")));
317
+ });
318
+ }
319
+ /** Build locally; the pinned cf uploader pushes this tag to the managed registry. */
320
+ async function buildContainerImage(dockerfile, buildContext = dirname(dockerfile)) {
321
+ const localReference = `void-sandbox-build:${randomUUID()}`;
322
+ await docker([
323
+ "build",
324
+ "--platform",
325
+ "linux/amd64",
326
+ "--file",
327
+ dockerfile,
328
+ "--tag",
329
+ localReference,
330
+ buildContext
331
+ ]);
332
+ return {
333
+ localReference,
334
+ dispose: () => docker([
335
+ "image",
336
+ "rm",
337
+ localReference
338
+ ], true).catch(() => {})
339
+ };
340
+ }
341
+ //#endregion
291
342
  //#region src/cli/cf-build-output.ts
292
343
  function object(value) {
293
344
  return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
@@ -298,6 +349,11 @@ const moduleTypes = {
298
349
  ".cjs": "cjs",
299
350
  ".wasm": "wasm",
300
351
  ".bin": "data",
352
+ ".woff": "data",
353
+ ".woff2": "data",
354
+ ".ttf": "data",
355
+ ".otf": "data",
356
+ ".eot": "data",
301
357
  ".txt": "text",
302
358
  ".html": "text",
303
359
  ".sql": "text",
@@ -320,7 +376,7 @@ function copyBundle(source, destination) {
320
376
  const name = relative(source, absolute);
321
377
  if (name === "wrangler.json" || name === ".dev.vars" || name === join(".vite", "manifest.json") || name.endsWith(".css") || name.endsWith(".css.map")) continue;
322
378
  const type = moduleTypes[extname(entry.name).toLowerCase()];
323
- if (!type) return null;
379
+ if (!type) throw new Error(`The built Worker contains an unsupported module ${JSON.stringify(name)}. Emit public assets into the client output or configure the plugin that produced this file to run only in the client environment.`);
324
380
  const destinationPath = join(destination, name);
325
381
  mkdirSync(dirname(destinationPath), { recursive: true });
326
382
  if (entry.isSymbolicLink()) copyFileSync(realpathSync(absolute), destinationPath);
@@ -337,10 +393,14 @@ async function prepareCfBuildOutput(workerDirectory, accountId) {
337
393
  if (typeof raw.account_id === "string" && raw.account_id !== accountId) return null;
338
394
  const config = migrateBuiltWranglerConfig(raw);
339
395
  if (!config.worker) throw new Error("cf did not produce a Worker configuration.");
340
- const main = raw.main;
341
- if (typeof main !== "string" || basename(main) !== main || !existsSync(join(source, main))) return null;
396
+ if (typeof raw.main !== "string" || !raw.main) throw new Error("The built Worker configuration is missing its main entry. Rebuild the app.");
397
+ const entry = raw.main.replaceAll("\\", "/");
398
+ const main = relative(source, resolve(source, entry));
399
+ if (isAbsolute(entry) || /^[a-z]:/i.test(entry) || !main || main === ".." || main.startsWith("../")) throw new Error("The built Worker main entry must be inside its output directory.");
400
+ if (!existsSync(join(source, main))) throw new Error(`The built Worker main entry ${JSON.stringify(main)} is missing. Rebuild the app.`);
342
401
  const assetsDirectory = object(raw.assets)?.directory;
343
402
  if (assetsDirectory !== void 0 && typeof assetsDirectory !== "string") return null;
403
+ const images = [];
344
404
  const directory = mkdtempSync(join(tmpdir(), "void-cf-deploy-"));
345
405
  try {
346
406
  const bundle = getWorkerBundleDir(directory);
@@ -366,11 +426,23 @@ async function prepareCfBuildOutput(workerDirectory, accountId) {
366
426
  modules
367
427
  }
368
428
  });
369
- for (const container of config.containers ?? []) await writeContainerConfig({
370
- root: directory,
371
- config: OutputContainerSchema.parse(container),
372
- directoryName: normalizeDirectoryName(container.name)
373
- });
429
+ for (const container of config.containers ?? []) {
430
+ const builtContainer = { ...container };
431
+ if ("images" in container && container.images) {
432
+ const prepared = {};
433
+ for (const [name, image] of Object.entries(container.images)) if ("dockerfile" in image) {
434
+ const built = await buildContainerImage(resolve(source, image.dockerfile), image.buildContext ? resolve(source, image.buildContext) : void 0);
435
+ images.push(built);
436
+ prepared[name] = { localReference: built.localReference };
437
+ } else prepared[name] = image;
438
+ builtContainer.images = prepared;
439
+ }
440
+ await writeContainerConfig({
441
+ root: directory,
442
+ config: OutputContainerSchema.parse(builtContainer),
443
+ directoryName: normalizeDirectoryName(container.name)
444
+ });
445
+ }
374
446
  if (typeof assetsDirectory === "string") {
375
447
  const assetPath = resolve(source, assetsDirectory);
376
448
  if (!existsSync(assetPath)) {
@@ -378,6 +450,7 @@ async function prepareCfBuildOutput(workerDirectory, accountId) {
378
450
  recursive: true,
379
451
  force: true
380
452
  });
453
+ await Promise.all(images.map((image) => image.dispose()));
381
454
  return null;
382
455
  }
383
456
  await writeAssets({
@@ -389,16 +462,20 @@ async function prepareCfBuildOutput(workerDirectory, accountId) {
389
462
  return {
390
463
  directory,
391
464
  ...typeof assetsDirectory === "string" ? { assetsDirectory: resolve(source, assetsDirectory) } : {},
392
- dispose: () => rmSync(directory, {
393
- recursive: true,
394
- force: true
395
- })
465
+ dispose: async () => {
466
+ rmSync(directory, {
467
+ recursive: true,
468
+ force: true
469
+ });
470
+ await Promise.all(images.map((image) => image.dispose()));
471
+ }
396
472
  };
397
473
  } catch (error) {
398
474
  rmSync(directory, {
399
475
  recursive: true,
400
476
  force: true
401
477
  });
478
+ await Promise.all(images.map((image) => image.dispose()));
402
479
  throw error;
403
480
  }
404
481
  }