@voltro/cli 0.19.0 → 0.20.1

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