@voltro/cli 0.13.0 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (166) hide show
  1. package/CHANGELOG.md +412 -0
  2. package/dist/{apiBuild-B6_ehbem.js → apiBuild-CHItlwPO.js} +2 -2
  3. package/dist/apiBuild-D8juhYsS.js +2 -0
  4. package/dist/bin.js +3 -3
  5. package/dist/{commands-DYOuGlEC.js → commands-CPQuQRXh.js} +3967 -2831
  6. package/dist/{dbCommand-DIOJQwsq.js → dbCommand-B8F29zV0.js} +2 -1
  7. package/dist/dbCommand-Dt7BtdMd.js +2 -0
  8. package/dist/{dev-xdijqojc.js → dev-BHLM3RPX.js} +1 -1
  9. package/dist/{dev-Fb9BmavX.js → dev-C2lCUhYI.js} +1478 -1347
  10. package/dist/fileConventions-Cu0tM-Bl.js +29 -0
  11. package/dist/{frameworkTableAssembly-CYlrafoK.js → frameworkTableAssembly-BA2bAmYN.js} +164 -163
  12. package/dist/frameworkTableAssembly-D1zJSgOU.js +2 -0
  13. package/dist/index.js +1 -1
  14. package/dist/{inspectMetrics-DOiiII34.js → inspectMetrics-CYDSO3za.js} +955 -945
  15. package/dist/{serveCommand-CqYxzBZR.js → serveCommand-DBzQcCuv.js} +410 -396
  16. package/dist/serveEntry.js +2 -2
  17. package/dist/{start-CjG_0xhR.js → start-BtgatJN3.js} +246 -246
  18. package/dist/startEntry.js +2 -2
  19. package/package.json +17 -17
  20. package/templates/AGENTS.core.md +77 -3
  21. package/templates/AGENTS.md +78 -4
  22. package/templates/agent-docs/_index.md +1 -1
  23. package/templates/agent-docs/_manifest.json +2 -2
  24. package/templates/agent-docs/authentication.md +34 -2
  25. package/templates/agent-docs/cli.md +116 -2
  26. package/templates/agent-docs/data.md +195 -3
  27. package/templates/agent-docs/database/hosting.md +2 -2
  28. package/templates/agent-docs/database/migrations.md +77 -3
  29. package/templates/agent-docs/database/overview.md +11 -0
  30. package/templates/agent-docs/database/seedsdialects.md +53 -1
  31. package/templates/agent-docs/internationalization.md +3 -3
  32. package/templates/agent-docs/introduction.md +133 -2
  33. package/templates/agent-docs/plugins.md +2 -1
  34. package/templates/agent-docs/reference.md +4 -4
  35. package/templates/agent-docs/routing.md +48 -43
  36. package/templates/agent-docs/schema-driven-ui.md +14 -3
  37. package/templates/agent-docs/templates/apibackends.md +1 -8
  38. package/templates/agent-docs/templates/appshells.md +24 -24
  39. package/templates/agent-docs/testing.md +16 -1
  40. package/templates/agent-docs/whats-new.md +247 -39
  41. package/templates/apps/api-ai/database/schema.ts +0 -2
  42. package/templates/apps/api-ai/package.json +7 -7
  43. package/templates/apps/api-auth/package.json +8 -8
  44. package/templates/apps/api-backend/database/schema.ts +0 -3
  45. package/templates/apps/api-backend/package.json +7 -7
  46. package/templates/apps/api-backend-deactivation/database/schema.ts +0 -1
  47. package/templates/apps/api-backend-deactivation/package.json +7 -7
  48. package/templates/apps/api-backend-mail/database/schema.ts +0 -3
  49. package/templates/apps/api-backend-mail/package.json +8 -8
  50. package/templates/apps/api-backend-mariadb/database/schema.ts +0 -3
  51. package/templates/apps/api-backend-mariadb/package.json +9 -9
  52. package/templates/apps/api-backend-storage/database/schema.ts +0 -3
  53. package/templates/apps/api-backend-storage/package.json +8 -8
  54. package/templates/apps/api-data-advanced/database/authors.entity.ts +0 -2
  55. package/templates/apps/api-data-advanced/database/books.entity.ts +0 -1
  56. package/templates/apps/api-data-advanced/package.json +8 -8
  57. package/templates/apps/api-durable/database/schema.ts +0 -3
  58. package/templates/apps/api-durable/package.json +8 -8
  59. package/templates/apps/api-feature-flags/database/schema.ts +0 -1
  60. package/templates/apps/api-feature-flags/package.json +9 -9
  61. package/templates/apps/api-governance/database/schema.ts +0 -1
  62. package/templates/apps/api-governance/package.json +8 -8
  63. package/templates/apps/api-kv/database/schema.ts +0 -3
  64. package/templates/apps/api-kv/package.json +8 -8
  65. package/templates/apps/api-moderation/database/schema.ts +0 -2
  66. package/templates/apps/api-moderation/package.json +8 -8
  67. package/templates/apps/api-observability/database/schema.ts +0 -1
  68. package/templates/apps/api-observability/package.json +8 -8
  69. package/templates/apps/api-ratelimit/database/schema.ts +0 -1
  70. package/templates/apps/api-ratelimit/package.json +8 -8
  71. package/templates/apps/api-rbac/database/schema.ts +0 -2
  72. package/templates/apps/api-rbac/package.json +8 -8
  73. package/templates/apps/api-rest/database/schema.ts +0 -3
  74. package/templates/apps/api-rest/package.json +7 -7
  75. package/templates/apps/api-saas/database/schema.ts +0 -1
  76. package/templates/apps/api-saas/package.json +11 -11
  77. package/templates/apps/api-search/database/schema.ts +0 -1
  78. package/templates/apps/api-search/package.json +8 -8
  79. package/templates/apps/api-versioning/database/schema.ts +0 -1
  80. package/templates/apps/api-versioning/package.json +8 -8
  81. package/templates/apps/api-webhooks/database/schema.ts +0 -1
  82. package/templates/apps/api-webhooks/package.json +9 -9
  83. package/templates/apps/changelog/package.json +6 -6
  84. package/templates/apps/changelog/src/pages/[locale]/{[slug].tsx → [slug].page.tsx} +2 -2
  85. package/templates/apps/changelog/src/pages/[locale]/{index.tsx → index.page.tsx} +2 -2
  86. package/templates/apps/changelog/src/pages/[locale]/mirrors.test.tsx +2 -2
  87. package/templates/apps/changelog/src/pages/{[slug].test.tsx → [slug].page.test.tsx} +1 -1
  88. package/templates/apps/changelog/src/pages/{index.test.tsx → index.page.test.tsx} +1 -1
  89. package/templates/apps/edge-functions/package.json +2 -2
  90. package/templates/apps/frontend-admin/package.json +8 -8
  91. package/templates/apps/frontend-admin/src/pages/(marketing)/{index.test.tsx → index.page.test.tsx} +1 -1
  92. package/templates/apps/frontend-admin/src/pages/(marketing)/{login.test.tsx → login.page.test.tsx} +1 -1
  93. package/templates/apps/frontend-admin/src/pages/admin/entity.test.tsx +1 -1
  94. package/templates/apps/frontend-admin/src/pages/admin/{index.test.tsx → index.page.test.tsx} +1 -1
  95. package/templates/apps/frontend-app/package.json +8 -8
  96. package/templates/apps/frontend-app/src/pages/{index.test.tsx → index.page.test.tsx} +1 -1
  97. package/templates/apps/frontend-app/src/pages/{schema-ui.test.tsx → schema-ui.page.test.tsx} +1 -1
  98. package/templates/apps/frontend-blank/package.json +7 -7
  99. package/templates/apps/frontend-blank/src/pages/{index.test.tsx → index.page.test.tsx} +1 -1
  100. package/templates/apps/frontend-contact/package.json +7 -7
  101. package/templates/apps/frontend-contact/src/pages/[locale]/{index.tsx → index.page.tsx} +2 -2
  102. package/templates/apps/frontend-contact/src/pages/{index.test.tsx → index.page.test.tsx} +1 -1
  103. package/templates/apps/frontend-dashboard/package.json +7 -7
  104. package/templates/apps/frontend-dashboard/src/pages/(marketing)/{index.test.tsx → index.page.test.tsx} +1 -1
  105. package/templates/apps/frontend-dashboard/src/pages/(marketing)/{login.test.tsx → login.page.test.tsx} +1 -1
  106. package/templates/apps/frontend-dashboard/src/pages/dashboard/{index.test.tsx → index.page.test.tsx} +1 -1
  107. package/templates/apps/frontend-dashboard/src/pages/dashboard/{settings.test.tsx → settings.page.test.tsx} +1 -1
  108. package/templates/apps/frontend-docs/package.json +7 -7
  109. package/templates/apps/frontend-docs/src/pages/[locale]/docs/{[...slug].tsx → [...slug].page.tsx} +3 -3
  110. package/templates/apps/frontend-docs/src/pages/[locale]/{index.tsx → index.page.tsx} +2 -2
  111. package/templates/apps/frontend-docs/src/pages/[locale]/mirrors.test.tsx +2 -2
  112. package/templates/apps/frontend-docs/src/pages/docs/{[...slug].test.tsx → [...slug].page.test.tsx} +1 -1
  113. package/templates/apps/frontend-docs/src/pages/{index.test.tsx → index.page.test.tsx} +1 -1
  114. package/templates/apps/frontend-i18n/package.json +6 -6
  115. package/templates/apps/frontend-i18n/src/pages/[locale]/{about.tsx → about.page.tsx} +2 -2
  116. package/templates/apps/frontend-i18n/src/pages/[locale]/{index.tsx → index.page.tsx} +2 -2
  117. package/templates/apps/frontend-i18n/src/pages/[locale]/mirrors.test.tsx +2 -2
  118. package/templates/apps/frontend-i18n/src/pages/{about.test.tsx → about.page.test.tsx} +1 -1
  119. package/templates/apps/frontend-i18n/src/pages/{index.test.tsx → index.page.test.tsx} +1 -1
  120. package/templates/apps/frontend-landing/package.json +7 -7
  121. package/templates/apps/frontend-landing/src/pages/[locale]/{index.tsx → index.page.tsx} +2 -2
  122. package/templates/apps/frontend-landing/src/pages/[locale]/mirrors.test.tsx +1 -1
  123. package/templates/apps/frontend-landing/src/pages/{index.test.tsx → index.page.test.tsx} +1 -1
  124. package/templates/apps/frontend-spa/package.json +7 -7
  125. package/templates/apps/frontend-spa/src/pages/{index.test.tsx → index.page.test.tsx} +1 -1
  126. package/templates/apps/frontend-ssr/package.json +7 -7
  127. package/templates/apps/frontend-ssr/src/pages/{feed-swr.test.tsx → feed-swr.page.test.tsx} +1 -1
  128. package/templates/apps/frontend-ssr/src/pages/{feed.test.tsx → feed.page.test.tsx} +1 -1
  129. package/templates/apps/frontend-ssr/src/pages/{index.test.tsx → index.page.test.tsx} +1 -1
  130. package/templates/apps/frontend-ssr-api/package.json +8 -8
  131. package/templates/apps/frontend-ssr-api/src/pages/{index.test.tsx → index.page.test.tsx} +1 -1
  132. package/templates/apps/frontend-static-blog/package.json +6 -6
  133. package/templates/apps/frontend-static-blog/src/pages/[locale]/blog/{[slug].tsx → [slug].page.tsx} +2 -2
  134. package/templates/apps/frontend-static-blog/src/pages/[locale]/{index.tsx → index.page.tsx} +2 -2
  135. package/templates/apps/frontend-static-blog/src/pages/[locale]/mirrors.test.tsx +2 -2
  136. package/templates/apps/frontend-static-blog/src/pages/blog/{[slug].test.tsx → [slug].page.test.tsx} +1 -1
  137. package/templates/apps/frontend-static-blog/src/pages/{index.test.tsx → index.page.test.tsx} +1 -1
  138. package/dist/apiBuild-Bzpb383i.js +0 -2
  139. package/dist/dbCommand-ADD4mrTI.js +0 -2
  140. package/dist/frameworkTableAssembly-XvKO7wQt.js +0 -2
  141. /package/templates/apps/changelog/src/pages/{[slug].tsx → [slug].page.tsx} +0 -0
  142. /package/templates/apps/changelog/src/pages/{index.tsx → index.page.tsx} +0 -0
  143. /package/templates/apps/frontend-admin/src/pages/(marketing)/{index.tsx → index.page.tsx} +0 -0
  144. /package/templates/apps/frontend-admin/src/pages/(marketing)/{login.tsx → login.page.tsx} +0 -0
  145. /package/templates/apps/frontend-admin/src/pages/admin/{[entity].tsx → [entity].page.tsx} +0 -0
  146. /package/templates/apps/frontend-admin/src/pages/admin/{index.tsx → index.page.tsx} +0 -0
  147. /package/templates/apps/frontend-app/src/pages/{index.tsx → index.page.tsx} +0 -0
  148. /package/templates/apps/frontend-app/src/pages/{schema-ui.tsx → schema-ui.page.tsx} +0 -0
  149. /package/templates/apps/frontend-blank/src/pages/{index.tsx → index.page.tsx} +0 -0
  150. /package/templates/apps/frontend-contact/src/pages/{index.tsx → index.page.tsx} +0 -0
  151. /package/templates/apps/frontend-dashboard/src/pages/(marketing)/{index.tsx → index.page.tsx} +0 -0
  152. /package/templates/apps/frontend-dashboard/src/pages/(marketing)/{login.tsx → login.page.tsx} +0 -0
  153. /package/templates/apps/frontend-dashboard/src/pages/dashboard/{index.tsx → index.page.tsx} +0 -0
  154. /package/templates/apps/frontend-dashboard/src/pages/dashboard/{settings.tsx → settings.page.tsx} +0 -0
  155. /package/templates/apps/frontend-docs/src/pages/docs/{[...slug].tsx → [...slug].page.tsx} +0 -0
  156. /package/templates/apps/frontend-docs/src/pages/{index.tsx → index.page.tsx} +0 -0
  157. /package/templates/apps/frontend-i18n/src/pages/{about.tsx → about.page.tsx} +0 -0
  158. /package/templates/apps/frontend-i18n/src/pages/{index.tsx → index.page.tsx} +0 -0
  159. /package/templates/apps/frontend-landing/src/pages/{index.tsx → index.page.tsx} +0 -0
  160. /package/templates/apps/frontend-spa/src/pages/{index.tsx → index.page.tsx} +0 -0
  161. /package/templates/apps/frontend-ssr/src/pages/{feed-swr.tsx → feed-swr.page.tsx} +0 -0
  162. /package/templates/apps/frontend-ssr/src/pages/{feed.tsx → feed.page.tsx} +0 -0
  163. /package/templates/apps/frontend-ssr/src/pages/{index.tsx → index.page.tsx} +0 -0
  164. /package/templates/apps/frontend-ssr-api/src/pages/{index.tsx → index.page.tsx} +0 -0
  165. /package/templates/apps/frontend-static-blog/src/pages/blog/{[slug].tsx → [slug].page.tsx} +0 -0
  166. /package/templates/apps/frontend-static-blog/src/pages/{index.tsx → index.page.tsx} +0 -0
