@voltro/cli 0.30.1 → 0.30.2

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 (77) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/dist/{apiBuild-DmkzRyv7.js → apiBuild-BUS1RfPi.js} +2 -2
  3. package/dist/apiBuild-DMlxvL8h.js +2 -0
  4. package/dist/bin.js +3 -3
  5. package/dist/checkCommand-CARZ36Tr.js +2 -0
  6. package/dist/{checkCommand-C4konUy9.js → checkCommand-D_wdOFhw.js} +346 -293
  7. package/dist/{commands-BkJft9K2.js → commands-BgGAUcku.js} +1680 -1680
  8. package/dist/{dbCommand-qn__kLEt.js → dbCommand-CbPRCD1x.js} +56 -19
  9. package/dist/dbCommand-Ht47LrV-.js +2 -0
  10. package/dist/{dev-C_NPcLDp.js → dev-GAOIot9G.js} +2169 -2153
  11. package/dist/{dev-DXhhZ7-f.js → dev-tPcOmjPJ.js} +1 -1
  12. package/dist/{frameworkTableAssembly-Cpgn2e88.js → frameworkTableAssembly-BwIrO5nv.js} +122 -103
  13. package/dist/frameworkTableAssembly-D-EebUQX.js +2 -0
  14. package/dist/index.js +1 -1
  15. package/dist/{inspectMetrics-CkB2J0Zn.js → inspectMetrics-BM1vrsga.js} +314 -314
  16. package/dist/{sdkgen-wsWLrq4l.js → sdkgen-BV4fFucu.js} +1 -1
  17. package/dist/{serveCommand-HtI4X5kj.js → serveCommand-ClqXCX1y.js} +17 -16
  18. package/dist/serveEntry.js +2 -2
  19. package/dist/{start-egkbpugc.js → start-CTnNvKlk.js} +348 -348
  20. package/dist/startEntry.js +2 -2
  21. package/package.json +17 -17
  22. package/templates/AGENTS.md +1 -1
  23. package/templates/agent-docs/_index.md +1 -1
  24. package/templates/agent-docs/cli.md +4 -2
  25. package/templates/agent-docs/internationalization.md +25 -3
  26. package/templates/agent-docs/whats-new.md +24 -47
  27. package/templates/apps/api-ai/package.json +7 -7
  28. package/templates/apps/api-auth/package.json +8 -8
  29. package/templates/apps/api-backend/package.json +7 -7
  30. package/templates/apps/api-backend-deactivation/package.json +7 -7
  31. package/templates/apps/api-backend-mail/package.json +8 -8
  32. package/templates/apps/api-backend-mariadb/package.json +9 -9
  33. package/templates/apps/api-backend-sqlite/package.json +8 -8
  34. package/templates/apps/api-backend-storage/package.json +8 -8
  35. package/templates/apps/api-cms/package.json +10 -10
  36. package/templates/apps/api-collab/package.json +8 -8
  37. package/templates/apps/api-data-advanced/package.json +8 -8
  38. package/templates/apps/api-durable/package.json +8 -8
  39. package/templates/apps/api-feature-flags/package.json +9 -9
  40. package/templates/apps/api-governance/package.json +8 -8
  41. package/templates/apps/api-kv/package.json +8 -8
  42. package/templates/apps/api-moderation/package.json +8 -8
  43. package/templates/apps/api-observability/package.json +8 -8
  44. package/templates/apps/api-ratelimit/package.json +8 -8
  45. package/templates/apps/api-rbac/package.json +8 -8
  46. package/templates/apps/api-rest/package.json +7 -7
  47. package/templates/apps/api-saas/package.json +11 -11
  48. package/templates/apps/api-saas-starter/package.json +10 -10
  49. package/templates/apps/api-search/package.json +8 -8
  50. package/templates/apps/api-status/package.json +8 -8
  51. package/templates/apps/api-versioning/package.json +8 -8
  52. package/templates/apps/api-webhooks/package.json +9 -9
  53. package/templates/apps/changelog/package.json +6 -6
  54. package/templates/apps/edge-functions/package.json +2 -2
  55. package/templates/apps/frontend-admin/package.json +8 -8
  56. package/templates/apps/frontend-app/package.json +8 -8
  57. package/templates/apps/frontend-auth/package.json +8 -8
  58. package/templates/apps/frontend-blank/package.json +7 -7
  59. package/templates/apps/frontend-cms/package.json +9 -9
  60. package/templates/apps/frontend-collab/package.json +9 -9
  61. package/templates/apps/frontend-contact/package.json +7 -7
  62. package/templates/apps/frontend-dashboard/package.json +7 -7
  63. package/templates/apps/frontend-docs/package.json +7 -7
  64. package/templates/apps/frontend-i18n/package.json +6 -6
  65. package/templates/apps/frontend-landing/package.json +7 -7
  66. package/templates/apps/frontend-portal/package.json +8 -8
  67. package/templates/apps/frontend-saas/package.json +8 -8
  68. package/templates/apps/frontend-spa/package.json +7 -7
  69. package/templates/apps/frontend-ssr/package.json +7 -7
  70. package/templates/apps/frontend-ssr-api/package.json +8 -8
  71. package/templates/apps/frontend-static-blog/package.json +6 -6
  72. package/templates/apps/frontend-status/package.json +8 -8
  73. package/templates/apps/mobile-app/package.json +2 -2
  74. package/dist/apiBuild-Ca6Sq5jy.js +0 -2
  75. package/dist/checkCommand-DHD0aBeR.js +0 -2
  76. package/dist/dbCommand-wfGi3FgG.js +0 -2
  77. package/dist/frameworkTableAssembly-Bn_c4Mnl.js +0 -2
@@ -1,14 +1,14 @@
1
- import { B as e, E as t, G as n, I as r, K as i, N as a, O as o, Q as s, S as c, T as l, U as u, W as ee, Z as d, _ as f, _t as p, a as m, at as h, b as g, c as _, f as v, ft as y, g as b, gt as x, h as S, ht as te, i as ne, it as re, lt as ie, m as C, mt as w, nt as ae, o as oe, ot as T, p as E, q as D, r as O, rt as k, s as A, t as j, v as M, x as se, y as N } from "./inspectMetrics-CkB2J0Zn.js";
2
- import { A as ce, E as P, O as F, a as le, k as I, m as ue } from "./inspect-BUUjt773.js";
1
+ import { $ as e, C as t, D as n, E as r, G as i, J as a, K as o, L as s, P as c, Q as l, S as u, V as d, W as ee, _ as f, _t as p, a as m, at as h, b as g, c as _, f as v, g as y, gt as b, h as x, ht as S, i as C, it as te, k as w, m as T, o as ne, ot as re, p as ie, pt as E, q as D, r as ae, rt as O, s as k, st as oe, t as A, ut as j, v as M, vt as N, x as P, y as F } from "./inspectMetrics-BM1vrsga.js";
2
+ import { A as se, E as I, O as ce, a as le, k as L, m as ue } from "./inspect-BUUjt773.js";
3
3
  import { t as de } from "./bootTiming-BdyP9nYw.js";
4
- import { dirname as L, extname as fe, join as R, resolve as pe } from "node:path";
5
- import { fileURLToPath as z, pathToFileURL as B } from "node:url";
6
- import { createLogger as V, printReadyBlock as me } from "@voltro/logger";
7
- import { promises as H } from "node:fs";
4
+ import { dirname as fe, extname as pe, join as R, resolve as z } from "node:path";
5
+ import { fileURLToPath as B, pathToFileURL as V } from "node:url";
6
+ import { createLogger as H, printReadyBlock as me } from "@voltro/logger";
7
+ import { promises as U } from "node:fs";
8
8
  import { snapshotMetricsSync as he } from "@voltro/runtime";
9
9
  import { createServer as ge } from "node:http";
10
10
  //#region src/isrCdcInvalidator.ts
11
- var U = V({ scope: "voltro:start:cdc" }), W = (e) => (t) => {
11
+ var W = H({ scope: "voltro:start:cdc" }), G = (e) => (t) => {
12
12
  let n = 0;
13
13
  for (let [r, i] of e.tableSubscriptionsByPattern) {
14
14
  if (!i.includes(t)) continue;
@@ -19,23 +19,23 @@ var U = V({ scope: "voltro:start:cdc" }), W = (e) => (t) => {
19
19
  }));
20
20
  }
21
21
  return n;
