@voltro/cli 0.59.0 → 0.60.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 (67) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/dist/bin.js +1 -1
  3. package/dist/{build-uRMZrT8z.js → build-BxAsLzyU.js} +14 -10
  4. package/dist/{codemodRunner-kNnh1I7_.js → codemodRunner-ClUqkhvR.js} +86 -37
  5. package/dist/{commands-cu34ENUT.js → commands-Ro4hYBHD.js} +7 -7
  6. package/dist/{dashboardCommand-gG1y4PFG.js → dashboardCommand-t8Qsebjr.js} +1 -1
  7. package/dist/{evolveCommand-8CuFBlbQ.js → evolveCommand-CThb0EZZ.js} +1 -1
  8. package/dist/index.js +1 -1
  9. package/dist/{infoCommand-D02A4WI2.js → infoCommand-a0WkKcUY.js} +1 -1
  10. package/dist/{start-C75w6ftA.js → start-BhoDQ25C.js} +1 -1
  11. package/dist/{start-DNtIlBcn.js → start-CcdPRG8L.js} +418 -367
  12. package/dist/startEntry.js +1 -1
  13. package/dist/{updateCommand-Bw3mCUDT.js → updateCommand-D9avpQFT.js} +1 -1
  14. package/dist/updateCommand-QMOirvXC.js +2 -0
  15. package/package.json +25 -19
  16. package/templates/AGENTS.md +1 -1
  17. package/templates/agent-docs/_index.md +1 -1
  18. package/templates/agent-docs/plugins/sentry.md +93 -6
  19. package/templates/agent-docs/whats-new.md +29 -26
  20. package/templates/apps/api-ai/package.json +6 -6
  21. package/templates/apps/api-auth/package.json +8 -8
  22. package/templates/apps/api-backend/package.json +7 -7
  23. package/templates/apps/api-backend-deactivation/package.json +7 -7
  24. package/templates/apps/api-backend-mail/package.json +8 -8
  25. package/templates/apps/api-backend-mariadb/package.json +9 -9
  26. package/templates/apps/api-backend-sqlite/package.json +8 -8
  27. package/templates/apps/api-backend-storage/package.json +8 -8
  28. package/templates/apps/api-cms/package.json +9 -9
  29. package/templates/apps/api-collab/package.json +8 -8
  30. package/templates/apps/api-data-advanced/package.json +8 -8
  31. package/templates/apps/api-durable/package.json +8 -8
  32. package/templates/apps/api-feature-flags/package.json +9 -9
  33. package/templates/apps/api-governance/package.json +8 -8
  34. package/templates/apps/api-kv/package.json +8 -8
  35. package/templates/apps/api-moderation/package.json +8 -8
  36. package/templates/apps/api-observability/package.json +8 -8
  37. package/templates/apps/api-ratelimit/package.json +8 -8
  38. package/templates/apps/api-rbac/package.json +8 -8
  39. package/templates/apps/api-rest/package.json +7 -7
  40. package/templates/apps/api-row-history/package.json +8 -8
  41. package/templates/apps/api-saas/package.json +11 -11
  42. package/templates/apps/api-saas-starter/package.json +10 -10
  43. package/templates/apps/api-search/package.json +8 -8
  44. package/templates/apps/api-status/package.json +8 -8
  45. package/templates/apps/api-webhooks/package.json +9 -9
  46. package/templates/apps/changelog/package.json +7 -7
  47. package/templates/apps/edge-functions/package.json +2 -2
  48. package/templates/apps/frontend-admin/package.json +7 -7
  49. package/templates/apps/frontend-app/package.json +8 -8
  50. package/templates/apps/frontend-auth/package.json +7 -7
  51. package/templates/apps/frontend-blank/package.json +6 -6
  52. package/templates/apps/frontend-cms/package.json +8 -8
  53. package/templates/apps/frontend-collab/package.json +9 -9
  54. package/templates/apps/frontend-contact/package.json +7 -7
  55. package/templates/apps/frontend-dashboard/package.json +6 -6
  56. package/templates/apps/frontend-docs/package.json +8 -8
  57. package/templates/apps/frontend-i18n/package.json +6 -6
  58. package/templates/apps/frontend-landing/package.json +7 -7
  59. package/templates/apps/frontend-portal/package.json +7 -7
  60. package/templates/apps/frontend-saas/package.json +7 -7
  61. package/templates/apps/frontend-spa/package.json +6 -6
  62. package/templates/apps/frontend-ssr/package.json +6 -6
  63. package/templates/apps/frontend-ssr-api/package.json +7 -7
  64. package/templates/apps/frontend-static-blog/package.json +8 -8
  65. package/templates/apps/frontend-status/package.json +7 -7
  66. package/templates/apps/mobile-app/package.json +4 -4
  67. package/dist/updateCommand-inInBIAh.js +0 -2
@@ -1,22 +1,23 @@
1
1
  import { i as e, t } from "./nodeEnvironment-cGFAj1J8.js";
2
- import { $ as n, $t as r, A as i, B as a, D as o, E as s, Et as c, F as l, Ft as u, G as d, H as ee, I as f, It as p, J as m, K as te, L as h, Lt as g, M as _, N as v, O as y, P as b, Pt as x, Q as ne, Qt as S, R as C, Rt as w, T as re, U as ie, W as ae, X as T, Y as E, Yt as oe, Z as se, a as ce, bt as le, c as D, en as ue, et as de, ft as fe, h as O, it as pe, j as me, jt as k, k as he, lt as A, m as j, mt as ge, n as _e, nt as ve, ot as ye, q as M, rt as be, s as xe, st as Se, tn as Ce, tt as N, u as we, xt as Te, z as P } from "./webDev-CBN9KkyQ.js";
3
- import { A as F, I as Ee, M as De, O as Oe, g as ke, j as Ae, o as je } from "./inspect-PcC5J-Dl.js";
4
- import { r as Me } from "./appPort-B_HpJ_ck.js";
5
- import { o as Ne, t as Pe } from "./connectionConfig-Bk9IC7D0.js";
6
- import { n as Fe, r as Ie, t as Le } from "./inspectMetrics-BY0Sjb2F.js";
7
- import { a as Re, c as ze, d as Be, f as Ve, l as He, p as I, u as Ue } from "./renderModeScan-43yQ2opo.js";
8
- import { i as We, n as Ge, r as Ke, t as qe } from "./runtimeRegistry-DMeKfTHP.js";
9
- import { n as Je } from "./logFileSink-B4uP8pvf.js";
10
- import { t as Ye } from "./bootTiming-BdyP9nYw.js";
11
- import { a as Xe, n as Ze, r as Qe, t as $e } from "./staticCachePolicy-CIyj6DbS.js";
12
- import { extname as L, join as R, resolve as z } from "node:path";
13
- import { promises as B } from "node:fs";
14
- import { pathToFileURL as V } from "node:url";
15
- import { createLogger as H, printReadyBlock as et } from "@voltro/logger";
16
- import { appMode as tt, frameworkVersion as nt, setProcessBootPath as rt } from "@voltro/protocol/identity";
17
- import { applyKeepAlive as it, maybeCompress as U, negotiateEncoding as at, resolveKeepAlive as ot, snapshotMetricsSync as st } from "@voltro/runtime";
18
- import { Effect as ct } from "effect";
19
- import { createHash as W } from "node:crypto";
2
+ import { $ as n, $t as r, A as i, B as a, D as o, E as s, Et as c, F as l, Ft as u, G as d, H as ee, I as f, It as p, J as m, K as te, L as h, Lt as g, M as _, N as v, O as y, P as b, Pt as x, Q as S, Qt as C, R as w, Rt as T, T as ne, U as re, W as ie, X as E, Y as D, Yt as ae, Z as oe, a as se, bt as ce, c as O, en as le, et as ue, ft as de, h as k, it as fe, j as pe, jt as A, k as me, lt as j, m as M, mt as he, n as ge, nt as _e, ot as ve, q as N, rt as ye, s as be, st as xe, tn as Se, tt as P, u as Ce, xt as we, z as F } from "./webDev-CBN9KkyQ.js";
3
+ import { A as I, I as Te, M as Ee, O as De, g as Oe, j as ke, o as Ae } from "./inspect-PcC5J-Dl.js";
4
+ import { r as je } from "./appPort-B_HpJ_ck.js";
5
+ import { o as Me, t as Ne } from "./connectionConfig-Bk9IC7D0.js";
6
+ import { n as Pe, r as Fe, t as Ie } from "./inspectMetrics-BY0Sjb2F.js";
7
+ import { a as Le, c as Re, d as ze, f as Be, l as Ve, p as L, u as He } from "./renderModeScan-43yQ2opo.js";
8
+ import { i as Ue, n as We, r as Ge, t as Ke } from "./runtimeRegistry-DMeKfTHP.js";
9
+ import { n as qe } from "./logFileSink-B4uP8pvf.js";
10
+ import { t as Je } from "./bootTiming-BdyP9nYw.js";
11
+ import { a as Ye, n as Xe, r as Ze, t as Qe } from "./staticCachePolicy-CIyj6DbS.js";
12
+ import { extname as R, join as z, resolve as B } from "node:path";
13
+ import { promises as V } from "node:fs";
14
+ import { pathToFileURL as H } from "node:url";
15
+ import { createLogger as U, printReadyBlock as $e } from "@voltro/logger";
16
+ import { appMode as et, frameworkVersion as tt, setProcessBootPath as nt } from "@voltro/protocol/identity";
17
+ import { applyKeepAlive as rt, maybeCompress as W, negotiateEncoding as it, resolveKeepAlive as at, snapshotMetricsSync as ot } from "@voltro/runtime";
18
+ import { Effect as st } from "effect";
19
+ import { createRequire as G } from "node:module";
20
+ import { createHash as ct } from "node:crypto";
20
21
  import { resolveBroadcastProvider as lt } from "@voltro/plugin-broadcast";
21
22
  import { createServer as ut } from "node:http";
22
23
  //#region src/inertPublicEnv.ts
@@ -41,7 +42,7 @@ var dt = "VOLTRO_PUBLIC_", ft = (e, t) => {
41
42
  return `${e.length} VOLTRO_PUBLIC_* variable${e.length === 1 ? "" : "s"} set in this process's environment cannot reach the browser:\n${t.join("\n")}\n Public values are BAKED into the bundle by \`voltro build\` — that is what makes them
42
43
  readable in a browser — so they must exist when the bundle is BUILT, not when it runs.
43
44
  → pass them to the build (a Docker build-arg / CI build step), not as deployment env.`;
44
- }, mt = (e) => `W/"${W("md5").update(e).digest("hex")}"`, ht = (e) => {
45
+ }, mt = (e) => `W/"${ct("md5").update(e).digest("hex")}"`, ht = (e) => {
45
46
  let { response: t, status: n, headers: r, body: i, requestHeaders: a } = e, o = r["cache-control"], s = (typeof o == "string" ? o : "").toLowerCase();
46
47
  if (i === void 0 || n !== 200 || s.includes("no-store")) return !1;
47
48
  let c = r["content-type"], l = typeof c == "string" ? c : void 0, u = r.etag, d = typeof u == "string" ? u : mt(i), ee = a["if-none-match"];
@@ -53,7 +54,7 @@ var dt = "VOLTRO_PUBLIC_", ft = (e, t) => {
53
54
  ...r,
54
55
  etag: d
55
56
  }), t.end(i), !0;