@@ -1,4 +1,4 @@
1
- import { $ as e, A as t, C as n, E as r, G as i, H as a, I as o, J as s, N as c, O as l, Q as u, R as ee, U as d, V as f, W as p, _ as m, a as h, at as g, b as _, c as v, ct as y, et as b, f as te, g as x, h as S, i as C, j as w, k as ne, m as T, nt as re, o as ie, p as E, q as D, r as O, s as k, t as A, tt as j, v as M, w as ae, y as N } from "./inspectMetrics-DOiiII34.js";
1
+ import { A as e, C as t, E as n, G as r, I as i, J as a, K as o, N as s, O as c, V as l, W as u, X as d, Z as f, _ as ee, a as p, at as m, b as h, c as g, ct as _, dt as v, f as te, g as y, h as b, i as x, it as ne, j as S, k as C, m as w, nt as T, o as re, p as ie, q as E, r as D, rt as O, s as k, t as A, tt as j, v as M, w as ae, y as N } from "./inspectMetrics-CYDSO3za.js";
2
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
3
  import { t as de } from "./bootTiming-BdyP9nYw.js";
4
4
  import { dirname as fe, extname as F, join as I, resolve as L } from "node:path";
@@ -205,28 +205,28 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
205
205
  }
206
206
  return null;
