@voltro/cli 0.39.1 → 0.41.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 (110) hide show
  1. package/CHANGELOG.md +232 -0
  2. package/dist/agentsMd-Bu_XQgVf.js +2 -0
  3. package/dist/{agentsMd-7zI2h5l9.js → agentsMd-D6yD7IQv.js} +31 -14
  4. package/dist/{apiBuild-D9FB13_2.js → apiBuild-B_iH24qf.js} +2 -2
  5. package/dist/apiBuild-RM5W5YXk.js +2 -0
  6. package/dist/bin.js +1 -1
  7. package/dist/{build-DORV5mLM.js → build-DUdi6F_Q.js} +100 -97
  8. package/dist/{checkCommand-D9qK_gtA.js → checkCommand-B2RWrpWi.js} +1 -1
  9. package/dist/{checkCommand-Bf6oMao4.js → checkCommand-DWL2_PPR.js} +2 -2
  10. package/dist/{cloudCmd-C42gaO8s.js → cloudCmd-F4YJeqM3.js} +1 -1
  11. package/dist/{codegenCommand-CxOyKmc1.js → codegenCommand-DkjoJ30Q.js} +2 -2
  12. package/dist/{codemodRunner-D-jTyvWo.js → codemodRunner-sFuWDETH.js} +520 -357
  13. package/dist/{commands-D6aW_6AR.js → commands-D0VR1yBB.js} +32 -32
  14. package/dist/{dashboardCommand-CwTZh-XZ.js → dashboardCommand-Bro7Jwts.js} +3 -3
  15. package/dist/{dataCommand-Cc9RiLQZ.js → dataCommand-OKC5FscP.js} +183 -172
  16. package/dist/{dbCommand-DSwGv9wS.js → dbCommand-BHRamDsy.js} +441 -414
  17. package/dist/dbCommand-C9iE1pd9.js +2 -0
  18. package/dist/{dev-3mgc8c-H.js → dev-D4l_YOzI.js} +1570 -1570
  19. package/dist/{dev-CjJAasDs.js → dev-DuqBJC7g.js} +1 -1
  20. package/dist/doctorCommand-Bw3V4L1j.js +2 -0
  21. package/dist/{doctorCommand-oLuzc-aC.js → doctorCommand-TmZTAepc.js} +386 -280
  22. package/dist/{dormancyCommand-Bxe4WtHU.js → dormancyCommand-CUKhRmGG.js} +1 -1
  23. package/dist/{embeddingsCommand-CyNQkFIc.js → embeddingsCommand-Db-iQM3l.js} +1 -1
  24. package/dist/{envCommand-CAkSgBbh.js → envCommand-DQ_URZq9.js} +14 -14
  25. package/dist/{evolveCommand-CWhBoe_P.js → evolveCommand-CghRPrGO.js} +2 -2
  26. package/dist/index.js +1 -1
  27. package/dist/{infoCommand-CTo8Jnhq.js → infoCommand-BCs_ZFnl.js} +1 -1
  28. package/dist/{metaCommands-DUYR--Ts.js → metaCommands-CfRLra0s.js} +1 -1
  29. package/dist/{migrate-BnPw2zC8.js → migrate-DLtPv2_D.js} +1 -1
  30. package/dist/{projectScaffold-BEhhHjPr.js → projectScaffold-BIl97_E6.js} +1 -1
  31. package/dist/{projectScaffold-BvhLOrLq.js → projectScaffold-mIX_DpSe.js} +1 -1
  32. package/dist/{runtimeTrace-gNXeLf6H.js → runtimeTrace-jFKvOPBz.js} +1 -1
  33. package/dist/{sdkgen-C8zz10-X.js → sdkgen-COQqHB9V.js} +1 -1
  34. package/dist/{serveCommand-BpK8-m1N.js → serveCommand-Cba_M2Su.js} +656 -656
  35. package/dist/serveCommand-DRbYK646.js +2 -0
  36. package/dist/serveEntry.js +1 -1
  37. package/dist/{start-ft_KzFTd.js → start-BjcuFME_.js} +421 -361
  38. package/dist/{start-BNuTWdRd.js → start-fifc0xpW.js} +1 -1
  39. package/dist/startEntry.js +1 -1
  40. package/dist/updateCommand-B2alql9k.js +2 -0
  41. package/dist/{updateCommand-CHBmCB17.js → updateCommand-HZQVBU3T.js} +1 -1
  42. package/dist/webDev-D6QeXw3P.js +2 -0
  43. package/dist/{webDev-CTpSY-e_.js → webDev-Dk8lFUzf.js} +672 -501
  44. package/dist/{webhooksCommand-EccPZQZ4.js → webhooksCommand-D7ZpH7w0.js} +1 -1
  45. package/package.json +35 -17
  46. package/templates/AGENTS.md +1 -1
  47. package/templates/agent-docs/_index.md +1 -1
  48. package/templates/agent-docs/_manifest.json +1 -1
  49. package/templates/agent-docs/cli.md +6 -0
  50. package/templates/agent-docs/data.md +43 -0
  51. package/templates/agent-docs/plugins/governance.md +8 -0
  52. package/templates/agent-docs/routing.md +153 -0
  53. package/templates/agent-docs/security.md +24 -0
  54. package/templates/agent-docs/whats-new.md +49 -27
  55. package/templates/apps/api-ai/package.json +7 -7
  56. package/templates/apps/api-auth/package.json +8 -8
  57. package/templates/apps/api-backend/package.json +7 -7
  58. package/templates/apps/api-backend-deactivation/package.json +7 -7
  59. package/templates/apps/api-backend-mail/package.json +8 -8
  60. package/templates/apps/api-backend-mariadb/package.json +9 -9
  61. package/templates/apps/api-backend-sqlite/package.json +8 -8
  62. package/templates/apps/api-backend-storage/package.json +8 -8
  63. package/templates/apps/api-cms/package.json +10 -10
  64. package/templates/apps/api-collab/package.json +8 -8
  65. package/templates/apps/api-data-advanced/package.json +8 -8
  66. package/templates/apps/api-durable/package.json +8 -8
  67. package/templates/apps/api-durable/tests/orders.place.test.ts +17 -4
  68. package/templates/apps/api-feature-flags/package.json +9 -9
  69. package/templates/apps/api-governance/package.json +8 -8
  70. package/templates/apps/api-kv/package.json +8 -8
  71. package/templates/apps/api-moderation/package.json +8 -8
  72. package/templates/apps/api-observability/package.json +8 -8
  73. package/templates/apps/api-ratelimit/package.json +8 -8
  74. package/templates/apps/api-rbac/package.json +8 -8
  75. package/templates/apps/api-rest/package.json +7 -7
  76. package/templates/apps/api-saas/package.json +11 -11
  77. package/templates/apps/api-saas-starter/package.json +10 -10
  78. package/templates/apps/api-search/package.json +8 -8
  79. package/templates/apps/api-status/package.json +8 -8
  80. package/templates/apps/api-versioning/package.json +8 -8
  81. package/templates/apps/api-webhooks/package.json +9 -9
  82. package/templates/apps/changelog/package.json +6 -6
  83. package/templates/apps/changelog/src/pages/[slug]/page.test.tsx +8 -1
  84. package/templates/apps/edge-functions/package.json +2 -2
  85. package/templates/apps/frontend-admin/package.json +8 -8
  86. package/templates/apps/frontend-app/package.json +9 -9
  87. package/templates/apps/frontend-auth/package.json +8 -8
  88. package/templates/apps/frontend-blank/package.json +7 -7
  89. package/templates/apps/frontend-cms/package.json +9 -9
  90. package/templates/apps/frontend-collab/package.json +10 -10
  91. package/templates/apps/frontend-contact/package.json +7 -7
  92. package/templates/apps/frontend-dashboard/package.json +7 -7
  93. package/templates/apps/frontend-docs/package.json +7 -7
  94. package/templates/apps/frontend-i18n/package.json +6 -6
  95. package/templates/apps/frontend-landing/package.json +7 -7
  96. package/templates/apps/frontend-portal/package.json +8 -8
  97. package/templates/apps/frontend-saas/package.json +8 -8
  98. package/templates/apps/frontend-spa/package.json +7 -7
  99. package/templates/apps/frontend-ssr/package.json +7 -7
  100. package/templates/apps/frontend-ssr-api/package.json +8 -8
  101. package/templates/apps/frontend-static-blog/package.json +6 -6
  102. package/templates/apps/frontend-status/package.json +8 -8
  103. package/templates/apps/mobile-app/package.json +4 -4
  104. package/dist/agentsMd-BFCXh2gl.js +0 -2
  105. package/dist/apiBuild-BmR_bIxN.js +0 -2
  106. package/dist/dbCommand-DcqEyxju.js +0 -2
  107. package/dist/doctorCommand-Cghssndo.js +0 -2
  108. package/dist/serveCommand-CW-goXvh.js +0 -2
  109. package/dist/updateCommand-6FMU2klq.js +0 -2
  110. package/dist/webDev-id3I5PvG.js +0 -2
@@ -1,21 +1,21 @@
1
1
  import { i as e, t } from "./nodeEnvironment-cGFAj1J8.js";
2
2
  import { r as n } from "./appPort-B_HpJ_ck.js";
