void 0.10.12 → 0.10.13

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 (28) hide show
  1. package/dist/cli/cli.mjs +10 -10
  2. package/dist/{config-BkTvs43g.mjs → config-qHGgPuWT.mjs} +10 -0
  3. package/dist/{db-DOiJMRt2.mjs → db-C0i0sYMS.mjs} +3 -3
  4. package/dist/{deploy-u7Rv9q_q.mjs → deploy-jBJT1fUT.mjs} +227 -21
  5. package/dist/{gen-o_w-8yI8.mjs → gen-BzXf3Jh2.mjs} +1 -1
  6. package/dist/{headers-nsHIFixA.mjs → headers-ChAADPQu.mjs} +1 -1
  7. package/dist/index.mjs +49 -39
  8. package/dist/{init-3rgHKBVi.mjs → init-7JCAcKNQ.mjs} +1 -1
  9. package/dist/{node-Da0UcsGA.mjs → node-pRg81HqV.mjs} +3 -3
  10. package/dist/pages/index.mjs +3 -3
  11. package/dist/pages/islands-plugin.mjs +1 -1
  12. package/dist/{prepare-BoKHgMNx.mjs → prepare-BvvgAz-3.mjs} +3 -3
  13. package/dist/{provision-rShh6MKY.mjs → provision-CPx2ZxsH.mjs} +1 -1
  14. package/dist/{route-types-COI2DsZv.mjs → route-types-z1jtHEi_.mjs} +8 -1
  15. package/dist/{scan-DYXkrasO.mjs → scan-ChWt4pX1.mjs} +12 -13
  16. package/dist/{scan-DEwlM_Xy.mjs → scan-NU4xKGci.mjs} +4 -1
  17. package/package.json +2 -2
  18. package/schema.json +13 -0
  19. package/skills/migrate-vite-cloudflare-to-void/SKILL.md +1 -1
  20. package/skills/void/docs/guide/deployment.md +68 -1
  21. package/skills/void/docs/guide/edge/static-assets.md +15 -2
  22. package/skills/void/docs/guide/server-routing.md +21 -1
  23. package/skills/void/docs/guide/websockets.md +3 -0
  24. package/skills/void/docs/node_modules/void/CLAUDE.md +3 -1
  25. package/skills/void/docs/node_modules/void/skills/migrate-vite-cloudflare-to-void/SKILL.md +1 -1
  26. package/skills/void/docs/reference/cli.md +24 -0
  27. package/skills/void/docs/reference/config.md +15 -0
  28. package/skills/void/docs/reference/structure.md +1 -0
package/dist/cli/cli.mjs CHANGED
@@ -2078,7 +2078,7 @@ else if (command === "deploy") {
2078
2078
  log.error(err instanceof Error ? err.message : String(err));
2079
2079
  process.exit(1);
2080
2080
  }