207
207
  }, we = async (e) => {
208
- let { provider: t, route: n, params: r, pathname: i, dirs: a, shellTemplate: s, requestHeaders: c, requestUrl: l = "", apiOrigin: u, apiName: ee } = e, d = C(u, c.cookie, { apiName: ee }), f = await t.getPage(n.pattern, n.file), p = o(f, n.file), g = p === "spa" && ie(a, n.dirChain).some((e) => e.hasLayout);
209
- if (p !== "ssr" && p !== "isr" && !g) return null;
210
- let v = ie(a, n.dirChain), y = {}, b = null, te, x = new AbortController();
208
+ let { provider: t, route: n, params: r, pathname: a, dirs: o, shellTemplate: s, requestHeaders: c, requestUrl: l = "", apiOrigin: u, apiName: d } = e, f = x(u, c.cookie, { apiName: d }), g = await t.getPage(n.pattern, n.file), _ = i(g, n.file), v = _ === "spa" && re(o, n.dirChain).some((e) => e.hasLayout);
209
+ if (_ !== "ssr" && _ !== "isr" && !v) return null;
210
+ let te = re(o, n.dirChain), y = {}, ne = null, S, C = new AbortController();
211
211
  try {
212
- ({chain: te, segmentLoaderData: y} = await h({
213
- entries: v,
212
+ (await t.getHelpers()).beginStoreSeeds(), {chain: S, segmentLoaderData: y} = await p({
213
+ entries: te,
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
- pathname: i,
220
- signal: x.signal,
219
+ pathname: a,
220
+ signal: C.signal,
221
221
  headers: c,
222
- query: d
222
+ query: f
223
223
  }
224
- })), typeof f.loader == "function" && !g && (b = await f.loader({
224
+ }), typeof g.loader == "function" && !v && (ne = await g.loader({
225
225
  params: r,
226
- pathname: i,
227
- signal: x.signal,
226
+ pathname: a,
227
+ signal: C.signal,
228
228
  headers: c,
229
- query: d
229
+ query: f
230
230
  }));
231
231
  } catch (e) {
232
232
  if (J(e)) return {
@@ -237,30 +237,30 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
237
237
  if (be(e)) return { control: "not-found" };
238
238
  throw e;
239
239
  }
240
- let w = await t.getHelpers(), ne = {
240
+ let T = await t.getHelpers(), ie = {
241
241
  pattern: n.pattern,
242
- Component: f.default,
243
- meta: f.meta,
244
- loader: f.loader,
245
- ErrorBoundary: f.ErrorBoundary,
246
- Pending: f.Pending,
247
- renderMode: p,
248
- chain: te
242
+ Component: g.default,
243
+ meta: g.meta,
244
+ loader: g.loader,
245
+ ErrorBoundary: g.ErrorBoundary,
246
+ Pending: g.Pending,
247
+ renderMode: _,
248
+ chain: S
249
249
  }, E = {
250
- cookies: w.parseCookieHeader(c.cookie),
250
+ cookies: T.parseCookieHeader(c.cookie),
251
251
  headers: c,
252
252
  url: l
253
- }, D = w.i18n?.resolve(c.cookie, c["accept-language"]), O = f.interactive ?? "full";
254
- if (g) {
253
+ }, D = T.i18n?.resolve(c.cookie, c["accept-language"]), O = g.interactive ?? "full";
254
+ if (v) {
255
255
  let e = M({
256
- helpers: w,
256
+ helpers: T,
257
257
  page: n.pattern,
258
258
  interactive: O,
259
259
  delivery: "stream",
260
260
  renderInput: {
261
- descriptor: ne,
261
+ descriptor: ie,
262
262
  params: r,
263
- pathname: i,
263
+ pathname: a,
264
264
  segmentLoaderData: y,
265
265
  requestContext: E,
266
266
  ...D ? {
@@ -268,17 +268,17 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
268
268
  locale: D.locale
269
269
  } : {}
270
270
  }
271
- }), t = D?.locale ?? E.cookies["voltro:lang"] ?? "en", a = (t) => _({
272
- helpers: w,
271
+ }), t = D?.locale ?? E.cookies["voltro:lang"] ?? "en", i = (t) => h({
272
+ helpers: T,
273
273
  prepared: e,
274
274
  meta: t,
275
275
  interactive: O
276
276
  });
277
277
  if (e.hasDeferred) {
278
- let n = T({ shell: s });
278
+ let n = w({ shell: s });
279
279
  return {
280
280
  renderMode: "spa",
281
- stream: (r) => S({
281
+ stream: (r) => b({
282
282
  res: r,
283
283
  shell: n,
284
284
  htmlLang: t,
@@ -286,40 +286,40 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
286
286
  "content-type": "text/html; charset=utf-8",
287
287
  "x-voltro-rendered-by": "spa"
288
288
  },
289
- headInjection: a,
290
- render: (t) => w.renderPageToStream({
289
+ headInjection: i,
290
+ render: (t) => T.renderPageToStream({
291
291
  ...e.renderInput,
292
292
  ...t
293
293
  }),
294
294
  onShellError: (e) => {
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");
295
+ q.error("spa layout shell render failed", { pathname: a }, e), r.writeHead(500, { "content-type": "text/plain; charset=utf-8" }), r.end("server error");
296
296
  }
297
297
  })
298
298
  };
299
299
  }
300
300
  let o = N({
301
- helpers: w,
301
+ helpers: T,
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: s.replace("<div id=\"root\"></div>", `<div id="root">${o.body}</div>`).replace("</head>", ` ${i(o.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 k = m({
311
- helpers: w,
310
+ let k = ee({
311
+ helpers: T,
312
312
  page: n.pattern,
313
- pathname: i,
314
- renderMode: p,
313
+ pathname: a,
314
+ renderMode: _,
315
315
  interactive: O,
316
- loaderData: b,
316
+ loaderData: ne,
317
317
  segmentLoaderData: y,
318
- pageLoaderRan: typeof f.loader == "function"
318
+ pageLoaderRan: typeof g.loader == "function"
319
319
  }), A = {
320
- descriptor: ne,
320
+ descriptor: ie,
321
321
  params: r,
322
- pathname: i,
322
+ pathname: a,
323
323
  loaderData: k.loaderData,
324
324
  segmentLoaderData: k.segmentLoaderData,
325
325
  requestContext: E,
@@ -328,16 +328,16 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
328
328
  locale: D.locale
329
329
  } : {}
330
330
  }, j = (e) => [
331
- w.renderMetaToHtml(e),
331
+ T.renderMetaToHtml(e),
332
332
  `<meta name="voltro-interactive" content="${O}" />`,
333
- ...k.hasDeferred ? [w.renderDeferredRegistryScript()] : [],
334
- w.renderRouterStateScript(k.stateInput)
333
+ ...k.hasDeferred ? [T.renderDeferredRegistryScript()] : [],
334
+ T.renderRouterStateScript(k.stateInput)
335
335
  ].filter((e) => e.length > 0).join("\n ");
336
- if (p === "ssr" && O === "full" && e.buffered !== !0) {
337
- let e = D?.locale ?? E.cookies["voltro:lang"] ?? "en", t = T({ shell: s });
336
+ if (_ === "ssr" && O === "full" && e.buffered !== !0) {
337
+ let e = D?.locale ?? E.cookies["voltro:lang"] ?? "en", t = w({ shell: s });
338
338
  return {
339
339
  renderMode: "ssr",
340
- stream: (n) => S({
340
+ stream: (n) => b({
341
341
  res: n,
342
342
  shell: t,
343
343
  htmlLang: e,
@@ -346,22 +346,22 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
346
346
  "x-voltro-rendered-by": "ssr"
347
347
  },
348
348
  headInjection: j,
349
- render: (e) => w.renderPageToStream({
349
+ render: (e) => T.renderPageToStream({
350
350
  ...A,
351
351
  ...e
352
352
  }),
353
353
  onShellError: (e) => {
354
- q.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: a }, 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: ae, meta: oe } = w.renderPageToHtml(A), se = j(oe), ce = D?.locale ?? E.cookies["voltro:lang"] ?? "en", P = s.replace("<div id=\"root\"></div>", `<div id="root">${ae}</div>`).replace("</head>", ` ${se}\n </head>`).replace(/<html(\s+lang="[^"]*")?/i, `<html lang="${ce}"`);
359
+ let { html: ae, meta: oe } = T.renderPageToHtml(A), se = j(oe), ce = D?.locale ?? E.cookies["voltro:lang"] ?? "en", P = s.replace("<div id=\"root\"></div>", `<div id="root">${ae}</div>`).replace("</head>", ` ${se}\n </head>`).replace(/<html(\s+lang="[^"]*")?/i, `<html lang="${ce}"`);
360
360
  O === "none" && (P = X(P));
361
- let le = p === "isr" ? re(f.revalidate) : null;
361
+ let le = _ === "isr" ? m(g.revalidate) : null;
362
362
  return {
363
363
  html: P,
364
- renderMode: p,
364
+ renderMode: _,
365
365
  revalidateMs: le
366
366
  };
367
367
  }, $ = (e) => e === "" ? "/" : e, Te = async (e) => {
@@ -395,7 +395,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
395
395
  async close() {}
396
396
  };
397
397
  }, Ee = async (e, t) => {
398
- let n = await y("vite", () => import("vite")), r = (await import("@vitejs/plugin-react")).default, i = (await import("@tailwindcss/vite")).default, a = await n.createServer({
398
+ let n = await v("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,87 +407,87 @@ 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 = I(e, "src", "pages"), c = (e) => e === "" ? o : I(o, e), l = D({ limit: s() }), u = (e) => l.load(e, async () => await a.ssrLoadModule(e));
410
+ }), o = I(e, "src", "pages"), s = (e) => e === "" ? o : I(o, e), c = d({ limit: f() }), l = (e) => c.load(e, async () => await a.ssrLoadModule(e));
411
411
  return {
412
412
  kind: "middleware",
413
413
  async getPage(e, t) {
414
- return u(I(o, t));
414
+ return l(I(o, t));
415
415
  },
416
416
  async getLayout(e) {
417
- return u(I(c(e), "layout.tsx"));
417
+ return l(I(s(e), "layout.tsx"));
418
418
  },
419
419
  async getError(e) {
420
- return u(I(c(e), "error.tsx"));
420
+ return l(I(s(e), "error.tsx"));
421
421
  },
422
422
  async getPending(e) {
423
- return u(I(c(e), "loading.tsx"));
423
+ return l(I(s(e), "loading.tsx"));
424
424
  },
425
425
  async getHelpers() {
426
- return await u("@voltro/web/ssr");
426
+ return await l("@voltro/web/ssr");
427
427
  },
428
428
  async close() {
429
429
  await a.close();
430
430
  }
431
431
  };
432
- }, De = async (o) => {
433
- let s = de(), m = await k(o);
434
- if (!m) return {
432
+ }, De = async (i) => {
433
+ let d = de(), f = await k(i);
434
+ if (!f) return {
435
435
  ran: !1,
436
436
  exitCode: 0
437
437
  };
438
- if (m.type !== "web") return q.error("only web apps are supported by `voltro start`"), {
438
+ if (f.type !== "web") return q.error("only web apps are supported by `voltro start`"), {
439
439
  ran: !0,
440
440
  exitCode: 1
441
441
  };
442
- let { resolved: h } = await g({
443
- rawEnv: m.env,
442
+ let { resolved: ee } = await _({
443
+ rawEnv: f.env,
444
444
  appType: "web",
445
- root: o,
445
+ root: i,
446
446
  log: q,
447
447
  generateTypes: !1
448
- }), _ = h.publicValues;
449
- s.mark("config");
450
- let y = p();
451
- f(y), q.info("booting voltro start", { app: m.name ?? "(unnamed)" });
452
- let S = (() => {
448
+ }), p = ee.publicValues;
449
+ d.mark("config");
450
+ let m = E();
451
+ u(m), q.info("booting voltro start", { app: f.name ?? "(unnamed)" });
452
+ let h = (() => {
453
453
  if (process.env.VOLTRO_IS_DASHBOARD === "1" && process.env.VOLTRO_DASHBOARD_PORT) return Number(process.env.VOLTRO_DASHBOARD_PORT);
454
454
  if (process.env.PORT) {
455
455
  let e = Number(process.env.PORT);
456
456
  if (Number.isFinite(e) && e > 0) return e;
457
457
  }
458
- return m.port ?? 5173;
459
- })(), C = I(o, ".framework"), T = I(C, "dist"), re = I(T, "index.html");
460
- if (!await Z(re)) return q.error("no built dist found — run `voltro build` first", { distDir: T }), {
458
+ return f.port ?? 5173;
459
+ })(), v = I(i, ".framework"), b = I(v, "dist"), x = I(b, "index.html");
460
+ if (!await Z(x)) return q.error("no built dist found — run `voltro build` first", { distDir: b }), {
461
461
  ran: !0,
462
462
  exitCode: 1
463
463
  };
464
- let D = m.name ?? "unnamed", M = l("web", D, S), N = r(D);
465
- await w({
464
+ let w = f.name ?? "unnamed", M = c("web", w, h), N = n(w);
465
+ await S({
466
466
  id: M,
467
- name: D,
467
+ name: w,
468
468
  kind: "web",
469
- url: `http://localhost:${S}`,
469
+ url: `http://localhost:${h}`,
470
470
  pid: process.pid,
471
471
  status: "booting",
472
472
  logFile: N.path
473
473
  }).catch(() => {});
474
- let fe = I(T, "_voltro", "shell.html"), F = await Z(fe) ? await V.readFile(fe, "utf8") : await V.readFile(re, "utf8"), L = await v(o, m), R = O(L[0]), z = L[0]?.name, B, H = null;
474
+ let fe = I(b, "_voltro", "shell.html"), F = await Z(fe) ? await V.readFile(fe, "utf8") : await V.readFile(x, "utf8"), L = await g(i, f), R = D(L[0]), z = L[0]?.name, B, H = null;
475
475
  process.env.SSR_CACHE === "postgres" && process.env.PG_HOST ? (H = new (await (import("pg"))).default.Client({
476
476
  host: process.env.PG_HOST,
477
477
  port: Number(process.env.PG_PORT ?? 5432),
478
478
  user: process.env.PG_USER ?? "app",
479
479
  password: process.env.PG_PASSWORD ?? "app",
480
480
  database: process.env.PG_DATABASE ?? "app"
481
- }), await H.connect(), B = ve({ client: H }), q.info("isr cache backend: postgres", { table: "voltro_isr_cache" })) : (B = j(), q.info("isr cache backend: memory (per-process)", { hint: "set SSR_CACHE=postgres for persistent storage" })), await E(o, m, L, _);
482
- let { pages: U, dirs: W } = await te(I(o, "src", "pages")), G = Se(U);
483
- s.mark("scan");
484
- let K = I(T, "server", "ssrEntry.js"), _e = await Z(K);
481
+ }), await H.connect(), B = ve({ client: H }), q.info("isr cache backend: postgres", { table: "voltro_isr_cache" })) : (B = ne(), q.info("isr cache backend: memory (per-process)", { hint: "set SSR_CACHE=postgres for persistent storage" })), await ie(i, f, L, p);
482
+ let { pages: U, dirs: W } = await te(I(i, "src", "pages")), G = Se(U);
483
+ d.mark("scan");
484
+ let K = I(b, "server", "ssrEntry.js"), _e = await Z(K);
485
485
  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}`);
486
- let J = _e ? await Te(K) : await Ee(o, C);
486
+ let J = _e ? await Te(K) : await Ee(i, v);
487
487
  q.info(`ssr loader: ${J.kind}`, {
488
488
  kind: J.kind,
489
489
  ...J.kind === "middleware" ? { hint: "no pre-built SSR bundle found; run `voltro build` to enable bundle mode" } : {}
490
- }), s.mark("provider");
490
+ }), d.mark("provider");
491
491
  let be = J.getPageMeta?.(), Y = /* @__PURE__ */ new Map(), X = 0;
492
492
  for (let e of U) {
493
493
  let t = be?.[e.pattern];
@@ -497,7 +497,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
497
497
  }
498
498
  try {
499
499
  let t = await J.getPage(e.pattern, e.file);
500
- Y.set(e.pattern, c(t, e.file)), X++;
500
+ Y.set(e.pattern, s(t, e.file)), X++;
501
501
  } catch (t) {
502
502
  q.warn("failed to load page metadata", { pattern: e.pattern }, t);
503
503
  }
@@ -506,9 +506,9 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
506
506
  count: Y.size,
507
507
  fromManifest: Y.size - X,
508
508
  fromModules: X
509
- }), s.mark("routes");
509
+ }), d.mark("routes");
510
510
  let Q = /* @__PURE__ */ new Set();
511
- for (let e of G) Y.get(e.pattern)?.renderMode === "spa" && ie(W, e.dirChain).some((e) => e.hasLayout) && Q.add(e.pattern);
511
+ for (let e of G) Y.get(e.pattern)?.renderMode === "spa" && re(W, e.dirChain).some((e) => e.hasLayout) && Q.add(e.pattern);
512
512
  Q.size > 0 && q.info(`${Q.size} spa route(s) render an SSR layout shell`, { patterns: [...Q] });
513
513
  let $ = /* @__PURE__ */ new Map();
514
514
  for (let [e, t] of Y) t.cacheInvalidatesOn.length > 0 && $.set(e, t.cacheInvalidatesOn);
@@ -519,7 +519,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
519
519
  tableSubscriptionsByPattern: $,
520
520
  regexByPattern: De
521
521
  });
522
- await Oe.start(), s.mark("cdc");
522
+ await Oe.start(), d.mark("cdc");
523
523
  let ke = A(), Ae = U.map((e) => {
524
524
  let t = Y.get(e.pattern);
525
525
  return {
@@ -545,11 +545,11 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
545
545
  })), Me = H ? "postgres" : "memory", Ne = {
546
546
  kind: "web",
547
547
  meta: {
548
- name: m.name ?? "(unnamed)",
548
+ name: f.name ?? "(unnamed)",
549
549
  voltroVersion: ye,
550
- port: S,
550
+ port: h,
551
551
  mode: "start",
552
- apis: Object.entries(m.apis ?? {}).map(([e, t]) => {
552
+ apis: Object.entries(f.apis ?? {}).map(([e, t]) => {
553
553
  let n = {
554
554
  name: e,
555
555
  package: t.package
@@ -577,10 +577,10 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
577
577
  };
578
578
  },
579
579
  metrics: () => me()
580
- }, Pe = async (t, n) => {
581
- let r = t.split("?")[0] ?? "/";
582
- if (m.name === "voltroDashboard" && r === "/api/dashboard/registry") try {
583
- let e = await ne();
580
+ }, Pe = async (e, t) => {
581
+ let n = e.split("?")[0] ?? "/";
582
+ if (f.name === "voltroDashboard" && n === "/api/dashboard/registry") try {
583
+ let e = await C();
584
584
  return {
585
585
  status: 200,
586
586
  headers: { "content-type": "application/json; charset=utf-8" },
@@ -593,7 +593,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
593
593
  body: `registry read error: ${e.message}`
594
594
  };
595
595
  }
596
- if (m.name === "voltroDashboard" && r === "/api/dashboard/config") {
596
+ if (f.name === "voltroDashboard" && n === "/api/dashboard/config") {
597
597
  let e = process.env.VOLTRO_DASHBOARD_APPS, t = [];
598
598
  if (e && e.trim().length > 0) {
599
599
  let n;
@@ -622,36 +622,36 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
622
622
  body: JSON.stringify({ apps: t })
623
623
  };
624
624
  }
625
- if (r === "/_voltro/inspect/logs") {
626
- let e = ee(t, a(), n);
625
+ if (n === "/_voltro/inspect/logs") {
626
+ let n = l(e, r(), t);
627
627
  return {
628
- status: e.status,
628
+ status: n.status,
629
629
  headers: {
630
- "content-type": e.contentType,
631
- ...ue(n.origin)
630
+ "content-type": n.contentType,
631
+ ...ue(t.origin)
632
632
  },
633
- body: e.body
633
+ body: n.body
634
634
  };
635
635
  }
636
- if (r !== "/_voltro/inspect/stream") {
637
- let e = le(t, Ne, n);
638
- if (e !== null) return {
639
- status: e.status,
636
+ if (n !== "/_voltro/inspect/stream") {
637
+ let n = le(e, Ne, t);
638
+ if (n !== null) return {
639
+ status: n.status,
640
640
  headers: {
641
- "content-type": e.contentType,
642
- ...e.headers ?? {}
641
+ "content-type": n.contentType,
642
+ ...n.headers ?? {}
643
643
  },
644
- body: e.body
644
+ body: n.body
645
645
  };
646
646
  }
647
- let i = Ce(r, G), s = i ? Y.get(i.route.pattern)?.renderMode : void 0, c = s === "ssr" || s === "isr" || (i ? Q.has(i.route.pattern) : !1), l = r === "/" ? I(T, "index.html") : I(T, r.replace(/^\//, ""), "index.html");
648
- if (!c && await Z(l)) return {
647
+ let a = Ce(n, G), o = a ? Y.get(a.route.pattern)?.renderMode : void 0, s = o === "ssr" || o === "isr" || (a ? Q.has(a.route.pattern) : !1), c = n === "/" ? I(b, "index.html") : I(b, n.replace(/^\//, ""), "index.html");
648
+ if (!s && await Z(c)) return {
649
649
  status: 200,
650
650
  headers: { "content-type": "text/html; charset=utf-8" },
651
- body: await V.readFile(l)
651
+ body: await V.readFile(c)
652
652
  };
653
- if (/\.[a-z0-9]+$/i.test(r)) {
654
- let e = I(T, r.replace(/^\//, ""));
653
+ if (/\.[a-z0-9]+$/i.test(n)) {
654
+ let e = I(b, n.replace(/^\//, ""));
655
655
  if (await Z(e)) {
656
656
  let t = await V.readFile(e);
657
657
  return {
@@ -661,64 +661,64 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
661
661
  };
662
662
  }
663
663
  }
664
- let d = Ce(r, G);
665
- if (!d) return {
664
+ let u = Ce(n, G);
665
+ if (!u) return {
666
666
  status: 404,
667
667
  headers: { "content-type": "text/plain" },
668
668
  body: "not found"
669
669
  };
670
- let f = Y.get(d.route.pattern), p = n["x-tenant"] ?? "anonymous", h = (await J.getHelpers()).i18n?.resolve(n.cookie, n["accept-language"])?.locale, g = u(r, {
671
- ...f?.tenantAware ? { tenant: p } : {},
672
- ...h ? { locale: h } : {}
673
- }), _ = B.get(g), v = Date.now();
674
- if (_ && e(_, v)) return y.emit("cache", {
670
+ let d = Y.get(u.route.pattern), ee = t["x-tenant"] ?? "anonymous", p = (await J.getHelpers()).i18n?.resolve(t.cookie, t["accept-language"])?.locale, h = j(n, {
671
+ ...d?.tenantAware ? { tenant: ee } : {},
672
+ ...p ? { locale: p } : {}
673
+ }), g = B.get(h), _ = Date.now();
674
+ if (g && T(g, _)) return m.emit("cache", {
675
675
  kind: "HIT",
676
- key: g,
677
- ageMs: v - _.renderedAt
676
+ key: h,
677
+ ageMs: _ - g.renderedAt
678
678
  }), {
679
679
  status: 200,
680
680
  headers: {
681
681
  "content-type": "text/html; charset=utf-8",
682
682
  "x-voltro-rendered-by": "isr",
683
683
  "x-voltro-cache": "HIT",
684
- "x-voltro-cache-key": g,
685
- "x-voltro-cache-age-ms": String(v - _.renderedAt)
684
+ "x-voltro-cache-key": h,
685
+ "x-voltro-cache-age-ms": String(_ - g.renderedAt)
686
686
  },
687
- body: _.html
687
+ body: g.html
688
688
  };
689
- if (_ && b(_, v)) return y.emit("cache", {
689
+ if (g && O(g, _)) return m.emit("cache", {
690
690
  kind: "STALE",
691
- key: g,
692
- ageMs: v - _.renderedAt
691
+ key: h,
692
+ ageMs: _ - g.renderedAt
693
693
  }), (async () => {
694
694
  try {
695
- let e = await we({
695
+ let r = await we({
696
696
  provider: J,
697
- root: o,
698
- route: d.route,
699
- params: d.params,
700
- pathname: r,
697
+ root: i,
698
+ route: u.route,
699
+ params: u.params,
700
+ pathname: n,
701
701
  dirs: W,
702
702
  shellTemplate: F,
703
- requestHeaders: n,
703
+ requestHeaders: t,
704
704
  apiOrigin: R,
705
705
  apiName: z,
706
- requestUrl: t,
706
+ requestUrl: e,
707
707
  buffered: !0
708
708
  });
709
- if (e && "html" in e && e.renderMode === "isr" && e.revalidateMs !== null) {
710
- let t = Y.get(d.route.pattern)?.staleWhileRevalidateMs ?? 0, n = Date.now();
711
- B.set(g, {
712
- html: e.html,
713
- renderedAt: n,
714
- expiresAt: n + e.revalidateMs,
715
- servableUntil: n + e.revalidateMs + t,
716
- revalidateMs: e.revalidateMs,
717
- staleWhileRevalidateMs: t
709
+ if (r && "html" in r && r.renderMode === "isr" && r.revalidateMs !== null) {
710
+ let e = Y.get(u.route.pattern)?.staleWhileRevalidateMs ?? 0, t = Date.now();
711
+ B.set(h, {
712
+ html: r.html,
713
+ renderedAt: t,
714
+ expiresAt: t + r.revalidateMs,
715
+ servableUntil: t + r.revalidateMs + e,
716
+ revalidateMs: r.revalidateMs,
717
+ staleWhileRevalidateMs: e
718
718
  });
719
719
  }
720
720
  } catch (e) {
721
- q.warn("background SWR refresh failed", { url: r }, e);
721
+ q.warn("background SWR refresh failed", { url: n }, e);
722
722
  }
723
723
  })(), {
724
724
  status: 200,
@@ -726,26 +726,26 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
726
726
  "content-type": "text/html; charset=utf-8",
727
727
  "x-voltro-rendered-by": "isr",
728
728
  "x-voltro-cache": "STALE",
729
- "x-voltro-cache-key": g,
730
- "x-voltro-cache-age-ms": String(v - _.renderedAt)
729
+ "x-voltro-cache-key": h,
730
+ "x-voltro-cache-age-ms": String(_ - g.renderedAt)
731
731
  },
732
- body: _.html
732
+ body: g.html
733
733
  };
734
734
  try {
735
- let e = await we({
735
+ let r = await we({
736
736
  provider: J,
737
- root: o,
738
- route: d.route,
739
- params: d.params,
740
- pathname: r,
737
+ root: i,
738
+ route: u.route,
739
+ params: u.params,
740
+ pathname: n,
741
741
  dirs: W,
742
742
  shellTemplate: F,
743
- requestHeaders: n,
743
+ requestHeaders: t,
744
744
  apiOrigin: R,
745
745
  apiName: z,
746
- requestUrl: t
746
+ requestUrl: e
747
747
  });
748
- if (!e) return {
748
+ if (!r) return {
749
749
  status: 200,
750
750
  headers: {
751
751
  "content-type": "text/html; charset=utf-8",
@@ -753,16 +753,16 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
753
753
  },
754
754
  body: F
755
755
  };
756
- if ("stream" in e) return {
756
+ if ("stream" in r) return {
757
757
  status: 200,
758
- headers: { "x-voltro-rendered-by": e.renderMode },
758
+ headers: { "x-voltro-rendered-by": r.renderMode },
759
759
  body: "",
760
- stream: e.stream
760
+ stream: r.stream
761
761
  };
762
- if ("control" in e) return e.control === "redirect" ? {
763
- status: e.status,
762
+ if ("control" in r) return r.control === "redirect" ? {
763
+ status: r.status,
764
764
  headers: {
765
- location: e.location,
765
+ location: r.location,
766
766
  "x-voltro-rendered-by": "loader-redirect"
767
767
  },
768
768
  body: ""
@@ -774,36 +774,36 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
774
774
  },
775
775
  body: "not found"
776
776
  };
777
- let i = {
777
+ let a = {
778
778
  "content-type": "text/html; charset=utf-8",
779
- "x-voltro-rendered-by": e.renderMode
779
+ "x-voltro-rendered-by": r.renderMode
780
780
  };
781
- if (e.renderMode === "isr" && e.revalidateMs !== null) {
782
- let t = Date.now(), n = Y.get(d.route.pattern)?.staleWhileRevalidateMs ?? 0;
783
- B.set(g, {
784
- html: e.html,
785
- renderedAt: t,
786
- expiresAt: t + e.revalidateMs,
787
- servableUntil: t + e.revalidateMs + n,
788
- revalidateMs: e.revalidateMs,
789
- staleWhileRevalidateMs: n
790
- }), i["x-voltro-cache"] = "MISS", i["x-voltro-cache-key"] = g, i["x-voltro-cache-revalidate-ms"] = String(e.revalidateMs), n > 0 && (i["x-voltro-cache-swr-ms"] = String(n)), y.emit("cache", {
781
+ if (r.renderMode === "isr" && r.revalidateMs !== null) {
782
+ let e = Date.now(), t = Y.get(u.route.pattern)?.staleWhileRevalidateMs ?? 0;
783
+ B.set(h, {
784
+ html: r.html,
785
+ renderedAt: e,
786
+ expiresAt: e + r.revalidateMs,
787
+ servableUntil: e + r.revalidateMs + t,
788
+ revalidateMs: r.revalidateMs,
789
+ staleWhileRevalidateMs: t
790
+ }), a["x-voltro-cache"] = "MISS", a["x-voltro-cache-key"] = h, a["x-voltro-cache-revalidate-ms"] = String(r.revalidateMs), t > 0 && (a["x-voltro-cache-swr-ms"] = String(t)), m.emit("cache", {
791
791
  kind: "MISS",
792
- key: g,
793
- revalidateMs: e.revalidateMs,
794
- swrMs: n
792
+ key: h,
793
+ revalidateMs: r.revalidateMs,
794
+ swrMs: t
795
795
  });
796
- } else e.renderMode === "isr" && (i["x-voltro-cache"] = "BYPASS", y.emit("cache", {
796
+ } else r.renderMode === "isr" && (a["x-voltro-cache"] = "BYPASS", m.emit("cache", {
797
797
  kind: "BYPASS",
798
- key: g
798
+ key: h
799
799
  }));
800
800
  return {
801
801
  status: 200,
802
- headers: i,
803
- body: e.html
802
+ headers: a,
803
+ body: r.html
804
804
  };
805
805
  } catch (e) {
806
- return q.error("render error", { url: r }, e), x(e) ? {
806
+ return q.error("render error", { url: n }, e), y(e) ? {
807
807
  status: 500,
808
808
  headers: {
809
809
  "content-type": "text/plain; charset=utf-8",
@@ -817,17 +817,17 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
817
817
  };
818
818
  }
819
819
  }, Fe = !1, Ie = he(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") {
820
+ let n = e.url ?? "/", r = Date.now(), i = {};
821
+ for (let [t, n] of Object.entries(e.headers)) n !== void 0 && (i[t.toLowerCase()] = Array.isArray(n) ? n.join(", ") : n);
822
+ let s = n.split("?")[0] ?? "/", c = (e.method ?? "GET").toUpperCase();
823
+ if (s === "/internal/liveness") {
824
824
  t.writeHead(200, {
825
825
  "content-type": "text/plain",
826
826
  "cache-control": "no-store"
827
827
  }), t.end("ok");
828
828
  return;
829
829
  }
830
- if (o === "/internal/readiness") {
830
+ if (s === "/internal/readiness") {
831
831
  let e = Fe ? 200 : 503;
832
832
  t.writeHead(e, {
833
833
  "content-type": "text/plain",
@@ -835,12 +835,12 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
835
835
  }), t.end(Fe ? "ready" : "not-ready");
836
836
  return;
837
837
  }
838
- if (s === "OPTIONS" && o.startsWith("/_voltro/inspect")) {
839
- let e = ue(a.origin);
838
+ if (c === "OPTIONS" && s.startsWith("/_voltro/inspect")) {
839
+ let e = ue(i.origin);
840
840
  t.writeHead(204, e), t.end();
841
841
  return;
842
842
  }
843
- if (m.name === "voltroDashboard" && o === "/api/dashboard/proxy") {
843
+ if (f.name === "voltroDashboard" && s === "/api/dashboard/proxy") {
844
844
  let r = new URL(n, "http://x").searchParams.get("target");
845
845
  if (!r) {
846
846
  t.writeHead(400, { "content-type": "text/plain" }), t.end("missing ?target=");
@@ -851,24 +851,24 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
851
851
  return;
852
852
  }
853
853
  try {
854
- let n = { accept: a.accept ?? "application/json" }, i = a.authorization;
855
- i ? n.authorization = Array.isArray(i) ? i[0] : i : oe(r) && process.env.VOLTRO_INSPECT_TOKEN && (n.authorization = `Bearer ${process.env.VOLTRO_INSPECT_TOKEN}`);
854
+ let n = { accept: i.accept ?? "application/json" }, a = i.authorization;
855
+ a ? n.authorization = Array.isArray(a) ? a[0] : a : oe(r) && process.env.VOLTRO_INSPECT_TOKEN && (n.authorization = `Bearer ${process.env.VOLTRO_INSPECT_TOKEN}`);
856
856
  let o;
857
- if (s && s !== "GET" && s !== "HEAD") {
857
+ if (c && c !== "GET" && c !== "HEAD") {
858
858
  let t = [];
859
859
  for await (let n of e) t.push(n);
860
860
  o = Buffer.concat(t);
861
- let r = a["content-type"];
861
+ let r = i["content-type"];
862
862
  r && (n["content-type"] = Array.isArray(r) ? r[0] : r);
863
863
  }
864
- let c = await fetch(r, {
864
+ let s = await fetch(r, {
865
865
  redirect: "manual",
866
- method: s,
866
+ method: c,
867
867
  headers: n,
868
868
  ...o ? { body: new Uint8Array(o.buffer, o.byteOffset, o.byteLength) } : {}
869
- }), l = Buffer.from(await c.arrayBuffer());
870
- t.writeHead(c.status, {
871
- "content-type": c.headers.get("content-type") ?? "application/octet-stream",
869
+ }), l = Buffer.from(await s.arrayBuffer());
870
+ t.writeHead(s.status, {
871
+ "content-type": s.headers.get("content-type") ?? "application/octet-stream",
872
872
  "content-length": String(l.length)
873
873
  }), t.end(l);
874
874
  } catch (e) {
@@ -876,7 +876,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
876
876
  }
877
877
  return;
878
878
  }
879
- if (m.name === "voltroDashboard" && o === "/api/dashboard/proxy/stream") {
879
+ if (f.name === "voltroDashboard" && s === "/api/dashboard/proxy/stream") {
880
880
  let r = new URL(n, "http://x").searchParams.get("target");
881
881
  if (!r) {
882
882
  t.writeHead(400, { "content-type": "text/plain" }), t.end("missing ?target=");
@@ -886,17 +886,17 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
886
886
  t.writeHead(400, { "content-type": "text/plain" }), t.end("target not allowed: must be loopback or an origin configured in VOLTRO_DASHBOARD_APPS");
887
887
  return;
888
888
  }
889
- let i = new AbortController();
890
- e.on("close", () => i.abort()), t.on("close", () => i.abort());
889
+ let a = new AbortController();
890
+ e.on("close", () => a.abort()), t.on("close", () => a.abort());
891
891
  try {
892
- let e = a.authorization ?? (oe(r) && process.env.VOLTRO_INSPECT_TOKEN ? `Bearer ${process.env.VOLTRO_INSPECT_TOKEN}` : void 0), n = await fetch(r, {
892
+ let e = i.authorization ?? (oe(r) && process.env.VOLTRO_INSPECT_TOKEN ? `Bearer ${process.env.VOLTRO_INSPECT_TOKEN}` : void 0), n = await fetch(r, {
893
893
  redirect: "manual",
894
894
  method: "GET",
895
895
  headers: {
896
896
  accept: "text/event-stream",
897
897
  ...e ? { authorization: Array.isArray(e) ? e[0] : e } : {}
898
898
  },
899
- signal: i.signal
899
+ signal: a.signal
900
900
  });
901
901
  if (!n.ok || !n.body) {
902
902
  t.writeHead(n.status, { "content-type": "text/plain" }), t.end(`upstream ${n.status}`);
@@ -923,8 +923,8 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
923
923
  }
924
924
  return;
925
925
  }
926
- if (o === "/_voltro/inspect/stream") {
927
- let n = ue(a.origin);
926
+ if (s === "/_voltro/inspect/stream") {
927
+ let n = ue(i.origin);
928
928
  if (se()) {
929
929
  t.writeHead(503, {
930
930
  "content-type": "application/json",
@@ -932,7 +932,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
932
932
  }), t.end(JSON.stringify({ error: "inspect disabled (VOLTRO_INSPECT=off)" }));
933
933
  return;
934
934
  }
935
- let r = P(a);
935
+ let r = P(i);
936
936
  if (!r.ok) {
937
937
  t.writeHead(401, {
938
938
  "content-type": "application/json",
@@ -950,29 +950,29 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
950
950
  "x-accel-buffering": "no",
951
951
  ...n
952
952
  }), t.flushHeaders(), t.write("retry: 5000\n\n");
953
- for (let e of y.buffered()) t.write(d(e));
954
- let o = y.subscribe((e) => {
955
- t.write(d(e));
956
- }), s = setInterval(() => {
957
- t.write(i());
958
- }, 15e3), c = () => {
959
- clearInterval(s), o();
953
+ for (let e of m.buffered()) t.write(o(e));
954
+ let s = m.subscribe((e) => {
955
+ t.write(o(e));
956
+ }), c = setInterval(() => {
957
+ t.write(a());
958
+ }, 15e3), l = () => {
959
+ clearInterval(c), s();
960
960
  };
961
- e.on("close", c), t.on("close", c);
961
+ e.on("close", l), t.on("close", l);
962
962
  return;
963
963
  }
964
964
  try {
965
- let e = await Pe(n, a);
966
- if (e.stream ? e.stream(t) : (t.writeHead(e.status, e.headers), t.end(e.body)), !o.startsWith("/_voltro/inspect")) {
965
+ let e = await Pe(n, i);
966
+ if (e.stream ? e.stream(t) : (t.writeHead(e.status, e.headers), t.end(e.body)), !s.startsWith("/_voltro/inspect")) {
967
967
  let t = Date.now() - r;
968
- y.emit("request", {
969
- url: o,
968
+ m.emit("request", {
969
+ url: s,
970
970
  status: e.status,
971
971
  durationMs: t,
972
972
  renderedBy: e.headers["x-voltro-rendered-by"],
973
973
  cache: e.headers["x-voltro-cache"]
974
974
  });
975
- let n = Ce(o, G)?.route.pattern ?? (e.status === 404 ? "<unmatched>" : "<asset>");
975
+ let n = Ce(s, G)?.route.pattern ?? (e.status === 404 ? "<unmatched>" : "<asset>");
976
976
  ke.record({
977
977
  kind: "request",
978
978
  tag: n,
@@ -984,31 +984,31 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
984
984
  t.writeHead(500, { "content-type": "text/plain" }), t.end(`internal error: ${e.message}`);
985
985
  }
986
986
  });
987
- await new Promise((e) => Ie.listen(S, "::", e)), Fe = !0, s.mark("ready"), q.info(`listening on http://localhost:${S}`, {
988
- port: S,
989
- distDir: T
987
+ await new Promise((e) => Ie.listen(h, "::", e)), Fe = !0, d.mark("ready"), q.info(`listening on http://localhost:${h}`, {
988
+ port: h,
989
+ distDir: b
990
990
  }), q.debug("dynamic + ssr/isr routes resolve via SSR loader");
991
991
  try {
992
- await w({
992
+ await S({
993
993
  id: M,
994
- name: D,
994
+ name: w,
995
995
  kind: "web",
996
- url: `http://localhost:${S}`,
996
+ url: `http://localhost:${h}`,
997
997
  pid: process.pid,
998
998
  status: "live",
999
999
  logFile: N.path
1000
1000
  });
1001
- let e = ae(o);
1001
+ let e = ae(i);
1002
1002
  if (e) {
1003
- let t = await n({ dashboardAppPath: e });
1004
- t.status === "launched" ? q.info(`dashboard launched at http://localhost:${t.port}`, { port: t.port }) : t.status === "already-running" && q.debug(`dashboard already running on :${t.port}`, { port: t.port });
1003
+ let n = await t({ dashboardAppPath: e });
1004
+ 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
1005
  }
1006
1006
  setInterval(() => {
1007
- w({
1007
+ S({
1008
1008
  id: M,
1009
- name: D,
1009
+ name: w,
1010
1010
  kind: "web",
1011
- url: `http://localhost:${S}`,
1011
+ url: `http://localhost:${h}`,
1012
1012
  pid: process.pid,
1013
1013
  status: "live",
1014
1014
  logFile: N.path
@@ -1018,22 +1018,22 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
1018
1018
  q.warn("runtime-registry write failed", {}, e);
1019
1019
  }
1020
1020
  pe({
1021
- app: m.name ?? "unnamed",
1021
+ app: f.name ?? "unnamed",
1022
1022
  kind: "web",
1023
- url: `http://localhost:${S}`,
1024
- bootMs: s.total()
1023
+ url: `http://localhost:${h}`,
1024
+ bootMs: d.total()
1025
1025
  });
1026
- let Le = s.phaseBreakdown();
1027
- q.info(`start: ready in ${s.total()}ms`, {
1028
- bootMs: s.total(),
1026
+ let Le = d.phaseBreakdown();
1027
+ q.info(`start: ready in ${d.total()}ms`, {
1028
+ bootMs: d.total(),
1029
1029
  ...Le ? { phases: Le } : {}
1030
1030
  });
1031
- let Re = !1, ze = (e) => async () => {
1031
+ let Re = !1, ze = (t) => async () => {
1032
1032
  if (!Re) {
1033
- if (Re = !0, q.info(`received ${e}, shutting down`, { signal: e }), Ie.close(), await Oe.stop(), H) try {
1033
+ if (Re = !0, q.info(`received ${t}, shutting down`, { signal: t }), Ie.close(), await Oe.stop(), H) try {
1034
1034
  await H.end();
1035
1035
  } catch {}
1036
- await J.close(), await t(M), await N.dispose(), process.exit(0);
1036
+ await J.close(), await e(M), await N.dispose(), process.exit(0);
1037
1037
  }
1038
1038
  };
1039
1039
  process.on("SIGINT", ze("SIGINT")), process.on("SIGTERM", ze("SIGTERM"));