22
- }, G = () => !process.env.PG_HOST && !process.env.PG_DATABASE ? null : {
22
+ }, _e = () => !process.env.PG_HOST && !process.env.PG_DATABASE ? null : {
23
23
  host: process.env.PG_HOST ?? "localhost",
24
24
  port: Number(process.env.PG_PORT ?? 5432),
25
25
  user: process.env.PG_USER ?? "app",
26
26
  password: process.env.PG_PASSWORD ?? "app",
27
27
  database: process.env.PG_DATABASE ?? "app"
28
- }, _e = (e) => {
29
- let t = e.channel ?? "framework_changes", n = W(e), r = null, i = null;
28
+ }, ve = (e) => {
29
+ let t = e.channel ?? "framework_changes", n = G(e), r = null, i = null;
30
30
  return {
31
31
  start: async () => {
32
- let a = G();
32
+ let a = _e();
33
33
  if (!a) {
34
- U.debug("skipped — no PG_* env vars set");
34
+ W.debug("skipped — no PG_* env vars set");
35
35
  return;
36
36
  }
37
37
  if (e.tableSubscriptionsByPattern.size === 0) {
38
- U.debug("skipped — no pages declare cacheInvalidatesOn");
38
+ W.debug("skipped — no pages declare cacheInvalidatesOn");
39
39
  return;
40
40
  }
41
41
  r = new (await (import("pg"))).default.Client(a), await r.connect(), i = (e) => {
@@ -44,16 +44,16 @@ var U = V({ scope: "voltro:start:cdc" }), W = (e) => (t) => {
44
44
  try {
45
45
  r = JSON.parse(e.payload);
46
46
  } catch (e) {
47
- U.warn("bad CDC payload", {}, e);
47
+ W.warn("bad CDC payload", {}, e);
48
48
  return;
49
49
  }
50
50
  let i = n(r.table);
51
- i > 0 && U.info(`${r.op} on '${r.table}' → dropped ${i} cache entries`, {
51
+ i > 0 && W.info(`${r.op} on '${r.table}' → dropped ${i} cache entries`, {
52
52
  op: r.op,
53
53
  table: r.table,
54
54
  dropped: i
55
55
  });
56
- }, r.on("notification", i), await r.query(`LISTEN ${t}`), U.info(`LISTEN ${t}`, {
56
+ }, r.on("notification", i), await r.query(`LISTEN ${t}`), W.info(`LISTEN ${t}`, {
57
57
  channel: t,
58
58
  host: a.host,
59
59
  port: a.port,
@@ -69,7 +69,7 @@ var U = V({ scope: "voltro:start:cdc" }), W = (e) => (t) => {
69
69
  }
70
70
  }
71
71
  };
72
- }, K = V({ scope: "voltro:start:isr-cache" }), q = "voltro_isr_cache", ve = (e) => `
72
+ }, K = H({ scope: "voltro:start:isr-cache" }), ye = "voltro_isr_cache", q = (e) => `
73
73
  CREATE TABLE IF NOT EXISTS ${e} (
74
74
  cache_key TEXT PRIMARY KEY,
75
75
  html TEXT NOT NULL,
@@ -80,9 +80,9 @@ CREATE TABLE IF NOT EXISTS ${e} (
80
80
  stale_while_revalidate_ms BIGINT NOT NULL DEFAULT 0
81
81
  );
82
82
  CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
83
- `, ye = (e) => {
84
- let t = e.tableName ?? q, { client: n } = e, r = /* @__PURE__ */ new Map(), i = !1, a = (async () => {
85
- i || (i = !0, await n.query(ve(t)));
83
+ `, be = (e) => {
84
+ let t = e.tableName ?? ye, { client: n } = e, r = /* @__PURE__ */ new Map(), i = !1, a = (async () => {
85
+ i || (i = !0, await n.query(q(t)));
86
86
  })().then(async () => {
87
87
  let e = await n.query(`SELECT * FROM ${t}`);
88
88
  for (let t of e.rows) r.set(t.cache_key, {
@@ -142,14 +142,14 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
142
142
  return Array.from(r.entries());
143
143
  }
144
144
  };
145
- }, J = V({ scope: "voltro:start" }), be = await (async () => {
145
+ }, J = H({ scope: "voltro:start" }), xe = await (async () => {
146
146
  try {
147
- let e = R(L(z(import.meta.url)), "..", "package.json"), t = await H.readFile(e, "utf8");
147
+ let e = R(fe(B(import.meta.url)), "..", "package.json"), t = await U.readFile(e, "utf8");
148
148
  return JSON.parse(t).version ?? "0.0.0";
149
149
  } catch {
150
150
  return "0.0.0";
151
151
  }
152
- })(), Y = (e) => e instanceof Error && e._voltroControl === "redirect" && typeof e.location == "string", X = (e) => e instanceof Error && e._voltroControl === "not-found", Z = {
152
+ })(), Y = (e) => e instanceof Error && e._voltroControl === "redirect" && typeof e.location == "string", X = (e) => e instanceof Error && e._voltroControl === "not-found", Se = {
153
153
  ".html": "text/html; charset=utf-8",
154
154
  ".js": "application/javascript",
155
155
  ".mjs": "application/javascript",
@@ -167,13 +167,13 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
167
167
  ".woff": "font/woff",
168
168
  ".woff2": "font/woff2",
169
169
  ".txt": "text/plain; charset=utf-8"
170
- }, xe = (e) => Z[fe(e).toLowerCase()] ?? "application/octet-stream", Se = (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) => {
170
+ }, Ce = (e) => Se[pe(e).toLowerCase()] ?? "application/octet-stream", we = (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) => {
171
171
  try {
172
- return await H.stat(e), !0;
172
+ return await U.stat(e), !0;
173
173
  } catch {
174
174
  return !1;
175
175
  }
176
- }, Ce = (e) => {
176
+ }, Q = (e) => {
177
177
  let t = [], n = 0, r = e.split("/").filter(Boolean), i = [];
178
178
  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, "\\$&"));
179
179
  let a = i.join("/");
@@ -182,8 +182,8 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
182
182
  paramNames: t,
183
183
  priority: n
184
184
  };
185
- }, we = (e) => e.map((e) => {
186
- let { regex: t, paramNames: n, priority: r } = Ce(e.pattern);
185
+ }, Te = (e) => e.map((e) => {
186
+ let { regex: t, paramNames: n, priority: r } = Q(e.pattern);
187
187
  return {
188
188
  pattern: e.pattern,
189
189
  file: e.file,
@@ -192,7 +192,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
192
192
  paramNames: n,
193
193
  priority: r
194
194
  };
195
- }).slice().sort((e, t) => e.priority - t.priority), Te = (e, t) => {
195
+ }).slice().sort((e, t) => e.priority - t.priority), Ee = (e, t) => {
196
196
  for (let n of t) {
197
197
  let t = n.regex.exec(e);
198
198
  if (!t) continue;
@@ -204,31 +204,31 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
204
204
  };
205
205
  }
206
206
  return null;
207
- }, Ee = async (e) => {
208
- let { provider: t, route: n, params: i, pathname: a, dirs: o, shellTemplate: s, requestHeaders: l, requestUrl: u = "", apiOrigin: ee, apiName: d } = e, { search: f } = c(u), p = ne(ee, l.cookie, { apiName: d }), h = await t.getPage(n.pattern, n.file), _ = r(h, n.file), v = _ === "spa" && oe(o, n.dirChain).some((e) => e.hasLayout);
209
- if (_ !== "ssr" && _ !== "isr" && !v) return null;
210
- let y = oe(o, n.dirChain), x = {}, te = null, re, ie = new AbortController();
207
+ }, De = async (e) => {
208
+ let { provider: n, route: r, params: i, pathname: a, dirs: o, shellTemplate: c, requestHeaders: l, requestUrl: d = "", apiOrigin: ee, apiName: p } = e, { search: h } = t(d), _ = C(ee, l.cookie, { apiName: p }), v = await n.getPage(r.pattern, r.file), b = s(v, r.file), S = b === "spa" && ne(o, r.dirChain).some((e) => e.hasLayout);
209
+ if (b !== "ssr" && b !== "isr" && !S) return null;
210
+ let te = ne(o, r.dirChain), w = {}, re = null, ie, E = new AbortController();
211
211
  try {
212
- (await t.getHelpers()).beginStoreSeeds(), {chain: re, segmentLoaderData: x} = await m({
213
- entries: y,
214
- loadLayout: (e) => t.getLayout(e.dir),
215
- loadError: (e) => t.getError(e.dir),
216
- loadPending: (e) => t.getPending(e.dir),
212
+ (await n.getHelpers()).beginStoreSeeds(), {chain: ie, segmentLoaderData: w} = await m({
213
+ entries: te,
214
+ loadLayout: (e) => n.getLayout(e.dir),
215
+ loadError: (e) => n.getError(e.dir),
216
+ loadPending: (e) => n.getPending(e.dir),
217
217
  ctx: {
218
218
  params: i,
219
219
  pathname: a,
220
- search: f,
221
- signal: ie.signal,
220
+ search: h,
221
+ signal: E.signal,
222
222
  headers: l,
223
- query: p
223
+ query: _
224
224
  }
225
- }), typeof h.loader == "function" && !v && (te = await h.loader({
225
+ }), typeof v.loader == "function" && !S && (re = await v.loader({
226
226
  params: i,
227
227
  pathname: a,
228
- search: f,
229
- signal: ie.signal,
228
+ search: h,
229
+ signal: E.signal,
230
230
  headers: l,
231
- query: p
231
+ query: _
232
232
  }));
233
233
  } catch (e) {
234
234
  if (Y(e)) return {
@@ -239,13 +239,13 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
239
239
  if (X(e)) return { control: "not-found" };
240
240
  throw e;
241
241
  }
242
- let w = await t.getHelpers();
243
- v || await C({
244
- pageMod: h,
242
+ let D = await n.getHelpers();
243
+ S || await T({
244
+ pageMod: v,
245
245
  params: i,
246
- query: p,
247
- apiName: d,
248
- seed: w.seedPreloadedSubscription,
246
+ query: _,
247
+ apiName: p,
248
+ seed: D.seedPreloadedSubscription,
249
249
  onError: ({ tag: e, apiName: t }, n) => J.warn("preload seed failed", {
250
250
  tag: e,
251
251
  apiName: t,
@@ -253,57 +253,57 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
253
253
  }, n)
254
254
  });
255
255
  let ae = {
256
- pattern: n.pattern,
257
- Component: h.default,
258
- meta: h.meta,
259
- loader: h.loader,
260
- ErrorBoundary: h.ErrorBoundary,
261
- Pending: h.Pending,
262
- renderMode: _,
263
- chain: re
264
- }, E = {
265
- cookies: w.parseCookieHeader(l.cookie),
256
+ pattern: r.pattern,
257
+ Component: v.default,
258
+ meta: v.meta,
259
+ loader: v.loader,
260
+ ErrorBoundary: v.ErrorBoundary,
261
+ Pending: v.Pending,
262
+ renderMode: b,
263
+ chain: ie
264
+ }, O = {
265
+ cookies: D.parseCookieHeader(l.cookie),
266
266
  headers: l,
267
- url: u
268
- }, D = w.i18n?.resolve(l.cookie, l["accept-language"]), O = h.interactive ?? "full";
269
- if (v) {
270
- let e = N({
271
- helpers: w,
272
- page: n.pattern,
273
- interactive: O,
267
+ url: d
268
+ }, k = D.i18n?.resolve(l.cookie, l["accept-language"]), A = v.interactive ?? "full";
269
+ if (S) {
270
+ let e = g({
271
+ helpers: D,
272
+ page: r.pattern,
273
+ interactive: A,
274
274
  delivery: "stream",
275
275
  renderInput: {
276
276
  descriptor: ae,
277
277
  params: i,
278
278
  pathname: a,
279
- search: f,
280
- segmentLoaderData: x,
281
- requestContext: E,
282
- ...D ? {
283
- outerWrap: D.outerWrap,
284
- locale: D.locale
279
+ search: h,
280
+ segmentLoaderData: w,
281
+ requestContext: O,
282
+ ...k ? {
283
+ outerWrap: k.outerWrap,
284
+ locale: k.locale
285
285
  } : {}
286
286
  }
287
- }), t = D?.locale ?? E.cookies["voltro:locale"] ?? "en", r = (t) => se({
288
- helpers: w,
287
+ }), t = k?.locale ?? O.cookies["voltro:locale"] ?? "en", n = (t) => u({
288
+ helpers: D,
289
289
  prepared: e,
290
290
  meta: t,
291
- interactive: O
291
+ interactive: A
292
292
  });
293
293
  if (e.hasDeferred) {
294
- let n = S({ shell: s });
294
+ let r = y({ shell: c });
295
295
  return {
296
296
  renderMode: "spa",
297
- stream: (i) => b({
297
+ stream: (i) => f({
298
298
  res: i,
299
- shell: n,
299
+ shell: r,
300
300
  htmlLang: t,
301
301
  headers: {
302
302
  "content-type": "text/html; charset=utf-8",
303
303
  "x-voltro-rendered-by": "spa"
304
304
  },
305
- headInjection: r,
306
- render: (t) => w.renderPageToStream({
305
+ headInjection: n,
306
+ render: (t) => D.renderPageToStream({
307
307
  ...e.renderInput,
308
308
  ...t
309
309
  }),
@@ -313,48 +313,48 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
313
313
  })
314
314
  };
315
315
  }
316
- let o = g({
317
- helpers: w,
316
+ let o = P({
317
+ helpers: D,
318
318
  prepared: e
319
319
  });
320
320
  return {
321
- html: s.replace("<div id=\"root\"></div>", `<div id="root">${o.body}</div>`).replace("</head>", ` ${r(o.meta)}\n </head>`).replace(/<html(\s+lang="[^"]*")?/i, `<html lang="${t}"`),
321
+ html: x(c.replace("<div id=\"root\"></div>", `<div id="root">${o.body}</div>`), n(o.meta)).replace(/<html(\s+lang="[^"]*")?/i, `<html lang="${t}"`),
322
322
  renderMode: "spa",
323
323
  revalidateMs: null
324
324
  };
325
325
  }
326
- let k = M({
327
- helpers: w,
328
- page: n.pattern,
326
+ let j = F({
327
+ helpers: D,
328
+ page: r.pattern,
329
329
  pathname: a,
330
- renderMode: _,
331
- interactive: O,
332
- loaderData: te,
333
- segmentLoaderData: x,
334
- pageLoaderRan: typeof h.loader == "function"
335
- }), A = {
330
+ renderMode: b,
331
+ interactive: A,
332
+ loaderData: re,
333
+ segmentLoaderData: w,
334
+ pageLoaderRan: typeof v.loader == "function"
335
+ }), M = {
336
336
  descriptor: ae,
337
337
  params: i,
338
338
  pathname: a,
339
- search: f,
340
- loaderData: k.loaderData,
341
- segmentLoaderData: k.segmentLoaderData,
342
- requestContext: E,
343
- ...D ? {
344
- outerWrap: D.outerWrap,
345
- locale: D.locale
339
+ search: h,
340
+ loaderData: j.loaderData,
341
+ segmentLoaderData: j.segmentLoaderData,
342
+ requestContext: O,
343
+ ...k ? {
344
+ outerWrap: k.outerWrap,
345
+ locale: k.locale
346
346
  } : {}
347
- }, j = (e) => [
348
- w.renderMetaToHtml(e),
349
- `<meta name="voltro-interactive" content="${O}" />`,
350
- ...k.hasDeferred ? [w.renderDeferredRegistryScript()] : [],
351
- w.renderRouterStateScript(k.stateInput)
347
+ }, N = (e) => [
348
+ D.renderMetaToHtml(e),
349
+ `<meta name="voltro-interactive" content="${A}" />`,
350
+ ...j.hasDeferred ? [D.renderDeferredRegistryScript()] : [],
351
+ D.renderRouterStateScript(j.stateInput)
352
352
  ].filter((e) => e.length > 0).join("\n ");
353
- if (_ === "ssr" && O === "full" && e.buffered !== !0) {
354
- let e = D?.locale ?? E.cookies["voltro:locale"] ?? "en", t = S({ shell: s });
353
+ if (b === "ssr" && A === "full" && e.buffered !== !0) {
354
+ let e = k?.locale ?? O.cookies["voltro:locale"] ?? "en", t = y({ shell: c });
355
355
  return {
356
356
  renderMode: "ssr",
357
- stream: (n) => b({
357
+ stream: (n) => f({
358
358
  res: n,
359
359
  shell: t,
360
360
  htmlLang: e,
@@ -362,9 +362,9 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
362
362
  "content-type": "text/html; charset=utf-8",
363
363
  "x-voltro-rendered-by": "ssr"
364
364
  },
365
- headInjection: j,
366
- render: (e) => w.renderPageToStream({
367
- ...A,
365
+ headInjection: N,
366
+ render: (e) => D.renderPageToStream({
367
+ ...M,
368
368
  ...e
369
369
  }),
370
370
  onShellError: (e) => {
@@ -373,16 +373,16 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
373
373
  })
374
374
  };
375
375
  }
376
- let { html: ce, meta: P } = w.renderPageToHtml(A), F = j(P), le = D?.locale ?? E.cookies["voltro:locale"] ?? "en", I = s.replace("<div id=\"root\"></div>", `<div id="root">${ce}</div>`).replace("</head>", ` ${F}\n </head>`).replace(/<html(\s+lang="[^"]*")?/i, `<html lang="${le}"`);
377
- O === "none" && (I = Se(I));
378
- let ue = _ === "isr" ? T(h.revalidate) : null;
376
+ let { html: se, meta: I } = D.renderPageToHtml(M), ce = N(I), le = k?.locale ?? O.cookies["voltro:locale"] ?? "en", L = x(c.replace("<div id=\"root\"></div>", `<div id="root">${se}</div>`), ce).replace(/<html(\s+lang="[^"]*")?/i, `<html lang="${le}"`);
377
+ A === "none" && (L = we(L));
378
+ let ue = b === "isr" ? oe(v.revalidate) : null;
379
379
  return {
380
- html: I,
381
- renderMode: _,
380
+ html: L,
381
+ renderMode: b,
382
382
  revalidateMs: ue
383
383
  };
384
- }, $ = (e) => e === "" ? "/" : e, De = async (e) => {
385
- let t = await import(B(e).href);
384
+ }, $ = (e) => e === "" ? "/" : e, Oe = async (e) => {
385
+ let t = await import(V(e).href);
386
386
  return {
387
387
  kind: "bundle",
388
388
  getPageMeta: () => t.pageMeta,
@@ -411,11 +411,11 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
411
411
  },
412
412
  async close() {}
413
413
  };
414
- }, Oe = async (e, t) => {
415
- let n = await y("vite", () => import("vite")), r = (await import("@vitejs/plugin-react")).default, i = (await import("@tailwindcss/vite")).default, a = await n.createServer({
416
- root: t,
414
+ }, ke = async (t, n) => {
415
+ let r = await E("vite", () => import("vite")), i = (await import("@vitejs/plugin-react")).default, a = (await import("@tailwindcss/vite")).default, o = await r.createServer({
416
+ root: n,
417
417
  envPrefix: "__VOLTRO_VITE_ENV_DISABLED__",
418
- plugins: [r(), i()],
418
+ plugins: [i(), a()],
419
419
  resolve: { dedupe: ["react", "react-dom"] },
420
420
  ssr: { noExternal: ["react-intl"] },
421
421
  server: {
@@ -424,129 +424,129 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
424
424
  },
425
425
  appType: "custom",
426
426
  logLevel: "warn"
427
- }), o = R(e, "src", "pages"), c = (e) => e === "" ? o : R(o, e), l = d({
428
- limit: s(),
427
+ }), s = R(t, "src", "pages"), c = (e) => e === "" ? s : R(s, e), u = l({
428
+ limit: e(),
429
429
  onColdStart: (e) => J.debug("ssr cold-compile start", { id: e }),
430
430
  onColdEnd: (e, { durationMs: t, failed: n }) => J.debug(`ssr cold-compile ${n ? "FAILED" : "end"} ${t}ms`, {
431
431
  id: e,
432
432
  ms: t,
433
433
  ...n ? { failed: !0 } : {}
434
434
  })
435
- }), u = (e) => l.load(e, async () => await a.ssrLoadModule(e));
435
+ }), d = (e) => u.load(e, async () => await o.ssrLoadModule(e));
436
436
  return {
437
437
  kind: "middleware",
438
438
  async getPage(e, t) {
439
- return u(R(o, t));
439
+ return d(R(s, t));
440
440
  },
441
441
  async getLayout(e) {
442
- return u(R(c(e), "layout.tsx"));
442
+ return d(R(c(e), "layout.tsx"));
443
443
  },
444
444
  async getError(e) {
445
- return u(R(c(e), "error.tsx"));
445
+ return d(R(c(e), "error.tsx"));
446
446
  },
447
447
  async getPending(e) {
448
- return u(R(c(e), "loading.tsx"));
448
+ return d(R(c(e), "loading.tsx"));
449
449
  },
450
450
  async getHelpers() {
451
- return await u("@voltro/web/ssr");
451
+ return await d("@voltro/web/ssr");
452
452
  },
453
453
  async close() {
454
- await a.close();
454
+ await o.close();
455
455
  }
456
456
  };
457
- }, ke = async (r) => {
458
- let s = de(), c = await A(r);
459
- if (!c) return {
457
+ }, Ae = async (e) => {
458
+ let t = de(), s = await k(e);
459
+ if (!s) return {
460
460
  ran: !1,
461
461
  exitCode: 0
462
462
  };
463
- if (c.type !== "web") return J.error("only web apps are supported by `voltro start`"), {
463
+ if (s.type !== "web") return J.error("only web apps are supported by `voltro start`"), {
464
464
  ran: !0,
465
465
  exitCode: 1
466
466
  };
467
- let { resolved: d } = await ie({
468
- rawEnv: c.env,
467
+ let { resolved: l } = await j({
468
+ rawEnv: s.env,
469
469
  appType: "web",
470
- root: r,
470
+ root: e,
471
471
  log: J,
472
472
  generateTypes: !1
473
- }), m = d.publicValues;
474
- s.mark("config");
475
- let g = i();
476
- u(g), J.info("booting voltro start", { app: c.name ?? "(unnamed)" });
477
- let y = (() => {
473
+ }), u = l.publicValues;
474
+ t.mark("config");
475
+ let f = D();
476
+ ee(f), J.info("booting voltro start", { app: s.name ?? "(unnamed)" });
477
+ let m = (() => {
478
478
  if (process.env.VOLTRO_IS_DASHBOARD === "1" && process.env.VOLTRO_DASHBOARD_PORT) return Number(process.env.VOLTRO_DASHBOARD_PORT);
479
479
  if (process.env.PORT) {
480
480
  let e = Number(process.env.PORT);
481
481
  if (Number.isFinite(e) && e > 0) return e;
482
482
  }
483
- return c.port ?? 5173;
484
- })(), b = R(r, ".framework"), S = R(b, "dist"), ne = R(S, "index.html");
485
- if (!await Q(ne)) return J.error("no built dist found — run `voltro build` first", { distDir: S }), {
483
+ return s.port ?? 5173;
484
+ })(), g = R(e, ".framework"), y = R(g, "dist"), x = R(y, "index.html");
485
+ if (!await Z(x)) return J.error("no built dist found — run `voltro build` first", { distDir: y }), {
486
486
  ran: !0,
487
487
  exitCode: 1
488
488
  };
489
- let C = c.name ?? "unnamed", T = w("web", C, y), M = o(C);
490
- await p({
489
+ let C = s.name ?? "unnamed", T = S("web", C, m), E = w(C);
490
+ await N({
491
491
  id: T,
492
492
  name: C,
493
493
  kind: "web",
494
- url: `http://localhost:${y}`,
494
+ url: `http://localhost:${m}`,
495
495
  pid: process.pid,
496
496
  status: "booting",
497
- logFile: M.path
497
+ logFile: E.path
498
498
  }).catch(() => {});
499
- let se = R(S, "_voltro", "shell.html"), N = await Q(se) ? await H.readFile(se, "utf8") : await H.readFile(ne, "utf8"), L = await _(r, c), fe = O(L[0]), pe = L[0]?.name, z, B = null;
499
+ let oe = R(y, "_voltro", "shell.html"), P = await Z(oe) ? await U.readFile(oe, "utf8") : await U.readFile(x, "utf8"), F = await _(e, s), fe = ae(F[0]), pe = F[0]?.name, z, B = null;
500
500
  process.env.SSR_CACHE === "postgres" && process.env.PG_HOST ? (B = new (await (import("pg"))).default.Client({
501
501
  host: process.env.PG_HOST,
502
502
  port: Number(process.env.PG_PORT ?? 5432),
503
503
  user: process.env.PG_USER ?? "app",
504
504
  password: process.env.PG_PASSWORD ?? "app",
505
505
  database: process.env.PG_DATABASE ?? "app"
506
- }), await B.connect(), z = ye({ client: B }), J.info("isr cache backend: postgres", { table: "voltro_isr_cache" })) : (z = h(), J.info("isr cache backend: memory (per-process)", { hint: "set SSR_CACHE=postgres for persistent storage" })), await E(r, c, L, m);
507
- let { pages: V, dirs: U } = await v(R(r, "src", "pages")), W = we(V);
508
- s.mark("scan");
509
- let G = R(S, "server", "ssrEntry.js"), K = await Q(G);
510
- if (!K && process.env.NODE_ENV === "production") throw J.fatal(`production \`voltro start\` requires a precompiled SSR bundle at ${G} 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 ${G}`);
511
- let q = K ? await De(G) : await Oe(r, b);
512
- J.info(`ssr loader: ${q.kind}`, {
513
- kind: q.kind,
514
- ...q.kind === "middleware" ? { hint: "no pre-built SSR bundle found; run `voltro build` to enable bundle mode" } : {}
515
- }), s.mark("provider");
516
- let ve = q.getPageMeta?.(), Y = /* @__PURE__ */ new Map(), X = 0;
506
+ }), await B.connect(), z = be({ client: B }), J.info("isr cache backend: postgres", { table: "voltro_isr_cache" })) : (z = re(), J.info("isr cache backend: memory (per-process)", { hint: "set SSR_CACHE=postgres for persistent storage" })), await ie(e, s, F, u);
507
+ let { pages: V, dirs: H } = await v(R(e, "src", "pages")), W = Te(V);
508
+ t.mark("scan");
509
+ let G = R(y, "server", "ssrEntry.js"), _e = await Z(G);
510
+ if (!_e && process.env.NODE_ENV === "production") throw J.fatal(`production \`voltro start\` requires a precompiled SSR bundle at ${G} 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 ${G}`);
511
+ let K = _e ? await Oe(G) : await ke(e, g);
512
+ J.info(`ssr loader: ${K.kind}`, {
513
+ kind: K.kind,
514
+ ...K.kind === "middleware" ? { hint: "no pre-built SSR bundle found; run `voltro build` to enable bundle mode" } : {}
515
+ }), t.mark("provider");
516
+ let ye = K.getPageMeta?.(), q = /* @__PURE__ */ new Map(), Y = 0;
517
517
  for (let e of V) {
518
- let t = ve?.[e.pattern];
518
+ let t = ye?.[e.pattern];
519
519
  if (t) {
520
- Y.set(e.pattern, t);
520
+ q.set(e.pattern, t);
521
521
  continue;
522
522
  }
523
523
  try {
524
- let t = await q.getPage(e.pattern, e.file);
525
- Y.set(e.pattern, a(t, e.file)), X++;
524
+ let t = await K.getPage(e.pattern, e.file);
525
+ q.set(e.pattern, c(t, e.file)), Y++;
526
526
  } catch (t) {
527
527
  J.warn("failed to load page metadata", { pattern: e.pattern }, t);
528
528
  }
529
529
  }
530
- J.info(`registered ${Y.size} route(s)`, {
531
- count: Y.size,
532
- fromManifest: Y.size - X,
533
- fromModules: X
534
- }), s.mark("routes");
535
- let Z = /* @__PURE__ */ new Set();
536
- for (let e of W) Y.get(e.pattern)?.renderMode === "spa" && oe(U, e.dirChain).some((e) => e.hasLayout) && Z.add(e.pattern);
537
- Z.size > 0 && J.info(`${Z.size} spa route(s) render an SSR layout shell`, { patterns: [...Z] });
530
+ J.info(`registered ${q.size} route(s)`, {
531
+ count: q.size,
532
+ fromManifest: q.size - Y,
533
+ fromModules: Y
534
+ }), t.mark("routes");
535
+ let X = /* @__PURE__ */ new Set();
536
+ for (let e of W) q.get(e.pattern)?.renderMode === "spa" && ne(H, e.dirChain).some((e) => e.hasLayout) && X.add(e.pattern);
537
+ X.size > 0 && J.info(`${X.size} spa route(s) render an SSR layout shell`, { patterns: [...X] });
538
538
  let Se = /* @__PURE__ */ new Map();
539
- for (let [e, t] of Y) t.cacheInvalidatesOn.length > 0 && Se.set(e, t.cacheInvalidatesOn);
540
- let Ce = /* @__PURE__ */ new Map();
541
- for (let e of W) Ce.set(e.pattern, e.regex);
542
- let $ = _e({
539
+ for (let [e, t] of q) t.cacheInvalidatesOn.length > 0 && Se.set(e, t.cacheInvalidatesOn);
540
+ let we = /* @__PURE__ */ new Map();
541
+ for (let e of W) we.set(e.pattern, e.regex);
542
+ let Q = ve({
543
543
  cache: z,
544
544
  tableSubscriptionsByPattern: Se,
545
- regexByPattern: Ce
545
+ regexByPattern: we
546
546
  });
547
- await $.start(), s.mark("cdc");
548
- let ke = j(), Ae = V.map((e) => {
549
- let t = Y.get(e.pattern);
547
+ await Q.start(), t.mark("cdc");
548
+ let $ = A(), Ae = V.map((e) => {
549
+ let t = q.get(e.pattern);
550
550
  return {
551
551
  pattern: e.pattern,
552
552
  file: e.file,
@@ -561,7 +561,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
561
561
  hasMeta: t?.hasMeta ?? !1,
562
562
  hasGetStaticPaths: t?.hasGetStaticPaths ?? !1
563
563
  };
564
- }), je = U.map((e) => ({
564
+ }), je = H.map((e) => ({
565
565
  dir: e.dir,
566
566
  hasLayout: e.hasLayout,
567
567
  hasError: e.hasError,
@@ -570,11 +570,11 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
570
570
  })), Me = B ? "postgres" : "memory", Ne = {
571
571
  kind: "web",
572
572
  meta: {
573
- name: c.name ?? "(unnamed)",
574
- voltroVersion: be,
575
- port: y,
573
+ name: s.name ?? "(unnamed)",
574
+ voltroVersion: xe,
575
+ port: m,
576
576
  mode: "start",
577
- apis: Object.entries(c.apis ?? {}).map(([e, t]) => {
577
+ apis: Object.entries(s.apis ?? {}).map(([e, t]) => {
578
578
  let n = {
579
579
  name: e,
580
580
  package: t.package
@@ -603,9 +603,9 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
603
603
  },
604
604
  metrics: () => he()
605
605
  }, Pe = async (t, n) => {
606
- let i = t.split("?")[0] ?? "/";
607
- if (c.name === "voltroDashboard" && i === "/api/dashboard/registry") try {
608
- let e = await te();
606
+ let r = t.split("?")[0] ?? "/";
607
+ if (s.name === "voltroDashboard" && r === "/api/dashboard/registry") try {
608
+ let e = await b();
609
609
  return {
610
610
  status: 200,
611
611
  headers: { "content-type": "application/json; charset=utf-8" },
@@ -618,7 +618,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
618
618
  body: `registry read error: ${e.message}`
619
619
  };
620
620
  }
621
- if (c.name === "voltroDashboard" && i === "/api/dashboard/config") {
621
+ if (s.name === "voltroDashboard" && r === "/api/dashboard/config") {
622
622
  let e = process.env.VOLTRO_DASHBOARD_APPS, t = [];
623
623
  if (e && e.trim().length > 0) {
624
624
  let n;
@@ -647,18 +647,18 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
647
647
  body: JSON.stringify({ apps: t })
648
648
  };
649
649
  }
650
- if (i === "/_voltro/inspect/logs") {
651
- let r = e(t, ee(), n);
650
+ if (r === "/_voltro/inspect/logs") {
651
+ let e = d(t, i(), n);
652
652
  return {
653
- status: r.status,
653
+ status: e.status,
654
654
  headers: {
655
- "content-type": r.contentType,
656
- ...P(n.origin)
655
+ "content-type": e.contentType,
656
+ ...I(n.origin)
657
657
  },
658
- body: r.body
658
+ body: e.body
659
659
  };
660
660
  }
661
- if (i !== "/_voltro/inspect/stream") {
661
+ if (r !== "/_voltro/inspect/stream") {
662
662
  let e = ue(t, Ne, n);
663
663
  if (e !== null) return {
664
664
  status: e.status,
@@ -669,36 +669,36 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
669
669
  body: e.body
670
670
  };
671
671
  }
672
- let a = Te(i, W), o = a ? Y.get(a.route.pattern)?.renderMode : void 0, s = o === "ssr" || o === "isr" || (a ? Z.has(a.route.pattern) : !1), l = i === "/" ? R(S, "index.html") : R(S, i.replace(/^\//, ""), "index.html");
673
- if (!s && await Q(l)) return {
672
+ let a = Ee(r, W), o = a ? q.get(a.route.pattern)?.renderMode : void 0, c = o === "ssr" || o === "isr" || (a ? X.has(a.route.pattern) : !1), l = r === "/" ? R(y, "index.html") : R(y, r.replace(/^\//, ""), "index.html");
673
+ if (!c && await Z(l)) return {
674
674
  status: 200,
675
675
  headers: { "content-type": "text/html; charset=utf-8" },
676
- body: await H.readFile(l)
676
+ body: await U.readFile(l)
677
677
  };
678
- if (/\.[a-z0-9]+$/i.test(i)) {
679
- let e = R(S, i.replace(/^\//, ""));
680
- if (await Q(e)) {
681
- let t = await H.readFile(e);
678
+ if (/\.[a-z0-9]+$/i.test(r)) {
679
+ let e = R(y, r.replace(/^\//, ""));
680
+ if (await Z(e)) {
681
+ let t = await U.readFile(e);
682
682
  return {
683
683
  status: 200,
684
- headers: { "content-type": xe(e) },
684
+ headers: { "content-type": Ce(e) },
685
685
  body: t
686
686
  };
687
687
  }
688
688
  }
689
- let u = Te(i, W);
689
+ let u = Ee(r, W);
690
690
  if (!u) return {
691
691
  status: 404,
692
692
  headers: { "content-type": "text/plain" },
693
693
  body: "not found"
694
694
  };
695
- let d = Y.get(u.route.pattern), p = n["x-tenant"] ?? "anonymous", m = (await q.getHelpers()).i18n?.resolve(n.cookie, n["accept-language"])?.locale, h = ae(i, {
696
- ...d?.tenantAware ? { tenant: p } : {},
695
+ let ee = q.get(u.route.pattern), p = n["x-tenant"] ?? "anonymous", m = (await K.getHelpers()).i18n?.resolve(n.cookie, n["accept-language"])?.locale, g = O(r, {
696
+ ...ee?.tenantAware ? { tenant: p } : {},
697
697
  ...m ? { locale: m } : {}
698
- }), _ = z.get(h), v = Date.now();
699
- if (_ && k(_, v)) return g.emit("cache", {
698
+ }), _ = z.get(g), v = Date.now();
699
+ if (_ && te(_, v)) return f.emit("cache", {
700
700
  kind: "HIT",
701
- key: h,
701
+ key: g,
702
702
  ageMs: v - _.renderedAt
703
703
  }), {
704
704
  status: 200,
@@ -706,44 +706,44 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
706
706
  "content-type": "text/html; charset=utf-8",
707
707
  "x-voltro-rendered-by": "isr",
708
708
  "x-voltro-cache": "HIT",
709
- "x-voltro-cache-key": h,
709
+ "x-voltro-cache-key": g,
710
710
  "x-voltro-cache-age-ms": String(v - _.renderedAt)
711
711
  },
712
712
  body: _.html
713
713
  };
714
- if (_ && re(_, v)) return g.emit("cache", {
714
+ if (_ && h(_, v)) return f.emit("cache", {
715
715
  kind: "STALE",
716
- key: h,
716
+ key: g,
717
717
  ageMs: v - _.renderedAt
718
718
  }), (async () => {
719
719
  try {
720
- let e = await Ee({
721
- provider: q,
722
- root: r,
720
+ let i = await De({
721
+ provider: K,
722
+ root: e,
723
723
  route: u.route,
724
724
  params: u.params,
725
- pathname: i,
726
- dirs: U,
727
- shellTemplate: N,
725
+ pathname: r,
726
+ dirs: H,
727
+ shellTemplate: P,
728
728
  requestHeaders: n,
729
729
  apiOrigin: fe,
730
730
  apiName: pe,
731
731
  requestUrl: t,
732
732
  buffered: !0
733
733
  });
734
- if (e && "html" in e && e.renderMode === "isr" && e.revalidateMs !== null) {
735
- let t = Y.get(u.route.pattern)?.staleWhileRevalidateMs ?? 0, n = Date.now();
736
- z.set(h, {
737
- html: e.html,
738
- renderedAt: n,
739
- expiresAt: n + e.revalidateMs,
740
- servableUntil: n + e.revalidateMs + t,
741
- revalidateMs: e.revalidateMs,
742
- staleWhileRevalidateMs: t
734
+ if (i && "html" in i && i.renderMode === "isr" && i.revalidateMs !== null) {
735
+ let e = q.get(u.route.pattern)?.staleWhileRevalidateMs ?? 0, t = Date.now();
736
+ z.set(g, {
737
+ html: i.html,
738
+ renderedAt: t,
739
+ expiresAt: t + i.revalidateMs,
740
+ servableUntil: t + i.revalidateMs + e,
741
+ revalidateMs: i.revalidateMs,
742
+ staleWhileRevalidateMs: e
743
743
  });
744
744
  }
745
745
  } catch (e) {
746
- J.warn("background SWR refresh failed", { url: i }, e);
746
+ J.warn("background SWR refresh failed", { url: r }, e);
747
747
  }
748
748
  })(), {
749
749
  status: 200,
@@ -751,43 +751,43 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
751
751
  "content-type": "text/html; charset=utf-8",
752
752
  "x-voltro-rendered-by": "isr",
753
753
  "x-voltro-cache": "STALE",
754
- "x-voltro-cache-key": h,
754
+ "x-voltro-cache-key": g,
755
755
  "x-voltro-cache-age-ms": String(v - _.renderedAt)
756
756
  },
757
757
  body: _.html
758
758
  };
759
759
  try {
760
- let e = await Ee({
761
- provider: q,
762
- root: r,
760
+ let i = await De({
761
+ provider: K,
762
+ root: e,
763
763
  route: u.route,
764
764
  params: u.params,
765
- pathname: i,
766
- dirs: U,
767
- shellTemplate: N,
765
+ pathname: r,
766
+ dirs: H,
767
+ shellTemplate: P,
768
768
  requestHeaders: n,
769
769
  apiOrigin: fe,
770
770
  apiName: pe,
771
771
  requestUrl: t
772
772
  });
773
- if (!e) return {
773
+ if (!i) return {
774
774
  status: 200,
775
775
  headers: {
776
776
  "content-type": "text/html; charset=utf-8",
777
777
  "x-voltro-rendered-by": "spa-fallback"
778
778
  },
779
- body: N
779
+ body: P
780
780
  };
781
- if ("stream" in e) return {
781
+ if ("stream" in i) return {
782
782
  status: 200,
783
- headers: { "x-voltro-rendered-by": e.renderMode },
783
+ headers: { "x-voltro-rendered-by": i.renderMode },
784
784
  body: "",
785
- stream: e.stream
785
+ stream: i.stream
786
786
  };
787
- if ("control" in e) return e.control === "redirect" ? {
788
- status: e.status,
787
+ if ("control" in i) return i.control === "redirect" ? {
788
+ status: i.status,
789
789
  headers: {
790
- location: e.location,
790
+ location: i.location,
791
791
  "x-voltro-rendered-by": "loader-redirect"
792
792
  },
793
793
  body: ""
@@ -801,34 +801,34 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
801
801
  };
802
802
  let a = {
803
803
  "content-type": "text/html; charset=utf-8",
804
- "x-voltro-rendered-by": e.renderMode
804
+ "x-voltro-rendered-by": i.renderMode
805
805
  };
806
- if (e.renderMode === "isr" && e.revalidateMs !== null) {
807
- let t = Date.now(), n = Y.get(u.route.pattern)?.staleWhileRevalidateMs ?? 0;
808
- z.set(h, {
809
- html: e.html,
810
- renderedAt: t,
811
- expiresAt: t + e.revalidateMs,
812
- servableUntil: t + e.revalidateMs + n,
813
- revalidateMs: e.revalidateMs,
814
- staleWhileRevalidateMs: n
815
- }), a["x-voltro-cache"] = "MISS", a["x-voltro-cache-key"] = h, a["x-voltro-cache-revalidate-ms"] = String(e.revalidateMs), n > 0 && (a["x-voltro-cache-swr-ms"] = String(n)), g.emit("cache", {
806
+ if (i.renderMode === "isr" && i.revalidateMs !== null) {
807
+ let e = Date.now(), t = q.get(u.route.pattern)?.staleWhileRevalidateMs ?? 0;
808
+ z.set(g, {
809
+ html: i.html,
810
+ renderedAt: e,
811
+ expiresAt: e + i.revalidateMs,
812
+ servableUntil: e + i.revalidateMs + t,
813
+ revalidateMs: i.revalidateMs,
814
+ staleWhileRevalidateMs: t
815
+ }), 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)), f.emit("cache", {
816
816
  kind: "MISS",
817
- key: h,
818
- revalidateMs: e.revalidateMs,
819
- swrMs: n
817
+ key: g,
818
+ revalidateMs: i.revalidateMs,
819
+ swrMs: t
820
820
  });
821
- } else e.renderMode === "isr" && (a["x-voltro-cache"] = "BYPASS", g.emit("cache", {
821
+ } else i.renderMode === "isr" && (a["x-voltro-cache"] = "BYPASS", f.emit("cache", {
822
822
  kind: "BYPASS",
823
- key: h
823
+ key: g
824
824
  }));
825
825
  return {
826
826
  status: 200,
827
827
  headers: a,
828
- body: e.html
828
+ body: i.html
829
829
  };
830
830
  } catch (e) {
831
- return J.error("render error", { url: i }, e), f(e) ? {
831
+ return J.error("render error", { url: r }, e), M(e) ? {
832
832
  status: 500,
833
833
  headers: {
834
834
  "content-type": "text/plain; charset=utf-8",
@@ -842,17 +842,17 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
842
842
  };
843
843
  }
844
844
  }, Fe = !1, Ie = ge(async (e, t) => {
845
- let r = e.url ?? "/", i = Date.now(), a = {};
846
- for (let [t, n] of Object.entries(e.headers)) n !== void 0 && (a[t.toLowerCase()] = Array.isArray(n) ? n.join(", ") : n);
847
- let o = r.split("?")[0] ?? "/", s = (e.method ?? "GET").toUpperCase();
848
- if (o === "/internal/liveness") {
845
+ let n = e.url ?? "/", r = Date.now(), i = {};
846
+ for (let [t, n] of Object.entries(e.headers)) n !== void 0 && (i[t.toLowerCase()] = Array.isArray(n) ? n.join(", ") : n);
847
+ let c = n.split("?")[0] ?? "/", l = (e.method ?? "GET").toUpperCase();
848
+ if (c === "/internal/liveness") {
849
849
  t.writeHead(200, {
850
850
  "content-type": "text/plain",
851
851
  "cache-control": "no-store"
852
852
  }), t.end("ok");
853
853
  return;
854
854
  }
855
- if (o === "/internal/readiness") {
855
+ if (c === "/internal/readiness") {
856
856
  let e = Fe ? 200 : 503;
857
857
  t.writeHead(e, {
858
858
  "content-type": "text/plain",
@@ -860,71 +860,71 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
860
860
  }), t.end(Fe ? "ready" : "not-ready");
861
861
  return;
862
862
  }
863
- if (s === "OPTIONS" && o.startsWith("/_voltro/inspect")) {
864
- let e = P(a.origin);
863
+ if (l === "OPTIONS" && c.startsWith("/_voltro/inspect")) {
864
+ let e = I(i.origin);
865
865
  t.writeHead(204, e), t.end();
866
866
  return;
867
867
  }
868
- if (c.name === "voltroDashboard" && o === "/api/dashboard/proxy") {
869
- let n = new URL(r, "http://x").searchParams.get("target");
870
- if (!n) {
868
+ if (s.name === "voltroDashboard" && c === "/api/dashboard/proxy") {
869
+ let r = new URL(n, "http://x").searchParams.get("target");
870
+ if (!r) {
871
871
  t.writeHead(400, { "content-type": "text/plain" }), t.end("missing ?target=");
872
872
  return;
873
873
  }
874
- if (!F(n)) {
874
+ if (!ce(r)) {
875
875
  t.writeHead(400, { "content-type": "text/plain" }), t.end("target not allowed: must be loopback or an origin configured in VOLTRO_DASHBOARD_APPS");
876
876
  return;
877
877
  }
878
878
  try {
879
- let r = { accept: a.accept ?? "application/json" }, i = a.authorization;
880
- i ? r.authorization = Array.isArray(i) ? i[0] : i : ce(n) && process.env.VOLTRO_INSPECT_TOKEN && (r.authorization = `Bearer ${process.env.VOLTRO_INSPECT_TOKEN}`);
879
+ let n = { accept: i.accept ?? "application/json" }, a = i.authorization;
880
+ a ? n.authorization = Array.isArray(a) ? a[0] : a : se(r) && process.env.VOLTRO_INSPECT_TOKEN && (n.authorization = `Bearer ${process.env.VOLTRO_INSPECT_TOKEN}`);
881
881
  let o;
882
- if (s && s !== "GET" && s !== "HEAD") {
882
+ if (l && l !== "GET" && l !== "HEAD") {
883
883
  let t = [];
884
884
  for await (let n of e) t.push(n);
885
885
  o = Buffer.concat(t);
886
- let n = a["content-type"];
887
- n && (r["content-type"] = Array.isArray(n) ? n[0] : n);
886
+ let r = i["content-type"];
887
+ r && (n["content-type"] = Array.isArray(r) ? r[0] : r);
888
888
  }
889
- let c = await fetch(n, {
889
+ let s = await fetch(r, {
890
890
  redirect: "manual",
891
- method: s,
892
- headers: r,
891
+ method: l,
892
+ headers: n,
893
893
  ...o ? { body: new Uint8Array(o.buffer, o.byteOffset, o.byteLength) } : {}
894
- }), l = Buffer.from(await c.arrayBuffer());
895
- t.writeHead(c.status, {
896
- "content-type": c.headers.get("content-type") ?? "application/octet-stream",
897
- "content-length": String(l.length)
898
- }), t.end(l);
894
+ }), c = Buffer.from(await s.arrayBuffer());
895
+ t.writeHead(s.status, {
896
+ "content-type": s.headers.get("content-type") ?? "application/octet-stream",
897
+ "content-length": String(c.length)
898
+ }), t.end(c);
899
899
  } catch (e) {
900
900
  t.writeHead(502, { "content-type": "text/plain" }), t.end(`proxy error: ${e.message}`);
901
901
  }
902
902
  return;
903
903
  }
904
- if (c.name === "voltroDashboard" && o === "/api/dashboard/proxy/stream") {
905
- let n = new URL(r, "http://x").searchParams.get("target");
906
- if (!n) {
904
+ if (s.name === "voltroDashboard" && c === "/api/dashboard/proxy/stream") {
905
+ let r = new URL(n, "http://x").searchParams.get("target");
906
+ if (!r) {
907
907
  t.writeHead(400, { "content-type": "text/plain" }), t.end("missing ?target=");
908
908
  return;
909
909
  }
910
- if (!F(n)) {
910
+ if (!ce(r)) {
911
911
  t.writeHead(400, { "content-type": "text/plain" }), t.end("target not allowed: must be loopback or an origin configured in VOLTRO_DASHBOARD_APPS");
912
912
  return;
913
913
  }
914
- let i = new AbortController();
915
- e.on("close", () => i.abort()), t.on("close", () => i.abort());
914
+ let a = new AbortController();
915
+ e.on("close", () => a.abort()), t.on("close", () => a.abort());
916
916
  try {
917
- let e = a.authorization ?? (ce(n) && process.env.VOLTRO_INSPECT_TOKEN ? `Bearer ${process.env.VOLTRO_INSPECT_TOKEN}` : void 0), r = await fetch(n, {
917
+ let e = i.authorization ?? (se(r) && process.env.VOLTRO_INSPECT_TOKEN ? `Bearer ${process.env.VOLTRO_INSPECT_TOKEN}` : void 0), n = await fetch(r, {
918
918
  redirect: "manual",
919
919
  method: "GET",
920
920
  headers: {
921
921
  accept: "text/event-stream",
922
922
  ...e ? { authorization: Array.isArray(e) ? e[0] : e } : {}
923
923
  },
924
- signal: i.signal
924
+ signal: a.signal
925
925
  });
926
- if (!r.ok || !r.body) {
927
- t.writeHead(r.status, { "content-type": "text/plain" }), t.end(`upstream ${r.status}`);
926
+ if (!n.ok || !n.body) {
927
+ t.writeHead(n.status, { "content-type": "text/plain" }), t.end(`upstream ${n.status}`);
928
928
  return;
929
929
  }
930
930
  t.writeHead(200, {
@@ -933,7 +933,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
933
933
  connection: "keep-alive",
934
934
  "x-accel-buffering": "no"
935
935
  }), t.flushHeaders();
936
- let o = r.body.getReader();
936
+ let o = n.body.getReader();
937
937
  try {
938
938
  for (;;) {
939
939
  let { done: e, value: n } = await o.read();
@@ -948,23 +948,23 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
948
948
  }
949
949
  return;
950
950
  }
951
- if (o === "/_voltro/inspect/stream") {
952
- let r = P(a.origin);
953
- if (I()) {
951
+ if (c === "/_voltro/inspect/stream") {
952
+ let n = I(i.origin);
953
+ if (L()) {
954
954
  t.writeHead(503, {
955
955
  "content-type": "application/json",
956
- ...r
956
+ ...n
957
957
  }), t.end(JSON.stringify({ error: "inspect disabled (VOLTRO_INSPECT=off)" }));
958
958
  return;
959
959
  }
960
- let i = le(a, "GET");
961
- if (!i.ok) {
960
+ let r = le(i, "GET");
961
+ if (!r.ok) {
962
962
  t.writeHead(401, {
963
963
  "content-type": "application/json",
964
- ...r
964
+ ...n
965
965
  }), t.end(JSON.stringify({
966
966
  error: "unauthorized",
967
- reason: i.reason
967
+ reason: r.reason
968
968
  }));
969
969
  return;
970
970
  }
@@ -973,32 +973,32 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
973
973
  "cache-control": "no-cache, no-transform",
974
974
  connection: "keep-alive",
975
975
  "x-accel-buffering": "no",
976
- ...r
976
+ ...n
977
977
  }), t.flushHeaders(), t.write("retry: 5000\n\n");
978
- for (let e of g.buffered()) t.write(n(e));
979
- let o = g.subscribe((e) => {
980
- t.write(n(e));
981
- }), s = setInterval(() => {
982
- t.write(D());
983
- }, 15e3), c = () => {
984
- clearInterval(s), o();
978
+ for (let e of f.buffered()) t.write(o(e));
979
+ let s = f.subscribe((e) => {
980
+ t.write(o(e));
981
+ }), c = setInterval(() => {
982
+ t.write(a());
983
+ }, 15e3), l = () => {
984
+ clearInterval(c), s();
985
985
  };
986
- e.on("close", c), t.on("close", c);
986
+ e.on("close", l), t.on("close", l);
987
987
  return;
988
988
  }
989
989
  try {
990
- let e = await Pe(r, a);
991
- if (e.stream ? e.stream(t) : (t.writeHead(e.status, e.headers), t.end(e.body)), !o.startsWith("/_voltro/inspect")) {
992
- let t = Date.now() - i;
993
- g.emit("request", {
994
- url: o,
990
+ let e = await Pe(n, i);
991
+ if (e.stream ? e.stream(t) : (t.writeHead(e.status, e.headers), t.end(e.body)), !c.startsWith("/_voltro/inspect")) {
992
+ let t = Date.now() - r;
993
+ f.emit("request", {
994
+ url: c,
995
995
  status: e.status,
996
996
  durationMs: t,
997
997
  renderedBy: e.headers["x-voltro-rendered-by"],
998
998
  cache: e.headers["x-voltro-cache"]
999
999
  });
1000
- let n = Te(o, W)?.route.pattern ?? (e.status === 404 ? "<unmatched>" : "<asset>");
1001
- ke.record({
1000
+ let n = Ee(c, W)?.route.pattern ?? (e.status === 404 ? "<unmatched>" : "<asset>");
1001
+ $.record({
1002
1002
  kind: "request",
1003
1003
  tag: n,
1004
1004
  durationMs: t,
@@ -1009,56 +1009,56 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
1009
1009
  t.writeHead(500, { "content-type": "text/plain" }), t.end(`internal error: ${e.message}`);
1010
1010
  }
1011
1011
  });
1012
- await new Promise((e) => Ie.listen(y, "::", e)), Fe = !0, s.mark("ready"), J.info(`listening on http://localhost:${y}`, {
1013
- port: y,
1014
- distDir: S
1012
+ await new Promise((e) => Ie.listen(m, "::", e)), Fe = !0, t.mark("ready"), J.info(`listening on http://localhost:${m}`, {
1013
+ port: m,
1014
+ distDir: y
1015
1015
  }), J.debug("dynamic + ssr/isr routes resolve via SSR loader");
1016
1016
  try {
1017
- await p({
1017
+ await N({
1018
1018
  id: T,
1019
1019
  name: C,
1020
1020
  kind: "web",
1021
- url: `http://localhost:${y}`,
1021
+ url: `http://localhost:${m}`,
1022
1022
  pid: process.pid,
1023
1023
  status: "live",
1024
- logFile: M.path
1024
+ logFile: E.path
1025
1025
  });
1026
- let e = t(r);
1027
- if (e) {
1028
- let t = await l({ dashboardAppPath: e });
1029
- t.status === "launched" ? J.info(`dashboard launched at http://localhost:${t.port}`, { port: t.port }) : t.status === "already-running" && J.debug(`dashboard already running on :${t.port}`, { port: t.port });
1026
+ let t = n(e);
1027
+ if (t) {
1028
+ let e = await r({ dashboardAppPath: t });
1029
+ e.status === "launched" ? J.info(`dashboard launched at http://localhost:${e.port}`, { port: e.port }) : e.status === "already-running" && J.debug(`dashboard already running on :${e.port}`, { port: e.port });
1030
1030
  }
1031
1031
  setInterval(() => {
1032
- p({
1032
+ N({
1033
1033
  id: T,
1034
1034
  name: C,
1035
1035
  kind: "web",
1036
- url: `http://localhost:${y}`,
1036
+ url: `http://localhost:${m}`,
1037
1037
  pid: process.pid,
1038
1038
  status: "live",
1039
- logFile: M.path
1039
+ logFile: E.path
1040
1040
  }).catch(() => {});
1041
1041
  }, 1e4).unref();
1042
1042
  } catch (e) {
1043
1043
  J.warn("runtime-registry write failed", {}, e);
1044
1044
  }
1045
1045
  me({
1046
- app: c.name ?? "unnamed",
1046
+ app: s.name ?? "unnamed",
1047
1047
  kind: "web",
1048
- url: `http://localhost:${y}`,
1049
- bootMs: s.total()
1048
+ url: `http://localhost:${m}`,
1049
+ bootMs: t.total()
1050
1050
  });
1051
- let Le = s.phaseBreakdown();
1052
- J.info(`start: ready in ${s.total()}ms`, {
1053
- bootMs: s.total(),
1051
+ let Le = t.phaseBreakdown();
1052
+ J.info(`start: ready in ${t.total()}ms`, {
1053
+ bootMs: t.total(),
1054
1054
  ...Le ? { phases: Le } : {}
1055
1055
  });
1056
1056
  let Re = !1, ze = (e) => async () => {
1057
1057
  if (!Re) {
1058
- if (Re = !0, J.info(`received ${e}, shutting down`, { signal: e }), Ie.close(), await $.stop(), B) try {
1058
+ if (Re = !0, J.info(`received ${e}, shutting down`, { signal: e }), Ie.close(), await Q.stop(), B) try {
1059
1059
  await B.end();
1060
1060
  } catch {}
1061
- await q.close(), await x(T), await M.dispose(), process.exit(0);
1061
+ await K.close(), await p(T), await E.dispose(), process.exit(0);
1062
1062
  }
1063
1063
  };
1064
1064
  process.on("SIGINT", ze("SIGINT")), process.on("SIGTERM", ze("SIGTERM"));
@@ -1070,10 +1070,10 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
1070
1070
  e.unref();
1071
1071
  }
1072
1072
  return new Promise(() => {});
1073
- }, Ae = async (e) => {
1073
+ }, je = async (e) => {
1074
1074
  process.env.NODE_ENV || (process.env.NODE_ENV = "production");
1075
- let t = await ke(pe(e.find((e) => !e.startsWith("-")) ?? process.cwd()));
1075
+ let t = await Ae(z(e.find((e) => !e.startsWith("-")) ?? process.cwd()));
1076
1076
  return t.ran ? t.exitCode : (J.error("no web app found at this path"), 1);
1077
1077
  };
1078
1078
  //#endregion
1079
- export { Ae as t };
1079
+ export { je as t };