3
- import { A as r, B as i, C as a, D as o, E as s, H as c, I as l, J as u, N as d, O as f, P as p, S as m, T as ee, U as h, V as g, a as _, b as v, d as y, f as b, i as x, j as S, k as te, n as ne, q as C, s as re, st as ie, ut as w, w as T, x as ae, y as oe, z as E } from "./webDev-CTpSY-e_.js";
4
- import { o as D, t as O } from "./connectionConfig-Bk9IC7D0.js";
5
- import { A as k, D as A, a as j, h as se, j as M, k as ce } from "./inspect-B7U7Cl_Z.js";
6
- import { a as le, c as N, d as ue, f as de, l as P, p as F, u as fe } from "./renderModeScan-D7J1B7Kw.js";
7
- import { i as pe, n as me, r as he, t as ge } from "./runtimeRegistry-DMeKfTHP.js";
8
- import { n as _e } from "./logFileSink-B4uP8pvf.js";
9
- import { t as ve } from "./inspectMetrics-CfdKLh6t.js";
10
- import { t as ye } from "./bootTiming-BdyP9nYw.js";
11
- import { dirname as be, extname as xe, join as I, resolve as L } from "node:path";
12
- import { promises as R } from "node:fs";
13
- import { fileURLToPath as z, pathToFileURL as Se } from "node:url";
14
- import { createLogger as B, printReadyBlock as Ce } from "@voltro/logger";
15
- import { snapshotMetricsSync as we } from "@voltro/runtime";
16
- import { createServer as Te } from "node:http";
3
+ import { A as r, C as i, D as a, E as o, F as s, H as c, I as l, J as ee, L as u, M as d, N as f, O as te, P as p, R as m, S as h, T as ne, V as g, W as re, X as _, Y as v, Z as y, a as b, b as x, d as S, f as C, ht as w, i as ie, j as T, k as E, n as D, nt as O, q as k, s as ae, tt as A, vt as j, x as oe, y as M, z as se } from "./webDev-Dk8lFUzf.js";
4
+ import { o as N, t as P } from "./connectionConfig-Bk9IC7D0.js";
5
+ import { A as F, D as I, a as ce, h as le, j as ue, k as de } from "./inspect-B7U7Cl_Z.js";
6
+ import { a as fe, c as L, d as pe, f as R, l as me, p as he, u as ge } from "./renderModeScan-D7J1B7Kw.js";
7
+ import { i as _e, n as ve, r as ye, t as be } from "./runtimeRegistry-DMeKfTHP.js";
8
+ import { n as xe } from "./logFileSink-B4uP8pvf.js";
9
+ import { t as Se } from "./inspectMetrics-CfdKLh6t.js";
10
+ import { t as Ce } from "./bootTiming-BdyP9nYw.js";
11
+ import { dirname as we, extname as Te, join as z, resolve as Ee } from "node:path";
12
+ import { promises as B } from "node:fs";
13
+ import { fileURLToPath as V, pathToFileURL as H } from "node:url";
14
+ import { createLogger as U, printReadyBlock as De } from "@voltro/logger";
15
+ import { snapshotMetricsSync as Oe } from "@voltro/runtime";
16
+ import { createServer as ke } from "node:http";
17
17
  //#region src/isrCdcInvalidator.ts
18
- var V = B({ scope: "voltro:start:cdc" }), H = (e) => (t) => {
18
+ var W = U({ scope: "voltro:start:cdc" }), Ae = (e) => (t) => {
19
19
  let n = 0;
20
20
  for (let [r, i] of e.tableSubscriptionsByPattern) {
21
21
  if (!i.includes(t)) continue;
@@ -26,17 +26,17 @@ var V = B({ scope: "voltro:start:cdc" }), H = (e) => (t) => {
26
26
  }));
27
27
  }
28
28
  return n;
29
- }, U = () => O() ? D() : null, Ee = (e) => {
30
- let t = e.channel ?? "framework_changes", n = H(e), r = null, i = null;
29
+ }, G = () => P() ? N() : null, je = (e) => {
30
+ let t = e.channel ?? "framework_changes", n = Ae(e), r = null, i = null;
31
31
  return {
32
32
  start: async () => {
33
33
  if (e.tableSubscriptionsByPattern.size === 0) {
34
- V.debug("skipped — no pages declare cacheInvalidatesOn");
34
+ W.debug("skipped — no pages declare cacheInvalidatesOn");
35
35
  return;
36
36
  }
37
- let a = U();
37
+ let a = G();
38
38
  if (!a) {
39
- V.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()] });
39
+ W.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()] });
40
40
  return;
41
41
  }