2081
- import("../deploy-u7Rv9q_q.mjs").then((n) => n.t).then(({ runDeploy }) => {
2081
+ import("../deploy-jBJT1fUT.mjs").then((n) => n.t).then(({ runDeploy }) => {
2082
2082
  runDeploy(root, {
2083
2083
  projectSlug: deployArgs.projectSlug,
2084
2084
  dir: deployArgs.dir,
@@ -2096,9 +2096,9 @@ else if (command === "deploy") {
2096
2096
  else if (command === "project") runSubcommandGroup("project", projectSubcommands, parseProjectArgs, (root, parsed) => import("../project-cmd-D_w-4w5B.mjs").then(({ runProjectCommand }) => runProjectCommand(root, parsed)));
2097
2097
  else if (command === "secret") runSubcommandGroup("secret", secretSubcommands, parseSecretArgs, (root, parsed) => import("../secret-Dt32J6RI.mjs").then(({ runSecretCommand }) => runSecretCommand(root, parsed)));
2098
2098
  else if (command === "domain") runSubcommandGroup("domain", domainSubcommands, parseDomainArgs, (root, parsed) => import("../domain-DiaNQbrl.mjs").then(({ runDomainCommand }) => runDomainCommand(root, parsed)));
2099
- else if (command === "db") runSubcommandGroup("db", dbSubcommands, parseDbArgs, (root, parsed) => import("../db-DOiJMRt2.mjs").then(({ runDbCommand }) => runDbCommand(root, parsed)));
2099
+ else if (command === "db") runSubcommandGroup("db", dbSubcommands, parseDbArgs, (root, parsed) => import("../db-C0i0sYMS.mjs").then(({ runDbCommand }) => runDbCommand(root, parsed)));
2100
2100
  else if (command === "env") runSubcommandGroup("env", envSubcommands, parseEnvArgs, (root, parsed) => import("../env-CZy5MorI.mjs").then(({ runEnvCommand }) => runEnvCommand(root, parsed)));
2101
- else if (command === "gen") runSubcommandGroup("gen", genSubcommands, parseGenArgs, (root, parsed) => import("../gen-o_w-8yI8.mjs").then(({ runGenCommand }) => runGenCommand(root, parsed)));
2101
+ else if (command === "gen") runSubcommandGroup("gen", genSubcommands, parseGenArgs, (root, parsed) => import("../gen-BzXf3Jh2.mjs").then(({ runGenCommand }) => runGenCommand(root, parsed)));
2102
2102
  else if (command === "github") runSubcommandGroup("github", githubSubcommands, parseGithubArgs, (root, parsed) => import("../github-cmd-DKcGUNsj.mjs").then(({ runGithubCommand }) => runGithubCommand(root, parsed)));
2103
2103
  else if (command === "build") runSubcommandGroup("build", buildSubcommands, parseBuildArgs, (root, parsed) => import("../build-cmd-Bujrv5q-.mjs").then(({ runBuildCommand }) => runBuildCommand(root, parsed)));
2104
2104
  else if (command === "prepare") {
@@ -2110,7 +2110,7 @@ else if (command === "prepare") {
2110
2110
  log.error(err instanceof Error ? err.message : String(err));
2111
2111
  process.exit(1);
2112
2112
  }
2113
- import("../prepare-BoKHgMNx.mjs").then(({ runPrepareCommand }) => {
2113
+ import("../prepare-BvvgAz-3.mjs").then(({ runPrepareCommand }) => {
2114
2114
  runPrepareCommand(root, prepareArgs).catch((err) => {
2115
2115
  log.error(err.message ?? err);
2116
2116
  process.exit(1);
@@ -2118,7 +2118,7 @@ else if (command === "prepare") {
2118
2118
  });
2119
2119
  } else if (command === "init") {
2120
2120
  const root = process.cwd();
2121
- import("../init-3rgHKBVi.mjs").then(({ runInitCommand, parseInitArgs }) => {
2121
+ import("../init-7JCAcKNQ.mjs").then(({ runInitCommand, parseInitArgs }) => {
2122
2122
  let initArgs;
2123
2123
  try {
2124
2124
  initArgs = parseInitArgs(args.slice(1));
@@ -2217,12 +2217,12 @@ else if (command === "-v" || command === "--version") {
2217
2217
  const root = process.cwd();
2218
2218
  switch (cmd) {
2219
2219
  case "init": {
2220
- const { runInitCommand, parseInitArgs } = await import("../init-3rgHKBVi.mjs");
2220
+ const { runInitCommand, parseInitArgs } = await import("../init-7JCAcKNQ.mjs");
2221
2221
  await runInitCommand(root, parseInitArgs([]));
2222
2222
  return;
2223
2223
  }
2224
2224
  case "deploy": {
2225
- const { runDeploy } = await import("../deploy-u7Rv9q_q.mjs").then((n) => n.t);
2225
+ const { runDeploy } = await import("../deploy-jBJT1fUT.mjs").then((n) => n.t);
2226
2226
  await runDeploy(root);
2227
2227
  return;
2228
2228
  }
@@ -2237,11 +2237,11 @@ else if (command === "-v" || command === "--version") {
2237
2237
  case "domain": return runSubcommandGroup("domain", domainSubcommands, parseDomainArgs, (r, p) => import("../domain-DiaNQbrl.mjs").then(({ runDomainCommand }) => runDomainCommand(r, p)));
2238
2238
  case "github": return runSubcommandGroup("github", githubSubcommands, parseGithubArgs, (r, p) => import("../github-cmd-DKcGUNsj.mjs").then(({ runGithubCommand }) => runGithubCommand(r, p)));
2239
2239
  case "build": return runSubcommandGroup("build", buildSubcommands, parseBuildArgs, (r, p) => import("../build-cmd-Bujrv5q-.mjs").then(({ runBuildCommand }) => runBuildCommand(r, p)));
2240
- case "db": return runSubcommandGroup("db", dbSubcommands, parseDbArgs, (r, p) => import("../db-DOiJMRt2.mjs").then(({ runDbCommand }) => runDbCommand(r, p)));
2240
+ case "db": return runSubcommandGroup("db", dbSubcommands, parseDbArgs, (r, p) => import("../db-C0i0sYMS.mjs").then(({ runDbCommand }) => runDbCommand(r, p)));
2241
2241
  case "env": return runSubcommandGroup("env", envSubcommands, parseEnvArgs, (r, p) => import("../env-CZy5MorI.mjs").then(({ runEnvCommand }) => runEnvCommand(r, p)));
2242
- case "gen": return runSubcommandGroup("gen", genSubcommands, parseGenArgs, (r, p) => import("../gen-o_w-8yI8.mjs").then(({ runGenCommand }) => runGenCommand(r, p)));
2242
+ case "gen": return runSubcommandGroup("gen", genSubcommands, parseGenArgs, (r, p) => import("../gen-BzXf3Jh2.mjs").then(({ runGenCommand }) => runGenCommand(r, p)));
2243
2243
  case "prepare": {
2244
- const { runPrepareCommand } = await import("../prepare-BoKHgMNx.mjs");
2244
+ const { runPrepareCommand } = await import("../prepare-BvvgAz-3.mjs");
2245
2245
  await runPrepareCommand(root, parsePrepareArgs([]));
2246
2246
  return;
2247
2247
  }
@@ -58,6 +58,8 @@ const VALID_REDIRECT_STATUSES = /* @__PURE__ */ new Set([
58
58
  308
59
59
  ]);
60
60
  const VALID_DATABASE_VALUES = /* @__PURE__ */ new Set(["pg"]);
61
+ /** Cloudflare's hard maximum for Workers CPU time per request (5 minutes). */
62
+ const MAX_WORKER_CPU_MS = 3e5;
61
63
  const VALID_SANDBOX_INSTANCE_TYPES = /* @__PURE__ */ new Set([
62
64
  "dev",
63
65
  "lite",
@@ -439,6 +441,14 @@ function readConfig(root) {
439
441
  if (typeof w.vars !== "object" || w.vars === null || Array.isArray(w.vars)) throw new Error(`config: "worker.vars" in ${CONFIG_FILE} must be an object.`);
440
442
  for (const [key, value] of Object.entries(w.vars)) if (typeof value !== "string") throw new Error(`config: "worker.vars.${key}" in ${CONFIG_FILE} must be a string.`);
441
443
  }
444
+ if (w.limits !== void 0) {
445
+ if (typeof w.limits !== "object" || w.limits === null || Array.isArray(w.limits)) throw new Error(`config: "worker.limits" in ${CONFIG_FILE} must be an object.`);
446
+ const limits = w.limits;
447
+ for (const key of Object.keys(limits)) if (key !== "cpu_ms") throw new Error(`config: Unknown key 'worker.limits.${key}' in ${CONFIG_FILE}. Valid: cpu_ms.`);
448
+ if (limits.cpu_ms !== void 0) {
449
+ if (typeof limits.cpu_ms !== "number" || !Number.isInteger(limits.cpu_ms) || limits.cpu_ms < 1 || limits.cpu_ms > MAX_WORKER_CPU_MS) throw new Error(`config: "worker.limits.cpu_ms" in ${CONFIG_FILE} must be an integer between 1 and ${MAX_WORKER_CPU_MS}.`);
450
+ }
451
+ }
442
452
  }
443
453
  if (obj.database !== void 0) {
444
454
  if (typeof obj.database !== "string" || !VALID_DATABASE_VALUES.has(obj.database)) throw new Error(`config: "database" in ${CONFIG_FILE} must be "pg".`);
@@ -3,11 +3,11 @@ import { D as outro, S as confirm, T as log, a as cliTitle, j as isCancel, s as
3
3
  import { n as readProjectPaths } from "./project-paths-BQd7OmIo.mjs";
4
4
  import { t as cfAccessHeaders } from "./cf-access-Bqw81xAf.mjs";
5
5
  import { b as readProjectConfig, f as getToken, m as isStagingMode, n as PlatformClient, t as PlatformApiError } from "./client-Gb71-XkG.mjs";
6
- import { c as getDatabaseDialect, f as readConfig, p as resolveBindingNames } from "./config-BkTvs43g.mjs";
6
+ import { c as getDatabaseDialect, f as readConfig, p as resolveBindingNames } from "./config-qHGgPuWT.mjs";
7
7
  import { r as detectFramework } from "./plugin-inference-DMeavIJ6.mjs";
8
8
  import { c as collectMigrations, d as stripSqlExt, f as writeJournal, n as listDrizzleArtifacts, r as validateMigrations, t as assertJournalCoherence, u as readJournal } from "./validate-Cw_RLeTj.mjs";
9
9
  import { n as STAGING_PROXY_URL, t as DEFAULT_PROXY_URL } from "./proxy-D-3_D-Gl.mjs";
10
- import { formatTimestamp } from "./gen-o_w-8yI8.mjs";
10
+ import { formatTimestamp } from "./gen-BzXf3Jh2.mjs";
11
11
  import { existsSync, readFileSync, readdirSync, renameSync, rmSync, writeFileSync } from "node:fs";
12
12
  import { fileURLToPath, pathToFileURL } from "node:url";
13
13
  import { execFileSync } from "node:child_process";
@@ -947,7 +947,7 @@ async function runExport(root, args, dialect) {
947
947
  }
948
948
  }
949
949
  async function runSetUrl(root) {
950
- const { readConfig: readVoidConfig, getDatabaseDialect: getDialect } = await import("./config-BkTvs43g.mjs").then((n) => n.n);
950
+ const { readConfig: readVoidConfig, getDatabaseDialect: getDialect } = await import("./config-qHGgPuWT.mjs").then((n) => n.n);
951
951
  if (getDialect(readVoidConfig(root)) !== "postgresql") {
952
952
  log.error("db: This command is only for PostgreSQL projects. Set \"database\": \"pg\" in void.json.");
953
953
  process.exit(1);
@@ -1,11 +1,11 @@
1
- import { n as __exportAll } from "./rolldown-runtime-DJK8HYOj.mjs";
1
+ import { n as __exportAll, r as __toESM } from "./rolldown-runtime-DJK8HYOj.mjs";
2
2
  import { a as join, c as resolve, i as isAbsolute, n as dirname, o as normalize, r as extname, s as relative, t as basename } from "./dist-DaKKDf8D.mjs";
3
- import { D as outro, E as note, S as confirm, T as log, a as cliTitle, j as isCancel, o as createSpinner, u as import_picocolors, w as intro } from "./agents-CtgBYqld.mjs";
3
+ import { D as outro, E as note, M as require_picocolors, S as confirm, T as log, a as cliTitle, j as isCancel, o as createSpinner, u as import_picocolors$1, w as intro } from "./agents-CtgBYqld.mjs";
4
4
  import { i as resolveProjectPaths, n as readProjectPaths, t as assertNoRootSourceConventionConflicts } from "./project-paths-BQd7OmIo.mjs";
5
- import { a as scanQueuesSync, i as scanWebSocketRoutesSync, o as scanJobsSync, r as scanRoutes, s as findVoidAuthConfig } from "./scan-DYXkrasO.mjs";
5
+ import { a as scanQueuesSync, i as scanWebSocketRoutesSync, o as scanJobsSync, r as scanRoutes, s as findVoidAuthConfig } from "./scan-ChWt4pX1.mjs";
6
6
  import { t as cfAccessHeaders } from "./cf-access-Bqw81xAf.mjs";
7
7
  import { C as ensureCloudflaredToken, S as writeProjectConfig, a as isExpiredTokenError, b as readProjectConfig, f as getToken, i as isCliOutdatedError, m as isStagingMode, n as PlatformClient, o as parsePlatformErrorBody, p as getTokenSource, t as PlatformApiError, u as getApiUrl } from "./client-Gb71-XkG.mjs";
8
- import { c as getDatabaseDialect, f as readConfig, l as isNodeTarget, p as resolveBindingNames } from "./config-BkTvs43g.mjs";
8
+ import { c as getDatabaseDialect, f as readConfig, l as isNodeTarget, p as resolveBindingNames } from "./config-qHGgPuWT.mjs";
9
9
  import { i as inferProjectBindings, n as FRAMEWORK_SCAN_DIRS, r as detectFramework } from "./plugin-inference-DMeavIJ6.mjs";
10
10
  import { o as validateSsrEntry } from "./entry-D7yy4xVH.mjs";
11
11
  import { i as voidWarn, r as voidLog } from "./log-ChfPKsVd.mjs";
@@ -15,12 +15,12 @@ import { t as findEnvFile } from "./env-types-QBj-ndax.mjs";
15
15
  import { a as collectPlaintextVarWarningsFromVars, d as getDeployEnvDefaults, f as readEmittedWorkerVars, i as SelfHostSecretListError, l as fetchRemoteSecretNames, m as validateProdEnv, n as SelfHostFirstDeployError, o as deriveSelfHostEnvContextFromVars, p as selfHostSchemaFailureMessage, r as SelfHostSchemaError, s as dischargeSelfHostEnvContext, t as SelfHostEnvValidationError, u as formatEnvReport } from "./env-validation-Dea3v3ej.mjs";
16
16
  import { n as writeDrizzleConfig } from "./config-CutEMNGJ.mjs";
17
17
  import { a as buildMigrationPlanBundle, c as collectMigrations, r as validateMigrations, t as assertJournalCoherence } from "./validate-Cw_RLeTj.mjs";
18
- import { t as scanPages } from "./scan-DEwlM_Xy.mjs";
18
+ import { t as scanPages } from "./scan-NU4xKGci.mjs";
19
19
  import { n as STAGING_PROXY_URL, t as DEFAULT_PROXY_URL } from "./proxy-D-3_D-Gl.mjs";
20
20
  import { i as promptProjectSetupAction, n as promptAndCreateProject, r as promptProjectSelection } from "./create-project-DsYvl3TB.mjs";
21
21
  import { r as resolveProjectBySlug, t as getRequestedProjectSlug } from "./resolve-project-BBMtLLV9.mjs";
22
22
  import { t as collectGitDeployMetadata } from "./git-metadata-D-gurjzG.mjs";
23
- import { n as lintDuplicateSources, r as mergeRoutingRules, t as lintDestinationSplats } from "./headers-nsHIFixA.mjs";
23
+ import { n as lintDuplicateSources, r as mergeRoutingRules, t as lintDestinationSplats } from "./headers-ChAADPQu.mjs";
24
24
  import { t as promptForLoginToken } from "./login-BT3H8PN3.mjs";
25
25
  import { createRequire } from "node:module";
26
26
  import { copyFileSync, cpSync, createWriteStream, existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, renameSync, rmSync, unlinkSync, writeFileSync } from "node:fs";
@@ -2115,7 +2115,7 @@ async function uploadOne(item, cliLog, fetchImpl) {
2115
2115
  path: item.path,
2116
2116
  attempt: attempt + 1,
2117
2117
  status: res.status,
2118
- body: truncate(errBody)
2118
+ body: truncate$1(errBody)
2119
2119
  });
2120
2120
  await sleep(RETRY_BACKOFF_MS[attempt]);
2121
2121
  attempt++;
@@ -2126,9 +2126,9 @@ async function uploadOne(item, cliLog, fetchImpl) {
2126
2126
  path: item.path,
2127
2127
  durationMs: Date.now() - startedAt,
2128
2128
  status: res.status,
2129
- body: truncate(errBody)
2129
+ body: truncate$1(errBody)
2130
2130
  });
2131
- throw new DirectR2PutError(res.status, item.hash, item.path, truncate(errBody));
2131
+ throw new DirectR2PutError(res.status, item.hash, item.path, truncate$1(errBody));
2132
2132
  }
2133
2133
  }
2134
2134
  async function safeReadText(res) {
@@ -2138,7 +2138,7 @@ async function safeReadText(res) {
2138
2138
  return "";
2139
2139
  }
2140
2140
  }
2141
- function truncate(s) {
2141
+ function truncate$1(s) {
2142
2142
  return s.length > 500 ? `${s.slice(0, 500)}...` : s;
2143
2143
  }
2144
2144
  function sleep(ms) {
@@ -2270,6 +2270,23 @@ async function safeText(res) {
2270
2270
  //#endregion
2271
2271
  //#region src/cli/log-file.ts
2272
2272
  /**
2273
+ * Flatten an already-serialized `ErrChainNode` (as read back out of a JSONL
2274
+ * record) to a single inline string. Mirrors `formatErrorChainInline`, which
2275
+ * does the same job for a live `Error` before it is written.
2276
+ */
2277
+ function formatErrorNodeInline(node, depth = 0) {
2278
+ if (node == null || typeof node !== "object") return String(node);
2279
+ const message = node.message == null ? "" : String(node.message);
2280
+ if (depth > 5) return message;
2281
+ let head = node.name ? `${String(node.name)}: ${message}` : message;
2282
+ const tags = [];
2283
+ if (node.code !== void 0) tags.push(`code=${node.code}`);
2284
+ if (node.errno !== void 0) tags.push(`errno=${node.errno}`);
2285
+ if (tags.length > 0) head = `${head} (${tags.join(" ")})`;
2286
+ if (node.cause != null) return `${head} -> ${formatErrorNodeInline(node.cause, depth + 1)}`;
2287
+ return head;
2288
+ }
2289
+ /**
2273
2290
  * Walk `err.cause` up to 6 levels and return a plain JSON-friendly chain.
2274
2291
  * Skips stack traces deliberately — keeps output line-oriented and readable.
2275
2292
  */
@@ -2422,6 +2439,160 @@ function openDeployLog(opts) {
2422
2439
  };
2423
2440
  }
2424
2441
  //#endregion
2442
+ //#region src/cli/log-summary.ts
2443
+ var import_picocolors = /* @__PURE__ */ __toESM(require_picocolors(), 1);
2444
+ const FIELD_VALUE_MAX = 80;
2445
+ const LINE_MAX = 160;
2446
+ const MSG_COLUMN_MAX = 28;
2447
+ const ELAPSED_WIDTH = 7;
2448
+ const LEVEL_WIDTH = 5;
2449
+ /** Width of `' ' + elapsed + ' '`, used to indent the error sub-lines. */
2450
+ const DETAIL_INDENT = " ".repeat(11);
2451
+ /**
2452
+ * `runDeploy` writes this record last, and its `err` field is the very message
2453
+ * printed above the summary. Keeping it out of the error block avoids echoing
2454
+ * the same text twice; it still shows up as one line in the tail.
2455
+ */
2456
+ const TERMINAL_ERROR_MSG = "deploy_end";
2457
+ const RESERVED_KEYS = /* @__PURE__ */ new Set([
2458
+ "ts",
2459
+ "elapsedMs",
2460
+ "lvl",
2461
+ "msg",
2462
+ "err"
2463
+ ]);
2464
+ /**
2465
+ * The trace was a file the user opened by hand; the summary publishes it to
2466
+ * whatever reads stderr, which in CI is a stored, often public, log.
2467
+ *
2468
+ * Scrubbing here covers only credentials this code emits itself — a presigned
2469
+ * URL it built, an auth header it set, a field it named. Scrubbing user data is
2470
+ * left to the CI platform, which owns the secrets and masks them before the log
2471
+ * is written. GitHub Actions does this for everything under `secrets.*`. Void
2472
+ * does not guess at credential-shaped names or at credentials embedded in
2473
+ * values the user supplied.
2474
+ */
2475
+ /** Query parameters whose value must never reach a CI log. */
2476
+ const SIGNED_QUERY_RE = /([?&](?:X-Amz-[A-Za-z0-9-]+|[Ss]ignature|sig|token|access_token|key)=)[^&\s]+/g;
2477
+ const BEARER_RE = /\b(Bearer\s+)\S+/g;
2478
+ /**
2479
+ * Field keys whose value is masked whole, whatever it looks like. `auth` is
2480
+ * deliberately absent — it matches metadata keys such as `authMethod` far more
2481
+ * often than credentials.
2482
+ */
2483
+ const SECRET_KEY_RE = /token|secret|password|passwd|credential|cookie|signature|api[-_]?key|private[-_]?key/i;
2484
+ function redact(text) {
2485
+ return text.replace(SIGNED_QUERY_RE, "$1[redacted]").replace(BEARER_RE, "$1[redacted]");
2486
+ }
2487
+ function truncate(text, max) {
2488
+ return text.length <= max ? text : `${text.slice(0, max)}...`;
2489
+ }
2490
+ /** Collapse every run of whitespace so one record always renders as one line. */
2491
+ function oneLine(text) {
2492
+ return text.replace(/\s+/g, " ").trim();
2493
+ }
2494
+ function stringifyValue(value) {
2495
+ if (typeof value === "string") return value;
2496
+ if (value === null || typeof value === "number" || typeof value === "boolean") return String(value);
2497
+ try {
2498
+ return JSON.stringify(value) ?? String(value);
2499
+ } catch {
2500
+ return String(value);
2501
+ }
2502
+ }
2503
+ /** Render one `key=value` pair, collapsed, redacted, and length-capped. */
2504
+ function formatField(key, value) {
2505
+ if (SECRET_KEY_RE.test(key)) return `${key}=[redacted]`;
2506
+ return `${key}=${truncate(redact(oneLine(stringifyValue(value))), FIELD_VALUE_MAX)}`;
2507
+ }
2508
+ function fieldPairs(record) {
2509
+ const pairs = [];
2510
+ for (const [key, value] of Object.entries(record)) {
2511
+ if (RESERVED_KEYS.has(key) || value === void 0) continue;
2512
+ pairs.push(formatField(key, value));
2513
+ }
2514
+ if (record.err !== void 0) pairs.push(`err=${truncate(redact(oneLine(formatErrorNodeInline(record.err))), FIELD_VALUE_MAX)}`);
2515
+ return pairs;
2516
+ }
2517
+ function formatElapsed(elapsedMs) {
2518
+ return `${((typeof elapsedMs === "number" && Number.isFinite(elapsedMs) ? elapsedMs : 0) / 1e3).toFixed(1)}s`.padStart(ELAPSED_WIDTH);
2519
+ }
2520
+ function colorLevel(level, padded) {
2521
+ if (level === "error") return import_picocolors.default.red(padded);
2522
+ if (level === "warn") return import_picocolors.default.yellow(padded);
2523
+ return import_picocolors.default.dim(padded);
2524
+ }
2525
+ function parseRecords(lines) {
2526
+ const records = [];
2527
+ for (const raw of lines) {
2528
+ const trimmed = raw.trim();
2529
+ if (!trimmed) continue;
2530
+ try {
2531
+ const parsed = JSON.parse(trimmed);
2532
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) records.push(parsed);
2533
+ } catch {}
2534
+ }
2535
+ return records;
2536
+ }
2537
+ /** One aligned line: ` 8.9s error deploy_server_error message=...`. */
2538
+ function formatTailLine(record, msgWidth) {
2539
+ const level = typeof record.lvl === "string" ? record.lvl : "info";
2540
+ const msg = typeof record.msg === "string" ? record.msg : "";
2541
+ const elapsed = formatElapsed(record.elapsedMs);
2542
+ const paddedLevel = level.padEnd(LEVEL_WIDTH);
2543
+ const paddedMsg = msg.padEnd(msgWidth);
2544
+ const head = ` ${elapsed} ${paddedLevel} ${paddedMsg}`;
2545
+ const fields = fieldPairs(record).join(" ");
2546
+ if (!fields) return ` ${elapsed} ${colorLevel(level, paddedLevel)} ${msg}`;
2547
+ const budget = Math.max(20, LINE_MAX - head.length);
2548
+ return ` ${elapsed} ${colorLevel(level, paddedLevel)} ${paddedMsg} ${truncate(fields, budget)}`;
2549
+ }
2550
+ /** An error entry: a headline, then one indented line per field. */
2551
+ function formatErrorEntry(record) {
2552
+ const msg = typeof record.msg === "string" ? record.msg : "error";
2553
+ const lines = [` ${formatElapsed(record.elapsedMs)} ${import_picocolors.default.red(msg)}`];
2554
+ for (const pair of fieldPairs(record)) lines.push(`${DETAIL_INDENT}${pair}`);
2555
+ return lines;
2556
+ }
2557
+ /**
2558
+ * Turn raw JSONL lines into the block appended to a failed deploy's error
2559
+ * message. Returns `null` when there is nothing worth printing.
2560
+ *
2561
+ * The block has two parts: every `error` record with its flattened cause
2562
+ * chain, then the last `LOG_TAIL_LIMIT` records for timeline context.
2563
+ */
2564
+ function formatDeployLogSummary(lines) {
2565
+ const records = parseRecords(lines);
2566
+ if (records.length === 0) return null;
2567
+ const blocks = [];
2568
+ const errors = records.filter((r) => r.lvl === "error" && r.msg !== TERMINAL_ERROR_MSG);
2569
+ if (errors.length > 0) {
2570
+ const shown = errors.slice(0, 5);
2571
+ const errorLines = shown.flatMap((record) => formatErrorEntry(record));
2572
+ if (errors.length > shown.length) errorLines.push(`${DETAIL_INDENT}(+${errors.length - shown.length} more)`);
2573
+ blocks.push([import_picocolors.default.bold("Errors"), ...errorLines].join("\n"));
2574
+ }
2575
+ const tail = records.slice(-20);
2576
+ const msgWidth = Math.min(MSG_COLUMN_MAX, tail.reduce((max, r) => Math.max(max, typeof r.msg === "string" ? r.msg.length : 0), 0));
2577
+ const heading = records.length > tail.length ? `Last 20 of ${records.length} entries` : `Log (${records.length} ${records.length === 1 ? "entry" : "entries"})`;
2578
+ blocks.push([import_picocolors.default.bold(heading), ...tail.map((record) => formatTailLine(record, msgWidth))].join("\n"));
2579
+ return `\n${blocks.join("\n\n")}`;
2580
+ }
2581
+ /**
2582
+ * Read a deploy JSONL log and format its summary. Returns `null` for a missing
2583
+ * path or any read failure — a postmortem aid must never mask the real error.
2584
+ */
2585
+ function buildDeployLogSummary(path) {
2586
+ if (!path) return null;
2587
+ let text;
2588
+ try {
2589
+ text = readFileSync(path, "utf-8");
2590
+ } catch {
2591
+ return null;
2592
+ }
2593
+ return formatDeployLogSummary(text.split("\n"));
2594
+ }
2595
+ //#endregion
2425
2596
  //#region src/shared/utils.ts
2426
2597
  const isWindows = typeof process !== "undefined" && process.platform === "win32";
2427
2598
  function slash(p) {
@@ -2823,6 +2994,7 @@ function buildVoidManifest(opts) {
2823
2994
  if (options?.workerMain) manifest.workerMain = options.workerMain;
2824
2995
  if (options?.compatibilityDate) manifest.compatibilityDate = options.compatibilityDate;
2825
2996
  if (options?.compatibilityFlags && options.compatibilityFlags.length > 0) manifest.compatibilityFlags = options.compatibilityFlags;
2997
+ if (options?.cpuMs) manifest.limits = { cpuMs: options.cpuMs };
2826
2998
  if (hashedAssetsPrefix) manifest.hashedAssetsPrefix = hashedAssetsPrefix;
2827
2999
  if (headerRules && headerRules.length > 0) manifest.headerRules = headerRules;
2828
3000
  if (redirectRules && redirectRules.length > 0) manifest.redirectRules = stripDevOnlyRuleFields(redirectRules);
@@ -2916,6 +3088,7 @@ function buildFrameworkManifest(opts) {
2916
3088
  manifest.workerMain = po?.workerMain ?? opts.workerMain;
2917
3089
  if (po?.compatibilityDate) manifest.compatibilityDate = po.compatibilityDate;
2918
3090
  if (po?.compatibilityFlags && po.compatibilityFlags.length > 0) manifest.compatibilityFlags = po.compatibilityFlags;
3091
+ if (po?.cpuMs) manifest.limits = { cpuMs: po.cpuMs };
2919
3092
  if (opts.hashedAssetsPrefix) manifest.hashedAssetsPrefix = opts.hashedAssetsPrefix;
2920
3093
  if (opts.headerRules && opts.headerRules.length > 0) manifest.headerRules = opts.headerRules;
2921
3094
  if (opts.redirectRules && opts.redirectRules.length > 0) manifest.redirectRules = stripDevOnlyRuleFields(opts.redirectRules);
@@ -3390,7 +3563,7 @@ let loadedProvisionModule;
3390
3563
  * so a managed deploy never imports it — and thus never loads `proper-lockfile`.
3391
3564
  */
3392
3565
  async function loadProvisionModule() {
3393
- loadedProvisionModule ??= await import("./provision-rShh6MKY.mjs");
3566
+ loadedProvisionModule ??= await import("./provision-CPx2ZxsH.mjs");
3394
3567
  return loadedProvisionModule;
3395
3568
  }
3396
3569
  /**
@@ -3512,6 +3685,13 @@ async function runDeploy(root, options) {
3512
3685
  cliLog.info("deploy_end", { ok: true });
3513
3686
  } catch (err) {
3514
3687
  cliLog.error("deploy_end", err, { ok: false });
3688
+ await cliLog.close().catch(() => {});
3689
+ try {
3690
+ if (err instanceof Error) {
3691
+ const summary = buildDeployLogSummary(cliLog.path);
3692
+ if (summary) err.message = `${err.message}\n${summary}`;
3693
+ }
3694
+ } catch {}
3515
3695
  throw err;
3516
3696
  } finally {
3517
3697
  await cliLog.close().catch(() => {});
@@ -3575,6 +3755,26 @@ function prependLocalBinToPath(env, root) {
3575
3755
  return env;
3576
3756
  }
3577
3757
  /**
3758
+ * Marks a build child as driven by a MANAGED `void deploy`.
3759
+ *
3760
+ * The platform resolves the asset routing policy out-of-band (`resolveAssetConfig`
3761
+ * → `manifest.assetConfig`) and applies it to the uploaded script, so settings the
3762
+ * Vite plugin cannot safely write into the built wrangler config — `routing.notFound`
3763
+ * for a Class A framework, which needs an `assets` policy Void does not own there —
3764
+ * are still honored on this path. `void:framework-build-wrapper` warns about exactly
3765
+ * those when this flag is ABSENT, i.e. on a self-hosted `vite build && wrangler deploy`.
3766
+ *
3767
+ * Passed through the CHILD env only (never `process.env`), the same way
3768
+ * `VOID_DEPLOY_PROJECT_ID` is, so it cannot leak into an unrelated child process or a
3769
+ * later `void dev` in the same shell.
3770
+ *
3771
+ * Deliberately NOT set by `runCloudflareDeploy` (`--backend cloudflare`): that flow
3772
+ * hands the built output to `wrangler deploy` against the user's own account and IS the
3773
+ * self-host path the warning is about. (It rejects framework SSR outright today, so no
3774
+ * Class A build reaches it either way.)
3775
+ */
3776
+ const MANAGED_DEPLOY_BUILD_ENV = { VOID_DEPLOY_BUILD: "1" };
3777
+ /**
3578
3778
  * Deploy-time env selectors that pin the WRONG worker/config out from under the
3579
3779
  * top-level config this flow provisions + preflights. Scrubbed from every child env
3580
3780
  * and fenced in the project dotenv (see below), on top of the provisioner's transport
@@ -5359,7 +5559,7 @@ async function runCloudflareDeploy(root, options, cliLog, deps = {}) {
5359
5559
  log.error(`deploy: ${getErrorMessage(err)}`);
5360
5560
  return exit(1);
5361
5561
  }
5362
- if (scanWebSocketRoutesSync(root, paths).length > 0) {
5562
+ if (scanWebSocketRoutesSync(root, paths, "prod").length > 0) {
5363
5563
  log.error([
5364
5564
  "deploy: --backend cloudflare does not yet support WebSocket / Durable Object routes.",
5365
5565
  "A `.ws.ts` route makes the build emit a key-value-backed Durable Object namespace",
@@ -5949,7 +6149,7 @@ async function promptDeployProjectConfig(root, client, cliLog) {
5949
6149
  slug: result.project.slug
5950
6150
  };
5951
6151
  writeProjectConfig(root, config);
5952
- log.step(`Linked to ${import_picocolors.default.blue(config.slug)}`);
6152
+ log.step(`Linked to ${import_picocolors$1.default.blue(config.slug)}`);
5953
6153
  cliLog?.info("project_linked", {
5954
6154
  projectId: config.projectId,
5955
6155
  slug: config.slug
@@ -6285,7 +6485,7 @@ async function runStaticDeploy(root, config, client, preset, skipBuild, gitMetad
6285
6485
  execSync(preset.buildCommand, {
6286
6486
  cwd: root,
6287
6487
  stdio: "inherit",
6288
- env: buildEnv(void 0, { localBinRoot: root })
6488
+ env: buildEnv({ ...MANAGED_DEPLOY_BUILD_ENV }, { localBinRoot: root })
6289
6489
  });
6290
6490
  cliLog?.info("build_end", { durationMs: Date.now() - buildStartedAt });
6291
6491
  } else if (skipBuild) cliLog?.info("build_skipped", { reason: "skipBuild" });
@@ -6402,7 +6602,7 @@ async function runFrameworkDeploy(root, config, client, detected, fwPreset, void
6402
6602
  execSync(voidConfig.inference?.build ?? resolveProjectCommand(root, fwPreset.buildCommand), {
6403
6603
  cwd: root,
6404
6604
  stdio: "inherit",
6405
- env: buildEnv(void 0, { localBinRoot: root })
6605
+ env: buildEnv({ ...MANAGED_DEPLOY_BUILD_ENV }, { localBinRoot: root })
6406
6606
  });
6407
6607
  cliLog?.info("build_end", { durationMs: Date.now() - buildStartedAt });
6408
6608
  } else cliLog?.info("build_skipped", { reason: "skipBuild" });
@@ -6543,7 +6743,8 @@ async function runFrameworkDeploy(root, config, client, detected, fwPreset, void
6543
6743
  bindingNames: resolveBindingNames(voidConfig.inference?.bindings),
6544
6744
  workerMain: actualWorkerMain,
6545
6745
  compatibilityDate: wranglerCompat?.compatibilityDate,
6546
- compatibilityFlags: wranglerCompat?.compatibilityFlags
6746
+ compatibilityFlags: wranglerCompat?.compatibilityFlags,
6747
+ cpuMs: voidConfig.worker?.limits?.cpu_ms
6547
6748
  };
6548
6749
  const manifest = buildFrameworkManifest({
6549
6750
  frameworkName: detected.name,
@@ -6597,7 +6798,10 @@ async function runFullDeploy(root, config, client, voidConfig, fwPreset, skipBui
6597
6798
  execSync(buildExec, {
6598
6799
  cwd: root,
6599
6800
  stdio: "inherit",
6600
- env: buildEnv({ VOID_DEPLOY_PROJECT_ID: config.projectId }, { localBinRoot: root })
6801
+ env: buildEnv({
6802
+ VOID_DEPLOY_PROJECT_ID: config.projectId,
6803
+ ...MANAGED_DEPLOY_BUILD_ENV
6804
+ }, { localBinRoot: root })
6601
6805
  });
6602
6806
  cliLog?.info("build_end", { durationMs: Date.now() - buildStartedAt });
6603
6807
  } catch (err) {
@@ -6707,9 +6911,10 @@ async function runFullDeploy(root, config, client, voidConfig, fwPreset, skipBui
6707
6911
  })));
6708
6912
  const routeScan = await scanRoutes(root, {
6709
6913
  output: deployConfig.output,
6710
- paths
6914
+ paths,
6915
+ environment: "prod"
6711
6916
  });
6712
- const webSockets = routeScan.websockets ?? scanWebSocketRoutesSync(root, paths);
6917
+ const webSockets = routeScan.websockets ?? scanWebSocketRoutesSync(root, paths, "prod");
6713
6918
  const liveConfig = await resolveDeployLiveBindingConfig(root, client, config.projectId, {
6714
6919
  isFrameworkMode,
6715
6920
  needsLive: effectiveBindings.needsLive,
@@ -6812,6 +7017,7 @@ async function runFullDeploy(root, config, client, voidConfig, fwPreset, skipBui
6812
7017
  const voidPackageOptions = {
6813
7018
  compatibilityDate: wranglerCompat?.compatibilityDate,
6814
7019
  compatibilityFlags: wranglerCompat?.compatibilityFlags,
7020
+ cpuMs: deployConfig.worker?.limits?.cpu_ms,
6815
7021
  ...workerMain && { workerMain },
6816
7022
  ...sandboxConfig && { sandbox: sandboxConfig },
6817
7023
  ...liveConfig && { live: liveConfig },
@@ -6880,7 +7086,7 @@ async function runFullDeploy(root, config, client, voidConfig, fwPreset, skipBui
6880
7086
  outro("Done!");
6881
7087
  }
6882
7088
  async function createProjectFromSlug(root, client, slug, cliLog) {
6883
- log.step(`Creating project ${import_picocolors.default.blue(slug)}...`);
7089
+ log.step(`Creating project ${import_picocolors$1.default.blue(slug)}...`);
6884
7090
  cliLog?.info("project_create_start", { slug });
6885
7091
  const project = await client.createProject(slug);
6886
7092
  const config = {
@@ -6888,7 +7094,7 @@ async function createProjectFromSlug(root, client, slug, cliLog) {
6888
7094
  slug: project.slug
6889
7095
  };
6890
7096
  writeProjectConfig(root, config);
6891
- log.success(`Project created: ${import_picocolors.default.blue(config.slug)}`);
7097
+ log.success(`Project created: ${import_picocolors$1.default.blue(config.slug)}`);
6892
7098
  cliLog?.info("project_create_success", {
6893
7099
  projectId: config.projectId,
6894
7100
  slug: config.slug
@@ -2,7 +2,7 @@ import { a as join, n as dirname, s as relative } from "./dist-DaKKDf8D.mjs";
2
2
  import { D as outro, T as log, a as cliTitle, j as isCancel, k as select, w as intro, x as cancel } from "./agents-CtgBYqld.mjs";
3
3
  import { n as readProjectPaths } from "./project-paths-BQd7OmIo.mjs";
4
4
  import { n as ensureProjectTsconfig } from "./project-tsconfig-B-QtXjLQ.mjs";
5
- import { c as getDatabaseDialect, f as readConfig } from "./config-BkTvs43g.mjs";
5
+ import { c as getDatabaseDialect, f as readConfig } from "./config-qHGgPuWT.mjs";
6
6
  import { n as writeDrizzleConfig } from "./config-CutEMNGJ.mjs";
7
7
  import { c as collectMigrations, n as listDrizzleArtifacts, t as assertJournalCoherence, u as readJournal } from "./validate-Cw_RLeTj.mjs";
8
8
  import { t as buildDrizzleKitSpawnEnv } from "./yarn-pnp-DJn3SAHF.mjs";
@@ -1,5 +1,5 @@
1
1
  import { a as join } from "./dist-DaKKDf8D.mjs";
2
- import { a as convertRedirectsConfig, d as parseHostPrefixedSource, i as convertHeadersConfig, o as convertRewritesConfig, r as convertFallbacksConfig, s as countSplats, t as VALID_REDIRECT_STATUSES, u as isProtocolRelative } from "./config-BkTvs43g.mjs";
2
+ import { a as convertRedirectsConfig, d as parseHostPrefixedSource, i as convertHeadersConfig, o as convertRewritesConfig, r as convertFallbacksConfig, s as countSplats, t as VALID_REDIRECT_STATUSES, u as isProtocolRelative } from "./config-qHGgPuWT.mjs";
3
3
  import { i as voidWarn } from "./log-ChfPKsVd.mjs";
4
4
  import { existsSync, readFileSync } from "node:fs";
5
5
  //#region src/cli/headers.ts