56
- let f = U({
57
+ let f = W({
57
58
  body: typeof i == "string" ? new TextEncoder().encode(i) : new Uint8Array(i),
58
59
  contentType: l,
59
60
  acceptEncoding: a["accept-encoding"],
@@ -64,7 +65,7 @@ var dt = "VOLTRO_PUBLIC_", ft = (e, t) => {
64
65
  etag: d
65
66
  };
66
67
  return f.compressed && delete p["content-length"], t.writeHead(n, p), t.end(Buffer.from(f.bytes)), !0;
67
- }, G = H({ scope: "voltro:start:cdc" }), gt = (e) => (t) => {
68
+ }, K = U({ scope: "voltro:start:cdc" }), gt = (e) => (t) => {
68
69
  let n = 0;
69
70
  for (let [r, i] of e.tableSubscriptionsByPattern) {
70
71
  if (!i.includes(t)) continue;
@@ -75,15 +76,15 @@ var dt = "VOLTRO_PUBLIC_", ft = (e, t) => {
75
76
  }));
76
77
  }
77
78
  return n;
78
- }, K = () => Pe() ? Ne() : null, _t = (e) => {
79
+ }, _t = () => Ne() ? Me() : null, vt = (e) => {
79
80
  let t = e.channel ?? "framework_changes", n = e.revalidateChannel ?? "voltro_revalidate", r = gt(e), i = null, a = null;
80
81
  return {
81
82
  start: async () => {
82
83
  let o = e.tableSubscriptionsByPattern.size > 0, s = e.onRevalidate !== void 0;
83
- if (!o && !s) return G.debug("skipped — no pages declare cacheInvalidatesOn and no revalidation handler is wired"), !1;
84
- let c = K();
85
- if (!c && !o) return G.debug("no database configured — the revalidation LISTEN line is unavailable"), !1;
86
- if (!c) return G.warn(`${e.tableSubscriptionsByPattern.size} route(s) declare \`cacheInvalidatesOn\` and will NOT be invalidated live — no database is configured for this web process. Set DB_URL (or DB_HOST / PG_HOST) so the CDC listener can connect; until then those routes go stale until their \`revalidate\` window expires.`, { routes: [...e.tableSubscriptionsByPattern.keys()] }), !1;
84
+ if (!o && !s) return K.debug("skipped — no pages declare cacheInvalidatesOn and no revalidation handler is wired"), !1;
85
+ let c = _t();
86
+ if (!c && !o) return K.debug("no database configured — the revalidation LISTEN line is unavailable"), !1;
87
+ if (!c) return K.warn(`${e.tableSubscriptionsByPattern.size} route(s) declare \`cacheInvalidatesOn\` and will NOT be invalidated live — no database is configured for this web process. Set DB_URL (or DB_HOST / PG_HOST) so the CDC listener can connect; until then those routes go stale until their \`revalidate\` window expires.`, { routes: [...e.tableSubscriptionsByPattern.keys()] }), !1;
87
88
  i = new (await (import("pg"))).default.Client(c), await i.connect(), a = (i) => {
88
89
  if (i.channel === n && i.payload && e.onRevalidate) {
89
90
  e.onRevalidate(i.payload);
@@ -94,18 +95,18 @@ var dt = "VOLTRO_PUBLIC_", ft = (e, t) => {
94
95
  try {
95
96
  a = JSON.parse(i.payload);
96
97
  } catch (e) {
97
- G.warn("bad CDC payload", {}, e);
98
+ K.warn("bad CDC payload", {}, e);
98
99
  return;
99
100
  }
100
101
  let o = r(a.table);
101
- o > 0 && G.info(`${a.op} on '${a.table}' → dropped ${o} cache entries`, {
102
+ o > 0 && K.info(`${a.op} on '${a.table}' → dropped ${o} cache entries`, {
102
103
  op: a.op,
103
104
  table: a.table,
104
105
  dropped: o
105
106
  });
106
107
  }, i.on("notification", a), o && await i.query(`LISTEN ${t}`), s && await i.query(`LISTEN ${n}`);
107
108
  let l = [...o ? [t] : [], ...s ? [n] : []];
108
- return G.info(`LISTEN ${l.join(", ")}`, {
109
+ return K.info(`LISTEN ${l.join(", ")}`, {
109
110
  channels: l,
110
111
  ..."connectionString" in c ? { target: c.connectionString.replace(/\/\/[^@/]*@/, "//") } : {
111
112
  host: c.host,
@@ -123,7 +124,7 @@ var dt = "VOLTRO_PUBLIC_", ft = (e, t) => {
123
124
  }
124
125
  }
125
126
  };
126
- }, vt = H({ scope: "voltro:start:isr-cache" }), q = "voltro_isr_cache", yt = (e) => `
127
+ }, q = U({ scope: "voltro:start:isr-cache" }), yt = "voltro_isr_cache", bt = (e) => `
127
128
  CREATE TABLE IF NOT EXISTS ${e} (
128
129
  cache_key TEXT PRIMARY KEY,
129
130
  html TEXT NOT NULL,
@@ -134,9 +135,9 @@ CREATE TABLE IF NOT EXISTS ${e} (
134
135
  stale_while_revalidate_ms BIGINT NOT NULL DEFAULT 0
135
136
  );
136
137
  CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
137
- `, bt = (e) => {
138
- let t = e.tableName ?? q, { client: n } = e, r = /* @__PURE__ */ new Map(), i = !1, a = (async () => {
139
- i || (i = !0, await n.query(yt(t)));
138
+ `, xt = (e) => {
139
+ let t = e.tableName ?? yt, { client: n } = e, r = /* @__PURE__ */ new Map(), i = !1, a = (async () => {
140
+ i || (i = !0, await n.query(bt(t)));
140
141
  })().then(async () => {
141
142
  let e = await n.query(`SELECT * FROM ${t}`);
142
143
  for (let t of e.rows) r.set(t.cache_key, {
@@ -148,10 +149,10 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
148
149
  staleWhileRevalidateMs: Number(t.stale_while_revalidate_ms)
149
150
  });
150
151
  }).catch((e) => {
151
- vt.warn("postgres bootstrap failed", {}, e);
152
+ q.warn("postgres bootstrap failed", {}, e);
152
153
  }), o = (e, t) => {
153
154
  a.then(() => n.query(e, t)).catch((e) => {
154
- vt.warn("postgres write failed", {}, e);
155
+ q.warn("postgres write failed", {}, e);
155
156
  });
156
157
  }, s = /* @__PURE__ */ new Map(), c = (e) => {
157
158
  s.set(e, (s.get(e) ?? 0) + 1);
@@ -202,7 +203,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
202
203
  return Array.from(r.entries());
203
204
  }
204
205
  };
205
- }, J = H({ scope: "voltro:start:revalidate" }), xt = (e) => {
206
+ }, J = U({ scope: "voltro:start:revalidate" }), St = (e) => {
206
207
  try {
207
208
  let t = JSON.parse(e);
208
209
  return (t.kind === "path" || t.kind === "table" || t.kind === "tag") && typeof t.value == "string" && t.value.length > 0 && (t.tenant === void 0 || typeof t.tenant == "string") ? {
@@ -213,7 +214,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
213
214
  } catch {
214
215
  return J.warn("bad revalidation payload (not JSON)", { payload: e }), null;
215
216
  }
216
- }, St = (e, t) => {
217
+ }, Ct = (e, t) => {
217
218
  if (t.kind === "table" || t.kind === "tag") {
218
219
  let n = e.tableSink(t.value);
219
220
  return J.info(`revalidate ${t.kind} '${t.value}' → dropped ${n} cache entries`, {
@@ -253,7 +254,47 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
253
254
  dropped: s,
254
255
  ...t.tenant === void 0 ? {} : { tenant: t.tenant }
255
256
  }), s;
256
- }, Y = H({ scope: "voltro:start" }), Ct = nt() ?? "unknown", X = (e) => e instanceof Error && e._voltroControl === "redirect" && typeof e.location == "string", wt = (e) => e instanceof Error && e._voltroControl === "not-found", Tt = {
257
+ }, wt = async (e) => {
258
+ let t = G(z(e, "package.json")), n;
259
+ try {
260
+ n = t.resolve("@voltro/plugin-sentry/server");
261
+ } catch {
262
+ return { reason: "SENTRY_DSN is set but `@voltro/plugin-sentry` is not installed in this app — the web server cannot report SSR errors. → `pnpm add @voltro/plugin-sentry` in the web app." };
263
+ }
264
+ try {
265
+ return await import(H(n).href);
266
+ } catch (e) {
267
+ return { reason: `@voltro/plugin-sentry/server resolved but could not be loaded: ${e instanceof Error ? e.message : String(e)}` };
268
+ }
269
+ }, Tt = async (e, t, n, r = {}) => {
270
+ let i = t.SENTRY_DSN;
271
+ if (i === void 0 || i === "") return;
272
+ let a = await (r.load ?? wt)(e);
273
+ if ("reason" in a) {
274
+ n.warn(a.reason);
275
+ return;
276
+ }
277
+ let o = {
278
+ dsn: i,
279
+ environment: t.SENTRY_ENVIRONMENT,
280
+ release: t.SENTRY_RELEASE,
281
+ traces: !1
282
+ }, s = await a.initSentryServer(o, n);
283
+ if (s !== void 0) return n.info("sentry active", {
284
+ ...a.sentryActiveFields(s, o),
285
+ process: "web"
286
+ }), (e, t) => {
287
+ try {
288
+ s.sdk.captureException(e, {
289
+ tags: {
290
+ "voltro.process": "web",
291
+ "voltro.stage": t.stage
292
+ },
293
+ ...t.pathname === void 0 ? {} : { extra: { pathname: t.pathname } }
294
+ });
295
+ } catch {}
296
+ };
297
+ }, Y = U({ scope: "voltro:start" }), Et = tt() ?? "unknown", Dt = (e) => e instanceof Error && e._voltroControl === "redirect" && typeof e.location == "string", Ot = (e) => e instanceof Error && e._voltroControl === "not-found", kt = {
257
298
  ".html": "text/html; charset=utf-8",
258
299
  ".js": "application/javascript",
259
300
  ".mjs": "application/javascript",
@@ -271,13 +312,13 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
271
312
  ".woff": "font/woff",
272
313
  ".woff2": "font/woff2",
273
314
  ".txt": "text/plain; charset=utf-8"
274
- }, Et = (e) => Tt[L(e).toLowerCase()] ?? "application/octet-stream", Dt = (e) => e.replace(/<script\b(?=[^>]*\btype="module")(?:(?!<\/script>).)*<\/script>/gi, "").replace(/<script\b(?=[^>]*\bsrc=)(?:(?!<\/script>).)*<\/script>/gi, "").replace(/<link\b[^>]*\brel="modulepreload"[^>]*>/gi, ""), Z = async (e) => {
315
+ }, At = (e) => kt[R(e).toLowerCase()] ?? "application/octet-stream", jt = (e) => e.replace(/<script\b(?=[^>]*\btype="module")(?:(?!<\/script>).)*<\/script>/gi, "").replace(/<script\b(?=[^>]*\bsrc=)(?:(?!<\/script>).)*<\/script>/gi, "").replace(/<link\b[^>]*\brel="modulepreload"[^>]*>/gi, ""), X = async (e) => {
275
316
  try {
276
- return await B.stat(e), !0;
317
+ return await V.stat(e), !0;
277
318
  } catch {
278
319
  return !1;
279
320
  }
280
- }, Ot = (e) => {
321
+ }, Mt = (e) => {
281
322
  let t = [], n = 0, r = e.split("/").filter(Boolean), i = [];
282
323
  for (let e of r) e.startsWith("[[...") && e.endsWith("]]") ? (i.push("(.*)"), t.push(e.slice(5, -2)), n += 2) : e.startsWith("[...") && e.endsWith("]") ? (i.push("(.+)"), t.push(e.slice(4, -1)), n += 3) : e.startsWith("[") && e.endsWith("]") ? (i.push("([^/]+)"), t.push(e.slice(1, -1)), n += 1) : i.push(e.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"));
283
324
  let a = i.join("/");
@@ -286,8 +327,8 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
286
327
  paramNames: t,
287
328
  priority: n
288
329
  };
289
- }, kt = (e) => e.map((e) => {
290
- let { regex: t, paramNames: n, priority: r } = Ot(e.pattern);
330
+ }, Nt = (e) => e.map((e) => {
331
+ let { regex: t, paramNames: n, priority: r } = Mt(e.pattern);
291
332
  return {
292
333
  pattern: e.pattern,
293
334
  file: e.file,
@@ -296,7 +337,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
296
337
  paramNames: n,
297
338
  priority: r
298
339
  };
299
- }).slice().sort((e, t) => e.priority - t.priority), At = (e, t) => {
340
+ }).slice().sort((e, t) => e.priority - t.priority), Pt = (e, t) => {
300
341
  for (let n of t) {
301
342
  let t = n.regex.exec(e);
302
343
  if (!t) continue;
@@ -308,7 +349,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
308
349
  };
309
350
  }
310
351
  return null;
311
- }, jt = null, Mt, Nt = (e, t) => t === void 0 ? Promise.resolve() : (Mt ??= (async () => {
352
+ }, Z = null, Ft, It = (e, t) => t === void 0 ? Promise.resolve() : (Ft ??= (async () => {
312
353
  try {
313
354
  let n = await e.getHelpers(), r = n.apiDescriptors?.[t];
314
355
  if (r === void 0) return;
@@ -316,10 +357,10 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
316
357
  if (i === void 0) return;
317
358
  i(t, await r());
318
359
  } catch {}
319
- })(), Mt), Pt = async (e) => {
360
+ })(), Ft), Lt = async (e) => {
320
361
  let { provider: t, route: r, params: i, pathname: a, dirs: o, shellTemplate: s, requestHeaders: c, requestUrl: l = "", apiOrigin: u, apiName: d } = e;
321
- await Nt(t, d);
322
- let { search: p } = be(l), g = await ie(ae(e.middlewares ?? [], {
362
+ await It(t, d);
363
+ let { search: p } = ye(l), g = await re(ie(e.middlewares ?? [], {
323
364
  route: r.pattern,
324
365
  pathname: a
325
366
  }), {
@@ -328,9 +369,9 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
328
369
  headers: c,
329
370
  cookies: ee(c.cookie),
330
371
  route: r.pattern
331
- }, e.onCookieWarning), y = await t.getPage(r.pattern, r.file), x = e.forceSsrRender === !0 ? "ssr" : ze(y, r.file), ne = x === "isr" && y.ppr === !0, S = x === "isr" && e.holesOnly !== !0 ? h(g.headers) : g.headers, C = xe(u, S.cookie, {
372
+ }, e.onCookieWarning), y = await t.getPage(r.pattern, r.file), x = e.forceSsrRender === !0 ? "ssr" : Re(y, r.file), S = x === "isr" && y.ppr === !0, C = x === "isr" && e.holesOnly !== !0 ? h(g.headers) : g.headers, w = be(u, C.cookie, {
332
373
  apiName: d,
333
- headers: S
374
+ headers: C
334
375
  });
335
376
  if (e.holesOnly === !0) {
336
377
  if (typeof y.loader != "function") return null;
@@ -343,8 +384,8 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
343
384
  pathname: a,
344
385
  search: p,
345
386
  signal: e.signal,
346
- headers: S,
347
- query: C,
387
+ headers: C,
388
+ query: w,
348
389
  isServer: !0
349
390
  },
350
391
  helpers: await t.getHelpers(),
@@ -353,12 +394,12 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
353
394
  setCookies: g.setCookies
354
395
  };
355
396
  }
356
- let w = x === "spa" && we(o, r.dirChain).some((e) => e.hasLayout);
357
- if (x !== "ssr" && x !== "isr" && !w) return null;
358
- let re = we(o, r.dirChain), oe = {}, ce = null, le, ue = new AbortController(), fe = ne ? b(S, r.pattern) : S;
397
+ let T = x === "spa" && Ce(o, r.dirChain).some((e) => e.hasLayout);
398
+ if (x !== "ssr" && x !== "isr" && !T) return null;
399
+ let ne = Ce(o, r.dirChain), ae = {}, se = null, ce, le = new AbortController(), de = S ? b(C, r.pattern) : C;
359
400
  try {
360
- (await t.getHelpers()).beginStoreSeeds(), {chain: le, segmentLoaderData: oe} = await D({
361
- entries: re,
401
+ (await t.getHelpers()).beginStoreSeeds(), {chain: ce, segmentLoaderData: ae} = await O({
402
+ entries: ne,
362
403
  loadLayout: (e) => t.getLayout(e.dir),
363
404
  loadError: (e) => t.getError(e.dir),
364
405
  loadPending: (e) => t.getPending(e.dir),
@@ -366,50 +407,50 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
366
407
  params: i,
367
408
  pathname: a,
368
409
  search: p,
369
- signal: ue.signal,
370
- headers: fe,
371
- query: C,
410
+ signal: le.signal,
411
+ headers: de,
412
+ query: w,
372
413
  isServer: !0
373
414
  }
374
- }), typeof y.loader == "function" && !w && (ce = await y.loader({
415
+ }), typeof y.loader == "function" && !T && (se = await y.loader({
375
416
  params: i,
376
417
  pathname: a,
377
418
  search: p,
378
- signal: ue.signal,
379
- headers: fe,
380
- query: C,
419
+ signal: le.signal,
420
+ headers: de,
421
+ query: w,
381
422
  isServer: !0
382
423
  }));
383
424
  } catch (e) {
384
- if (X(e)) return {
425
+ if (Dt(e)) return {
385
426
  control: "redirect",
386
427
  status: e.status,
387
428
  location: e.location,
388
429
  setCookies: g.setCookies,
389
430
  responseHeaders: g.responseHeaders
390
431
  };
391
- if (wt(e)) return {
432
+ if (Ot(e)) return {
392
433
  control: "not-found",
393
434
  setCookies: g.setCookies,
394
435
  responseHeaders: g.responseHeaders
395
436
  };
396
437
  throw e;
397
438
  }
398
- let O = await t.getHelpers();
399
- w || await te({
439
+ let k = await t.getHelpers();
440
+ T || await te({
400
441
  pageMod: y,
401
442
  params: i,
402
- query: C,
443
+ query: w,
403
444
  apiName: d,
404
- seed: O.seedPreloadedSubscription,
405
- seedFailure: O.seedPreloadedSubscriptionFailure,
445
+ seed: k.seedPreloadedSubscription,
446
+ seedFailure: k.seedPreloadedSubscriptionFailure,
406
447
  onError: ({ tag: e, apiName: t }, n) => Y.warn("preload seed failed", {
407
448
  tag: e,
408
449
  apiName: t,
409
450
  pathname: a
410
451
  }, n)
411
452
  });
412
- let pe = {
453
+ let fe = {
413
454
  pattern: r.pattern,
414
455
  Component: y.default,
415
456
  meta: y.meta,
@@ -417,162 +458,168 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
417
458
  ErrorBoundary: y.ErrorBoundary,
418
459
  Pending: y.Pending,
419
460
  renderMode: x,
420
- chain: le
461
+ chain: ce
421
462
  };
422
463
  if (x === "isr" && g.cspNonce !== void 0) throw Error(`page '${r.pattern}' is renderMode 'isr' while middleware.ts mints a cspNonce — an isr render is CACHED and a cached nonce is a lie the browser enforces. Use renderMode 'ssr' for nonce'd pages, or a hash-based CSP for isr.`);
423
- let me = {
424
- cookies: ne ? v(f(g.cookies), r.pattern) : x === "isr" ? f(g.cookies) : g.cookies,
425
- headers: fe,
464
+ let pe = {
465
+ cookies: S ? v(f(g.cookies), r.pattern) : x === "isr" ? f(g.cookies) : g.cookies,
466
+ headers: de,
426
467
  url: l,
427
468
  ...e.formFlash === void 0 ? {} : { formFlash: e.formFlash }
428
- }, k = O.i18n?.resolve(S.cookie, S["accept-language"]), he = {
429
- lang: k?.locale ?? me.cookies["voltro:locale"] ?? "en",
430
- ...k?.timeZone === void 0 ? {} : { timeZone: k.timeZone },
469
+ }, A = k.i18n?.resolve(C.cookie, C["accept-language"]), me = {
470
+ lang: A?.locale ?? pe.cookies["voltro:locale"] ?? "en",
471
+ ...A?.timeZone === void 0 ? {} : { timeZone: A.timeZone },
431
472
  renderedAt: Date.now()
432
- }, A = y.interactive ?? "full";
433
- if (w) {
434
- let e = de({
435
- helpers: O,
473
+ }, j = y.interactive ?? "full";
474
+ if (T) {
475
+ let e = ue({
476
+ helpers: k,
436
477
  page: r.pattern,
437
- interactive: A,
478
+ interactive: j,
438
479
  delivery: "stream",
439
480
  renderInput: {
440
- descriptor: pe,
481
+ descriptor: fe,
441
482
  params: i,
442
483
  pathname: a,
443
484
  search: p,
444
- segmentLoaderData: oe,
445
- requestContext: me,
446
- ...k ? {
447
- outerWrap: k.outerWrap,
448
- locale: k.locale
485
+ segmentLoaderData: ae,
486
+ requestContext: pe,
487
+ ...A ? {
488
+ outerWrap: A.outerWrap,
489
+ locale: A.locale
449
490
  } : {}
450
491
  }
451
- }), t = (t) => ve({
452
- helpers: O,
492
+ }), t = (t) => _e({
493
+ helpers: k,
453
494
  prepared: e,
454
495
  meta: t,
455
- interactive: A
496
+ interactive: j
456
497
  });
457
498
  if (e.hasDeferred) {
458
- let n = E({ shell: s });
499
+ let n = D({ shell: s });
459
500
  return {
460
501
  renderMode: "spa",
461
502
  setCookies: g.setCookies,
462
503
  responseHeaders: g.responseHeaders,
463
- stream: (r) => se({
504
+ stream: (r) => oe({
464
505
  res: r,
465
506
  shell: n,
466
- documentAttrs: he,
507
+ documentAttrs: me,
467
508
  headers: {
468
509
  ...g.responseHeaders,
469
510
  "content-type": "text/html; charset=utf-8",
470
511
  "x-voltro-rendered-by": "spa",
471
- ...P(g.setCookies)
512
+ ...F(g.setCookies)
472
513
  },
473
514
  headInjection: t,
474
515
  ...g.cspNonce === void 0 ? {} : { nonce: g.cspNonce },
475
- render: (t) => O.renderPageToStream({
516
+ render: (t) => k.renderPageToStream({
476
517
  ...e.renderInput,
477
518
  ...t,
478
519
  ...g.cspNonce === void 0 ? {} : { nonce: g.cspNonce }
479
520
  }),
480
521
  onShellError: (e) => {
481
- Y.error("spa layout shell render failed", { pathname: a }, e), r.writeHead(500, { "content-type": "text/plain; charset=utf-8" }), r.end("server error");
522
+ Y.error("spa layout shell render failed", { pathname: a }, e), Bt?.(e, {
523
+ stage: "spa-layout-shell",
524
+ pathname: a
525
+ }), r.writeHead(500, { "content-type": "text/plain; charset=utf-8" }), r.end("server error");
482
526
  }
483
527
  })
484
528
  };
485
529
  }
486
- let n = N({
487
- helpers: O,
530
+ let n = P({
531
+ helpers: k,
488
532
  prepared: e
489
- }), o = M(m(s.replace("<div id=\"root\"></div>", `<div id="root">${n.body}</div>`), t(n.meta)), he);
533
+ }), o = N(m(s.replace("<div id=\"root\"></div>", `<div id="root">${n.body}</div>`), t(n.meta)), me);
490
534
  return {
491
- html: g.cspNonce === void 0 ? o : T(o, g.cspNonce),
535
+ html: g.cspNonce === void 0 ? o : E(o, g.cspNonce),
492
536
  renderMode: "spa",
493
537
  revalidateMs: null,
494
538
  setCookies: g.setCookies,
495
539
  responseHeaders: g.responseHeaders
496
540
  };
497
541
  }
498
- let j = n({
499
- helpers: O,
542
+ let M = n({
543
+ helpers: k,
500
544
  page: r.pattern,
501
545
  pathname: a,
502
546
  renderMode: x,
503
- interactive: A,
504
- loaderData: ce,
505
- segmentLoaderData: oe,
547
+ interactive: j,
548
+ loaderData: se,
549
+ segmentLoaderData: ae,
506
550
  pageLoaderRan: typeof y.loader == "function",
507
- ...ne ? { ppr: !0 } : {}
551
+ ...S ? { ppr: !0 } : {}
508
552
  });
509
- ne && _(j.stateInput, r.pattern);
510
- let ge = {
511
- descriptor: pe,
553
+ S && _(M.stateInput, r.pattern);
554
+ let he = {
555
+ descriptor: fe,
512
556
  params: i,
513
557
  pathname: a,
514
558
  search: p,
515
- loaderData: j.loaderData,
516
- segmentLoaderData: j.segmentLoaderData,
517
- requestContext: me,
518
- ...k ? {
519
- outerWrap: k.outerWrap,
520
- locale: k.locale
559
+ loaderData: M.loaderData,
560
+ segmentLoaderData: M.segmentLoaderData,
561
+ requestContext: pe,
562
+ ...A ? {
563
+ outerWrap: A.outerWrap,
564
+ locale: A.locale
521
565
  } : {}
522
- }, _e = (t) => {
523
- if (jt === null || x !== "ssr" && x !== "isr" || typeof y.ogImage != "function" || t.includes("og:image")) return "";
524
- let n = S["x-tenant"], i = jt.signOgUrl({
566
+ }, ge = (t) => {
567
+ if (Z === null || x !== "ssr" && x !== "isr" || typeof y.ogImage != "function" || t.includes("og:image")) return "";
568
+ let n = C["x-tenant"], i = Z.signOgUrl({
525
569
  pattern: r.pattern,
526
570
  params: e.params,
527
571
  ...n === void 0 ? {} : { tenant: n }
528
572
  });
529
573
  return `<meta property="og:image" content="${i}" /><meta name="twitter:image" content="${i}" /><meta name="twitter:card" content="summary_large_image" />`;
530
- }, ye = (e) => [
531
- O.renderMetaToHtml(e) + _e(O.renderMetaToHtml(e)),
532
- `<meta name="voltro-interactive" content="${A}" />`,
533
- ...j.hasDeferred ? [O.renderDeferredRegistryScript()] : [],
534
- O.renderRouterStateScript(j.stateInput)
574
+ }, ve = (e) => [
575
+ k.renderMetaToHtml(e) + ge(k.renderMetaToHtml(e)),
576
+ `<meta name="voltro-interactive" content="${j}" />`,
577
+ ...M.hasDeferred ? [k.renderDeferredRegistryScript()] : [],
578
+ k.renderRouterStateScript(M.stateInput)
535
579
  ].filter((e) => e.length > 0).join("\n ");
536
- if (x === "ssr" && A === "full" && e.buffered !== !0) {
537
- let e = E({ shell: s });
580
+ if (x === "ssr" && j === "full" && e.buffered !== !0) {
581
+ let e = D({ shell: s });
538
582
  return {
539
583
  renderMode: "ssr",
540
584
  setCookies: g.setCookies,
541
- stream: (t) => se({
585
+ stream: (t) => oe({
542
586
  res: t,
543
587
  shell: e,
544
- documentAttrs: he,
588
+ documentAttrs: me,
545
589
  headers: {
546
590
  ...g.responseHeaders,
547
591
  "content-type": "text/html; charset=utf-8",
548
592
  "x-voltro-rendered-by": "ssr",
549
- ...P(g.setCookies)
593
+ ...F(g.setCookies)
550
594
  },
551
- headInjection: ye,
595
+ headInjection: ve,
552
596
  ...g.cspNonce === void 0 ? {} : { nonce: g.cspNonce },
553
- render: (e) => O.renderPageToStream({
554
- ...ge,
597
+ render: (e) => k.renderPageToStream({
598
+ ...he,
555
599
  ...e,
556
600
  ...g.cspNonce === void 0 ? {} : { nonce: g.cspNonce }
557
601
  }),
558
602
  onShellError: (e) => {
559
- Y.error("ssr shell render failed", { pathname: a }, e), t.writeHead(500, { "content-type": "text/plain; charset=utf-8" }), t.end("server error");
603
+ Y.error("ssr shell render failed", { pathname: a }, e), Bt?.(e, {
604
+ stage: "ssr-shell",
605
+ pathname: a
606
+ }), t.writeHead(500, { "content-type": "text/plain; charset=utf-8" }), t.end("server error");
560
607
  }
561
608
  })
562
609
  };
563
610
  }
564
- let { html: Se, meta: Ce } = O.renderPageToHtml(ge), Te = ye(Ce), F = M(m(s.replace("<div id=\"root\"></div>", `<div id="root">${Se}</div>`), Te), he);
565
- A === "none" && (F = Dt(F));
566
- let Ee = x === "isr" ? I(y.revalidate) : null;
611
+ let { html: xe, meta: Se } = k.renderPageToHtml(he), we = ve(Se), I = N(m(s.replace("<div id=\"root\"></div>", `<div id="root">${xe}</div>`), we), me);
612
+ j === "none" && (I = jt(I));
613
+ let Te = x === "isr" ? L(y.revalidate) : null;
567
614
  return {
568
- html: g.cspNonce === void 0 ? F : T(F, g.cspNonce),
615
+ html: g.cspNonce === void 0 ? I : E(I, g.cspNonce),
569
616
  renderMode: x,
570
- revalidateMs: Ee,
617
+ revalidateMs: Te,
571
618
  setCookies: g.setCookies,
572
619
  responseHeaders: g.responseHeaders
573
620
  };
574
- }, Q = (e) => e === "" ? "/" : e, Ft = async (e) => {
575
- let t = await import(V(e).href);
621
+ }, Q = (e) => e === "" ? "/" : e, Rt = async (e) => {
622
+ let t = await import(H(e).href);
576
623
  return {
577
624
  kind: "bundle",
578
625
  getPageMeta: () => t.pageMeta,
@@ -601,8 +648,8 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
601
648
  },
602
649
  async close() {}
603
650
  };
604
- }, It = async (e, t) => {
605
- let n = await S("vite", () => import("vite")), r = (await import("@vitejs/plugin-react")).default, i = (await import("@tailwindcss/vite")).default, a = await n.createServer({
651
+ }, zt = async (e, t) => {
652
+ let n = await C("vite", () => import("vite")), r = (await import("@vitejs/plugin-react")).default, i = (await import("@tailwindcss/vite")).default, a = await n.createServer({
606
653
  root: t,
607
654
  envPrefix: "__VOLTRO_VITE_ENV_DISABLED__",
608
655
  plugins: [r(), i()],
@@ -619,8 +666,8 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
619
666
  },
620
667
  appType: "custom",
621
668
  logLevel: "warn"
622
- }), o = R(e, "src", "pages"), s = (e) => e === "" ? o : R(o, e), c = g({
623
- limit: w(),
669
+ }), o = z(e, "src", "pages"), s = (e) => e === "" ? o : z(o, e), c = g({
670
+ limit: T(),
624
671
  onColdStart: (e) => Y.debug("ssr cold-compile start", { id: e }),
625
672
  onColdEnd: (e, { durationMs: t, failed: n }) => Y.debug(`ssr cold-compile ${n ? "FAILED" : "end"} ${t}ms`, {
626
673
  id: e,
@@ -631,16 +678,16 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
631
678
  return {
632
679
  kind: "middleware",
633
680
  async getPage(e, t) {
634
- return l(R(o, t));
681
+ return l(z(o, t));
635
682
  },
636
683
  async getLayout(e) {
637
- return l(R(s(e), "layout.tsx"));
684
+ return l(z(s(e), "layout.tsx"));
638
685
  },
639
686
  async getError(e) {
640
- return l(R(s(e), "error.tsx"));
687
+ return l(z(s(e), "error.tsx"));
641
688
  },
642
689
  async getPending(e) {
643
- return l(R(s(e), "loading.tsx"));
690
+ return l(z(s(e), "loading.tsx"));
644
691
  },
645
692
  async getHelpers() {
646
693
  return await l("@voltro/web/ssr");
@@ -649,8 +696,8 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
649
696
  await a.close();
650
697
  }
651
698
  };
652
- }, Lt = async (t) => {
653
- let n = Ye(), f = await j(t);
699
+ }, Bt, $ = async (t) => {
700
+ let n = Je(), f = await M(t);
654
701
  if (!f) return {
655
702
  ran: !1,
656
703
  exitCode: 0
@@ -659,6 +706,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
659
706
  ran: !0,
660
707
  exitCode: 1
661
708
  };
709
+ Bt = await Tt(t, process.env, Y);
662
710
  {
663
711
  let e = s(f);
664
712
  if (e !== void 0) return Y.error(`voltro start: refusing to boot — ${e}`), {
@@ -666,7 +714,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
666
714
  exitCode: 1
667
715
  };
668
716
  }
669
- let { resolved: m } = await oe({
717
+ let { resolved: m } = await ae({
670
718
  rawEnv: f.env,
671
719
  appType: "web",
672
720
  root: t,
@@ -674,87 +722,87 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
674
722
  generateTypes: !1
675
723
  }), te = m.publicValues;
676
724
  n.mark("config");
677
- let h = ue();
678
- fe(h), Y.info("booting voltro start", { app: f.name ?? "(unnamed)" });
679
- let g = Me({
725
+ let h = le();
726
+ de(h), Y.info("booting voltro start", { app: f.name ?? "(unnamed)" });
727
+ let g = je({
680
728
  kind: "web",
681
729
  configPort: f.port,
682
730
  env: process.env,
683
- dashboardPin: process.env[pe] === "1"
731
+ dashboardPin: process.env[fe] === "1"
684
732
  });
685
733
  for (let e of g.warnings) Y.warn(e);
686
- let _ = g.port, v = R(t, ".framework");
734
+ let _ = g.port, v = z(t, ".framework");
687
735
  {
688
736
  let e;
689
737
  try {
690
- e = JSON.parse(await B.readFile(R(v, "env.public.json"), "utf8"));
738
+ e = JSON.parse(await V.readFile(z(v, "env.public.json"), "utf8"));
691
739
  } catch {
692
740
  e = void 0;
693
741
  }
694
742
  let t = ft(process.env, e);
695
743
  t.length > 0 && Y.warn(pt(t));
696
744
  }
697
- let b = R(v, "dist"), S = R(b, "index.html");
698
- if (!await Z(S)) return Y.error("no built dist found — run `voltro build` first", { distDir: b }), {
745
+ let b = z(v, "dist"), C = z(b, "index.html");
746
+ if (!await X(C)) return Y.error("no built dist found — run `voltro build` first", { distDir: b }), {
699
747
  ran: !0,
700
748
  exitCode: 1
701
749
  };
702
- let w = f.name ?? "unnamed", T = qe("web", w, _), E = Je(w);
703
- await We({
704
- id: T,
705
- name: w,
750
+ let T = f.name ?? "unnamed", E = Ke("web", T, _), D = qe(T);
751
+ await Ue({
752
+ id: E,
753
+ name: T,
706
754
  kind: "web",
707
755
  url: `http://localhost:${_}`,
708
756
  pid: process.pid,
709
757
  status: "booting",
710
- logFile: E.path
758
+ logFile: D.path
711
759
  }).catch(() => {});
712
- let se = R(b, "_voltro", "shell.html"), D = await Z(se) ? await B.readFile(se, "utf8") : await B.readFile(S, "utf8"), de = await O(t, f), ve = Fe(f), M = Xe(f), N = _e(de[0]), P = de[0]?.name, ze = /* @__PURE__ */ new Set(), I = (e) => {
713
- ze.has(e.name) || (ze.add(e.name), Y.warn(`middleware.ts wrote the cookie "${e.name}" with the HttpOnly default — a browser SDK cannot read it`, {
760
+ let oe = z(b, "_voltro", "shell.html"), O = await X(oe) ? await V.readFile(oe, "utf8") : await V.readFile(C, "utf8"), ue = await k(t, f), _e = Pe(f), N = Ye(f), P = ge(ue[0]), F = ue[0]?.name, Re = /* @__PURE__ */ new Set(), L = (e) => {
761
+ Re.has(e.name) || (Re.add(e.name), Y.warn(`middleware.ts wrote the cookie "${e.name}" with the HttpOnly default — a browser SDK cannot read it`, {
714
762
  cookie: e.name,
715
763
  hint: "If your IdP client reads this from `document.cookie` (Supabase's `createBrowserClient` does), pass `httpOnly: false`. Otherwise the SSR render succeeds and the user is signed out at the first client-side call. Set `httpOnly: true` explicitly to silence this."
716
764
  }));
717
- }, L = await a(t);
718
- L.length > 0 && Y.info(`middleware.ts loaded — ${L.length} middleware(s): ` + L.map((e) => e.exportName).join(", "));
719
- let z, V = null, H = process.env.SSR_CACHE === "postgres";
720
- if (H && Pe()) V = new (await (import("pg"))).default.Client(Ne()), await V.connect(), z = bt({ client: V }), Y.info("isr cache backend: postgres", { table: "voltro_isr_cache" });
721
- else if (H) {
765
+ }, R = await a(t);
766
+ R.length > 0 && Y.info(`middleware.ts loaded — ${R.length} middleware(s): ` + R.map((e) => e.exportName).join(", "));
767
+ let B, H = null, U = process.env.SSR_CACHE === "postgres";
768
+ if (U && Ne()) H = new (await (import("pg"))).default.Client(Me()), await H.connect(), B = xt({ client: H }), Y.info("isr cache backend: postgres", { table: "voltro_isr_cache" });
769
+ else if (U) {
722
770
  let t = "SSR_CACHE=postgres, but nothing in the environment names a database (looked for DB_URL, DB_PRIMARY_URL, DB_DIRECT_URL, DB_MIGRATE_URL, DB_HOST, PG_HOST).";
723
771
  if (e()) throw Y.fatal(`${t} Refusing to fall back to the per-process memory cache: it is not shared between instances and does not survive a restart, so the pages this process serves would differ from its replicas' with nothing to indicate it.`), Error("[voltro start] SSR_CACHE=postgres with no database configured");
724
- z = Ve(), Y.warn(`${t} Falling back to the per-process memory cache — this would be a hard failure in production.`);
725
- } else z = Ve(), Y.info("isr cache backend: memory (per-process)", { hint: "set SSR_CACHE=postgres for persistent storage" });
726
- await o(t, f, de, te);
727
- let nt = R(t, "src", "pages"), { pages: rt, dirs: U } = await re(nt), W = kt(rt);
728
- C(L, W.map((e) => e.pattern)), n.mark("scan");
729
- let dt = R(b, "server", "ssrEntry.js"), G = await Z(dt);
730
- if (!G && process.env.NODE_ENV === "production") throw Y.fatal(`production \`voltro start\` requires a precompiled SSR bundle at ${dt} but it is missing. Run \`voltro build\` before serving — production renders from the bundle and never compiles on demand.`), Error(`[voltro start] missing SSR bundle at ${dt}`);
731
- let K = G ? await Ft(dt) : await It(t, v);
772
+ B = Be(), Y.warn(`${t} Falling back to the per-process memory cache — this would be a hard failure in production.`);
773
+ } else B = Be(), Y.info("isr cache backend: memory (per-process)", { hint: "set SSR_CACHE=postgres for persistent storage" });
774
+ await o(t, f, ue, te);
775
+ let tt = z(t, "src", "pages"), { pages: nt, dirs: W } = await ne(tt), G = Nt(nt);
776
+ w(R, G.map((e) => e.pattern)), n.mark("scan");
777
+ let ct = z(b, "server", "ssrEntry.js"), dt = await X(ct);
778
+ if (!dt && process.env.NODE_ENV === "production") throw Y.fatal(`production \`voltro start\` requires a precompiled SSR bundle at ${ct} but it is missing. Run \`voltro build\` before serving — production renders from the bundle and never compiles on demand.`), Error(`[voltro start] missing SSR bundle at ${ct}`);
779
+ let K = dt ? await Rt(ct) : await zt(t, v);
732
780
  Y.info(`ssr loader: ${K.kind}`, {
733
781
  kind: K.kind,
734
782
  ...K.kind === "middleware" ? { hint: "no pre-built SSR bundle found; run `voltro build` to enable bundle mode" } : {}
735
783
  }), n.mark("provider");
736
- let vt = K.getPageMeta?.();
784
+ let _t = K.getPageMeta?.();
737
785
  c(t);
738
786
  let q = /* @__PURE__ */ new Map(), yt = 0;
739
- for (let e of rt) {
740
- let t = vt?.[e.pattern];
787
+ for (let e of nt) {
788
+ let t = _t?.[e.pattern];
741
789
  if (t) {
742
790
  q.set(e.pattern, t);
743
791
  continue;
744
792
  }
745
793
  try {
746
794
  let t = await K.getPage(e.pattern, e.file);
747
- q.set(e.pattern, Re(t, e.file)), yt++;
795
+ q.set(e.pattern, Le(t, e.file)), yt++;
748
796
  } catch (t) {
749
797
  Y.warn("failed to load page metadata", { pattern: e.pattern }, t);
750
798
  }
751
799
  }
752
- let J = /* @__PURE__ */ new Map();
800
+ let bt = /* @__PURE__ */ new Map();
753
801
  for (let [e, t] of q) {
754
802
  if (t.interactive !== "islands") continue;
755
- let n = R(b, "island-shells", `${k(e)}.html`);
803
+ let n = z(b, "island-shells", `${A(e)}.html`);
756
804
  try {
757
- J.set(e, await B.readFile(n, "utf8"));
805
+ bt.set(e, await V.readFile(n, "utf8"));
758
806
  } catch {
759
807
  Y.warn("islands page has no built per-page shell — serving the full app shell", {
760
808
  pattern: e,
@@ -767,23 +815,23 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
767
815
  fromManifest: q.size - yt,
768
816
  fromModules: yt
769
817
  }), n.mark("routes");
770
- let X = /* @__PURE__ */ new Set();
771
- for (let e of W) q.get(e.pattern)?.renderMode === "spa" && we(U, e.dirChain).some((e) => e.hasLayout) && X.add(e.pattern);
772
- X.size > 0 && Y.info(`${X.size} spa route(s) render an SSR layout shell`, { patterns: [...X] });
818
+ let J = /* @__PURE__ */ new Set();
819
+ for (let e of G) q.get(e.pattern)?.renderMode === "spa" && Ce(W, e.dirChain).some((e) => e.hasLayout) && J.add(e.pattern);
820
+ J.size > 0 && Y.info(`${J.size} spa route(s) render an SSR layout shell`, { patterns: [...J] });
773
821
  let wt = /* @__PURE__ */ new Map();
774
822
  for (let [e, t] of q) t.cacheInvalidatesOn.length > 0 && wt.set(e, t.cacheInvalidatesOn);
775
- let Tt = /* @__PURE__ */ new Map();
776
- for (let e of W) Tt.set(e.pattern, e.regex);
823
+ let Dt = /* @__PURE__ */ new Map();
824
+ for (let e of G) Dt.set(e.pattern, e.regex);
777
825
  {
778
826
  let n = new Set([...q].filter(([, e]) => (e.renderMode === "ssr" || e.renderMode === "isr") && e.hasOgImage).map(([e]) => e));
779
827
  if (n.size > 0) {
780
- let { secret: r, fromEnv: i } = Te();
828
+ let { secret: r, fromEnv: i } = we();
781
829
  if (!i && e()) throw Y.fatal(`${n.size} ssr route(s) export ogImage, but VOLTRO_OG_SECRET is unset. Behind a load balancer the signing replica and the fetching replica differ, so a per-boot secret would 403 every cross-replica image fetch. Set VOLTRO_OG_SECRET (any long random value, same on every replica).`), Error("[voltro start] ssr ogImage routes need VOLTRO_OG_SECRET in a deploy environment");
782
- let a = new Map(rt.map((e) => [e.pattern, e.file]));
783
- jt = le({
830
+ let a = new Map(nt.map((e) => [e.pattern, e.file]));
831
+ Z = ce({
784
832
  root: t,
785
833
  fonts: f.fonts,
786
- cache: z,
834
+ cache: B,
787
835
  secret: r,
788
836
  isOgSsrRoute: (e) => n.has(e),
789
837
  getPageModule: async (e) => {
@@ -793,39 +841,39 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
793
841
  }), Y.info(`og route active for ${n.size} ssr route(s)`, { secret: i ? "env" : "per-boot" });
794
842
  }
795
843
  }
796
- let Dt = /* @__PURE__ */ new Map();
797
- for (let [e, t] of q) Dt.set(e, t.renderMode);
798
- let Ot = [...q.values()].some((e) => e.renderMode === "isr"), Mt = {
799
- cache: z,
844
+ let Ot = /* @__PURE__ */ new Map();
845
+ for (let [e, t] of q) Ot.set(e, t.renderMode);
846
+ let kt = [...q.values()].some((e) => e.renderMode === "isr"), jt = {
847
+ cache: B,
800
848
  tableSink: gt({
801
- cache: z,
849
+ cache: B,
802
850
  tableSubscriptionsByPattern: wt,
803
- regexByPattern: Tt
851
+ regexByPattern: Dt
804
852
  }),
805
- regexByPattern: Tt,
806
- renderModeByPattern: Dt
807
- }, Nt = (e) => {
808
- let t = xt(e);
809
- t && St(Mt, t);
810
- }, Q = _t({
811
- cache: z,
853
+ regexByPattern: Dt,
854
+ renderModeByPattern: Ot
855
+ }, Mt = (e) => {
856
+ let t = St(e);
857
+ t && Ct(jt, t);
858
+ }, Ft = vt({
859
+ cache: B,
812
860
  tableSubscriptionsByPattern: wt,
813
- regexByPattern: Tt,
814
- ...Ot ? { onRevalidate: Nt } : {}
815
- }), Lt = await Q.start(), $ = null, Rt = null;
816
- if (Ot) {
861
+ regexByPattern: Dt,
862
+ ...kt ? { onRevalidate: Mt } : {}
863
+ }), It = await Ft.start(), Q = null, $ = null;
864
+ if (kt) {
817
865
  let e = lt({}, process.env);
818
866
  if (e.crossReplica) try {
819
- Rt = e.provider;
820
- let t = Ie(process.env);
821
- $ = await ct.runPromise(e.provider.subscribe(t, Nt)), Y.info(`revalidation subscriber: broker (${e.provider.name})`, { channel: t });
867
+ $ = e.provider;
868
+ let t = Fe(process.env);
869
+ Q = await st.runPromise(e.provider.subscribe(t, Mt)), Y.info(`revalidation subscriber: broker (${e.provider.name})`, { channel: t });
822
870
  } catch (e) {
823
- Y.warn("revalidation broker subscribe failed — broker leg disabled", {}, e), Rt = null;
871
+ Y.warn("revalidation broker subscribe failed — broker leg disabled", {}, e), $ = null;
824
872
  }
825
- Lt && $ === null && Y.info("revalidation subscriber: postgres LISTEN (voltro_revalidate)"), !Lt && $ === null && Y.warn("isr routes exist, but this web process has NO revalidation transport: no database is configured for the LISTEN line and no broker is configured. `revalidatePath` / `revalidateTable` / `revalidateTag` from the api will not reach this process — cached pages stay until their own `revalidate` window expires. Set DB_URL (postgres) or BROADCAST_URL (redis:// or nats://) on BOTH the api and this web deployment.");
873
+ It && Q === null && Y.info("revalidation subscriber: postgres LISTEN (voltro_revalidate)"), !It && Q === null && Y.warn("isr routes exist, but this web process has NO revalidation transport: no database is configured for the LISTEN line and no broker is configured. `revalidatePath` / `revalidateTable` / `revalidateTag` from the api will not reach this process — cached pages stay until their own `revalidate` window expires. Set DB_URL (postgres) or BROADCAST_URL (redis:// or nats://) on BOTH the api and this web deployment.");
826
874
  }
827
875
  n.mark("cdc");
828
- let zt = Le(), Bt = rt.map((e) => {
876
+ let Vt = Ie(), Ht = nt.map((e) => {
829
877
  let t = q.get(e.pattern);
830
878
  return {
831
879
  pattern: e.pattern,
@@ -841,19 +889,19 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
841
889
  hasMeta: t?.hasMeta ?? !1,
842
890
  hasGetStaticPaths: t?.hasGetStaticPaths ?? !1
843
891
  };
844
- }), Vt = U.map((e) => ({
892
+ }), Ut = W.map((e) => ({
845
893
  dir: e.dir,
846
894
  hasLayout: e.hasLayout,
847
895
  hasError: e.hasError,
848
896
  hasPending: e.hasPending,
849
897
  hasNotFound: e.hasNotFound
850
- })), Ht = V ? "postgres" : "memory", Ut = {
898
+ })), Wt = H ? "postgres" : "memory", Gt = {
851
899
  kind: "web",
852
900
  meta: {
853
901
  name: f.name ?? "(unnamed)",
854
- voltroVersion: Ct,
902
+ voltroVersion: Et,
855
903
  port: _,
856
- mode: tt(),
904
+ mode: et(),
857
905
  apis: Object.entries(f.apis ?? {}).map(([e, t]) => {
858
906
  let n = {
859
907
  name: e,
@@ -862,10 +910,10 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
862
910
  return t.url !== void 0 && (n.url = t.url), n;
863
911
  })
864
912
  },
865
- routes: Bt,
866
- dirs: Vt,
913
+ routes: Ht,
914
+ dirs: Ut,
867
915
  cache: () => {
868
- let e = Date.now(), t = z.snapshot().map(([t, n]) => ({
916
+ let e = Date.now(), t = B.snapshot().map(([t, n]) => ({
869
917
  key: t,
870
918
  renderedAt: n.renderedAt,
871
919
  expiresAt: n.expiresAt,
@@ -876,16 +924,16 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
876
924
  staleWhileRevalidateMs: n.staleWhileRevalidateMs
877
925
  }));
878
926
  return {
879
- backend: Ht,
880
- size: z.size(),
927
+ backend: Wt,
928
+ size: B.size(),
881
929
  entries: t
882
930
  };
883
931
  },
884
- metrics: () => st()
885
- }, Wt = async (e, n) => {
932
+ metrics: () => ot()
933
+ }, Kt = async (e, n) => {
886
934
  let r = e.split("?")[0] ?? "/";
887
935
  if (f.name === "voltroDashboard" && r === "/api/dashboard/registry") try {
888
- let e = await Ge();
936
+ let e = await We();
889
937
  return {
890
938
  status: 200,
891
939
  headers: { "content-type": "application/json; charset=utf-8" },
@@ -927,8 +975,8 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
927
975
  body: JSON.stringify({ apps: t })
928
976
  };
929
977
  }
930
- if (jt !== null && r === "/_voltro/og") {
931
- let t = await jt.handle(new URL(e, "http://localhost"));
978
+ if (Z !== null && r === "/_voltro/og") {
979
+ let t = await Z.handle(new URL(e, "http://localhost"));
932
980
  if (t !== null) return {
933
981
  status: t.status,
934
982
  headers: { ...t.headers },
@@ -936,18 +984,18 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
936
984
  };
937
985
  }
938
986
  if (r === "/_voltro/inspect/logs") {
939
- let t = A(e, ge(), n);
987
+ let t = j(e, he(), n);
940
988
  return {
941
989
  status: t.status,
942
990
  headers: {
943
991
  "content-type": t.contentType,
944
- ...Oe(n.origin)
992
+ ...De(n.origin)
945
993
  },
946
994
  body: t.body
947
995
  };
948
996
  }
949
997
  if (r !== "/_voltro/inspect/stream") {
950
- let t = ke(e, Ut, n);
998
+ let t = Oe(e, Gt, n);
951
999
  if (t !== null) return {
952
1000
  status: t.status,
953
1001
  headers: {
@@ -957,14 +1005,14 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
957
1005
  body: t.body
958
1006
  };
959
1007
  }
960
- let i = At(r, W), a = i ? q.get(i.route.pattern)?.renderMode : void 0, o = a === "ssr" || a === "isr" || (i ? X.has(i.route.pattern) : !1), s = [];
961
- if (!o && L.length > 0) {
962
- let t = ae(L, {
1008
+ let i = Pt(r, G), a = i ? q.get(i.route.pattern)?.renderMode : void 0, o = a === "ssr" || a === "isr" || (i ? J.has(i.route.pattern) : !1), s = [];
1009
+ if (!o && R.length > 0) {
1010
+ let t = ie(R, {
963
1011
  route: void 0,
964
1012
  pathname: r
965
1013
  });
966
1014
  if (t !== void 0) {
967
- let i = await ie(t, {
1015
+ let i = await re(t, {
968
1016
  pathname: r,
969
1017
  search: e.slice(r.length),
970
1018
  headers: n,
@@ -977,14 +1025,14 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
977
1025
  let c = (e) => s.length === 0 ? e : {
978
1026
  ...e,
979
1027
  "set-cookie": s.map(d)
980
- }, u = r === "/" ? R(b, "index.html") : R(b, r.replace(/^\//, ""), "index.html");
981
- if (!o && await Z(u)) {
982
- let e = await B.readFile(u);
1028
+ }, u = r === "/" ? z(b, "index.html") : z(b, r.replace(/^\//, ""), "index.html");
1029
+ if (!o && await X(u)) {
1030
+ let e = await V.readFile(u);
983
1031
  return {
984
1032
  status: 200,
985
1033
  headers: c({
986
1034
  "content-type": "text/html; charset=utf-8",
987
- "cache-control": Qe(M)
1035
+ "cache-control": Ze(N)
988
1036
  }),
989
1037
  body: e
990
1038
  };
@@ -995,39 +1043,39 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
995
1043
  body: "not found"
996
1044
  };
997
1045
  if (/\.[a-z0-9]+$/i.test(r)) {
998
- let e = R(b, r.replace(/^\//, ""));
999
- if (await Z(e)) {
1000
- let t = $e(r, M), i = at(n["accept-encoding"]), a = i === "br" ? `${e}.br` : i === "gzip" ? `${e}.gz` : void 0;
1001
- if (a !== void 0 && await Z(a)) {
1002
- let n = await B.readFile(e);
1046
+ let e = z(b, r.replace(/^\//, ""));
1047
+ if (await X(e)) {
1048
+ let t = Qe(r, N), i = it(n["accept-encoding"]), a = i === "br" ? `${e}.br` : i === "gzip" ? `${e}.gz` : void 0;
1049
+ if (a !== void 0 && await X(a)) {
1050
+ let n = await V.readFile(e);
1003
1051
  return {
1004
1052
  status: 200,
1005
1053
  headers: c({
1006
- "content-type": Et(e),
1054
+ "content-type": At(e),
1007
1055
  "cache-control": t,
1008
1056
  "content-encoding": i === "br" ? "br" : "gzip",
1009
1057
  vary: "Accept-Encoding",
1010
1058
  etag: mt(n)
1011
1059
  }),
1012
- body: await B.readFile(a)
1060
+ body: await V.readFile(a)
1013
1061
  };
1014
1062
  }
1015
- let o = await B.readFile(e);
1063
+ let o = await V.readFile(e);
1016
1064
  return {
1017
1065
  status: 200,
1018
1066
  headers: c({
1019
- "content-type": Et(e),
1067
+ "content-type": At(e),
1020
1068
  "cache-control": t
1021
1069
  }),
1022
1070
  body: o
1023
1071
  };
1024
1072
  }
1025
1073
  }
1026
- let p = At(r, W);
1074
+ let p = Pt(r, G);
1027
1075
  if (!p) {
1028
- let i = ce(U, r);
1076
+ let i = se(W, r);
1029
1077
  if (i !== void 0) try {
1030
- let a = await Pt({
1078
+ let a = await Lt({
1031
1079
  provider: K,
1032
1080
  root: t,
1033
1081
  route: {
@@ -1040,13 +1088,13 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
1040
1088
  },
1041
1089
  params: {},
1042
1090
  pathname: r,
1043
- dirs: U,
1044
- shellTemplate: D,
1091
+ dirs: W,
1092
+ shellTemplate: O,
1045
1093
  requestHeaders: n,
1046
- apiOrigin: N,
1047
- apiName: P,
1048
- middlewares: L,
1049
- onCookieWarning: I,
1094
+ apiOrigin: P,
1095
+ apiName: F,
1096
+ middlewares: R,
1097
+ onCookieWarning: L,
1050
1098
  requestUrl: e,
1051
1099
  buffered: !0,
1052
1100
  forceSsrRender: !0
@@ -1071,7 +1119,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
1071
1119
  body: "not found"
1072
1120
  };
1073
1121
  }
1074
- let m = q.get(p.route.pattern), te = n["x-tenant"] ?? "anonymous", g = (await K.getHelpers()).i18n?.resolve(n.cookie, n["accept-language"])?.locale, _ = He(r, {
1122
+ let m = q.get(p.route.pattern), te = n["x-tenant"] ?? "anonymous", g = (await K.getHelpers()).i18n?.resolve(n.cookie, n["accept-language"])?.locale, _ = Ve(r, {
1075
1123
  ...m?.tenantAware ? { tenant: te } : {},
1076
1124
  ...g ? { locale: g } : {}
1077
1125
  }), v = m?.ppr === !0 && m.renderMode === "isr", y = (i, a) => ({
@@ -1086,23 +1134,23 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
1086
1134
  ...a
1087
1135
  }), o.write(i), (async () => {
1088
1136
  try {
1089
- let i = await Pt({
1137
+ let i = await Lt({
1090
1138
  provider: K,
1091
1139
  root: t,
1092
1140
  route: p.route,
1093
1141
  params: p.params,
1094
1142
  pathname: r,
1095
- dirs: U,
1096
- shellTemplate: J.get(p.route.pattern) ?? D,
1143
+ dirs: W,
1144
+ shellTemplate: bt.get(p.route.pattern) ?? O,
1097
1145
  requestHeaders: n,
1098
- apiOrigin: N,
1099
- apiName: P,
1100
- middlewares: L,
1101
- onCookieWarning: I,
1146
+ apiOrigin: P,
1147
+ apiName: F,
1148
+ middlewares: R,
1149
+ onCookieWarning: L,
1102
1150
  requestUrl: e,
1103
1151
  holesOnly: !0
1104
1152
  });
1105
- i !== null && "holes" in i ? await me({
1153
+ i !== null && "holes" in i ? await pe({
1106
1154
  loader: i.holes.loader,
1107
1155
  ctx: i.holes.ctx,
1108
1156
  res: o,
@@ -1115,56 +1163,56 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
1115
1163
  }
1116
1164
  })();
1117
1165
  }
1118
- }), x = z.get(_), S = Date.now();
1119
- if (x && Ue(x, S)) return h.emit("cache", {
1166
+ }), x = B.get(_), C = Date.now();
1167
+ if (x && He(x, C)) return h.emit("cache", {
1120
1168
  kind: "HIT",
1121
1169
  key: _,
1122
- ageMs: S - x.renderedAt
1170
+ ageMs: C - x.renderedAt
1123
1171
  }), v ? y(x.html, {
1124
- "cache-control": Ze(M, x.revalidateMs, x.staleWhileRevalidateMs),
1172
+ "cache-control": Xe(N, x.revalidateMs, x.staleWhileRevalidateMs),
1125
1173
  "x-voltro-cache": "HIT",
1126
1174
  "x-voltro-cache-key": _,
1127
- "x-voltro-cache-age-ms": String(S - x.renderedAt)
1175
+ "x-voltro-cache-age-ms": String(C - x.renderedAt)
1128
1176
  }) : {
1129
1177
  status: 200,
1130
1178
  headers: {
1131
1179
  "content-type": "text/html; charset=utf-8",
1132
- "cache-control": Ze(M, x.revalidateMs, x.staleWhileRevalidateMs),
1180
+ "cache-control": Xe(N, x.revalidateMs, x.staleWhileRevalidateMs),
1133
1181
  "x-voltro-rendered-by": "isr",
1134
1182
  "x-voltro-cache": "HIT",
1135
1183
  "x-voltro-cache-key": _,
1136
- "x-voltro-cache-age-ms": String(S - x.renderedAt)
1184
+ "x-voltro-cache-age-ms": String(C - x.renderedAt)
1137
1185
  },
1138
1186
  body: x.html
1139
1187
  };
1140
- if (x && Be(x, S)) {
1188
+ if (x && ze(x, C)) {
1141
1189
  h.emit("cache", {
1142
1190
  kind: "STALE",
1143
1191
  key: _,
1144
- ageMs: S - x.renderedAt
1192
+ ageMs: C - x.renderedAt
1145
1193
  });
1146
- let i = z.generation(_);
1194
+ let i = B.generation(_);
1147
1195
  return (async () => {
1148
1196
  try {
1149
- let a = await Pt({
1197
+ let a = await Lt({
1150
1198
  provider: K,
1151
1199
  root: t,
1152
1200
  route: p.route,
1153
1201
  params: p.params,
1154
1202
  pathname: r,
1155
- dirs: U,
1156
- shellTemplate: J.get(p.route.pattern) ?? D,
1203
+ dirs: W,
1204
+ shellTemplate: bt.get(p.route.pattern) ?? O,
1157
1205
  requestHeaders: n,
1158
- apiOrigin: N,
1159
- apiName: P,
1160
- middlewares: L,
1161
- onCookieWarning: I,
1206
+ apiOrigin: P,
1207
+ apiName: F,
1208
+ middlewares: R,
1209
+ onCookieWarning: L,
1162
1210
  requestUrl: e,
1163
1211
  buffered: !0
1164
1212
  });
1165
1213
  if (a && "html" in a && a.renderMode === "isr" && a.revalidateMs !== null) {
1166
1214
  let e = q.get(p.route.pattern)?.staleWhileRevalidateMs ?? 0, t = Date.now();
1167
- z.set(_, {
1215
+ B.set(_, {
1168
1216
  html: a.html,
1169
1217
  renderedAt: t,
1170
1218
  expiresAt: t + a.revalidateMs,
@@ -1177,37 +1225,37 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
1177
1225
  Y.warn("background SWR refresh failed", { url: r }, e);
1178
1226
  }
1179
1227
  })(), v ? y(x.html, {
1180
- "cache-control": Ze(M, x.revalidateMs, x.staleWhileRevalidateMs),
1228
+ "cache-control": Xe(N, x.revalidateMs, x.staleWhileRevalidateMs),
1181
1229
  "x-voltro-cache": "STALE",
1182
1230
  "x-voltro-cache-key": _,
1183
- "x-voltro-cache-age-ms": String(S - x.renderedAt)
1231
+ "x-voltro-cache-age-ms": String(C - x.renderedAt)
1184
1232
  }) : {
1185
1233
  status: 200,
1186
1234
  headers: {
1187
1235
  "content-type": "text/html; charset=utf-8",
1188
- "cache-control": Ze(M, x.revalidateMs, x.staleWhileRevalidateMs),
1236
+ "cache-control": Xe(N, x.revalidateMs, x.staleWhileRevalidateMs),
1189
1237
  "x-voltro-rendered-by": "isr",
1190
1238
  "x-voltro-cache": "STALE",
1191
1239
  "x-voltro-cache-key": _,
1192
- "x-voltro-cache-age-ms": String(S - x.renderedAt)
1240
+ "x-voltro-cache-age-ms": String(C - x.renderedAt)
1193
1241
  },
1194
1242
  body: x.html
1195
1243
  };
1196
1244
  }
1197
1245
  try {
1198
- let i = z.generation(_), a = await Pt({
1246
+ let i = B.generation(_), a = await Lt({
1199
1247
  provider: K,
1200
1248
  root: t,
1201
1249
  route: p.route,
1202
1250
  params: p.params,
1203
1251
  pathname: r,
1204
- dirs: U,
1205
- shellTemplate: J.get(p.route.pattern) ?? D,
1252
+ dirs: W,
1253
+ shellTemplate: bt.get(p.route.pattern) ?? O,
1206
1254
  requestHeaders: n,
1207
- apiOrigin: N,
1208
- apiName: P,
1209
- middlewares: L,
1210
- onCookieWarning: I,
1255
+ apiOrigin: P,
1256
+ apiName: F,
1257
+ middlewares: R,
1258
+ onCookieWarning: L,
1211
1259
  requestUrl: e
1212
1260
  });
1213
1261
  if (!a) return {
@@ -1216,7 +1264,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
1216
1264
  "content-type": "text/html; charset=utf-8",
1217
1265
  "x-voltro-rendered-by": "spa-fallback"
1218
1266
  },
1219
- body: D
1267
+ body: O
1220
1268
  };
1221
1269
  let o = a.setCookies ?? [], s = a.responseHeaders ?? {}, c = (e) => ({
1222
1270
  ...s,
@@ -1251,7 +1299,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
1251
1299
  });
1252
1300
  if (a.renderMode === "isr" && a.revalidateMs !== null) {
1253
1301
  let e = Date.now(), t = q.get(p.route.pattern)?.staleWhileRevalidateMs ?? 0;
1254
- z.set(_, {
1302
+ B.set(_, {
1255
1303
  html: a.html,
1256
1304
  renderedAt: e,
1257
1305
  expiresAt: e + a.revalidateMs,
@@ -1277,7 +1325,10 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
1277
1325
  body: a.html
1278
1326
  };
1279
1327
  } catch (e) {
1280
- return Y.error("render error", { url: r }, e), ne(e) ? {
1328
+ return Y.error("render error", { url: r }, e), Bt?.(e, {
1329
+ stage: "render",
1330
+ pathname: r
1331
+ }), S(e) ? {
1281
1332
  status: 500,
1282
1333
  headers: {
1283
1334
  "content-type": "text/plain; charset=utf-8",
@@ -1297,16 +1348,16 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
1297
1348
  body: "server error"
1298
1349
  };
1299
1350
  }
1300
- }, Gt = !1, Kt = i(f.health, () => Gt), qt = p({
1301
- apiName: P,
1302
- apiOrigin: N,
1351
+ }, qt = !1, Jt = i(f.health, () => qt), Yt = p({
1352
+ apiName: F,
1353
+ apiOrigin: P,
1303
1354
  loadDescriptors: async () => {
1304
- if (P === void 0) return;
1305
- let e = (await K.getHelpers()).apiDescriptors?.[P];
1355
+ if (F === void 0) return;
1356
+ let e = (await K.getHelpers()).apiDescriptors?.[F];
1306
1357
  return e === void 0 ? void 0 : await e();
1307
1358
  },
1308
- rpcQuery: (e, t) => xe(N, e, {
1309
- apiName: P,
1359
+ rpcQuery: (e, t) => be(P, e, {
1360
+ apiName: F,
1310
1361
  headers: t
1311
1362
  }),
1312
1363
  resolveLocale: async (e, t) => {
@@ -1314,42 +1365,42 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
1314
1365
  return r === void 0 ? n.i18n?.resolve(e.cookie, e["accept-language"])?.locale ?? "en" : r;
1315
1366
  },
1316
1367
  renderErrorPage: async ({ path: e, headers: n, flash: r }) => {
1317
- let { pathname: i } = be(e), a = At(i, W);
1368
+ let { pathname: i } = ye(e), a = Pt(i, G);
1318
1369
  if (!a) return;
1319
- let o = await Pt({
1370
+ let o = await Lt({
1320
1371
  provider: K,
1321
1372
  root: t,
1322
1373
  route: a.route,
1323
1374
  params: a.params,
1324
1375
  pathname: i,
1325
- dirs: U,
1326
- shellTemplate: D,
1376
+ dirs: W,
1377
+ shellTemplate: O,
1327
1378
  requestHeaders: n,
1328
- apiOrigin: N,
1329
- apiName: P,
1330
- middlewares: L,
1331
- onCookieWarning: I,
1379
+ apiOrigin: P,
1380
+ apiName: F,
1381
+ middlewares: R,
1382
+ onCookieWarning: L,
1332
1383
  requestUrl: e,
1333
1384
  formFlash: r,
1334
1385
  buffered: !0
1335
1386
  });
1336
1387
  return o !== null && "html" in o ? o.html : void 0;
1337
1388
  }
1338
- }), Jt = ot(f), Yt = ut(async (e, t) => {
1389
+ }), Xt = at(f), Zt = ut(async (e, t) => {
1339
1390
  let n = e.url ?? "/", i = Date.now(), a = {};
1340
1391
  for (let [t, n] of Object.entries(e.headers)) n !== void 0 && (a[t.toLowerCase()] = Array.isArray(n) ? n.join(", ") : n);
1341
- let o = n.split("?")[0] ?? "/", s = (e.method ?? "GET").toUpperCase(), c = he(Kt, o);
1392
+ let o = n.split("?")[0] ?? "/", s = (e.method ?? "GET").toUpperCase(), c = me(Jt, o);
1342
1393
  if (c !== void 0) {
1343
- let e = await y(Kt, c);
1394
+ let e = await y(Jt, c);
1344
1395
  t.writeHead(e.status, {
1345
1396
  "content-type": "text/plain",
1346
1397
  "cache-control": "no-store"
1347
1398
  }), t.end(e.body);
1348
1399
  return;
1349
1400
  }
1350
- if (!(o.startsWith(x) && await qt(e, t))) {
1401
+ if (!(o.startsWith(x) && await Yt(e, t))) {
1351
1402
  if (s === "OPTIONS" && o.startsWith("/_voltro/inspect")) {
1352
- let e = Oe(a.origin);
1403
+ let e = De(a.origin);
1353
1404
  t.writeHead(204, e), t.end();
1354
1405
  return;
1355
1406
  }
@@ -1359,13 +1410,13 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
1359
1410
  t.writeHead(400, { "content-type": "text/plain" }), t.end("missing ?target=");
1360
1411
  return;
1361
1412
  }
1362
- if (!F(r)) {
1413
+ if (!I(r)) {
1363
1414
  t.writeHead(400, { "content-type": "text/plain" }), t.end("target not allowed: must be loopback or an origin configured in VOLTRO_DASHBOARD_APPS");
1364
1415
  return;
1365
1416
  }
1366
1417
  try {
1367
1418
  let n = { accept: a.accept ?? "application/json" }, i = a.authorization;
1368
- i ? n.authorization = Array.isArray(i) ? i[0] : i : De(r) && process.env.VOLTRO_INSPECT_TOKEN && (n.authorization = `Bearer ${process.env.VOLTRO_INSPECT_TOKEN}`);
1419
+ i ? n.authorization = Array.isArray(i) ? i[0] : i : Ee(r) && process.env.VOLTRO_INSPECT_TOKEN && (n.authorization = `Bearer ${process.env.VOLTRO_INSPECT_TOKEN}`);
1369
1420
  let o;
1370
1421
  if (s && s !== "GET" && s !== "HEAD") {
1371
1422
  let t = [];
@@ -1395,14 +1446,14 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
1395
1446
  t.writeHead(400, { "content-type": "text/plain" }), t.end("missing ?target=");
1396
1447
  return;
1397
1448
  }
1398
- if (!F(r)) {
1449
+ if (!I(r)) {
1399
1450
  t.writeHead(400, { "content-type": "text/plain" }), t.end("target not allowed: must be loopback or an origin configured in VOLTRO_DASHBOARD_APPS");
1400
1451
  return;
1401
1452
  }
1402
1453
  let i = new AbortController();
1403
1454
  e.on("close", () => i.abort()), t.on("close", () => i.abort());
1404
1455
  try {
1405
- let e = Ee(a, r), n = await fetch(r, {
1456
+ let e = Te(a, r), n = await fetch(r, {
1406
1457
  redirect: "manual",
1407
1458
  method: "GET",
1408
1459
  headers: {
@@ -1437,15 +1488,15 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
1437
1488
  return;
1438
1489
  }
1439
1490
  if (o === "/_voltro/inspect/stream") {
1440
- let n = Oe(a.origin);
1441
- if (Ae()) {
1491
+ let n = De(a.origin);
1492
+ if (ke()) {
1442
1493
  t.writeHead(503, {
1443
1494
  "content-type": "application/json",
1444
1495
  ...n
1445
1496
  }), t.end(JSON.stringify({ error: "inspect disabled (VOLTRO_INSPECT=off)" }));
1446
1497
  return;
1447
1498
  }
1448
- let i = je(a, "GET");
1499
+ let i = Ae(a, "GET");
1449
1500
  if (!i.ok) {
1450
1501
  t.writeHead(401, {
1451
1502
  "content-type": "application/json",
@@ -1467,7 +1518,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
1467
1518
  let o = h.subscribe((e) => {
1468
1519
  t.write(r(e));
1469
1520
  }), s = setInterval(() => {
1470
- t.write(Ce());
1521
+ t.write(Se());
1471
1522
  }, 15e3), c = () => {
1472
1523
  clearInterval(s), o();
1473
1524
  };
@@ -1475,14 +1526,14 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
1475
1526
  return;
1476
1527
  }
1477
1528
  try {
1478
- let e = await Wt(n, a);
1529
+ let e = await Kt(n, a);
1479
1530
  if (e.stream ? e.stream(t) : ht({
1480
1531
  response: t,
1481
1532
  status: e.status,
1482
1533
  headers: e.headers,
1483
1534
  body: e.body,
1484
1535
  requestHeaders: a,
1485
- compression: ve.compression
1536
+ compression: _e.compression
1486
1537
  }) || (t.writeHead(e.status, e.headers), t.end(e.body)), !o.startsWith("/_voltro/inspect")) {
1487
1538
  let t = Date.now() - i;
1488
1539
  h.emit("request", {
@@ -1492,8 +1543,8 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
1492
1543
  renderedBy: e.headers["x-voltro-rendered-by"],
1493
1544
  cache: e.headers["x-voltro-cache"]
1494
1545
  });
1495
- let n = At(o, W)?.route.pattern ?? (e.status === 404 ? "<unmatched>" : "<asset>");
1496
- zt.record({
1546
+ let n = Pt(o, G)?.route.pattern ?? (e.status === 404 ? "<unmatched>" : "<asset>");
1547
+ Vt.record({
1497
1548
  kind: "request",
1498
1549
  tag: n,
1499
1550
  durationMs: t,
@@ -1505,77 +1556,77 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
1505
1556
  }
1506
1557
  }
1507
1558
  });
1508
- await new Promise((e) => Yt.listen(_, "::", e)), Gt = !0, n.mark("ready"), it(Yt, Jt), Y.info(`listening on http://localhost:${_}`, {
1559
+ await new Promise((e) => Zt.listen(_, "::", e)), qt = !0, n.mark("ready"), rt(Zt, Xt), Y.info(`listening on http://localhost:${_}`, {
1509
1560
  port: _,
1510
1561
  distDir: b
1511
1562
  }), Y.debug("dynamic + ssr/isr routes resolve via SSR loader");
1512
1563
  try {
1513
- await We({
1514
- id: T,
1515
- name: w,
1564
+ await Ue({
1565
+ id: E,
1566
+ name: T,
1516
1567
  kind: "web",
1517
1568
  url: `http://localhost:${_}`,
1518
1569
  pid: process.pid,
1519
1570
  status: "live",
1520
- logFile: E.path
1571
+ logFile: D.path
1521
1572
  });
1522
- let e = Se(t);
1573
+ let e = xe(t);
1523
1574
  if (e) {
1524
- let t = await ye({ dashboardAppPath: e });
1575
+ let t = await ve({ dashboardAppPath: e });
1525
1576
  t.status === "launched" ? Y.info(`dashboard launched at http://localhost:${t.port}`, { port: t.port }) : t.status === "already-running" && Y.debug(`dashboard already running on :${t.port}`, { port: t.port });
1526
1577
  }
1527
1578
  setInterval(() => {
1528
- We({
1529
- id: T,
1530
- name: w,
1579
+ Ue({
1580
+ id: E,
1581
+ name: T,
1531
1582
  kind: "web",
1532
1583
  url: `http://localhost:${_}`,
1533
1584
  pid: process.pid,
1534
1585
  status: "live",
1535
- logFile: E.path
1586
+ logFile: D.path
1536
1587
  }).catch(() => {});
1537
1588
  }, 1e4).unref();
1538
1589
  } catch (e) {
1539
1590
  Y.warn("runtime-registry write failed", {}, e);
1540
1591
  }
1541
- et({
1592
+ $e({
1542
1593
  app: f.name ?? "unnamed",
1543
1594
  kind: "web",
1544
1595
  url: `http://localhost:${_}`,
1545
1596
  bootMs: n.total()
1546
1597
  });
1547
- let Xt = n.phaseBreakdown();
1598
+ let Qt = n.phaseBreakdown();
1548
1599
  Y.info(`start: ready in ${n.total()}ms`, {
1549
1600
  bootMs: n.total(),
1550
- ...Xt ? { phases: Xt } : {}
1601
+ ...Qt ? { phases: Qt } : {}
1551
1602
  });
1552
- let Zt = !1, Qt = (e) => async () => {
1553
- if (!Zt) {
1554
- if (Zt = !0, Y.info(`received ${e}, shutting down`, { signal: e }), Yt.close(), await Q.stop(), $) try {
1555
- $();
1603
+ let $t = !1, en = (e) => async () => {
1604
+ if (!$t) {
1605
+ if ($t = !0, Y.info(`received ${e}, shutting down`, { signal: e }), Zt.close(), await Ft.stop(), Q) try {
1606
+ Q();
1556
1607
  } catch {}
1557
- if (Rt) try {
1558
- await ct.runPromise(Rt.close());
1608
+ if ($) try {
1609
+ await st.runPromise($.close());
1559
1610
  } catch {}
1560
- if (V) try {
1561
- await V.end();
1611
+ if (H) try {
1612
+ await H.end();
1562
1613
  } catch {}
1563
- await K.close(), await Ke(T), await E.dispose(), process.exit(0);
1614
+ await K.close(), await Ge(E), await D.dispose(), process.exit(0);
1564
1615
  }
1565
1616
  };
1566
- process.on("SIGINT", Qt("SIGINT")), process.on("SIGTERM", Qt("SIGTERM"));
1567
- let $t = process.ppid;
1568
- if ($t > 1) {
1617
+ process.on("SIGINT", en("SIGINT")), process.on("SIGTERM", en("SIGTERM"));
1618
+ let tn = process.ppid;
1619
+ if (tn > 1) {
1569
1620
  let e = setInterval(() => {
1570
- (process.ppid !== $t || process.ppid === 1) && (clearInterval(e), Qt("SIGTERM")());
1621
+ (process.ppid !== tn || process.ppid === 1) && (clearInterval(e), en("SIGTERM")());
1571
1622
  }, 2e3);
1572
1623
  e.unref();
1573
1624
  }
1574
1625
  return new Promise(() => {});
1575
- }, $ = async (e) => {
1576
- rt("start"), t("start");
1577
- let n = e.find((e) => !e.startsWith("-")) ?? process.cwd(), r = await Lt(z(n));
1626
+ }, Vt = async (e) => {
1627
+ nt("start"), t("start");
1628
+ let n = e.find((e) => !e.startsWith("-")) ?? process.cwd(), r = await $(B(n));
1578
1629
  return r.ran ? r.exitCode : (Y.error("no web app found at this path"), 1);
1579
1630
  };
1580
1631
  //#endregion
1581
- export { Lt as n, $ as t };
1632
+ export { $ as n, Vt as t };