42
42
  r = new (await (import("pg"))).default.Client(a), await r.connect(), i = (e) => {
@@ -45,16 +45,16 @@ var V = B({ scope: "voltro:start:cdc" }), H = (e) => (t) => {
45
45
  try {
46
46
  r = JSON.parse(e.payload);
47
47
  } catch (e) {
48
- V.warn("bad CDC payload", {}, e);
48
+ W.warn("bad CDC payload", {}, e);
49
49
  return;
50
50
  }
51
51
  let i = n(r.table);
52
- i > 0 && V.info(`${r.op} on '${r.table}' → dropped ${i} cache entries`, {
52
+ i > 0 && W.info(`${r.op} on '${r.table}' → dropped ${i} cache entries`, {
53
53
  op: r.op,
54
54
  table: r.table,
55
55
  dropped: i
56
56
  });
57
- }, r.on("notification", i), await r.query(`LISTEN ${t}`), V.info(`LISTEN ${t}`, {
57
+ }, r.on("notification", i), await r.query(`LISTEN ${t}`), W.info(`LISTEN ${t}`, {
58
58
  channel: t,
59
59
  ..."connectionString" in a ? { target: a.connectionString.replace(/\/\/[^@/]*@/, "//") } : {
60
60
  host: a.host,
@@ -72,7 +72,7 @@ var V = B({ scope: "voltro:start:cdc" }), H = (e) => (t) => {
72
72
  }
73
73
  }
74
74
  };
75
- }, W = B({ scope: "voltro:start:isr-cache" }), De = "voltro_isr_cache", G = (e) => `
75
+ }, K = U({ scope: "voltro:start:isr-cache" }), q = "voltro_isr_cache", J = (e) => `
76
76
  CREATE TABLE IF NOT EXISTS ${e} (
77
77
  cache_key TEXT PRIMARY KEY,
78
78
  html TEXT NOT NULL,
@@ -83,9 +83,9 @@ CREATE TABLE IF NOT EXISTS ${e} (
83
83
  stale_while_revalidate_ms BIGINT NOT NULL DEFAULT 0
84
84
  );
85
85
  CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
86
- `, Oe = (e) => {
87
- let t = e.tableName ?? De, { client: n } = e, r = /* @__PURE__ */ new Map(), i = !1, a = (async () => {
88
- i || (i = !0, await n.query(G(t)));
86
+ `, Me = (e) => {
87
+ let t = e.tableName ?? q, { client: n } = e, r = /* @__PURE__ */ new Map(), i = !1, a = (async () => {
88
+ i || (i = !0, await n.query(J(t)));
89
89
  })().then(async () => {
90
90
  let e = await n.query(`SELECT * FROM ${t}`);
91
91
  for (let t of e.rows) r.set(t.cache_key, {
@@ -97,10 +97,10 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
97
97
  staleWhileRevalidateMs: Number(t.stale_while_revalidate_ms)
98
98
  });
99
99
  }).catch((e) => {
100
- W.warn("postgres bootstrap failed", {}, e);
100
+ K.warn("postgres bootstrap failed", {}, e);
101
101
  }), o = (e, t) => {
102
102
  a.then(() => n.query(e, t)).catch((e) => {
103
- W.warn("postgres write failed", {}, e);
103
+ K.warn("postgres write failed", {}, e);
104
104
  });
105
105
  };
106
106
  return {
@@ -145,14 +145,14 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
145
145
  return Array.from(r.entries());
146
146
  }
147
147
  };
148
- }, K = B({ scope: "voltro:start" }), ke = await (async () => {
148
+ }, Y = U({ scope: "voltro:start" }), Ne = await (async () => {
149
149
  try {
150
- let e = I(be(z(import.meta.url)), "..", "package.json"), t = await R.readFile(e, "utf8");
150
+ let e = z(we(V(import.meta.url)), "..", "package.json"), t = await B.readFile(e, "utf8");
151
151
  return JSON.parse(t).version ?? "0.0.0";
152
152
  } catch {
153
153
  return "0.0.0";
154
154
  }
155
- })(), Ae = (e) => e instanceof Error && e._voltroControl === "redirect" && typeof e.location == "string", q = (e) => e instanceof Error && e._voltroControl === "not-found", J = {
155
+ })(), Pe = (e) => e instanceof Error && e._voltroControl === "redirect" && typeof e.location == "string", X = (e) => e instanceof Error && e._voltroControl === "not-found", Fe = {
156
156
  ".html": "text/html; charset=utf-8",
157
157
  ".js": "application/javascript",
158
158
  ".mjs": "application/javascript",
@@ -170,13 +170,13 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
170
170
  ".woff": "font/woff",
171
171
  ".woff2": "font/woff2",
172
172
  ".txt": "text/plain; charset=utf-8"
173
- }, je = (e) => J[xe(e).toLowerCase()] ?? "application/octet-stream", Y = (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) => {
173
+ }, Ie = (e) => Fe[Te(e).toLowerCase()] ?? "application/octet-stream", Z = (e) => e.replace(/<script\b(?=[^>]*\btype="module")(?:(?!<\/script>).)*<\/script>/gi, "").replace(/<script\b(?=[^>]*\bsrc=)(?:(?!<\/script>).)*<\/script>/gi, "").replace(/<link\b[^>]*\brel="modulepreload"[^>]*>/gi, ""), Q = async (e) => {
174
174
  try {
175
- return await R.stat(e), !0;
175
+ return await B.stat(e), !0;
176
176
  } catch {
177
177
  return !1;
178
178
  }
179
- }, Me = (e) => {
179
+ }, Le = (e) => {
180
180
  let t = [], n = 0, r = e.split("/").filter(Boolean), i = [];
181
181
  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, "\\$&"));
182
182
  let a = i.join("/");
@@ -185,8 +185,8 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
185
185
  paramNames: t,
186
186
  priority: n
187
187
  };
188
- }, Ne = (e) => e.map((e) => {
189
- let { regex: t, paramNames: n, priority: r } = Me(e.pattern);
188
+ }, Re = (e) => e.map((e) => {
189
+ let { regex: t, paramNames: n, priority: r } = Le(e.pattern);
190
190
  return {
191
191
  pattern: e.pattern,
192
192
  file: e.file,
@@ -195,7 +195,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
195
195
  paramNames: n,
196
196
  priority: r
197
197
  };
198
- }).slice().sort((e, t) => e.priority - t.priority), Z = (e, t) => {
198
+ }).slice().sort((e, t) => e.priority - t.priority), ze = (e, t) => {
199
199
  for (let n of t) {
200
200
  let t = n.regex.exec(e);
201
201
  if (!t) continue;
@@ -207,188 +207,210 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
207
207
  };
208
208
  }
209
209
  return null;
210
- }, Pe = async (e) => {
211
- let { provider: t, route: n, params: i, pathname: c, dirs: l, shellTemplate: u, requestHeaders: d, requestUrl: p = "", apiOrigin: ee, apiName: h } = e, { search: g } = r(p), v = x(ee, d.cookie, { apiName: h }), y = await t.getPage(n.pattern, n.file), b = N(y, n.file), S = b === "spa" && re(l, n.dirChain).some((e) => e.hasLayout);
212
- if (b !== "ssr" && b !== "isr" && !S) return null;
213
- let ne = re(l, n.dirChain), C = {}, ie = null, w, oe = new AbortController();
210
+ }, Be = async (e) => {
211
+ let { provider: t, route: n, params: i, pathname: c, dirs: ee, shellTemplate: f, requestHeaders: te, requestUrl: g = "", apiOrigin: re, apiName: _ } = e, { search: v } = m(g), y = await o(a(e.middlewares ?? [], {
212
+ route: n.pattern,
213
+ pathname: c
214
+ }), {
215
+ pathname: c,
216
+ search: v,
217
+ headers: te,
218
+ cookies: ne(te.cookie),
219
+ route: n.pattern
220
+ }, e.onCookieWarning), x = y.headers, S = ie(re, x.cookie, {
221
+ apiName: _,
222
+ headers: x
223
+ }), C = await t.getPage(n.pattern, n.file), w = L(C, n.file), D = w === "spa" && ae(ee, n.dirChain).some((e) => e.hasLayout);
224
+ if (w !== "ssr" && w !== "isr" && !D) return null;
225
+ let O = ae(ee, n.dirChain), k = {}, A = null, j, oe = new AbortController();
214
226
  try {
215
- (await t.getHelpers()).beginStoreSeeds(), {chain: w, segmentLoaderData: C} = await _({
216
- entries: ne,
227
+ (await t.getHelpers()).beginStoreSeeds(), {chain: j, segmentLoaderData: k} = await b({
228
+ entries: O,
217
229
  loadLayout: (e) => t.getLayout(e.dir),
218
230
  loadError: (e) => t.getError(e.dir),
219
231
  loadPending: (e) => t.getPending(e.dir),
220
232
  ctx: {
221
233
  params: i,
222
234
  pathname: c,
223
- search: g,
235
+ search: v,
224
236
  signal: oe.signal,
225
- headers: d,
226
- query: v,
237
+ headers: x,
238
+ query: S,
227
239
  isServer: !0
228
240
  }
229
- }), typeof y.loader == "function" && !S && (ie = await y.loader({
241
+ }), typeof C.loader == "function" && !D && (A = await C.loader({
230
242
  params: i,
231
243
  pathname: c,
232
- search: g,
244
+ search: v,
233
245
  signal: oe.signal,
234
- headers: d,
235
- query: v,
246
+ headers: x,
247
+ query: S,
236
248
  isServer: !0
237
249
  }));
238
250
  } catch (e) {
239
- if (Ae(e)) return {
251
+ if (Pe(e)) return {
240
252
  control: "redirect",
241
253
  status: e.status,
242
- location: e.location
254
+ location: e.location,
255
+ setCookies: y.setCookies
256
+ };
257
+ if (X(e)) return {
258
+ control: "not-found",
259
+ setCookies: y.setCookies
243
260
  };
244
- if (q(e)) return { control: "not-found" };
245
261
  throw e;
246
262
  }
247
- let E = await t.getHelpers();
248
- S || await ae({
249
- pageMod: y,
263
+ let M = await t.getHelpers();
264
+ D || await E({
265
+ pageMod: C,
250
266
  params: i,
251
- query: v,
252
- apiName: h,
253
- seed: E.seedPreloadedSubscription,
254
- seedFailure: E.seedPreloadedSubscriptionFailure,
255
- onError: ({ tag: e, apiName: t }, n) => K.warn("preload seed failed", {
267
+ query: S,
268
+ apiName: _,
269
+ seed: M.seedPreloadedSubscription,
270
+ seedFailure: M.seedPreloadedSubscriptionFailure,
271
+ onError: ({ tag: e, apiName: t }, n) => Y.warn("preload seed failed", {
256
272
  tag: e,
257
273
  apiName: t,
258
274
  pathname: c
259
275
  }, n)
260
276
  });
261
- let D = {
277
+ let se = {
262
278
  pattern: n.pattern,
263
- Component: y.default,
264
- meta: y.meta,
265
- loader: y.loader,
266
- ErrorBoundary: y.ErrorBoundary,
267
- Pending: y.Pending,
268
- renderMode: b,
269
- chain: w
270
- }, O = {
271
- cookies: E.parseCookieHeader(d.cookie),
272
- headers: d,
273
- url: p
274
- }, k = E.i18n?.resolve(d.cookie, d["accept-language"]), A = y.interactive ?? "full";
275
- if (S) {
276
- let e = o({
277
- helpers: E,
279
+ Component: C.default,
280
+ meta: C.meta,
281
+ loader: C.loader,
282
+ ErrorBoundary: C.ErrorBoundary,
283
+ Pending: C.Pending,
284
+ renderMode: w,
285
+ chain: j
286
+ }, N = {
287
+ cookies: y.cookies,
288
+ headers: x,
289
+ url: g
290
+ }, P = M.i18n?.resolve(x.cookie, x["accept-language"]), F = C.interactive ?? "full";
291
+ if (D) {
292
+ let e = s({
293
+ helpers: M,
278
294
  page: n.pattern,
279
- interactive: A,
295
+ interactive: F,
280
296
  delivery: "stream",
281
297
  renderInput: {
282
- descriptor: D,
298
+ descriptor: se,
283
299
  params: i,
284
300
  pathname: c,
285
- search: g,
286
- segmentLoaderData: C,
287
- requestContext: O,
288
- ...k ? {
289
- outerWrap: k.outerWrap,
290
- locale: k.locale
301
+ search: v,
302
+ segmentLoaderData: k,
303
+ requestContext: N,
304
+ ...P ? {
305
+ outerWrap: P.outerWrap,
306
+ locale: P.locale
291
307
  } : {}
292
308
  }
293
- }), t = k?.locale ?? O.cookies["voltro:locale"] ?? "en", r = (t) => te({
294
- helpers: E,
309
+ }), t = P?.locale ?? N.cookies["voltro:locale"] ?? "en", a = (t) => u({
310
+ helpers: M,
295
311
  prepared: e,
296
312
  meta: t,
297
- interactive: A
313
+ interactive: F
298
314
  });
299
315
  if (e.hasDeferred) {
300
- let n = a({ shell: u });
316
+ let n = T({ shell: f });
301
317
  return {
302
318
  renderMode: "spa",
303
- stream: (i) => T({
304
- res: i,
319
+ setCookies: y.setCookies,
320
+ stream: (r) => d({
321
+ res: r,
305
322
  shell: n,
306
323
  htmlLang: t,
307
324
  headers: {
308
325
  "content-type": "text/html; charset=utf-8",
309
- "x-voltro-rendered-by": "spa"
326
+ "x-voltro-rendered-by": "spa",
327
+ ...h(y.setCookies)
310
328
  },
311
- headInjection: r,
312
- render: (t) => E.renderPageToStream({
329
+ headInjection: a,
330
+ render: (t) => M.renderPageToStream({
313
331
  ...e.renderInput,
314
332
  ...t
315
333
  }),
316
334
  onShellError: (e) => {
317
- K.error("spa layout shell render failed", { pathname: c }, e), i.writeHead(500, { "content-type": "text/plain; charset=utf-8" }), i.end("server error");
335
+ Y.error("spa layout shell render failed", { pathname: c }, e), r.writeHead(500, { "content-type": "text/plain; charset=utf-8" }), r.end("server error");
318
336
  }
319
337
  })
320
338
  };
321
339
  }
322
- let s = f({
323
- helpers: E,
340
+ let o = l({
341
+ helpers: M,
324
342
  prepared: e
325
343
  });
326
344
  return {
327
- html: m(u.replace("<div id=\"root\"></div>", `<div id="root">${s.body}</div>`), r(s.meta)).replace(/<html(\s+lang="[^"]*")?/i, `<html lang="${t}"`),
345
+ html: r(f.replace("<div id=\"root\"></div>", `<div id="root">${o.body}</div>`), a(o.meta)).replace(/<html(\s+lang="[^"]*")?/i, `<html lang="${t}"`),
328
346
  renderMode: "spa",
329
- revalidateMs: null
347
+ revalidateMs: null,
348
+ setCookies: y.setCookies
330
349
  };
331
350
  }
332
- let j = s({
333
- helpers: E,
351
+ let I = p({
352
+ helpers: M,
334
353
  page: n.pattern,
335
354
  pathname: c,
336
- renderMode: b,
337
- interactive: A,
338
- loaderData: ie,
339
- segmentLoaderData: C,
340
- pageLoaderRan: typeof y.loader == "function"
341
- }), se = {
342
- descriptor: D,
355
+ renderMode: w,
356
+ interactive: F,
357
+ loaderData: A,
358
+ segmentLoaderData: k,
359
+ pageLoaderRan: typeof C.loader == "function"
360
+ }), ce = {
361
+ descriptor: se,
343
362
  params: i,
344
363
  pathname: c,
345
- search: g,
346
- loaderData: j.loaderData,
347
- segmentLoaderData: j.segmentLoaderData,
348
- requestContext: O,
349
- ...k ? {
350
- outerWrap: k.outerWrap,
351
- locale: k.locale
364
+ search: v,
365
+ loaderData: I.loaderData,
366
+ segmentLoaderData: I.segmentLoaderData,
367
+ requestContext: N,
368
+ ...P ? {
369
+ outerWrap: P.outerWrap,
370
+ locale: P.locale
352
371
  } : {}
353
- }, M = (e) => [
354
- E.renderMetaToHtml(e),
355
- `<meta name="voltro-interactive" content="${A}" />`,
356
- ...j.hasDeferred ? [E.renderDeferredRegistryScript()] : [],
357
- E.renderRouterStateScript(j.stateInput)
372
+ }, le = (e) => [
373
+ M.renderMetaToHtml(e),
374
+ `<meta name="voltro-interactive" content="${F}" />`,
375
+ ...I.hasDeferred ? [M.renderDeferredRegistryScript()] : [],
376
+ M.renderRouterStateScript(I.stateInput)
358
377
  ].filter((e) => e.length > 0).join("\n ");
359
- if (b === "ssr" && A === "full" && e.buffered !== !0) {
360
- let e = k?.locale ?? O.cookies["voltro:locale"] ?? "en", t = a({ shell: u });
378
+ if (w === "ssr" && F === "full" && e.buffered !== !0) {
379
+ let e = P?.locale ?? N.cookies["voltro:locale"] ?? "en", t = T({ shell: f });
361
380
  return {
362
381
  renderMode: "ssr",
363
- stream: (n) => T({
382
+ setCookies: y.setCookies,
383
+ stream: (n) => d({
364
384
  res: n,
365
385
  shell: t,
366
386
  htmlLang: e,
367
387
  headers: {
368
388
  "content-type": "text/html; charset=utf-8",
369
- "x-voltro-rendered-by": "ssr"
389
+ "x-voltro-rendered-by": "ssr",
390
+ ...h(y.setCookies)
370
391
  },
371
- headInjection: M,
372
- render: (e) => E.renderPageToStream({
373
- ...se,
392
+ headInjection: le,
393
+ render: (e) => M.renderPageToStream({
394
+ ...ce,
374
395
  ...e
375
396
  }),
376
397
  onShellError: (e) => {
377
- K.error("ssr shell render failed", { pathname: c }, e), n.writeHead(500, { "content-type": "text/plain; charset=utf-8" }), n.end("server error");
398
+ Y.error("ssr shell render failed", { pathname: c }, e), n.writeHead(500, { "content-type": "text/plain; charset=utf-8" }), n.end("server error");
378
399
  }
379
400
  })
380
401
  };
381
402
  }
382
- let { html: ce, meta: le } = E.renderPageToHtml(se), ue = M(le), de = k?.locale ?? O.cookies["voltro:locale"] ?? "en", P = m(u.replace("<div id=\"root\"></div>", `<div id="root">${ce}</div>`), ue).replace(/<html(\s+lang="[^"]*")?/i, `<html lang="${de}"`);
383
- A === "none" && (P = Y(P));
384
- let fe = b === "isr" ? F(y.revalidate) : null;
403
+ let { html: ue, meta: de } = M.renderPageToHtml(ce), fe = le(de), pe = P?.locale ?? N.cookies["voltro:locale"] ?? "en", R = r(f.replace("<div id=\"root\"></div>", `<div id="root">${ue}</div>`), fe).replace(/<html(\s+lang="[^"]*")?/i, `<html lang="${pe}"`);
404
+ F === "none" && (R = Z(R));
405
+ let me = w === "isr" ? he(C.revalidate) : null;
385
406
  return {
386
- html: P,
387
- renderMode: b,
388
- revalidateMs: fe
407
+ html: R,
408
+ renderMode: w,
409
+ revalidateMs: me,
410
+ setCookies: y.setCookies
389
411
  };
390
- }, Q = (e) => e === "" ? "/" : e, Fe = async (e) => {
391
- let t = await import(Se(e).href);
412
+ }, $ = (e) => e === "" ? "/" : e, Ve = async (e) => {
413
+ let t = await import(H(e).href);
392
414
  return {
393
415
  kind: "bundle",
394
416
  getPageMeta: () => t.pageMeta,
@@ -398,18 +420,18 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
398
420
  return typeof r == "function" ? await r() : r;
399
421
  },
400
422
  async getLayout(e) {
401
- let n = t.layouts[Q(e)];
402
- if (!n) throw Error(`[voltro start] ssr bundle missing layout for dir ${Q(e)}`);
423
+ let n = t.layouts[$(e)];
424
+ if (!n) throw Error(`[voltro start] ssr bundle missing layout for dir ${$(e)}`);
403
425
  return typeof n == "function" ? await n() : n;
404
426
  },
405
427
  async getError(e) {
406
- let n = t.errors[Q(e)];
407
- if (!n) throw Error(`[voltro start] ssr bundle missing error for dir ${Q(e)}`);
428
+ let n = t.errors[$(e)];
429
+ if (!n) throw Error(`[voltro start] ssr bundle missing error for dir ${$(e)}`);
408
430
  return typeof n == "function" ? await n() : n;
409
431
  },
410
432
  async getPending(e) {
411
- let n = t.pendings[Q(e)];
412
- if (!n) throw Error(`[voltro start] ssr bundle missing pending for dir ${Q(e)}`);
433
+ let n = t.pendings[$(e)];
434
+ if (!n) throw Error(`[voltro start] ssr bundle missing pending for dir ${$(e)}`);
413
435
  return typeof n == "function" ? await n() : n;
414
436
  },
415
437
  async getHelpers() {
@@ -417,8 +439,8 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
417
439
  },
418
440
  async close() {}
419
441
  };
420
- }, Ie = async (e, t) => {
421
- let n = await w("vite", () => import("vite")), r = (await import("@vitejs/plugin-react")).default, i = (await import("@tailwindcss/vite")).default, a = await n.createServer({
442
+ }, He = async (e, t) => {
443
+ let n = await j("vite", () => import("vite")), r = (await import("@vitejs/plugin-react")).default, i = (await import("@tailwindcss/vite")).default, a = await n.createServer({
422
444
  root: t,
423
445
  envPrefix: "__VOLTRO_VITE_ENV_DISABLED__",
424
446
  plugins: [r(), i()],
@@ -435,10 +457,10 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
435
457
  },
436
458
  appType: "custom",
437
459
  logLevel: "warn"
438
- }), o = I(e, "src", "pages"), s = (e) => e === "" ? o : I(o, e), c = C({
439
- limit: u(),
440
- onColdStart: (e) => K.debug("ssr cold-compile start", { id: e }),
441
- onColdEnd: (e, { durationMs: t, failed: n }) => K.debug(`ssr cold-compile ${n ? "FAILED" : "end"} ${t}ms`, {
460
+ }), o = z(e, "src", "pages"), s = (e) => e === "" ? o : z(o, e), c = A({
461
+ limit: O(),
462
+ onColdStart: (e) => Y.debug("ssr cold-compile start", { id: e }),
463
+ onColdEnd: (e, { durationMs: t, failed: n }) => Y.debug(`ssr cold-compile ${n ? "FAILED" : "end"} ${t}ms`, {
442
464
  id: e,
443
465
  ms: t,
444
466
  ...n ? { failed: !0 } : {}
@@ -447,16 +469,16 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
447
469
  return {
448
470
  kind: "middleware",
449
471
  async getPage(e, t) {
450
- return l(I(o, t));
472
+ return l(z(o, t));
451
473
  },
452
474
  async getLayout(e) {
453
- return l(I(s(e), "layout.tsx"));
475
+ return l(z(s(e), "layout.tsx"));
454
476
  },
455
477
  async getError(e) {
456
- return l(I(s(e), "error.tsx"));
478
+ return l(z(s(e), "error.tsx"));
457
479
  },
458
480
  async getPending(e) {
459
- return l(I(s(e), "loading.tsx"));
481
+ return l(z(s(e), "loading.tsx"));
460
482
  },
461
483
  async getHelpers() {
462
484
  return await l("@voltro/web/ssr");
@@ -465,99 +487,106 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
465
487
  await a.close();
466
488
  }
467
489
  };
468
- }, $ = async (t) => {
469
- let r = ye(), a = await y(t);
470
- if (!a) return {
490
+ }, Ue = async (t) => {
491
+ let r = Ce(), s = await S(t);
492
+ if (!s) return {
471
493
  ran: !1,
472
494
  exitCode: 0
473
495
  };
474
- if (a.type !== "web") return K.error("only web apps are supported by `voltro start`"), {
496
+ if (s.type !== "web") return Y.error("only web apps are supported by `voltro start`"), {
475
497
  ran: !0,
476
498
  exitCode: 1
477
499
  };
478
- let { resolved: o } = await ie({
479
- rawEnv: a.env,
500
+ let { resolved: l } = await w({
501
+ rawEnv: s.env,
480
502
  appType: "web",
481
503
  root: t,
482
- log: K,
504
+ log: Y,
483
505
  generateTypes: !1
484
- }), s = o.publicValues;
506
+ }), u = l.publicValues;
485
507
  r.mark("config");
486
- let u = c();
487
- E(u), K.info("booting voltro start", { app: a.name ?? "(unnamed)" });
488
- let f = n({
508
+ let d = _();
509
+ k(d), Y.info("booting voltro start", { app: s.name ?? "(unnamed)" });
510
+ let p = n({
489
511
  kind: "web",
490
- configPort: a.port,
512
+ configPort: s.port,
491
513
  env: process.env,
492
- dashboardPin: process.env[S] === "1"
514
+ dashboardPin: process.env[se] === "1"
493
515
  });
494
- for (let e of f.warnings) K.warn(e);
495
- let m = f.port, _ = I(t, ".framework"), x = I(_, "dist"), te = I(x, "index.html");
496
- if (!await X(te)) return K.error("no built dist found — run `voltro build` first", { distDir: x }), {
516
+ for (let e of p.warnings) Y.warn(e);
517
+ let m = p.port, h = z(t, ".framework"), b = z(h, "dist"), ie = z(b, "index.html");
518
+ if (!await Q(ie)) return Y.error("no built dist found — run `voltro build` first", { distDir: b }), {
497
519
  ran: !0,
498
520
  exitCode: 1
499
521
  };
500
- let C = a.name ?? "unnamed", w = ge("web", C, m), T = _e(C);
501
- await pe({
502
- id: w,
503
- name: C,
522
+ let T = s.name ?? "unnamed", E = be("web", T, m), O = xe(T);
523
+ await _e({
524
+ id: E,
525
+ name: T,
504
526
  kind: "web",
505
527
  url: `http://localhost:${m}`,
506
528
  pid: process.pid,
507
529
  status: "booting",
508
- logFile: T.path
530
+ logFile: O.path
509
531
  }).catch(() => {});
510
- let ae = I(x, "_voltro", "shell.html"), N = await X(ae) ? await R.readFile(ae, "utf8") : await R.readFile(te, "utf8"), F = await b(t, a), be = ne(F[0]), xe = F[0]?.name, L, z = null, Se = process.env.SSR_CACHE === "postgres";
511
- if (Se && O()) z = new (await (import("pg"))).default.Client(D()), await z.connect(), L = Oe({ client: z }), K.info("isr cache backend: postgres", { table: "voltro_isr_cache" });
512
- else if (Se) {
532
+ let A = z(b, "_voltro", "shell.html"), j = await Q(A) ? await B.readFile(A, "utf8") : await B.readFile(ie, "utf8"), L = await C(t, s), he = D(L[0]), we = L[0]?.name, Te = /* @__PURE__ */ new Set(), Ee = (e) => {
533
+ Te.has(e.name) || (Te.add(e.name), Y.warn(`middleware.ts wrote the cookie "${e.name}" with the HttpOnly default a browser SDK cannot read it`, {
534
+ cookie: e.name,
535
+ 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."
536
+ }));
537
+ }, V = await i(t);
538
+ V.length > 0 && Y.info(`middleware.ts loaded — ${V.length} middleware(s): ` + V.map((e) => e.exportName).join(", "));
539
+ let H, U = null, W = process.env.SSR_CACHE === "postgres";
540
+ if (W && P()) U = new (await (import("pg"))).default.Client(N()), await U.connect(), H = Me({ client: U }), Y.info("isr cache backend: postgres", { table: "voltro_isr_cache" });
541
+ else if (W) {
513
542
  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).";
514
- if (e()) throw K.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");
515
- L = de(), K.warn(`${t} Falling back to the per-process memory cache — this would be a hard failure in production.`);
516
- } else L = de(), K.info("isr cache backend: memory (per-process)", { hint: "set SSR_CACHE=postgres for persistent storage" });
517
- await v(t, a, F, s);
518
- let B = I(t, "src", "pages"), { pages: V, dirs: H } = await oe(B), U = Ne(V);
519
- r.mark("scan");
520
- let W = I(x, "server", "ssrEntry.js"), De = await X(W);
521
- if (!De && process.env.NODE_ENV === "production") throw K.fatal(`production \`voltro start\` requires a precompiled SSR bundle at ${W} 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 ${W}`);
522
- let G = De ? await Fe(W) : await Ie(t, _);
523
- K.info(`ssr loader: ${G.kind}`, {
524
- kind: G.kind,
525
- ...G.kind === "middleware" ? { hint: "no pre-built SSR bundle found; run `voltro build` to enable bundle mode" } : {}
543
+ 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");
544
+ H = R(), Y.warn(`${t} Falling back to the per-process memory cache — this would be a hard failure in production.`);
545
+ } else H = R(), Y.info("isr cache backend: memory (per-process)", { hint: "set SSR_CACHE=postgres for persistent storage" });
546
+ await x(t, s, L, u);
547
+ let Ae = z(t, "src", "pages"), { pages: G, dirs: K } = await M(Ae), q = Re(G);
548
+ oe(V, q.map((e) => e.pattern)), r.mark("scan");
549
+ let J = z(b, "server", "ssrEntry.js"), Pe = await Q(J);
550
+ if (!Pe && process.env.NODE_ENV === "production") throw Y.fatal(`production \`voltro start\` requires a precompiled SSR bundle at ${J} 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 ${J}`);
551
+ let X = Pe ? await Ve(J) : await He(t, h);
552
+ Y.info(`ssr loader: ${X.kind}`, {
553
+ kind: X.kind,
554
+ ...X.kind === "middleware" ? { hint: "no pre-built SSR bundle found; run `voltro build` to enable bundle mode" } : {}
526
555
  }), r.mark("provider");
527
- let Ae = G.getPageMeta?.(), q = /* @__PURE__ */ new Map(), J = 0;
528
- for (let e of V) {
529
- let t = Ae?.[e.pattern];
556
+ let Fe = X.getPageMeta?.(), Z = /* @__PURE__ */ new Map(), Le = 0;
557
+ for (let e of G) {
558
+ let t = Fe?.[e.pattern];
530
559
  if (t) {
531
- q.set(e.pattern, t);
560
+ Z.set(e.pattern, t);
532
561
  continue;
533
562
  }
534
563
  try {
535
- let t = await G.getPage(e.pattern, e.file);
536
- q.set(e.pattern, le(t, e.file)), J++;
564
+ let t = await X.getPage(e.pattern, e.file);
565
+ Z.set(e.pattern, fe(t, e.file)), Le++;
537
566
  } catch (t) {
538
- K.warn("failed to load page metadata", { pattern: e.pattern }, t);
567
+ Y.warn("failed to load page metadata", { pattern: e.pattern }, t);
539
568
  }
540
569
  }
541
- K.info(`registered ${q.size} route(s)`, {
542
- count: q.size,
543
- fromManifest: q.size - J,
544
- fromModules: J
570
+ Y.info(`registered ${Z.size} route(s)`, {
571
+ count: Z.size,
572
+ fromManifest: Z.size - Le,
573
+ fromModules: Le
545
574
  }), r.mark("routes");
546
- let Y = /* @__PURE__ */ new Set();
547
- for (let e of U) q.get(e.pattern)?.renderMode === "spa" && re(H, e.dirChain).some((e) => e.hasLayout) && Y.add(e.pattern);
548
- Y.size > 0 && K.info(`${Y.size} spa route(s) render an SSR layout shell`, { patterns: [...Y] });
549
- let Me = /* @__PURE__ */ new Map();
550
- for (let [e, t] of q) t.cacheInvalidatesOn.length > 0 && Me.set(e, t.cacheInvalidatesOn);
551
- let Q = /* @__PURE__ */ new Map();
552
- for (let e of U) Q.set(e.pattern, e.regex);
553
- let $ = Ee({
554
- cache: L,
555
- tableSubscriptionsByPattern: Me,
556
- regexByPattern: Q
575
+ let $ = /* @__PURE__ */ new Set();
576
+ for (let e of q) Z.get(e.pattern)?.renderMode === "spa" && ae(K, e.dirChain).some((e) => e.hasLayout) && $.add(e.pattern);
577
+ $.size > 0 && Y.info(`${$.size} spa route(s) render an SSR layout shell`, { patterns: [...$] });
578
+ let Ue = /* @__PURE__ */ new Map();
579
+ for (let [e, t] of Z) t.cacheInvalidatesOn.length > 0 && Ue.set(e, t.cacheInvalidatesOn);
580
+ let We = /* @__PURE__ */ new Map();
581
+ for (let e of q) We.set(e.pattern, e.regex);
582
+ let Ge = je({
583
+ cache: H,
584
+ tableSubscriptionsByPattern: Ue,
585
+ regexByPattern: We
557
586
  });
558
- await $.start(), r.mark("cdc");
559
- let Le = ve(), Re = V.map((e) => {
560
- let t = q.get(e.pattern);
587
+ await Ge.start(), r.mark("cdc");
588
+ let Ke = Se(), qe = G.map((e) => {
589
+ let t = Z.get(e.pattern);
561
590
  return {
562
591
  pattern: e.pattern,
563
592
  file: e.file,
@@ -572,20 +601,20 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
572
601
  hasMeta: t?.hasMeta ?? !1,
573
602
  hasGetStaticPaths: t?.hasGetStaticPaths ?? !1
574
603
  };
575
- }), ze = H.map((e) => ({
604
+ }), Je = K.map((e) => ({
576
605
  dir: e.dir,
577
606
  hasLayout: e.hasLayout,
578
607
  hasError: e.hasError,
579
608
  hasPending: e.hasPending,
580
609
  hasNotFound: e.hasNotFound
581
- })), Be = z ? "postgres" : "memory", Ve = {
610
+ })), Ye = U ? "postgres" : "memory", Xe = {
582
611
  kind: "web",
583
612
  meta: {
584
- name: a.name ?? "(unnamed)",
585
- voltroVersion: ke,
613
+ name: s.name ?? "(unnamed)",
614
+ voltroVersion: Ne,
586
615
  port: m,
587
616
  mode: "start",
588
- apis: Object.entries(a.apis ?? {}).map(([e, t]) => {
617
+ apis: Object.entries(s.apis ?? {}).map(([e, t]) => {
589
618
  let n = {
590
619
  name: e,
591
620
  package: t.package
@@ -593,10 +622,10 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
593
622
  return t.url !== void 0 && (n.url = t.url), n;
594
623
  })
595
624
  },
596
- routes: Re,
597
- dirs: ze,
625
+ routes: qe,
626
+ dirs: Je,
598
627
  cache: () => {
599
- let e = Date.now(), t = L.snapshot().map(([t, n]) => ({
628
+ let e = Date.now(), t = H.snapshot().map(([t, n]) => ({
600
629
  key: t,
601
630
  renderedAt: n.renderedAt,
602
631
  expiresAt: n.expiresAt,
@@ -607,16 +636,16 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
607
636
  staleWhileRevalidateMs: n.staleWhileRevalidateMs
608
637
  }));
609
638
  return {
610
- backend: Be,
611
- size: L.size(),
639
+ backend: Ye,
640
+ size: H.size(),
612
641
  entries: t
613
642
  };
614
643
  },
615
- metrics: () => we()
616
- }, He = async (e, n) => {
644
+ metrics: () => Oe()
645
+ }, Ze = async (e, n) => {
617
646
  let r = e.split("?")[0] ?? "/";
618
- if (a.name === "voltroDashboard" && r === "/api/dashboard/registry") try {
619
- let e = await me();
647
+ if (s.name === "voltroDashboard" && r === "/api/dashboard/registry") try {
648
+ let e = await ve();
620
649
  return {
621
650
  status: 200,
622
651
  headers: { "content-type": "application/json; charset=utf-8" },
@@ -629,7 +658,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
629
658
  body: `registry read error: ${e.message}`
630
659
  };
631
660
  }
632
- if (a.name === "voltroDashboard" && r === "/api/dashboard/config") {
661
+ if (s.name === "voltroDashboard" && r === "/api/dashboard/config") {
633
662
  let e = process.env.VOLTRO_DASHBOARD_APPS, t = [];
634
663
  if (e && e.trim().length > 0) {
635
664
  let n;
@@ -659,18 +688,18 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
659
688
  };
660
689
  }
661
690
  if (r === "/_voltro/inspect/logs") {
662
- let t = l(e, i(), n);
691
+ let t = re(e, ee(), n);
663
692
  return {
664
693
  status: t.status,
665
694
  headers: {
666
695
  "content-type": t.contentType,
667
- ...A(n.origin)
696
+ ...I(n.origin)
668
697
  },
669
698
  body: t.body
670
699
  };
671
700
  }
672
701
  if (r !== "/_voltro/inspect/stream") {
673
- let t = se(e, Ve, n);
702
+ let t = le(e, Xe, n);
674
703
  if (t !== null) return {
675
704
  status: t.status,
676
705
  headers: {
@@ -680,71 +709,96 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
680
709
  body: t.body
681
710
  };
682
711
  }
683
- let o = Z(r, U), s = o ? q.get(o.route.pattern)?.renderMode : void 0, c = s === "ssr" || s === "isr" || (o ? Y.has(o.route.pattern) : !1), d = r === "/" ? I(x, "index.html") : I(x, r.replace(/^\//, ""), "index.html");
684
- if (!c && await X(d)) return {
685
- status: 200,
686
- headers: { "content-type": "text/html; charset=utf-8" },
687
- body: await R.readFile(d)
688
- };
712
+ let i = ze(r, q), c = i ? Z.get(i.route.pattern)?.renderMode : void 0, l = c === "ssr" || c === "isr" || (i ? $.has(i.route.pattern) : !1), u = [];
713
+ if (!l && V.length > 0) {
714
+ let t = a(V, {
715
+ route: void 0,
716
+ pathname: r
717
+ });
718
+ if (t !== void 0) {
719
+ let i = await o(t, {
720
+ pathname: r,
721
+ search: e.slice(r.length),
722
+ headers: n,
723
+ cookies: ne(n.cookie),
724
+ route: void 0
725
+ });
726
+ u.push(...i.setCookies);
727
+ }
728
+ }
729
+ let p = (e) => u.length === 0 ? e : {
730
+ ...e,
731
+ "set-cookie": u.map(te)
732
+ }, m = r === "/" ? z(b, "index.html") : z(b, r.replace(/^\//, ""), "index.html");
733
+ if (!l && await Q(m)) {
734
+ let e = await B.readFile(m);
735
+ return {
736
+ status: 200,
737
+ headers: p({ "content-type": "text/html; charset=utf-8" }),
738
+ body: e
739
+ };
740
+ }
689
741
  if (/\.[a-z0-9]+$/i.test(r)) {
690
- let e = I(x, r.replace(/^\//, ""));
691
- if (await X(e)) {
692
- let t = await R.readFile(e);
742
+ let e = z(b, r.replace(/^\//, ""));
743
+ if (await Q(e)) {
744
+ let t = await B.readFile(e);
693
745
  return {
694
746
  status: 200,
695
- headers: { "content-type": je(e) },
747
+ headers: p({ "content-type": Ie(e) }),
696
748
  body: t
697
749
  };
698
750
  }
699
751
  }
700
- let f = Z(r, U);
701
- if (!f) return {
752
+ let h = ze(r, q);
753
+ if (!h) return {
702
754
  status: 404,
703
- headers: { "content-type": "text/plain" },
755
+ headers: p({ "content-type": "text/plain" }),
704
756
  body: "not found"
705
757
  };
706
- let p = q.get(f.route.pattern), m = n["x-tenant"] ?? "anonymous", h = (await G.getHelpers()).i18n?.resolve(n.cookie, n["accept-language"])?.locale, g = P(r, {
707
- ...p?.tenantAware ? { tenant: m } : {},
708
- ...h ? { locale: h } : {}
709
- }), _ = L.get(g), v = Date.now();
710
- if (_ && fe(_, v)) return u.emit("cache", {
758
+ let g = Z.get(h.route.pattern), _ = n["x-tenant"] ?? "anonymous", v = (await X.getHelpers()).i18n?.resolve(n.cookie, n["accept-language"])?.locale, y = me(r, {
759
+ ...g?.tenantAware ? { tenant: _ } : {},
760
+ ...v ? { locale: v } : {}
761
+ }), x = H.get(y), S = Date.now();
762
+ if (x && ge(x, S)) return d.emit("cache", {
711
763
  kind: "HIT",
712
- key: g,
713
- ageMs: v - _.renderedAt
764
+ key: y,
765
+ ageMs: S - x.renderedAt
714
766
  }), {
715
767
  status: 200,
716
768
  headers: {
717
769
  "content-type": "text/html; charset=utf-8",
718
770
  "x-voltro-rendered-by": "isr",
719
771
  "x-voltro-cache": "HIT",
720
- "x-voltro-cache-key": g,
721
- "x-voltro-cache-age-ms": String(v - _.renderedAt)
772
+ "x-voltro-cache-key": y,
773
+ "x-voltro-cache-age-ms": String(S - x.renderedAt)
722
774
  },
723
- body: _.html
775
+ body: x.html
724
776
  };
725
- if (_ && ue(_, v)) return u.emit("cache", {
777
+ if (x && pe(x, S)) return d.emit("cache", {
726
778
  kind: "STALE",
727
- key: g,
728
- ageMs: v - _.renderedAt
779
+ key: y,
780
+ ageMs: S - x.renderedAt
729
781
  }), (async () => {
730
782
  try {
731
- let i = await Pe({
732
- provider: G,
783
+ let i = await Be({
784
+ provider: X,
733
785
  root: t,
734
- route: f.route,
735
- params: f.params,
786
+ route: h.route,
787
+ params: h.params,
736
788
  pathname: r,
737
- dirs: H,
738
- shellTemplate: N,
789
+ dirs: K,
790
+ shellTemplate: j,
739
791
  requestHeaders: n,
740
- apiOrigin: be,
741
- apiName: xe,
792
+ apiOrigin: he,
793
+ apiName: we,
794
+ middlewares: V,
795
+ onCookieWarning: Ee,
742
796
  requestUrl: e,
743
797
  buffered: !0
744
798
  });
745
799
  if (i && "html" in i && i.renderMode === "isr" && i.revalidateMs !== null) {
746
- let e = q.get(f.route.pattern)?.staleWhileRevalidateMs ?? 0, t = Date.now();
747
- L.set(g, {
800
+ let e = Z.get(h.route.pattern)?.staleWhileRevalidateMs ?? 0, t = Date.now();
801
+ H.set(y, {
748
802
  html: i.html,
749
803
  renderedAt: t,
750
804
  expiresAt: t + i.revalidateMs,
@@ -754,7 +808,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
754
808
  });
755
809
  }
756
810
  } catch (e) {
757
- K.warn("background SWR refresh failed", { url: r }, e);
811
+ Y.warn("background SWR refresh failed", { url: r }, e);
758
812
  }
759
813
  })(), {
760
814
  status: 200,
@@ -762,23 +816,25 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
762
816
  "content-type": "text/html; charset=utf-8",
763
817
  "x-voltro-rendered-by": "isr",
764
818
  "x-voltro-cache": "STALE",
765
- "x-voltro-cache-key": g,
766
- "x-voltro-cache-age-ms": String(v - _.renderedAt)
819
+ "x-voltro-cache-key": y,
820
+ "x-voltro-cache-age-ms": String(S - x.renderedAt)
767
821
  },
768
- body: _.html
822
+ body: x.html
769
823
  };
770
824
  try {
771
- let i = await Pe({
772
- provider: G,
825
+ let i = await Be({
826
+ provider: X,
773
827
  root: t,
774
- route: f.route,
775
- params: f.params,
828
+ route: h.route,
829
+ params: h.params,
776
830
  pathname: r,
777
- dirs: H,
778
- shellTemplate: N,
831
+ dirs: K,
832
+ shellTemplate: j,
779
833
  requestHeaders: n,
780
- apiOrigin: be,
781
- apiName: xe,
834
+ apiOrigin: he,
835
+ apiName: we,
836
+ middlewares: V,
837
+ onCookieWarning: Ee,
782
838
  requestUrl: e
783
839
  });
784
840
  if (!i) return {
@@ -787,7 +843,11 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
787
843
  "content-type": "text/html; charset=utf-8",
788
844
  "x-voltro-rendered-by": "spa-fallback"
789
845
  },
790
- body: N
846
+ body: j
847
+ };
848
+ let a = i.setCookies ?? [], o = (e) => a.length === 0 ? e : {
849
+ ...e,
850
+ "set-cookie": a.map(te)
791
851
  };
792
852
  if ("stream" in i) return {
793
853
  status: 200,
@@ -797,49 +857,49 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
797
857
  };
798
858
  if ("control" in i) return i.control === "redirect" ? {
799
859
  status: i.status,
800
- headers: {
860
+ headers: o({
801
861
  location: i.location,
802
862
  "x-voltro-rendered-by": "loader-redirect"
803
- },
863
+ }),
804
864
  body: ""
805
865
  } : {
806
866
  status: 404,
807
- headers: {
867
+ headers: o({
808
868
  "content-type": "text/plain; charset=utf-8",
809
869
  "x-voltro-rendered-by": "loader-not-found"
810
- },
870
+ }),
811
871
  body: "not found"
812
872
  };
813
- let a = {
873
+ let s = o({
814
874
  "content-type": "text/html; charset=utf-8",
815
875
  "x-voltro-rendered-by": i.renderMode
816
- };
876
+ });
817
877
  if (i.renderMode === "isr" && i.revalidateMs !== null) {
818
- let e = Date.now(), t = q.get(f.route.pattern)?.staleWhileRevalidateMs ?? 0;
819
- L.set(g, {
878
+ let e = Date.now(), t = Z.get(h.route.pattern)?.staleWhileRevalidateMs ?? 0;
879
+ H.set(y, {
820
880
  html: i.html,
821
881
  renderedAt: e,
822
882
  expiresAt: e + i.revalidateMs,
823
883
  servableUntil: e + i.revalidateMs + t,
824
884
  revalidateMs: i.revalidateMs,
825
885
  staleWhileRevalidateMs: t
826
- }), a["x-voltro-cache"] = "MISS", a["x-voltro-cache-key"] = g, a["x-voltro-cache-revalidate-ms"] = String(i.revalidateMs), t > 0 && (a["x-voltro-cache-swr-ms"] = String(t)), u.emit("cache", {
886
+ }), s["x-voltro-cache"] = "MISS", s["x-voltro-cache-key"] = y, s["x-voltro-cache-revalidate-ms"] = String(i.revalidateMs), t > 0 && (s["x-voltro-cache-swr-ms"] = String(t)), d.emit("cache", {
827
887
  kind: "MISS",
828
- key: g,
888
+ key: y,
829
889
  revalidateMs: i.revalidateMs,
830
890
  swrMs: t
831
891
  });
832
- } else i.renderMode === "isr" && (a["x-voltro-cache"] = "BYPASS", u.emit("cache", {
892
+ } else i.renderMode === "isr" && (s["x-voltro-cache"] = "BYPASS", d.emit("cache", {
833
893
  kind: "BYPASS",
834
- key: g
894
+ key: y
835
895
  }));
836
896
  return {
837
897
  status: 200,
838
- headers: a,
898
+ headers: s,
839
899
  body: i.html
840
900
  };
841
901
  } catch (e) {
842
- return K.error("render error", { url: r }, e), ee(e) ? {
902
+ return Y.error("render error", { url: r }, e), f(e) ? {
843
903
  status: 500,
844
904
  headers: {
845
905
  "content-type": "text/plain; charset=utf-8",
@@ -852,56 +912,56 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
852
912
  body: "server error"
853
913
  };
854
914
  }
855
- }, Ue = !1, We = Te(async (e, t) => {
915
+ }, Qe = !1, $e = ke(async (e, t) => {
856
916
  let n = e.url ?? "/", r = Date.now(), i = {};
857
917
  for (let [t, n] of Object.entries(e.headers)) n !== void 0 && (i[t.toLowerCase()] = Array.isArray(n) ? n.join(", ") : n);
858
- let o = n.split("?")[0] ?? "/", s = (e.method ?? "GET").toUpperCase();
859
- if (o === "/internal/liveness") {
918
+ let a = n.split("?")[0] ?? "/", o = (e.method ?? "GET").toUpperCase();
919
+ if (a === "/internal/liveness") {
860
920
  t.writeHead(200, {
861
921
  "content-type": "text/plain",
862
922
  "cache-control": "no-store"
863
923
  }), t.end("ok");
864
924
  return;
865
925
  }
866
- if (o === "/internal/readiness") {
867
- let e = Ue ? 200 : 503;
926
+ if (a === "/internal/readiness") {
927
+ let e = Qe ? 200 : 503;
868
928
  t.writeHead(e, {
869
929
  "content-type": "text/plain",
870
930
  "cache-control": "no-store"
871
- }), t.end(Ue ? "ready" : "not-ready");
931
+ }), t.end(Qe ? "ready" : "not-ready");
872
932
  return;
873
933
  }
874
- if (s === "OPTIONS" && o.startsWith("/_voltro/inspect")) {
875
- let e = A(i.origin);
934
+ if (o === "OPTIONS" && a.startsWith("/_voltro/inspect")) {
935
+ let e = I(i.origin);
876
936
  t.writeHead(204, e), t.end();
877
937
  return;
878
938
  }
879
- if (a.name === "voltroDashboard" && o === "/api/dashboard/proxy") {
939
+ if (s.name === "voltroDashboard" && a === "/api/dashboard/proxy") {
880
940
  let r = new URL(n, "http://x").searchParams.get("target");
881
941
  if (!r) {
882
942
  t.writeHead(400, { "content-type": "text/plain" }), t.end("missing ?target=");
883
943
  return;
884
944
  }
885
- if (!ce(r)) {
945
+ if (!de(r)) {
886
946
  t.writeHead(400, { "content-type": "text/plain" }), t.end("target not allowed: must be loopback or an origin configured in VOLTRO_DASHBOARD_APPS");
887
947
  return;
888
948
  }
889
949
  try {
890
950
  let n = { accept: i.accept ?? "application/json" }, a = i.authorization;
891
- a ? n.authorization = Array.isArray(a) ? a[0] : a : M(r) && process.env.VOLTRO_INSPECT_TOKEN && (n.authorization = `Bearer ${process.env.VOLTRO_INSPECT_TOKEN}`);
892
- let o;
893
- if (s && s !== "GET" && s !== "HEAD") {
951
+ a ? n.authorization = Array.isArray(a) ? a[0] : a : ue(r) && process.env.VOLTRO_INSPECT_TOKEN && (n.authorization = `Bearer ${process.env.VOLTRO_INSPECT_TOKEN}`);
952
+ let s;
953
+ if (o && o !== "GET" && o !== "HEAD") {
894
954
  let t = [];
895
955
  for await (let n of e) t.push(n);
896
- o = Buffer.concat(t);
956
+ s = Buffer.concat(t);
897
957
  let r = i["content-type"];
898
958
  r && (n["content-type"] = Array.isArray(r) ? r[0] : r);
899
959
  }
900
960
  let c = await fetch(r, {
901
961
  redirect: "manual",
902
- method: s,
962
+ method: o,
903
963
  headers: n,
904
- ...o ? { body: new Uint8Array(o.buffer, o.byteOffset, o.byteLength) } : {}
964
+ ...s ? { body: new Uint8Array(s.buffer, s.byteOffset, s.byteLength) } : {}
905
965
  }), l = Buffer.from(await c.arrayBuffer());
906
966
  t.writeHead(c.status, {
907
967
  "content-type": c.headers.get("content-type") ?? "application/octet-stream",
@@ -912,20 +972,20 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
912
972
  }
913
973
  return;
914
974
  }
915
- if (a.name === "voltroDashboard" && o === "/api/dashboard/proxy/stream") {
975
+ if (s.name === "voltroDashboard" && a === "/api/dashboard/proxy/stream") {
916
976
  let r = new URL(n, "http://x").searchParams.get("target");
917
977
  if (!r) {
918
978
  t.writeHead(400, { "content-type": "text/plain" }), t.end("missing ?target=");
919
979
  return;
920
980
  }
921
- if (!ce(r)) {
981
+ if (!de(r)) {
922
982
  t.writeHead(400, { "content-type": "text/plain" }), t.end("target not allowed: must be loopback or an origin configured in VOLTRO_DASHBOARD_APPS");
923
983
  return;
924
984
  }
925
985
  let a = new AbortController();
926
986
  e.on("close", () => a.abort()), t.on("close", () => a.abort());
927
987
  try {
928
- let e = i.authorization ?? (M(r) && process.env.VOLTRO_INSPECT_TOKEN ? `Bearer ${process.env.VOLTRO_INSPECT_TOKEN}` : void 0), n = await fetch(r, {
988
+ let e = i.authorization ?? (ue(r) && process.env.VOLTRO_INSPECT_TOKEN ? `Bearer ${process.env.VOLTRO_INSPECT_TOKEN}` : void 0), n = await fetch(r, {
929
989
  redirect: "manual",
930
990
  method: "GET",
931
991
  headers: {
@@ -959,16 +1019,16 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
959
1019
  }
960
1020
  return;
961
1021
  }
962
- if (o === "/_voltro/inspect/stream") {
963
- let n = A(i.origin);
964
- if (k()) {
1022
+ if (a === "/_voltro/inspect/stream") {
1023
+ let n = I(i.origin);
1024
+ if (F()) {
965
1025
  t.writeHead(503, {
966
1026
  "content-type": "application/json",
967
1027
  ...n
968
1028
  }), t.end(JSON.stringify({ error: "inspect disabled (VOLTRO_INSPECT=off)" }));
969
1029
  return;
970
1030
  }
971
- let r = j(i, "GET");
1031
+ let r = ce(i, "GET");
972
1032
  if (!r.ok) {
973
1033
  t.writeHead(401, {
974
1034
  "content-type": "application/json",
@@ -986,11 +1046,11 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
986
1046
  "x-accel-buffering": "no",
987
1047
  ...n
988
1048
  }), t.flushHeaders(), t.write("retry: 5000\n\n");
989
- for (let e of u.buffered()) t.write(g(e));
990
- let a = u.subscribe((e) => {
991
- t.write(g(e));
1049
+ for (let e of d.buffered()) t.write(v(e));
1050
+ let a = d.subscribe((e) => {
1051
+ t.write(v(e));
992
1052
  }), o = setInterval(() => {
993
- t.write(h());
1053
+ t.write(y());
994
1054
  }, 15e3), s = () => {
995
1055
  clearInterval(o), a();
996
1056
  };
@@ -998,18 +1058,18 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
998
1058
  return;
999
1059
  }
1000
1060
  try {
1001
- let e = await He(n, i);
1002
- if (e.stream ? e.stream(t) : (t.writeHead(e.status, e.headers), t.end(e.body)), !o.startsWith("/_voltro/inspect")) {
1061
+ let e = await Ze(n, i);
1062
+ if (e.stream ? e.stream(t) : (t.writeHead(e.status, e.headers), t.end(e.body)), !a.startsWith("/_voltro/inspect")) {
1003
1063
  let t = Date.now() - r;
1004
- u.emit("request", {
1005
- url: o,
1064
+ d.emit("request", {
1065
+ url: a,
1006
1066
  status: e.status,
1007
1067
  durationMs: t,
1008
1068
  renderedBy: e.headers["x-voltro-rendered-by"],
1009
1069
  cache: e.headers["x-voltro-cache"]
1010
1070
  });
1011
- let n = Z(o, U)?.route.pattern ?? (e.status === 404 ? "<unmatched>" : "<asset>");
1012
- Le.record({
1071
+ let n = ze(a, q)?.route.pattern ?? (e.status === 404 ? "<unmatched>" : "<asset>");
1072
+ Ke.record({
1013
1073
  kind: "request",
1014
1074
  tag: n,
1015
1075
  durationMs: t,
@@ -1020,71 +1080,71 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
1020
1080
  t.writeHead(500, { "content-type": "text/plain" }), t.end(`internal error: ${e.message}`);
1021
1081
  }
1022
1082
  });
1023
- await new Promise((e) => We.listen(m, "::", e)), Ue = !0, r.mark("ready"), K.info(`listening on http://localhost:${m}`, {
1083
+ await new Promise((e) => $e.listen(m, "::", e)), Qe = !0, r.mark("ready"), Y.info(`listening on http://localhost:${m}`, {
1024
1084
  port: m,
1025
- distDir: x
1026
- }), K.debug("dynamic + ssr/isr routes resolve via SSR loader");
1085
+ distDir: b
1086
+ }), Y.debug("dynamic + ssr/isr routes resolve via SSR loader");
1027
1087
  try {
1028
- await pe({
1029
- id: w,
1030
- name: C,
1088
+ await _e({
1089
+ id: E,
1090
+ name: T,
1031
1091
  kind: "web",
1032
1092
  url: `http://localhost:${m}`,
1033
1093
  pid: process.pid,
1034
1094
  status: "live",
1035
- logFile: T.path
1095
+ logFile: O.path
1036
1096
  });
1037
- let e = p(t);
1097
+ let e = c(t);
1038
1098
  if (e) {
1039
- let t = await d({ dashboardAppPath: e });
1040
- t.status === "launched" ? K.info(`dashboard launched at http://localhost:${t.port}`, { port: t.port }) : t.status === "already-running" && K.debug(`dashboard already running on :${t.port}`, { port: t.port });
1099
+ let t = await g({ dashboardAppPath: e });
1100
+ 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 });
1041
1101
  }
1042
1102
  setInterval(() => {
1043
- pe({
1044
- id: w,
1045
- name: C,
1103
+ _e({
1104
+ id: E,
1105
+ name: T,
1046
1106
  kind: "web",
1047
1107
  url: `http://localhost:${m}`,
1048
1108
  pid: process.pid,
1049
1109
  status: "live",
1050
- logFile: T.path
1110
+ logFile: O.path
1051
1111
  }).catch(() => {});
1052
1112
  }, 1e4).unref();
1053
1113
  } catch (e) {
1054
- K.warn("runtime-registry write failed", {}, e);
1114
+ Y.warn("runtime-registry write failed", {}, e);
1055
1115
  }
1056
- Ce({
1057
- app: a.name ?? "unnamed",
1116
+ De({
1117
+ app: s.name ?? "unnamed",
1058
1118
  kind: "web",
1059
1119
  url: `http://localhost:${m}`,
1060
1120
  bootMs: r.total()
1061
1121
  });
1062
- let Ge = r.phaseBreakdown();
1063
- K.info(`start: ready in ${r.total()}ms`, {
1122
+ let et = r.phaseBreakdown();
1123
+ Y.info(`start: ready in ${r.total()}ms`, {
1064
1124
  bootMs: r.total(),
1065
- ...Ge ? { phases: Ge } : {}
1125
+ ...et ? { phases: et } : {}
1066
1126
  });
1067
- let Ke = !1, qe = (e) => async () => {
1068
- if (!Ke) {
1069
- if (Ke = !0, K.info(`received ${e}, shutting down`, { signal: e }), We.close(), await $.stop(), z) try {
1070
- await z.end();
1127
+ let tt = !1, nt = (e) => async () => {
1128
+ if (!tt) {
1129
+ if (tt = !0, Y.info(`received ${e}, shutting down`, { signal: e }), $e.close(), await Ge.stop(), U) try {
1130
+ await U.end();
1071
1131
  } catch {}
1072
- await G.close(), await he(w), await T.dispose(), process.exit(0);
1132
+ await X.close(), await ye(E), await O.dispose(), process.exit(0);
1073
1133
  }
1074
1134
  };
1075
- process.on("SIGINT", qe("SIGINT")), process.on("SIGTERM", qe("SIGTERM"));
1076
- let Je = process.ppid;
1077
- if (Je > 1) {
1135
+ process.on("SIGINT", nt("SIGINT")), process.on("SIGTERM", nt("SIGTERM"));
1136
+ let rt = process.ppid;
1137
+ if (rt > 1) {
1078
1138
  let e = setInterval(() => {
1079
- (process.ppid !== Je || process.ppid === 1) && (clearInterval(e), qe("SIGTERM")());
1139
+ (process.ppid !== rt || process.ppid === 1) && (clearInterval(e), nt("SIGTERM")());
1080
1140
  }, 2e3);
1081
1141
  e.unref();
1082
1142
  }
1083
1143
  return new Promise(() => {});
1084
- }, Le = async (e) => {
1144
+ }, We = async (e) => {
1085
1145
  t("start");
1086
- let n = e.find((e) => !e.startsWith("-")) ?? process.cwd(), r = await $(L(n));
1087
- return r.ran ? r.exitCode : (K.error("no web app found at this path"), 1);
1146
+ let n = e.find((e) => !e.startsWith("-")) ?? process.cwd(), r = await Ue(Ee(n));
1147
+ return r.ran ? r.exitCode : (Y.error("no web app found at this path"), 1);
1088
1148
  };
1089
1149
  //#endregion
1090
- export { $ as n, Le as t };
1150
+ export { Ue as n, We as t };