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