@voltro/cli 0.53.0 → 0.55.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 (191) hide show
  1. package/CHANGELOG.md +335 -0
  2. package/dist/{agentsMd-0l980yhL.js → agentsMd-BaLC10Na.js} +110 -82
  3. package/dist/agentsMd-DCY1RSs8.js +2 -0
  4. package/dist/{apiBuild-CaPfoWku.js → apiBuild-CMvLJM_K.js} +2 -2
  5. package/dist/apiBuild-Cl0IDx8c.js +2 -0
  6. package/dist/bin.js +1 -1
  7. package/dist/{build-D-OnvNMf.js → build-S0QOzqPT.js} +115 -115
  8. package/dist/{checkCommand-D2ZduVlh.js → checkCommand-DNkY5kwF.js} +1 -1
  9. package/dist/{checkCommand-C5elt0tW.js → checkCommand-fbj9GDjN.js} +6 -6
  10. package/dist/{cloudCmd-QUXh-b5w.js → cloudCmd-DzKcSYuy.js} +1 -1
  11. package/dist/codegen-CN6vMM4J.js +2 -0
  12. package/dist/{codegen-FEk8AZHb.js → codegen-SIepQtUl.js} +76 -65
  13. package/dist/codegenCommand-3TDJezom.js +42 -0
  14. package/dist/{codemodRunner-BjtB2lq6.js → codemodRunner-C2zxZUIw.js} +64 -9
  15. package/dist/{commands-DyxAmhP0.js → commands-BBYJ7Q3B.js} +96 -73
  16. package/dist/{dashboardCommand-BdKTyT13.js → dashboardCommand-D2kmyCLL.js} +3 -3
  17. package/dist/{dataCommand-Bab9X7s8.js → dataCommand-BEPPQiTl.js} +267 -195
  18. package/dist/dbCommand-BTyBGhIA.js +2 -0
  19. package/dist/{dbCommand-06O2finM.js → dbCommand-DZTmOFT4.js} +3 -3
  20. package/dist/{dev-C6LGF4iY.js → dev-Ca_A_S9v.js} +2439 -2397
  21. package/dist/{dev-GjJWAYo2.js → dev-DfVZaoys.js} +1 -1
  22. package/dist/{doctorCommand-etMkflRc.js → doctorCommand-CGZJK_4o.js} +21 -21
  23. package/dist/doctorCommand-djmqEcDC.js +2 -0
  24. package/dist/{dormancyCommand-UwZ1AZzB.js → dormancyCommand-DY2rYpTa.js} +1 -1
  25. package/dist/{embeddingsCommand-C70zWHwo.js → embeddingsCommand-BoCqZsgp.js} +1 -1
  26. package/dist/{envCommand-dSyKvRkM.js → envCommand-Bxy2fOjc.js} +15 -15
  27. package/dist/{evolveCommand-CG0_ebO5.js → evolveCommand-BsbZ-XDg.js} +2 -2
  28. package/dist/fileConventions-l-RIXbx8.js +36 -0
  29. package/dist/{fileTaxonomy-B7uxipWS.js → fileTaxonomy-CbyMQYx_.js} +37 -37
  30. package/dist/frameworkTableAssembly-Df2Ymp2f.js +2 -0
  31. package/dist/{frameworkTableAssembly-DKx3ba3S.js → frameworkTableAssembly-Do-cf6RJ.js} +96 -102
  32. package/dist/index.js +2 -2
  33. package/dist/{infoCommand-_53iOc_j.js → infoCommand-EmM3jPKD.js} +1 -1
  34. package/dist/{inspect-Bd8-9wsi.js → inspect-DCqILJ1G.js} +4 -0
  35. package/dist/inspect-DGJwpOAb.js +2 -0
  36. package/dist/interruptedReplace-CwnkBb2X.js +41 -0
  37. package/dist/interruptedReplace-qzmFI020.js +2 -0
  38. package/dist/manifestBuild-CJ2zvPvT.js +2 -0
  39. package/dist/{manifestBuild-Cqgsx2bM.js → manifestBuild-DjX5MoXy.js} +1 -1
  40. package/dist/{metaCommands-Cn2oboG4.js → metaCommands-x7RCi2AF.js} +2 -2
  41. package/dist/{migrate-Cko9rswM.js → migrate-CGFZS-1a.js} +2 -2
  42. package/dist/mobileCommand-D9O6iq3D.js +428 -0
  43. package/dist/mobileCommand-DAum7tsG.js +2 -0
  44. package/dist/{pageConvention-C938S8oC.js → pageConvention-CMpfDN6r.js} +1 -1
  45. package/dist/{privacyCommand-DWTQMC6R.js → privacyCommand-BCa2OoZG.js} +2 -2
  46. package/dist/{probeCommand-DkGGLknv.js → probeCommand-Bs3iVBSL.js} +1 -1
  47. package/dist/{projectScaffold-EzlErR4E.js → projectScaffold-CJfP-xbT.js} +1 -1
  48. package/dist/{projectScaffold-B4dmTlwT.js → projectScaffold-CSN0OzBV.js} +2 -2
  49. package/dist/renderModeScan-43yQ2opo.js +147 -0
  50. package/dist/{renderProfile-CskIgAfn.js → renderProfile-DvrhVJHa.js} +2 -2
  51. package/dist/{runtimeTrace-c0APJz7E.js → runtimeTrace-C1BTpHGQ.js} +1 -1
  52. package/dist/{sdkgen-BiQCgIEr.js → sdkgen-CXMwLg9n.js} +1 -1
  53. package/dist/{serveCommand-CueKQgzl.js → serveCommand-C7IrCD58.js} +899 -897
  54. package/dist/serveCommand-Cjt5S9hD.js +2 -0
  55. package/dist/serveEntry.js +1 -1
  56. package/dist/start-DH7cat4-.js +3 -0
  57. package/dist/{start-ekPan8BT.js → start-EOV7s1NZ.js} +544 -527
  58. package/dist/startEntry.js +1 -1
  59. package/dist/{staticCommand-xlSL-IWk.js → staticCommand-ey0kYmOT.js} +1 -1
  60. package/dist/{subcommandNames-DpYs3DXr.js → subcommandNames-CDzfEtKV.js} +3 -3
  61. package/dist/{templates-BR-fb4SP.js → templates-BTWZkJJT.js} +41 -9
  62. package/dist/{test-BWPQcRoB.js → test-DO27-x2P.js} +1 -1
  63. package/dist/{updateCommand-C_8I8Rzo.js → updateCommand-C_jN1w18.js} +1 -1
  64. package/dist/updateCommand-nnFjDbl4.js +2 -0
  65. package/dist/{webDev-C7jWJ5dX.js → webDev-1XpVnYkW.js} +1 -1
  66. package/dist/{webDev-oczpugbx.js → webDev-B7vNj4Bq.js} +1231 -1186
  67. package/dist/{webhooksCommand-4SVPDjKg.js → webhooksCommand-B1LVcyO3.js} +1 -1
  68. package/dist/workspaceDeps-RKEkX92S.js +45 -0
  69. package/package.json +31 -19
  70. package/templates/AGENTS.core.md +2 -0
  71. package/templates/AGENTS.md +4 -2
  72. package/templates/agent-docs/_index.md +2 -2
  73. package/templates/agent-docs/_manifest.json +1 -1
  74. package/templates/agent-docs/ai.md +4 -4
  75. package/templates/agent-docs/authentication.md +115 -0
  76. package/templates/agent-docs/cli.md +98 -12
  77. package/templates/agent-docs/data.md +121 -21
  78. package/templates/agent-docs/database/advancedqueries.md +1 -1
  79. package/templates/agent-docs/database/migrations.md +1 -1
  80. package/templates/agent-docs/database/seedsdialects.md +64 -2
  81. package/templates/agent-docs/internationalization.md +2 -0
  82. package/templates/agent-docs/introduction.md +25 -0
  83. package/templates/agent-docs/local-first-mobile.md +139 -41
  84. package/templates/agent-docs/observability.md +4 -2
  85. package/templates/agent-docs/plugins/atlassian.md +2 -2
  86. package/templates/agent-docs/plugins/audit.md +2 -2
  87. package/templates/agent-docs/plugins/billing.md +1 -1
  88. package/templates/agent-docs/plugins/cdc-out.md +8 -3
  89. package/templates/agent-docs/plugins/comments.md +22 -0
  90. package/templates/agent-docs/plugins/presence.md +32 -3
  91. package/templates/agent-docs/plugins/prometheus.md +2 -0
  92. package/templates/agent-docs/plugins/queue.md +47 -4
  93. package/templates/agent-docs/plugins.md +52 -14
  94. package/templates/agent-docs/reference.md +25 -4
  95. package/templates/agent-docs/routing.md +81 -9
  96. package/templates/agent-docs/scheduling.md +1 -1
  97. package/templates/agent-docs/schema-driven-ui.md +137 -1
  98. package/templates/agent-docs/templates/appshells.md +36 -4
  99. package/templates/agent-docs/whats-new.md +75 -158
  100. package/templates/apps/api-ai/package.json +6 -6
  101. package/templates/apps/api-auth/package.json +8 -8
  102. package/templates/apps/api-backend/package.json +7 -7
  103. package/templates/apps/api-backend-deactivation/package.json +7 -7
  104. package/templates/apps/api-backend-mail/package.json +8 -8
  105. package/templates/apps/api-backend-mariadb/package.json +9 -9
  106. package/templates/apps/api-backend-sqlite/package.json +8 -8
  107. package/templates/apps/api-backend-storage/package.json +8 -8
  108. package/templates/apps/api-cms/package.json +9 -9
  109. package/templates/apps/api-collab/README.md +3 -3
  110. package/templates/apps/api-collab/app.config.ts +1 -1
  111. package/templates/apps/api-collab/database/schema.ts +12 -8
  112. package/templates/apps/api-collab/mutations/documents.create.mutation.server.ts +1 -1
  113. package/templates/apps/api-collab/mutations/documents.setBody.mutation.server.ts +1 -1
  114. package/templates/apps/api-collab/mutations/documents.setBody.mutation.ts +1 -1
  115. package/templates/apps/api-collab/package.json +8 -8
  116. package/templates/apps/api-collab/template.json +1 -1
  117. package/templates/apps/api-collab/tests/documents.setBody.test.ts +10 -2
  118. package/templates/apps/api-data-advanced/package.json +8 -8
  119. package/templates/apps/api-durable/package.json +8 -8
  120. package/templates/apps/api-feature-flags/package.json +9 -9
  121. package/templates/apps/api-governance/package.json +8 -8
  122. package/templates/apps/api-kv/package.json +8 -8
  123. package/templates/apps/api-moderation/package.json +8 -8
  124. package/templates/apps/api-observability/package.json +8 -8
  125. package/templates/apps/api-ratelimit/package.json +8 -8
  126. package/templates/apps/api-rbac/package.json +8 -8
  127. package/templates/apps/api-rest/package.json +7 -7
  128. package/templates/apps/api-row-history/package.json +8 -8
  129. package/templates/apps/api-saas/package.json +11 -10
  130. package/templates/apps/api-saas-starter/package.json +10 -10
  131. package/templates/apps/api-search/package.json +8 -8
  132. package/templates/apps/api-status/package.json +8 -8
  133. package/templates/apps/api-webhooks/package.json +9 -9
  134. package/templates/apps/changelog/package.json +7 -6
  135. package/templates/apps/edge-functions/package.json +2 -2
  136. package/templates/apps/frontend-admin/package.json +8 -8
  137. package/templates/apps/frontend-app/package.json +9 -9
  138. package/templates/apps/frontend-auth/package.json +8 -8
  139. package/templates/apps/frontend-blank/package.json +7 -7
  140. package/templates/apps/frontend-cms/package.json +9 -9
  141. package/templates/apps/frontend-collab/README.md +43 -24
  142. package/templates/apps/frontend-collab/app.config.ts +3 -3
  143. package/templates/apps/frontend-collab/package.json +14 -10
  144. package/templates/apps/frontend-collab/src/locales/de.ts +1 -2
  145. package/templates/apps/frontend-collab/src/locales/en.ts +1 -2
  146. package/templates/apps/frontend-collab/src/pages/page.test.tsx +72 -76
  147. package/templates/apps/frontend-collab/src/pages/page.tsx +45 -22
  148. package/templates/apps/frontend-collab/template.json +2 -2
  149. package/templates/apps/frontend-contact/package.json +7 -7
  150. package/templates/apps/frontend-dashboard/package.json +7 -7
  151. package/templates/apps/frontend-docs/package.json +8 -7
  152. package/templates/apps/frontend-i18n/package.json +6 -6
  153. package/templates/apps/frontend-landing/README.md +48 -0
  154. package/templates/apps/frontend-landing/app.config.ts +28 -0
  155. package/templates/apps/frontend-landing/package.json +7 -6
  156. package/templates/apps/frontend-landing/src/assets/hero.jpg +0 -0
  157. package/templates/apps/frontend-landing/src/fonts/Geist-Variable.woff2 +0 -0
  158. package/templates/apps/frontend-landing/src/fonts/LICENSE-Geist.txt +92 -0
  159. package/templates/apps/frontend-landing/src/globals.css +15 -0
  160. package/templates/apps/frontend-landing/src/globals.d.ts +17 -0
  161. package/templates/apps/frontend-landing/src/locales/de.ts +3 -2
  162. package/templates/apps/frontend-landing/src/locales/en.ts +5 -2
  163. package/templates/apps/frontend-landing/src/pages/page.test.tsx +79 -0
  164. package/templates/apps/frontend-landing/src/pages/page.tsx +26 -3
  165. package/templates/apps/frontend-landing/template.json +2 -2
  166. package/templates/apps/frontend-portal/package.json +8 -8
  167. package/templates/apps/frontend-saas/package.json +8 -8
  168. package/templates/apps/frontend-spa/package.json +7 -7
  169. package/templates/apps/frontend-ssr/package.json +7 -7
  170. package/templates/apps/frontend-ssr-api/package.json +8 -8
  171. package/templates/apps/frontend-static-blog/package.json +8 -7
  172. package/templates/apps/frontend-status/package.json +8 -8
  173. package/templates/apps/mobile-app/package.json +12 -11
  174. package/templates/apps/mobile-app/src/lib/deeplinks.ts +29 -17
  175. package/templates/apps/mobile-app/tests/deeplinks.test.ts +16 -0
  176. package/dist/agentsMd-SDDSkyl4.js +0 -2
  177. package/dist/apiBuild-DHtLXYx9.js +0 -2
  178. package/dist/codegen-BWpt3VgF.js +0 -2
  179. package/dist/codegenCommand-BOiWQ5hz.js +0 -137
  180. package/dist/dbCommand-B1EXBC6f.js +0 -2
  181. package/dist/doctorCommand-B0hX0tdz.js +0 -2
  182. package/dist/fileConventions-DASGEmj-.js +0 -35
  183. package/dist/frameworkTableAssembly-C_7Z-rMs.js +0 -2
  184. package/dist/inspect-CuoDInfZ.js +0 -2
  185. package/dist/interruptedReplace-C3O3M1MM.js +0 -28
  186. package/dist/interruptedReplace-CvmiAM9K.js +0 -2
  187. package/dist/manifestBuild-C4-J1-m_.js +0 -2
  188. package/dist/renderModeScan-CUbOeOAg.js +0 -122
  189. package/dist/serveCommand-DsnrVN3U.js +0 -2
  190. package/dist/start-BJzZLbt8.js +0 -3
  191. package/dist/updateCommand-Bqql_rsQ.js +0 -2
@@ -1,43 +1,43 @@
1
1
  import { i as e, t } from "./nodeEnvironment-cGFAj1J8.js";
2
2
  import { r as n } from "./appPort-B_HpJ_ck.js";
3
- import { $ as r, A as i, At as a, B as o, C as s, D as c, E as l, F as u, H as d, I as ee, K as f, L as te, M as p, N as m, O as h, Ot as g, Q as ne, R as _, S as v, T as y, Tt as b, U as x, V as S, W as C, Wt as w, Y as T, bt as re, ct as E, dt as ie, et as D, ft as O, ht as ae, i as oe, j as se, jt as k, k as ce, kt as le, l as ue, lt as A, m as de, mt as j, n as fe, nt as pe, o as me, ot as M, p as N, q as P, qt as F, s as he, st as I, tt as ge, ut as L, w as _e, x as ve, z as ye } from "./webDev-oczpugbx.js";
4
- import { o as be, t as xe } from "./connectionConfig-Bk9IC7D0.js";
5
- import { A as Se, D as R, a as Ce, h as we, j as Te, k as Ee } from "./inspect-Bd8-9wsi.js";
6
- import { n as De, r as Oe, t as ke } from "./inspectMetrics-CGF94puw.js";
7
- import { a as Ae, c as z, d as je, f as Me, l as Ne, p as B, u as Pe } from "./renderModeScan-CUbOeOAg.js";
8
- import { i as Fe, n as Ie, r as Le, t as Re } from "./runtimeRegistry-DMeKfTHP.js";
9
- import { n as ze } from "./logFileSink-B4uP8pvf.js";
10
- import { t as Be } from "./bootTiming-BdyP9nYw.js";
11
- import { dirname as V, extname as H, join as U, resolve as Ve } from "node:path";
12
- import { promises as W } from "node:fs";
13
- import { fileURLToPath as He, pathToFileURL as G } from "node:url";
14
- import { createLogger as K, printReadyBlock as Ue } from "@voltro/logger";
15
- import { Effect as We } from "effect";
16
- import { maybeCompress as q, snapshotMetricsSync as Ge } from "@voltro/runtime";
17
- import { createHash as J } from "node:crypto";
18
- import { resolveBroadcastProvider as Ke } from "@voltro/plugin-broadcast";
19
- import { createServer as qe } from "node:http";
3
+ import { $ as r, A as i, At as a, B as o, C as s, D as c, E as l, F as u, G as d, H as f, I as ee, J as te, K as p, Kt as m, L as ne, M as h, Mt as g, N as re, O as ie, Ot as _, R as v, S as y, T as b, Tt as x, U as S, Ut as ae, V as C, W as oe, X as se, Y as w, Z as T, at as E, bt as D, ct as ce, et as le, ht as ue, i as de, j as fe, jt as O, k as pe, kt as k, l as me, lt as he, m as ge, mt as A, n as j, nt as M, o as _e, ot as N, p as ve, q as P, s as F, st as ye, w as be, x as xe, z as Se } from "./webDev-B7vNj4Bq.js";
4
+ import { o as Ce, t as we } from "./connectionConfig-Bk9IC7D0.js";
5
+ import { A as I, D as Te, a as Ee, h as De, j as Oe, k as ke } from "./inspect-DCqILJ1G.js";
6
+ import { n as Ae, r as je, t as Me } from "./inspectMetrics-CGF94puw.js";
7
+ import { a as Ne, c as L, d as Pe, f as Fe, l as Ie, p as R, u as Le } from "./renderModeScan-43yQ2opo.js";
8
+ import { i as Re, n as ze, r as Be, t as Ve } from "./runtimeRegistry-DMeKfTHP.js";
9
+ import { n as He } from "./logFileSink-B4uP8pvf.js";
10
+ import { t as Ue } from "./bootTiming-BdyP9nYw.js";
11
+ import { dirname as z, extname as B, join as V, resolve as We } from "node:path";
12
+ import { promises as H } from "node:fs";
13
+ import { fileURLToPath as Ge, pathToFileURL as U } from "node:url";
14
+ import { createLogger as W, printReadyBlock as Ke } from "@voltro/logger";
15
+ import { Effect as qe } from "effect";
16
+ import { maybeCompress as G, snapshotMetricsSync as Je } from "@voltro/runtime";
17
+ import { createHash as K } from "node:crypto";
18
+ import { resolveBroadcastProvider as Ye } from "@voltro/plugin-broadcast";
19
+ import { createServer as Xe } from "node:http";
20
20
  //#region src/httpResponseWrite.ts
21
- var Je = (e) => `W/"${J("md5").update(e).digest("hex")}"`, Ye = (e) => {
21
+ var Ze = (e) => `W/"${K("md5").update(e).digest("hex")}"`, Qe = (e) => {
22
22
  let { response: t, status: n, headers: r, body: i, requestHeaders: a } = e, o = r["cache-control"], s = (typeof o == "string" ? o : "").toLowerCase();
23
23
  if (i === void 0 || n !== 200 || s.includes("no-store")) return !1;
24
- let c = r["content-type"], l = typeof c == "string" ? c : void 0, u = Je(i), d = a["if-none-match"];
24
+ let c = r["content-type"], l = typeof c == "string" ? c : void 0, u = Ze(i), d = a["if-none-match"];
25
25
  if (d !== void 0 && d.split(",").some((e) => e.trim() === u)) return t.writeHead(304, {
26
26
  ...r,
27
27
  etag: u
28
28
  }), t.end(), !0;
29
- let ee = q({
29
+ let f = G({
30
30
  body: typeof i == "string" ? new TextEncoder().encode(i) : new Uint8Array(i),
31
31
  contentType: l,
32
32
  acceptEncoding: a["accept-encoding"],
33
33
  options: e.compression
34
- }), f = {
34
+ }), ee = {
35
35
  ...r,
36
- ...ee.headers,
36
+ ...f.headers,
37
37
  etag: u
38
38
  };
39
- return ee.compressed && delete f["content-length"], t.writeHead(n, f), t.end(Buffer.from(ee.bytes)), !0;
40
- }, Y = K({ scope: "voltro:start:cdc" }), Xe = (e) => (t) => {
39
+ return f.compressed && delete ee["content-length"], t.writeHead(n, ee), t.end(Buffer.from(f.bytes)), !0;
40
+ }, q = W({ scope: "voltro:start:cdc" }), $e = (e) => (t) => {
41
41
  let n = 0;
42
42
  for (let [r, i] of e.tableSubscriptionsByPattern) {
43
43
  if (!i.includes(t)) continue;
@@ -48,15 +48,15 @@ var Je = (e) => `W/"${J("md5").update(e).digest("hex")}"`, Ye = (e) => {
48
48
  }));
49
49
  }
50
50
  return n;
51
- }, Ze = () => xe() ? be() : null, Qe = (e) => {
52
- let t = e.channel ?? "framework_changes", n = e.revalidateChannel ?? "voltro_revalidate", r = Xe(e), i = null, a = null;
51
+ }, et = () => we() ? Ce() : null, tt = (e) => {
52
+ let t = e.channel ?? "framework_changes", n = e.revalidateChannel ?? "voltro_revalidate", r = $e(e), i = null, a = null;
53
53
  return {
54
54
  start: async () => {
55
55
  let o = e.tableSubscriptionsByPattern.size > 0, s = e.onRevalidate !== void 0;
56
- if (!o && !s) return Y.debug("skipped — no pages declare cacheInvalidatesOn and no revalidation handler is wired"), !1;
57
- let c = Ze();
58
- if (!c && !o) return Y.debug("no database configured — the revalidation LISTEN line is unavailable"), !1;
59
- if (!c) return Y.warn(`${e.tableSubscriptionsByPattern.size} route(s) declare \`cacheInvalidatesOn\` and will NOT be invalidated live — no database is configured for this web process. Set DB_URL (or DB_HOST / PG_HOST) so the CDC listener can connect; until then those routes go stale until their \`revalidate\` window expires.`, { routes: [...e.tableSubscriptionsByPattern.keys()] }), !1;
56
+ if (!o && !s) return q.debug("skipped — no pages declare cacheInvalidatesOn and no revalidation handler is wired"), !1;
57
+ let c = et();
58
+ if (!c && !o) return q.debug("no database configured — the revalidation LISTEN line is unavailable"), !1;
59
+ if (!c) return q.warn(`${e.tableSubscriptionsByPattern.size} route(s) declare \`cacheInvalidatesOn\` and will NOT be invalidated live — no database is configured for this web process. Set DB_URL (or DB_HOST / PG_HOST) so the CDC listener can connect; until then those routes go stale until their \`revalidate\` window expires.`, { routes: [...e.tableSubscriptionsByPattern.keys()] }), !1;
60
60
  i = new (await (import("pg"))).default.Client(c), await i.connect(), a = (i) => {
61
61
  if (i.channel === n && i.payload && e.onRevalidate) {
62
62
  e.onRevalidate(i.payload);
@@ -67,18 +67,18 @@ var Je = (e) => `W/"${J("md5").update(e).digest("hex")}"`, Ye = (e) => {
67
67
  try {
68
68
  a = JSON.parse(i.payload);
69
69
  } catch (e) {
70
- Y.warn("bad CDC payload", {}, e);
70
+ q.warn("bad CDC payload", {}, e);
71
71
  return;
72
72
  }
73
73
  let o = r(a.table);
74
- o > 0 && Y.info(`${a.op} on '${a.table}' → dropped ${o} cache entries`, {
74
+ o > 0 && q.info(`${a.op} on '${a.table}' → dropped ${o} cache entries`, {
75
75
  op: a.op,
76
76
  table: a.table,
77
77
  dropped: o
78
78
  });
79
79
  }, i.on("notification", a), o && await i.query(`LISTEN ${t}`), s && await i.query(`LISTEN ${n}`);
80
80
  let l = [...o ? [t] : [], ...s ? [n] : []];
81
- return Y.info(`LISTEN ${l.join(", ")}`, {
81
+ return q.info(`LISTEN ${l.join(", ")}`, {
82
82
  channels: l,
83
83
  ..."connectionString" in c ? { target: c.connectionString.replace(/\/\/[^@/]*@/, "//") } : {
84
84
  host: c.host,
@@ -96,7 +96,7 @@ var Je = (e) => `W/"${J("md5").update(e).digest("hex")}"`, Ye = (e) => {
96
96
  }
97
97
  }
98
98
  };
99
- }, X = K({ scope: "voltro:start:isr-cache" }), $e = "voltro_isr_cache", et = (e) => `
99
+ }, J = W({ scope: "voltro:start:isr-cache" }), nt = "voltro_isr_cache", Y = (e) => `
100
100
  CREATE TABLE IF NOT EXISTS ${e} (
101
101
  cache_key TEXT PRIMARY KEY,
102
102
  html TEXT NOT NULL,
@@ -107,9 +107,9 @@ CREATE TABLE IF NOT EXISTS ${e} (
107
107
  stale_while_revalidate_ms BIGINT NOT NULL DEFAULT 0
108
108
  );
109
109
  CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
110
- `, tt = (e) => {
111
- let t = e.tableName ?? $e, { client: n } = e, r = /* @__PURE__ */ new Map(), i = !1, a = (async () => {
112
- i || (i = !0, await n.query(et(t)));
110
+ `, rt = (e) => {
111
+ let t = e.tableName ?? nt, { client: n } = e, r = /* @__PURE__ */ new Map(), i = !1, a = (async () => {
112
+ i || (i = !0, await n.query(Y(t)));
113
113
  })().then(async () => {
114
114
  let e = await n.query(`SELECT * FROM ${t}`);
115
115
  for (let t of e.rows) r.set(t.cache_key, {
@@ -121,10 +121,10 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
121
121
  staleWhileRevalidateMs: Number(t.stale_while_revalidate_ms)
122
122
  });
123
123
  }).catch((e) => {
124
- X.warn("postgres bootstrap failed", {}, e);
124
+ J.warn("postgres bootstrap failed", {}, e);
125
125
  }), o = (e, t) => {
126
126
  a.then(() => n.query(e, t)).catch((e) => {
127
- X.warn("postgres write failed", {}, e);
127
+ J.warn("postgres write failed", {}, e);
128
128
  });
129
129
  }, s = /* @__PURE__ */ new Map(), c = (e) => {
130
130
  s.set(e, (s.get(e) ?? 0) + 1);
@@ -175,21 +175,21 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
175
175
  return Array.from(r.entries());
176
176
  }
177
177
  };
178
- }, Z = K({ scope: "voltro:start:revalidate" }), nt = (e) => {
178
+ }, X = W({ scope: "voltro:start:revalidate" }), it = (e) => {
179
179
  try {
180
180
  let t = JSON.parse(e);
181
181
  return (t.kind === "path" || t.kind === "table" || t.kind === "tag") && typeof t.value == "string" && t.value.length > 0 && (t.tenant === void 0 || typeof t.tenant == "string") ? {
182
182
  kind: t.kind,
183
183
  value: t.value,
184
184
  ...t.tenant === void 0 ? {} : { tenant: t.tenant }
185
- } : (Z.warn("bad revalidation payload (shape)", { payload: e }), null);
185
+ } : (X.warn("bad revalidation payload (shape)", { payload: e }), null);
186
186
  } catch {
187
- return Z.warn("bad revalidation payload (not JSON)", { payload: e }), null;
187
+ return X.warn("bad revalidation payload (not JSON)", { payload: e }), null;
188
188
  }
189
- }, rt = (e, t) => {
189
+ }, at = (e, t) => {
190
190
  if (t.kind === "table" || t.kind === "tag") {
191
191
  let n = e.tableSink(t.value);
192
- return Z.info(`revalidate ${t.kind} '${t.value}' → dropped ${n} cache entries`, {
192
+ return X.info(`revalidate ${t.kind} '${t.value}' → dropped ${n} cache entries`, {
193
193
  kind: t.kind,
194
194
  value: t.value,
195
195
  dropped: n
@@ -198,7 +198,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
198
198
  let n = t.value, r = (e) => t.tenant === void 0 || e.split("|").includes(`tenant=${t.tenant}`), i = e.regexByPattern.get(n);
199
199
  if (i !== void 0) {
200
200
  let a = e.renderModeByPattern.get(n);
201
- if (a !== "isr") return Z.error(`revalidatePath('${n}') targets a '${a ?? "unknown"}' route — only \`renderMode: 'isr'\` routes have cache entries to drop. Static HTML is a build artifact this process never re-renders; rebuild to change it.`, {
201
+ if (a !== "isr") return X.error(`revalidatePath('${n}') targets a '${a ?? "unknown"}' route — only \`renderMode: 'isr'\` routes have cache entries to drop. Static HTML is a build artifact this process never re-renders; rebuild to change it.`, {
202
202
  path: n,
203
203
  renderMode: a ?? "unknown"
204
204
  }), 0;
@@ -206,34 +206,34 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
206
206
  let t = e.split("|")[0] ?? e;
207
207
  return i.test(t) && r(e);
208
208
  });
209
- return Z.info(`revalidate path pattern '${n}' → dropped ${o} cache entries`, {
209
+ return X.info(`revalidate path pattern '${n}' → dropped ${o} cache entries`, {
210
210
  path: n,
211
211
  dropped: o,
212
212
  ...t.tenant === void 0 ? {} : { tenant: t.tenant }
213
213
  }), o;
214
214
  }
215
215
  let a = [...e.regexByPattern.entries()].find(([, e]) => e.test(n));
216
- if (a === void 0) return Z.error(`revalidatePath('${n}') matches no declared route — nothing was dropped. Pass a declared route pattern (e.g. /blog/[slug]) or a concrete path of one.`, { path: n }), 0;
216
+ if (a === void 0) return X.error(`revalidatePath('${n}') matches no declared route — nothing was dropped. Pass a declared route pattern (e.g. /blog/[slug]) or a concrete path of one.`, { path: n }), 0;
217
217
  let o = e.renderModeByPattern.get(a[0]);
218
- if (o !== "isr") return Z.error(`revalidatePath('${n}') targets a '${o ?? "unknown"}' route (${a[0]}) — only \`renderMode: 'isr'\` routes have cache entries to drop.`, {
218
+ if (o !== "isr") return X.error(`revalidatePath('${n}') targets a '${o ?? "unknown"}' route (${a[0]}) — only \`renderMode: 'isr'\` routes have cache entries to drop.`, {
219
219
  path: n,
220
220
  route: a[0],
221
221
  renderMode: o ?? "unknown"
222
222
  }), 0;
223
223
  let s = e.cache.invalidateBy((e) => (e.split("|")[0] ?? e) === n && r(e));
224
- return Z.info(`revalidate path '${n}' → dropped ${s} cache entries`, {
224
+ return X.info(`revalidate path '${n}' → dropped ${s} cache entries`, {
225
225
  path: n,
226
226
  dropped: s,
227
227
  ...t.tenant === void 0 ? {} : { tenant: t.tenant }
228
228
  }), s;
229
- }, Q = K({ scope: "voltro:start" }), it = await (async () => {
229
+ }, Z = W({ scope: "voltro:start" }), ot = await (async () => {
230
230
  try {
231
- let e = U(V(He(import.meta.url)), "..", "package.json"), t = await W.readFile(e, "utf8");
231
+ let e = V(z(Ge(import.meta.url)), "..", "package.json"), t = await H.readFile(e, "utf8");
232
232
  return JSON.parse(t).version ?? "0.0.0";
233
233
  } catch {
234
234
  return "0.0.0";
235
235
  }
236
- })(), at = (e) => e instanceof Error && e._voltroControl === "redirect" && typeof e.location == "string", ot = (e) => e instanceof Error && e._voltroControl === "not-found", st = {
236
+ })(), st = (e) => e instanceof Error && e._voltroControl === "redirect" && typeof e.location == "string", ct = (e) => e instanceof Error && e._voltroControl === "not-found", lt = {
237
237
  ".html": "text/html; charset=utf-8",
238
238
  ".js": "application/javascript",
239
239
  ".mjs": "application/javascript",
@@ -251,13 +251,13 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
251
251
  ".woff": "font/woff",
252
252
  ".woff2": "font/woff2",
253
253
  ".txt": "text/plain; charset=utf-8"
254
- }, ct = (e) => st[H(e).toLowerCase()] ?? "application/octet-stream", lt = (e) => e.replace(/<script\b(?=[^>]*\btype="module")(?:(?!<\/script>).)*<\/script>/gi, "").replace(/<script\b(?=[^>]*\bsrc=)(?:(?!<\/script>).)*<\/script>/gi, "").replace(/<link\b[^>]*\brel="modulepreload"[^>]*>/gi, ""), ut = async (e) => {
254
+ }, ut = (e) => lt[B(e).toLowerCase()] ?? "application/octet-stream", dt = (e) => e.replace(/<script\b(?=[^>]*\btype="module")(?:(?!<\/script>).)*<\/script>/gi, "").replace(/<script\b(?=[^>]*\bsrc=)(?:(?!<\/script>).)*<\/script>/gi, "").replace(/<link\b[^>]*\brel="modulepreload"[^>]*>/gi, ""), ft = async (e) => {
255
255
  try {
256
- return await W.stat(e), !0;
256
+ return await H.stat(e), !0;
257
257
  } catch {
258
258
  return !1;
259
259
  }
260
- }, dt = (e) => {
260
+ }, pt = (e) => {
261
261
  let t = [], n = 0, r = e.split("/").filter(Boolean), i = [];
262
262
  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, "\\$&"));
263
263
  let a = i.join("/");
@@ -266,8 +266,8 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
266
266
  paramNames: t,
267
267
  priority: n
268
268
  };
269
- }, ft = (e) => e.map((e) => {
270
- let { regex: t, paramNames: n, priority: r } = dt(e.pattern);
269
+ }, mt = (e) => e.map((e) => {
270
+ let { regex: t, paramNames: n, priority: r } = pt(e.pattern);
271
271
  return {
272
272
  pattern: e.pattern,
273
273
  file: e.file,
@@ -276,7 +276,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
276
276
  paramNames: n,
277
277
  priority: r
278
278
  };
279
- }).slice().sort((e, t) => e.priority - t.priority), pt = (e, t) => {
279
+ }).slice().sort((e, t) => e.priority - t.priority), ht = (e, t) => {
280
280
  for (let n of t) {
281
281
  let t = n.regex.exec(e);
282
282
  if (!t) continue;
@@ -288,33 +288,43 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
288
288
  };
289
289
  }
290
290
  return null;
291
- }, mt = null, ht = async (e) => {
292
- let { provider: t, route: n, params: r, pathname: a, dirs: s, shellTemplate: l, requestHeaders: f, requestUrl: m = "", apiOrigin: g, apiName: ne } = e, { search: _ } = ie(m), v = await ee(te(e.middlewares ?? [], {
291
+ }, gt = null, _t, vt = (e, t) => t === void 0 ? Promise.resolve() : (_t ??= (async () => {
292
+ try {
293
+ let n = await e.getHelpers(), r = n.apiDescriptors?.[t];
294
+ if (r === void 0) return;
295
+ let i = n.registerSsrApiDescriptors;
296
+ if (i === void 0) return;
297
+ i(t, await r());
298
+ } catch {}
299
+ })(), _t), yt = async (e) => {
300
+ let { provider: t, route: n, params: r, pathname: a, dirs: s, shellTemplate: d, requestHeaders: m, requestUrl: g = "", apiOrigin: re, apiName: ie } = e;
301
+ await vt(t, ie);
302
+ let { search: _ } = se(g), v = await ee(ne(e.middlewares ?? [], {
293
303
  route: n.pattern,
294
304
  pathname: a
295
305
  }), {
296
306
  pathname: a,
297
307
  search: _,
298
- headers: f,
299
- cookies: u(f.cookie),
308
+ headers: m,
309
+ cookies: u(m.cookie),
300
310
  route: n.pattern
301
- }, e.onCookieWarning), b = await t.getPage(n.pattern, n.file), C = e.forceSsrRender === !0 ? "ssr" : z(b, n.file), w = C === "isr" && b.ppr === !0, T = C === "isr" && e.holesOnly !== !0 ? i(v.headers) : v.headers, re = me(g, T.cookie, {
302
- apiName: ne,
311
+ }, e.onCookieWarning), y = await t.getPage(n.pattern, n.file), x = e.forceSsrRender === !0 ? "ssr" : L(y, n.file), ae = x === "isr" && y.ppr === !0, T = x === "isr" && e.holesOnly !== !0 ? i(v.headers) : v.headers, E = _e(re, T.cookie, {
312
+ apiName: ie,
303
313
  headers: T
304
314
  });
305
315
  if (e.holesOnly === !0) {
306
- if (typeof b.loader != "function") return null;
316
+ if (typeof y.loader != "function") return null;
307
317
  let e = new AbortController();
308
318
  return {
309
319
  holes: {
310
- loader: b.loader,
320
+ loader: y.loader,
311
321
  ctx: {
312
322
  params: r,
313
323
  pathname: a,
314
324
  search: _,
315
325
  signal: e.signal,
316
326
  headers: T,
317
- query: re,
327
+ query: E,
318
328
  isServer: !0
319
329
  },
320
330
  helpers: await t.getHelpers(),
@@ -323,12 +333,12 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
323
333
  setCookies: v.setCookies
324
334
  };
325
335
  }
326
- let D = C === "spa" && ue(s, n.dirChain).some((e) => e.hasLayout);
327
- if (C !== "ssr" && C !== "isr" && !D) return null;
328
- let ae = ue(s, n.dirChain), oe = {}, se = null, k, le = new AbortController(), de = w ? h(T, n.pattern) : T;
336
+ let D = x === "spa" && me(s, n.dirChain).some((e) => e.hasLayout);
337
+ if (x !== "ssr" && x !== "isr" && !D) return null;
338
+ let ce = me(s, n.dirChain), le = {}, ue = null, de, fe = new AbortController(), O = ae ? c(T, n.pattern) : T;
329
339
  try {
330
- (await t.getHelpers()).beginStoreSeeds(), {chain: k, segmentLoaderData: oe} = await he({
331
- entries: ae,
340
+ (await t.getHelpers()).beginStoreSeeds(), {chain: de, segmentLoaderData: le} = await F({
341
+ entries: ce,
332
342
  loadLayout: (e) => t.getLayout(e.dir),
333
343
  loadError: (e) => t.getError(e.dir),
334
344
  loadPending: (e) => t.getPending(e.dir),
@@ -336,210 +346,213 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
336
346
  params: r,
337
347
  pathname: a,
338
348
  search: _,
339
- signal: le.signal,
340
- headers: de,
341
- query: re,
349
+ signal: fe.signal,
350
+ headers: O,
351
+ query: E,
342
352
  isServer: !0
343
353
  }
344
- }), typeof b.loader == "function" && !D && (se = await b.loader({
354
+ }), typeof y.loader == "function" && !D && (ue = await y.loader({
345
355
  params: r,
346
356
  pathname: a,
347
357
  search: _,
348
- signal: le.signal,
349
- headers: de,
350
- query: re,
358
+ signal: fe.signal,
359
+ headers: O,
360
+ query: E,
351
361
  isServer: !0
352
362
  }));
353
363
  } catch (e) {
354
- if (at(e)) return {
364
+ if (st(e)) return {
355
365
  control: "redirect",
356
366
  status: e.status,
357
367
  location: e.location,
358
368
  setCookies: v.setCookies,
359
369
  responseHeaders: v.responseHeaders
360
370
  };
361
- if (ot(e)) return {
371
+ if (ct(e)) return {
362
372
  control: "not-found",
363
373
  setCookies: v.setCookies,
364
374
  responseHeaders: v.responseHeaders
365
375
  };
366
376
  throw e;
367
377
  }
368
- let j = await t.getHelpers();
369
- D || await ye({
370
- pageMod: b,
378
+ let k = await t.getHelpers();
379
+ D || await Se({
380
+ pageMod: y,
371
381
  params: r,
372
- query: re,
373
- apiName: ne,
374
- seed: j.seedPreloadedSubscription,
375
- seedFailure: j.seedPreloadedSubscriptionFailure,
376
- onError: ({ tag: e, apiName: t }, n) => Q.warn("preload seed failed", {
382
+ query: E,
383
+ apiName: ie,
384
+ seed: k.seedPreloadedSubscription,
385
+ seedFailure: k.seedPreloadedSubscriptionFailure,
386
+ onError: ({ tag: e, apiName: t }, n) => Z.warn("preload seed failed", {
377
387
  tag: e,
378
388
  apiName: t,
379
389
  pathname: a
380
390
  }, n)
381
391
  });
382
- let fe = {
392
+ let he = {
383
393
  pattern: n.pattern,
384
- Component: b.default,
385
- meta: b.meta,
386
- loader: b.loader,
387
- ErrorBoundary: b.ErrorBoundary,
388
- Pending: b.Pending,
389
- renderMode: C,
390
- chain: k
394
+ Component: y.default,
395
+ meta: y.meta,
396
+ loader: y.loader,
397
+ ErrorBoundary: y.ErrorBoundary,
398
+ Pending: y.Pending,
399
+ renderMode: x,
400
+ chain: de
391
401
  };
392
- if (C === "isr" && v.cspNonce !== void 0) throw Error(`page '${n.pattern}' is renderMode 'isr' while middleware.ts mints a cspNonce — an isr render is CACHED and a cached nonce is a lie the browser enforces. Use renderMode 'ssr' for nonce'd pages, or a hash-based CSP for isr.`);
393
- let pe = {
394
- cookies: w ? c(ce(v.cookies), n.pattern) : C === "isr" ? ce(v.cookies) : v.cookies,
395
- headers: de,
396
- url: m,
402
+ if (x === "isr" && v.cspNonce !== void 0) throw Error(`page '${n.pattern}' is renderMode 'isr' while middleware.ts mints a cspNonce — an isr render is CACHED and a cached nonce is a lie the browser enforces. Use renderMode 'ssr' for nonce'd pages, or a hash-based CSP for isr.`);
403
+ let ge = {
404
+ cookies: ae ? l(pe(v.cookies), n.pattern) : x === "isr" ? pe(v.cookies) : v.cookies,
405
+ headers: O,
406
+ url: g,
397
407
  ...e.formFlash === void 0 ? {} : { formFlash: e.formFlash }
398
- }, M = j.i18n?.resolve(T.cookie, T["accept-language"]), N = {
399
- lang: M?.locale ?? pe.cookies["voltro:locale"] ?? "en",
400
- ...M?.timeZone === void 0 ? {} : { timeZone: M.timeZone },
408
+ }, A = k.i18n?.resolve(T.cookie, T["accept-language"]), j = {
409
+ lang: A?.locale ?? ge.cookies["voltro:locale"] ?? "en",
410
+ ...A?.timeZone === void 0 ? {} : { timeZone: A.timeZone },
401
411
  renderedAt: Date.now()
402
- }, P = b.interactive ?? "full";
412
+ }, M = y.interactive ?? "full";
403
413
  if (D) {
404
- let e = E({
405
- helpers: j,
414
+ let e = P({
415
+ helpers: k,
406
416
  page: n.pattern,
407
- interactive: P,
417
+ interactive: M,
408
418
  delivery: "stream",
409
419
  renderInput: {
410
- descriptor: fe,
420
+ descriptor: he,
411
421
  params: r,
412
422
  pathname: a,
413
423
  search: _,
414
- segmentLoaderData: oe,
415
- requestContext: pe,
416
- ...M ? {
417
- outerWrap: M.outerWrap,
418
- locale: M.locale
424
+ segmentLoaderData: le,
425
+ requestContext: ge,
426
+ ...A ? {
427
+ outerWrap: A.outerWrap,
428
+ locale: A.locale
419
429
  } : {}
420
430
  }
421
- }), t = (t) => L({
422
- helpers: j,
431
+ }), t = (t) => w({
432
+ helpers: k,
423
433
  prepared: e,
424
434
  meta: t,
425
- interactive: P
435
+ interactive: M
426
436
  });
427
437
  if (e.hasDeferred) {
428
- let n = d({ shell: l });
438
+ let n = f({ shell: d });
429
439
  return {
430
440
  renderMode: "spa",
431
441
  setCookies: v.setCookies,
432
442
  responseHeaders: v.responseHeaders,
433
- stream: (r) => x({
443
+ stream: (r) => oe({
434
444
  res: r,
435
445
  shell: n,
436
- documentAttrs: N,
446
+ documentAttrs: j,
437
447
  headers: {
438
448
  ...v.responseHeaders,
439
449
  "content-type": "text/html; charset=utf-8",
440
450
  "x-voltro-rendered-by": "spa",
441
- ...p(v.setCookies)
451
+ ...h(v.setCookies)
442
452
  },
443
453
  headInjection: t,
444
- render: (t) => j.renderPageToStream({
454
+ ...v.cspNonce === void 0 ? {} : { nonce: v.cspNonce },
455
+ render: (t) => k.renderPageToStream({
445
456
  ...e.renderInput,
446
- ...t
457
+ ...t,
458
+ ...v.cspNonce === void 0 ? {} : { nonce: v.cspNonce }
447
459
  }),
448
460
  onShellError: (e) => {
449
- Q.error("spa layout shell render failed", { pathname: a }, e), r.writeHead(500, { "content-type": "text/plain; charset=utf-8" }), r.end("server error");
461
+ Z.error("spa layout shell render failed", { pathname: a }, e), r.writeHead(500, { "content-type": "text/plain; charset=utf-8" }), r.end("server error");
450
462
  }
451
463
  })
452
464
  };
453
465
  }
454
- let i = A({
455
- helpers: j,
466
+ let i = te({
467
+ helpers: k,
456
468
  prepared: e
457
- });
469
+ }), s = o(C(d.replace("<div id=\"root\"></div>", `<div id="root">${i.body}</div>`), t(i.meta)), j);
458
470
  return {
459
- html: o(S(l.replace("<div id=\"root\"></div>", `<div id="root">${i.body}</div>`), t(i.meta)), N),
471
+ html: v.cspNonce === void 0 ? s : S(s, v.cspNonce),
460
472
  renderMode: "spa",
461
473
  revalidateMs: null,
462
474
  setCookies: v.setCookies,
463
475
  responseHeaders: v.responseHeaders
464
476
  };
465
477
  }
466
- let F = I({
467
- helpers: j,
478
+ let N = p({
479
+ helpers: k,
468
480
  page: n.pattern,
469
481
  pathname: a,
470
- renderMode: C,
471
- interactive: P,
472
- loaderData: se,
473
- segmentLoaderData: oe,
474
- pageLoaderRan: typeof b.loader == "function",
475
- ...w ? { ppr: !0 } : {}
482
+ renderMode: x,
483
+ interactive: M,
484
+ loaderData: ue,
485
+ segmentLoaderData: le,
486
+ pageLoaderRan: typeof y.loader == "function",
487
+ ...ae ? { ppr: !0 } : {}
476
488
  });
477
- w && y(F.stateInput, n.pattern);
478
- let ge = {
479
- descriptor: fe,
489
+ ae && b(N.stateInput, n.pattern);
490
+ let ve = {
491
+ descriptor: he,
480
492
  params: r,
481
493
  pathname: a,
482
494
  search: _,
483
- loaderData: F.loaderData,
484
- segmentLoaderData: F.segmentLoaderData,
485
- requestContext: pe,
486
- ...M ? {
487
- outerWrap: M.outerWrap,
488
- locale: M.locale
495
+ loaderData: N.loaderData,
496
+ segmentLoaderData: N.segmentLoaderData,
497
+ requestContext: ge,
498
+ ...A ? {
499
+ outerWrap: A.outerWrap,
500
+ locale: A.locale
489
501
  } : {}
490
- }, _e = (t) => {
491
- if (mt === null || C !== "ssr" && C !== "isr" || typeof b.ogImage != "function" || t.includes("og:image")) return "";
492
- let r = T["x-tenant"], i = mt.signOgUrl({
502
+ }, ye = (t) => {
503
+ if (gt === null || x !== "ssr" && x !== "isr" || typeof y.ogImage != "function" || t.includes("og:image")) return "";
504
+ let r = T["x-tenant"], i = gt.signOgUrl({
493
505
  pattern: n.pattern,
494
506
  params: e.params,
495
507
  ...r === void 0 ? {} : { tenant: r }
496
508
  });
497
509
  return `<meta property="og:image" content="${i}" /><meta name="twitter:image" content="${i}" /><meta name="twitter:card" content="summary_large_image" />`;
498
- }, ve = (e) => [
499
- j.renderMetaToHtml(e) + _e(j.renderMetaToHtml(e)),
500
- `<meta name="voltro-interactive" content="${P}" />`,
501
- ...F.hasDeferred ? [j.renderDeferredRegistryScript()] : [],
502
- j.renderRouterStateScript(F.stateInput)
510
+ }, be = (e) => [
511
+ k.renderMetaToHtml(e) + ye(k.renderMetaToHtml(e)),
512
+ `<meta name="voltro-interactive" content="${M}" />`,
513
+ ...N.hasDeferred ? [k.renderDeferredRegistryScript()] : [],
514
+ k.renderRouterStateScript(N.stateInput)
503
515
  ].filter((e) => e.length > 0).join("\n ");
504
- if (C === "ssr" && P === "full" && e.buffered !== !0) {
505
- let e = d({ shell: l });
516
+ if (x === "ssr" && M === "full" && e.buffered !== !0) {
517
+ let e = f({ shell: d });
506
518
  return {
507
519
  renderMode: "ssr",
508
520
  setCookies: v.setCookies,
509
- stream: (t) => x({
521
+ stream: (t) => oe({
510
522
  res: t,
511
523
  shell: e,
512
- documentAttrs: N,
524
+ documentAttrs: j,
513
525
  headers: {
514
526
  ...v.responseHeaders,
515
527
  "content-type": "text/html; charset=utf-8",
516
528
  "x-voltro-rendered-by": "ssr",
517
- ...p(v.setCookies)
529
+ ...h(v.setCookies)
518
530
  },
519
- headInjection: ve,
520
- render: (e) => j.renderPageToStream({
521
- ...ge,
531
+ headInjection: be,
532
+ ...v.cspNonce === void 0 ? {} : { nonce: v.cspNonce },
533
+ render: (e) => k.renderPageToStream({
534
+ ...ve,
522
535
  ...e,
523
536
  ...v.cspNonce === void 0 ? {} : { nonce: v.cspNonce }
524
537
  }),
525
538
  onShellError: (e) => {
526
- Q.error("ssr shell render failed", { pathname: a }, e), t.writeHead(500, { "content-type": "text/plain; charset=utf-8" }), t.end("server error");
539
+ Z.error("ssr shell render failed", { pathname: a }, e), t.writeHead(500, { "content-type": "text/plain; charset=utf-8" }), t.end("server error");
527
540
  }
528
541
  })
529
542
  };
530
543
  }
531
- let { html: be, meta: xe } = j.renderPageToHtml(ge), Se = ve(xe), R = o(S(l.replace("<div id=\"root\"></div>", `<div id="root">${be}</div>`), Se), N);
532
- P === "none" && (R = lt(R));
533
- let Ce = C === "isr" ? B(b.revalidate) : null;
544
+ let { html: xe, meta: Ce } = k.renderPageToHtml(ve), we = be(Ce), I = o(C(d.replace("<div id=\"root\"></div>", `<div id="root">${xe}</div>`), we), j);
545
+ M === "none" && (I = dt(I));
546
+ let Te = x === "isr" ? R(y.revalidate) : null;
534
547
  return {
535
- html: v.cspNonce === void 0 ? R : O(R, v.cspNonce),
536
- renderMode: C,
537
- revalidateMs: Ce,
548
+ html: v.cspNonce === void 0 ? I : S(I, v.cspNonce),
549
+ renderMode: x,
550
+ revalidateMs: Te,
538
551
  setCookies: v.setCookies,
539
552
  responseHeaders: v.responseHeaders
540
553
  };
541
- }, $ = (e) => e === "" ? "/" : e, gt = async (e) => {
542
- let t = await import(G(e).href);
554
+ }, Q = (e) => e === "" ? "/" : e, bt = async (e) => {
555
+ let t = await import(U(e).href);
543
556
  return {
544
557
  kind: "bundle",
545
558
  getPageMeta: () => t.pageMeta,
@@ -549,18 +562,18 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
549
562
  return typeof r == "function" ? await r() : r;
550
563
  },
551
564
  async getLayout(e) {
552
- let n = t.layouts[$(e)];
553
- if (!n) throw Error(`[voltro start] ssr bundle missing layout for dir ${$(e)}`);
565
+ let n = t.layouts[Q(e)];
566
+ if (!n) throw Error(`[voltro start] ssr bundle missing layout for dir ${Q(e)}`);
554
567
  return typeof n == "function" ? await n() : n;
555
568
  },
556
569
  async getError(e) {
557
- let n = t.errors[$(e)];
558
- if (!n) throw Error(`[voltro start] ssr bundle missing error for dir ${$(e)}`);
570
+ let n = t.errors[Q(e)];
571
+ if (!n) throw Error(`[voltro start] ssr bundle missing error for dir ${Q(e)}`);
559
572
  return typeof n == "function" ? await n() : n;
560
573
  },
561
574
  async getPending(e) {
562
- let n = t.pendings[$(e)];
563
- if (!n) throw Error(`[voltro start] ssr bundle missing pending for dir ${$(e)}`);
575
+ let n = t.pendings[Q(e)];
576
+ if (!n) throw Error(`[voltro start] ssr bundle missing pending for dir ${Q(e)}`);
564
577
  return typeof n == "function" ? await n() : n;
565
578
  },
566
579
  async getHelpers() {
@@ -568,8 +581,8 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
568
581
  },
569
582
  async close() {}
570
583
  };
571
- }, _t = async (e, t) => {
572
- let n = await F("vite", () => import("vite")), r = (await import("@vitejs/plugin-react")).default, i = (await import("@tailwindcss/vite")).default, o = await n.createServer({
584
+ }, xt = async (e, t) => {
585
+ let n = await m("vite", () => import("vite")), r = (await import("@vitejs/plugin-react")).default, i = (await import("@tailwindcss/vite")).default, a = await n.createServer({
573
586
  root: t,
574
587
  envPrefix: "__VOLTRO_VITE_ENV_DISABLED__",
575
588
  plugins: [r(), i()],
@@ -586,203 +599,203 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
586
599
  },
587
600
  appType: "custom",
588
601
  logLevel: "warn"
589
- }), s = U(e, "src", "pages"), c = (e) => e === "" ? s : U(s, e), l = a({
590
- limit: k(),
591
- onColdStart: (e) => Q.debug("ssr cold-compile start", { id: e }),
592
- onColdEnd: (e, { durationMs: t, failed: n }) => Q.debug(`ssr cold-compile ${n ? "FAILED" : "end"} ${t}ms`, {
602
+ }), o = V(e, "src", "pages"), s = (e) => e === "" ? o : V(o, e), c = O({
603
+ limit: g(),
604
+ onColdStart: (e) => Z.debug("ssr cold-compile start", { id: e }),
605
+ onColdEnd: (e, { durationMs: t, failed: n }) => Z.debug(`ssr cold-compile ${n ? "FAILED" : "end"} ${t}ms`, {
593
606
  id: e,
594
607
  ms: t,
595
608
  ...n ? { failed: !0 } : {}
596
609
  })
597
- }), u = (e) => l.load(e, async () => await o.ssrLoadModule(e));
610
+ }), l = (e) => c.load(e, async () => await a.ssrLoadModule(e));
598
611
  return {
599
612
  kind: "middleware",
600
613
  async getPage(e, t) {
601
- return u(U(s, t));
614
+ return l(V(o, t));
602
615
  },
603
616
  async getLayout(e) {
604
- return u(U(c(e), "layout.tsx"));
617
+ return l(V(s(e), "layout.tsx"));
605
618
  },
606
619
  async getError(e) {
607
- return u(U(c(e), "error.tsx"));
620
+ return l(V(s(e), "error.tsx"));
608
621
  },
609
622
  async getPending(e) {
610
- return u(U(c(e), "loading.tsx"));
623
+ return l(V(s(e), "loading.tsx"));
611
624
  },
612
625
  async getHelpers() {
613
- return await u("@voltro/web/ssr");
626
+ return await l("@voltro/web/ssr");
614
627
  },
615
628
  async close() {
616
- await o.close();
629
+ await a.close();
617
630
  }
618
631
  };
619
- }, vt = async (t) => {
620
- let i = Be(), a = await N(t);
621
- if (!a) return {
632
+ }, $ = async (t) => {
633
+ let i = Ue(), o = await ve(t);
634
+ if (!o) return {
622
635
  ran: !1,
623
636
  exitCode: 0
624
637
  };
625
- if (a.type !== "web") return Q.error("only web apps are supported by `voltro start`"), {
638
+ if (o.type !== "web") return Z.error("only web apps are supported by `voltro start`"), {
626
639
  ran: !0,
627
640
  exitCode: 1
628
641
  };
629
642
  {
630
- let e = v(a);
631
- if (e !== void 0) return Q.error(`voltro start: refusing to boot — ${e}`), {
643
+ let e = y(o);
644
+ if (e !== void 0) return Z.error(`voltro start: refusing to boot — ${e}`), {
632
645
  ran: !0,
633
646
  exitCode: 1
634
647
  };
635
648
  }
636
- let { resolved: o } = await w({
637
- rawEnv: a.env,
649
+ let { resolved: c } = await ae({
650
+ rawEnv: o.env,
638
651
  appType: "web",
639
652
  root: t,
640
- log: Q,
653
+ log: Z,
641
654
  generateTypes: !1
642
- }), c = o.publicValues;
655
+ }), l = c.publicValues;
643
656
  i.mark("config");
644
- let d = ge();
645
- ne(d), Q.info("booting voltro start", { app: a.name ?? "(unnamed)" });
646
- let p = n({
657
+ let f = ce();
658
+ E(f), Z.info("booting voltro start", { app: o.name ?? "(unnamed)" });
659
+ let te = n({
647
660
  kind: "web",
648
- configPort: a.port,
661
+ configPort: o.port,
649
662
  env: process.env,
650
- dashboardPin: process.env[C] === "1"
663
+ dashboardPin: process.env[T] === "1"
651
664
  });
652
- for (let e of p.warnings) Q.warn(e);
653
- let h = p.port, y = U(t, ".framework"), x = U(y, "dist"), S = U(x, "index.html");
654
- if (!await ut(S)) return Q.error("no built dist found — run `voltro build` first", { distDir: x }), {
665
+ for (let e of te.warnings) Z.warn(e);
666
+ let p = te.port, m = V(t, ".framework"), h = V(m, "dist"), g = V(h, "index.html");
667
+ if (!await ft(g)) return Z.error("no built dist found — run `voltro build` first", { distDir: h }), {
655
668
  ran: !0,
656
669
  exitCode: 1
657
670
  };
658
- let E = a.name ?? "unnamed", O = Re("web", E, h), k = ze(E);
659
- await Fe({
660
- id: O,
661
- name: E,
671
+ let b = o.name ?? "unnamed", S = Ve("web", b, p), C = He(b);
672
+ await Re({
673
+ id: S,
674
+ name: b,
662
675
  kind: "web",
663
- url: `http://localhost:${h}`,
676
+ url: `http://localhost:${p}`,
664
677
  pid: process.pid,
665
678
  status: "booting",
666
- logFile: k.path
679
+ logFile: C.path
667
680
  }).catch(() => {});
668
- let ce = U(x, "_voltro", "shell.html"), A = await ut(ce) ? await W.readFile(ce, "utf8") : await W.readFile(S, "utf8"), F = await de(t, a), he = De(a), I = fe(F[0]), L = F[0]?.name, ye = /* @__PURE__ */ new Set(), z = (e) => {
669
- ye.has(e.name) || (ye.add(e.name), Q.warn(`middleware.ts wrote the cookie "${e.name}" with the HttpOnly default — a browser SDK cannot read it`, {
681
+ let oe = V(h, "_voltro", "shell.html"), w = await ft(oe) ? await H.readFile(oe, "utf8") : await H.readFile(g, "utf8"), O = await ge(t, o), pe = Ae(o), P = j(O[0]), F = O[0]?.name, Se = /* @__PURE__ */ new Set(), L = (e) => {
682
+ Se.has(e.name) || (Se.add(e.name), Z.warn(`middleware.ts wrote the cookie "${e.name}" with the HttpOnly default — a browser SDK cannot read it`, {
670
683
  cookie: e.name,
671
684
  hint: "If your IdP client reads this from `document.cookie` (Supabase's `createBrowserClient` does), pass `httpOnly: false`. Otherwise the SSR render succeeds and the user is signed out at the first client-side call. Set `httpOnly: true` explicitly to silence this."
672
685
  }));
673
- }, B = await m(t);
674
- B.length > 0 && Q.info(`middleware.ts loaded — ${B.length} middleware(s): ` + B.map((e) => e.exportName).join(", "));
675
- let V, H = null, Ve = process.env.SSR_CACHE === "postgres";
676
- if (Ve && xe()) H = new (await (import("pg"))).default.Client(be()), await H.connect(), V = tt({ client: H }), Q.info("isr cache backend: postgres", { table: "voltro_isr_cache" });
677
- else if (Ve) {
686
+ }, R = await re(t);
687
+ R.length > 0 && Z.info(`middleware.ts loaded — ${R.length} middleware(s): ` + R.map((e) => e.exportName).join(", "));
688
+ let z, B = null, We = process.env.SSR_CACHE === "postgres";
689
+ if (We && we()) B = new (await (import("pg"))).default.Client(Ce()), await B.connect(), z = rt({ client: B }), Z.info("isr cache backend: postgres", { table: "voltro_isr_cache" });
690
+ else if (We) {
678
691
  let t = "SSR_CACHE=postgres, but nothing in the environment names a database (looked for DB_URL, DB_PRIMARY_URL, DB_DIRECT_URL, DB_MIGRATE_URL, DB_HOST, PG_HOST).";
679
- if (e()) throw Q.fatal(`${t} Refusing to fall back to the per-process memory cache: it is not shared between instances and does not survive a restart, so the pages this process serves would differ from its replicas' with nothing to indicate it.`), Error("[voltro start] SSR_CACHE=postgres with no database configured");
680
- V = Me(), Q.warn(`${t} Falling back to the per-process memory cache — this would be a hard failure in production.`);
681
- } else V = Me(), Q.info("isr cache backend: memory (per-process)", { hint: "set SSR_CACHE=postgres for persistent storage" });
682
- await s(t, a, F, c);
683
- let He = U(t, "src", "pages"), { pages: G, dirs: K } = await ve(He), q = ft(G);
684
- se(B, q.map((e) => e.pattern)), i.mark("scan");
685
- let J = U(x, "server", "ssrEntry.js"), Je = await ut(J);
686
- if (!Je && process.env.NODE_ENV === "production") throw Q.fatal(`production \`voltro start\` requires a precompiled SSR bundle at ${J} but it is missing. Run \`voltro build\` before serving — production renders from the bundle and never compiles on demand.`), Error(`[voltro start] missing SSR bundle at ${J}`);
687
- let Y = Je ? await gt(J) : await _t(t, y);
688
- Q.info(`ssr loader: ${Y.kind}`, {
689
- kind: Y.kind,
690
- ...Y.kind === "middleware" ? { hint: "no pre-built SSR bundle found; run `voltro build` to enable bundle mode" } : {}
692
+ if (e()) throw Z.fatal(`${t} Refusing to fall back to the per-process memory cache: it is not shared between instances and does not survive a restart, so the pages this process serves would differ from its replicas' with nothing to indicate it.`), Error("[voltro start] SSR_CACHE=postgres with no database configured");
693
+ z = Fe(), Z.warn(`${t} Falling back to the per-process memory cache — this would be a hard failure in production.`);
694
+ } else z = Fe(), Z.info("isr cache backend: memory (per-process)", { hint: "set SSR_CACHE=postgres for persistent storage" });
695
+ await s(t, o, O, l);
696
+ let Ge = V(t, "src", "pages"), { pages: U, dirs: W } = await xe(Ge), G = mt(U);
697
+ fe(R, G.map((e) => e.pattern)), i.mark("scan");
698
+ let K = V(h, "server", "ssrEntry.js"), Ze = await ft(K);
699
+ if (!Ze && process.env.NODE_ENV === "production") throw Z.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}`);
700
+ let q = Ze ? await bt(K) : await xt(t, m);
701
+ Z.info(`ssr loader: ${q.kind}`, {
702
+ kind: q.kind,
703
+ ...q.kind === "middleware" ? { hint: "no pre-built SSR bundle found; run `voltro build` to enable bundle mode" } : {}
691
704
  }), i.mark("provider");
692
- let Ze = Y.getPageMeta?.();
693
- re(t);
694
- let X = /* @__PURE__ */ new Map(), $e = 0;
695
- for (let e of G) {
696
- let t = Ze?.[e.pattern];
705
+ let et = q.getPageMeta?.();
706
+ D(t);
707
+ let J = /* @__PURE__ */ new Map(), nt = 0;
708
+ for (let e of U) {
709
+ let t = et?.[e.pattern];
697
710
  if (t) {
698
- X.set(e.pattern, t);
711
+ J.set(e.pattern, t);
699
712
  continue;
700
713
  }
701
714
  try {
702
- let t = await Y.getPage(e.pattern, e.file);
703
- X.set(e.pattern, Ae(t, e.file)), $e++;
715
+ let t = await q.getPage(e.pattern, e.file);
716
+ J.set(e.pattern, Ne(t, e.file)), nt++;
704
717
  } catch (t) {
705
- Q.warn("failed to load page metadata", { pattern: e.pattern }, t);
718
+ Z.warn("failed to load page metadata", { pattern: e.pattern }, t);
706
719
  }
707
720
  }
708
- let et = /* @__PURE__ */ new Map();
709
- for (let [e, t] of X) {
721
+ let Y = /* @__PURE__ */ new Map();
722
+ for (let [e, t] of J) {
710
723
  if (t.interactive !== "islands") continue;
711
- let n = U(x, "island-shells", `${b(e)}.html`);
724
+ let n = V(h, "island-shells", `${x(e)}.html`);
712
725
  try {
713
- et.set(e, await W.readFile(n, "utf8"));
726
+ Y.set(e, await H.readFile(n, "utf8"));
714
727
  } catch {
715
- Q.warn("islands page has no built per-page shell — serving the full app shell", {
728
+ Z.warn("islands page has no built per-page shell — serving the full app shell", {
716
729
  pattern: e,
717
730
  expected: n
718
731
  });
719
732
  }
720
733
  }
721
- Q.info(`registered ${X.size} route(s)`, {
722
- count: X.size,
723
- fromManifest: X.size - $e,
724
- fromModules: $e
734
+ Z.info(`registered ${J.size} route(s)`, {
735
+ count: J.size,
736
+ fromManifest: J.size - nt,
737
+ fromModules: nt
725
738
  }), i.mark("routes");
726
- let Z = /* @__PURE__ */ new Set();
727
- for (let e of q) X.get(e.pattern)?.renderMode === "spa" && ue(K, e.dirChain).some((e) => e.hasLayout) && Z.add(e.pattern);
728
- Z.size > 0 && Q.info(`${Z.size} spa route(s) render an SSR layout shell`, { patterns: [...Z] });
729
- let at = /* @__PURE__ */ new Map();
730
- for (let [e, t] of X) t.cacheInvalidatesOn.length > 0 && at.set(e, t.cacheInvalidatesOn);
731
- let ot = /* @__PURE__ */ new Map();
732
- for (let e of q) ot.set(e.pattern, e.regex);
739
+ let X = /* @__PURE__ */ new Set();
740
+ for (let e of G) J.get(e.pattern)?.renderMode === "spa" && me(W, e.dirChain).some((e) => e.hasLayout) && X.add(e.pattern);
741
+ X.size > 0 && Z.info(`${X.size} spa route(s) render an SSR layout shell`, { patterns: [...X] });
742
+ let st = /* @__PURE__ */ new Map();
743
+ for (let [e, t] of J) t.cacheInvalidatesOn.length > 0 && st.set(e, t.cacheInvalidatesOn);
744
+ let ct = /* @__PURE__ */ new Map();
745
+ for (let e of G) ct.set(e.pattern, e.regex);
733
746
  {
734
- let n = new Set([...X].filter(([, e]) => (e.renderMode === "ssr" || e.renderMode === "isr") && e.hasOgImage).map(([e]) => e));
747
+ let n = new Set([...J].filter(([, e]) => (e.renderMode === "ssr" || e.renderMode === "isr") && e.hasOgImage).map(([e]) => e));
735
748
  if (n.size > 0) {
736
- let { secret: r, fromEnv: i } = ae();
737
- if (!i && e()) throw Q.fatal(`${n.size} ssr route(s) export ogImage, but VOLTRO_OG_SECRET is unset. Behind a load balancer the signing replica and the fetching replica differ, so a per-boot secret would 403 every cross-replica image fetch. Set VOLTRO_OG_SECRET (any long random value, same on every replica).`), Error("[voltro start] ssr ogImage routes need VOLTRO_OG_SECRET in a deploy environment");
738
- let o = new Map(G.map((e) => [e.pattern, e.file]));
739
- mt = j({
749
+ let { secret: r, fromEnv: i } = ue();
750
+ if (!i && e()) throw Z.fatal(`${n.size} ssr route(s) export ogImage, but VOLTRO_OG_SECRET is unset. Behind a load balancer the signing replica and the fetching replica differ, so a per-boot secret would 403 every cross-replica image fetch. Set VOLTRO_OG_SECRET (any long random value, same on every replica).`), Error("[voltro start] ssr ogImage routes need VOLTRO_OG_SECRET in a deploy environment");
751
+ let a = new Map(U.map((e) => [e.pattern, e.file]));
752
+ gt = A({
740
753
  root: t,
741
- fonts: a.fonts,
742
- cache: V,
754
+ fonts: o.fonts,
755
+ cache: z,
743
756
  secret: r,
744
757
  isOgSsrRoute: (e) => n.has(e),
745
758
  getPageModule: async (e) => {
746
- let t = o.get(e);
747
- return t === void 0 ? null : await Y.getPage(e, t);
759
+ let t = a.get(e);
760
+ return t === void 0 ? null : await q.getPage(e, t);
748
761
  }
749
- }), Q.info(`og route active for ${n.size} ssr route(s)`, { secret: i ? "env" : "per-boot" });
762
+ }), Z.info(`og route active for ${n.size} ssr route(s)`, { secret: i ? "env" : "per-boot" });
750
763
  }
751
764
  }
752
- let st = /* @__PURE__ */ new Map();
753
- for (let [e, t] of X) st.set(e, t.renderMode);
754
- let lt = [...X.values()].some((e) => e.renderMode === "isr"), dt = {
755
- cache: V,
756
- tableSink: Xe({
757
- cache: V,
758
- tableSubscriptionsByPattern: at,
759
- regexByPattern: ot
765
+ let lt = /* @__PURE__ */ new Map();
766
+ for (let [e, t] of J) lt.set(e, t.renderMode);
767
+ let dt = [...J.values()].some((e) => e.renderMode === "isr"), pt = {
768
+ cache: z,
769
+ tableSink: $e({
770
+ cache: z,
771
+ tableSubscriptionsByPattern: st,
772
+ regexByPattern: ct
760
773
  }),
761
- regexByPattern: ot,
762
- renderModeByPattern: st
763
- }, $ = (e) => {
764
- let t = nt(e);
765
- t && rt(dt, t);
766
- }, vt = Qe({
767
- cache: V,
768
- tableSubscriptionsByPattern: at,
769
- regexByPattern: ot,
770
- ...lt ? { onRevalidate: $ } : {}
771
- }), yt = await vt.start(), bt = null, xt = null;
772
- if (lt) {
773
- let e = Ke({}, process.env);
774
+ regexByPattern: ct,
775
+ renderModeByPattern: lt
776
+ }, _t = (e) => {
777
+ let t = it(e);
778
+ t && at(pt, t);
779
+ }, vt = tt({
780
+ cache: z,
781
+ tableSubscriptionsByPattern: st,
782
+ regexByPattern: ct,
783
+ ...dt ? { onRevalidate: _t } : {}
784
+ }), Q = await vt.start(), $ = null, St = null;
785
+ if (dt) {
786
+ let e = Ye({}, process.env);
774
787
  if (e.crossReplica) try {
775
- xt = e.provider;
776
- let t = Oe(process.env);
777
- bt = await We.runPromise(e.provider.subscribe(t, $)), Q.info(`revalidation subscriber: broker (${e.provider.name})`, { channel: t });
788
+ St = e.provider;
789
+ let t = je(process.env);
790
+ $ = await qe.runPromise(e.provider.subscribe(t, _t)), Z.info(`revalidation subscriber: broker (${e.provider.name})`, { channel: t });
778
791
  } catch (e) {
779
- Q.warn("revalidation broker subscribe failed — broker leg disabled", {}, e), xt = null;
792
+ Z.warn("revalidation broker subscribe failed — broker leg disabled", {}, e), St = null;
780
793
  }
781
- yt && bt === null && Q.info("revalidation subscriber: postgres LISTEN (voltro_revalidate)"), !yt && bt === null && Q.warn("isr routes exist, but this web process has NO revalidation transport: no database is configured for the LISTEN line and no broker is configured. `revalidatePath` / `revalidateTable` / `revalidateTag` from the api will not reach this process — cached pages stay until their own `revalidate` window expires. Set DB_URL (postgres) or BROADCAST_URL (redis:// or nats://) on BOTH the api and this web deployment.");
794
+ Q && $ === null && Z.info("revalidation subscriber: postgres LISTEN (voltro_revalidate)"), !Q && $ === null && Z.warn("isr routes exist, but this web process has NO revalidation transport: no database is configured for the LISTEN line and no broker is configured. `revalidatePath` / `revalidateTable` / `revalidateTag` from the api will not reach this process — cached pages stay until their own `revalidate` window expires. Set DB_URL (postgres) or BROADCAST_URL (redis:// or nats://) on BOTH the api and this web deployment.");
782
795
  }
783
796
  i.mark("cdc");
784
- let St = ke(), Ct = G.map((e) => {
785
- let t = X.get(e.pattern);
797
+ let Ct = Me(), wt = U.map((e) => {
798
+ let t = J.get(e.pattern);
786
799
  return {
787
800
  pattern: e.pattern,
788
801
  file: e.file,
@@ -797,20 +810,20 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
797
810
  hasMeta: t?.hasMeta ?? !1,
798
811
  hasGetStaticPaths: t?.hasGetStaticPaths ?? !1
799
812
  };
800
- }), wt = K.map((e) => ({
813
+ }), Tt = W.map((e) => ({
801
814
  dir: e.dir,
802
815
  hasLayout: e.hasLayout,
803
816
  hasError: e.hasError,
804
817
  hasPending: e.hasPending,
805
818
  hasNotFound: e.hasNotFound
806
- })), Tt = H ? "postgres" : "memory", Et = {
819
+ })), Et = B ? "postgres" : "memory", Dt = {
807
820
  kind: "web",
808
821
  meta: {
809
- name: a.name ?? "(unnamed)",
810
- voltroVersion: it,
811
- port: h,
822
+ name: o.name ?? "(unnamed)",
823
+ voltroVersion: ot,
824
+ port: p,
812
825
  mode: "start",
813
- apis: Object.entries(a.apis ?? {}).map(([e, t]) => {
826
+ apis: Object.entries(o.apis ?? {}).map(([e, t]) => {
814
827
  let n = {
815
828
  name: e,
816
829
  package: t.package
@@ -818,10 +831,10 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
818
831
  return t.url !== void 0 && (n.url = t.url), n;
819
832
  })
820
833
  },
821
- routes: Ct,
822
- dirs: wt,
834
+ routes: wt,
835
+ dirs: Tt,
823
836
  cache: () => {
824
- let e = Date.now(), t = V.snapshot().map(([t, n]) => ({
837
+ let e = Date.now(), t = z.snapshot().map(([t, n]) => ({
825
838
  key: t,
826
839
  renderedAt: n.renderedAt,
827
840
  expiresAt: n.expiresAt,
@@ -832,16 +845,16 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
832
845
  staleWhileRevalidateMs: n.staleWhileRevalidateMs
833
846
  }));
834
847
  return {
835
- backend: Tt,
836
- size: V.size(),
848
+ backend: Et,
849
+ size: z.size(),
837
850
  entries: t
838
851
  };
839
852
  },
840
- metrics: () => Ge()
841
- }, Dt = async (e, n) => {
842
- let i = e.split("?")[0] ?? "/";
843
- if (a.name === "voltroDashboard" && i === "/api/dashboard/registry") try {
844
- let e = await Ie();
853
+ metrics: () => Je()
854
+ }, Ot = async (e, n) => {
855
+ let r = e.split("?")[0] ?? "/";
856
+ if (o.name === "voltroDashboard" && r === "/api/dashboard/registry") try {
857
+ let e = await ze();
845
858
  return {
846
859
  status: 200,
847
860
  headers: { "content-type": "application/json; charset=utf-8" },
@@ -854,7 +867,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
854
867
  body: `registry read error: ${e.message}`
855
868
  };
856
869
  }
857
- if (a.name === "voltroDashboard" && i === "/api/dashboard/config") {
870
+ if (o.name === "voltroDashboard" && r === "/api/dashboard/config") {
858
871
  let e = process.env.VOLTRO_DASHBOARD_APPS, t = [];
859
872
  if (e && e.trim().length > 0) {
860
873
  let n;
@@ -883,27 +896,27 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
883
896
  body: JSON.stringify({ apps: t })
884
897
  };
885
898
  }
886
- if (mt !== null && i === "/_voltro/og") {
887
- let t = await mt.handle(new URL(e, "http://localhost"));
899
+ if (gt !== null && r === "/_voltro/og") {
900
+ let t = await gt.handle(new URL(e, "http://localhost"));
888
901
  if (t !== null) return {
889
902
  status: t.status,
890
903
  headers: { ...t.headers },
891
904
  body: Buffer.from(t.body)
892
905
  };
893
906
  }
894
- if (i === "/_voltro/inspect/logs") {
895
- let t = T(e, r(), n);
907
+ if (r === "/_voltro/inspect/logs") {
908
+ let t = M(e, N(), n);
896
909
  return {
897
910
  status: t.status,
898
911
  headers: {
899
912
  "content-type": t.contentType,
900
- ...R(n.origin)
913
+ ...Te(n.origin)
901
914
  },
902
915
  body: t.body
903
916
  };
904
917
  }
905
- if (i !== "/_voltro/inspect/stream") {
906
- let t = we(e, Et, n);
918
+ if (r !== "/_voltro/inspect/stream") {
919
+ let t = De(e, Dt, n);
907
920
  if (t !== null) return {
908
921
  status: t.status,
909
922
  headers: {
@@ -913,227 +926,227 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
913
926
  body: t.body
914
927
  };
915
928
  }
916
- let o = pt(i, q), s = o ? X.get(o.route.pattern)?.renderMode : void 0, c = s === "ssr" || s === "isr" || (o ? Z.has(o.route.pattern) : !1), f = [];
917
- if (!c && B.length > 0) {
918
- let t = te(B, {
929
+ let i = ht(r, G), a = i ? J.get(i.route.pattern)?.renderMode : void 0, s = a === "ssr" || a === "isr" || (i ? X.has(i.route.pattern) : !1), c = [];
930
+ if (!s && R.length > 0) {
931
+ let t = ne(R, {
919
932
  route: void 0,
920
- pathname: i
933
+ pathname: r
921
934
  });
922
935
  if (t !== void 0) {
923
- let r = await ee(t, {
924
- pathname: i,
925
- search: e.slice(i.length),
936
+ let i = await ee(t, {
937
+ pathname: r,
938
+ search: e.slice(r.length),
926
939
  headers: n,
927
940
  cookies: u(n.cookie),
928
941
  route: void 0
929
942
  });
930
- f.push(...r.setCookies);
943
+ c.push(...i.setCookies);
931
944
  }
932
945
  }
933
- let p = (e) => f.length === 0 ? e : {
946
+ let l = (e) => c.length === 0 ? e : {
934
947
  ...e,
935
- "set-cookie": f.map(_)
936
- }, m = i === "/" ? U(x, "index.html") : U(x, i.replace(/^\//, ""), "index.html");
937
- if (!c && await ut(m)) {
938
- let e = await W.readFile(m);
948
+ "set-cookie": c.map(v)
949
+ }, te = r === "/" ? V(h, "index.html") : V(h, r.replace(/^\//, ""), "index.html");
950
+ if (!s && await ft(te)) {
951
+ let e = await H.readFile(te);
939
952
  return {
940
953
  status: 200,
941
- headers: p({ "content-type": "text/html; charset=utf-8" }),
954
+ headers: l({ "content-type": "text/html; charset=utf-8" }),
942
955
  body: e
943
956
  };
944
957
  }
945
- if (/\.[a-z0-9]+$/i.test(i)) {
946
- let e = U(x, i.replace(/^\//, ""));
947
- if (await ut(e)) {
948
- let t = await W.readFile(e);
958
+ if (/\.[a-z0-9]+$/i.test(r)) {
959
+ let e = V(h, r.replace(/^\//, ""));
960
+ if (await ft(e)) {
961
+ let t = await H.readFile(e);
949
962
  return {
950
963
  status: 200,
951
- headers: p({ "content-type": ct(e) }),
964
+ headers: l({ "content-type": ut(e) }),
952
965
  body: t
953
966
  };
954
967
  }
955
968
  }
956
- let h = pt(i, q);
957
- if (!h) {
958
- let r = oe(K, i);
959
- if (r !== void 0) try {
960
- let a = await ht({
961
- provider: Y,
969
+ let p = ht(r, G);
970
+ if (!p) {
971
+ let i = de(W, r);
972
+ if (i !== void 0) try {
973
+ let a = await yt({
974
+ provider: q,
962
975
  root: t,
963
976
  route: {
964
977
  pattern: "<not-found>",
965
- file: r.dir === "" ? "not-found.tsx" : `${r.dir}/not-found.tsx`,
966
- dirChain: r.chain,
978
+ file: i.dir === "" ? "not-found.tsx" : `${i.dir}/not-found.tsx`,
979
+ dirChain: i.chain,
967
980
  regex: /^$/,
968
981
  paramNames: [],
969
982
  priority: 2 ** 53 - 1
970
983
  },
971
984
  params: {},
972
- pathname: i,
973
- dirs: K,
974
- shellTemplate: A,
985
+ pathname: r,
986
+ dirs: W,
987
+ shellTemplate: w,
975
988
  requestHeaders: n,
976
- apiOrigin: I,
977
- apiName: L,
978
- middlewares: B,
979
- onCookieWarning: z,
989
+ apiOrigin: P,
990
+ apiName: F,
991
+ middlewares: R,
992
+ onCookieWarning: L,
980
993
  requestUrl: e,
981
994
  buffered: !0,
982
995
  forceSsrRender: !0
983
996
  });
984
997
  if (a && "html" in a && typeof a.html == "string") return {
985
998
  status: 404,
986
- headers: p({
999
+ headers: l({
987
1000
  "content-type": "text/html; charset=utf-8",
988
1001
  "x-voltro-rendered-by": "ssr-not-found"
989
1002
  }),
990
1003
  body: a.html
991
1004
  };
992
1005
  } catch (e) {
993
- Q.warn("not-found.tsx failed to render — serving the plain 404", { pathname: i }, e instanceof Error ? e : Error(String(e)));
1006
+ Z.warn("not-found.tsx failed to render — serving the plain 404", { pathname: r }, e instanceof Error ? e : Error(String(e)));
994
1007
  }
995
1008
  return {
996
1009
  status: 404,
997
- headers: p({
1010
+ headers: l({
998
1011
  "content-type": "text/plain",
999
1012
  "x-voltro-rendered-by": "plain-not-found"
1000
1013
  }),
1001
1014
  body: "not found"
1002
1015
  };
1003
1016
  }
1004
- let g = X.get(h.route.pattern), ne = n["x-tenant"] ?? "anonymous", v = (await Y.getHelpers()).i18n?.resolve(n.cookie, n["accept-language"])?.locale, y = Ne(i, {
1005
- ...g?.tenantAware ? { tenant: ne } : {},
1006
- ...v ? { locale: v } : {}
1007
- }), b = g?.ppr === !0 && g.renderMode === "isr", S = (r, a) => ({
1017
+ let m = J.get(p.route.pattern), g = n["x-tenant"] ?? "anonymous", re = (await q.getHelpers()).i18n?.resolve(n.cookie, n["accept-language"])?.locale, _ = Ie(r, {
1018
+ ...m?.tenantAware ? { tenant: g } : {},
1019
+ ...re ? { locale: re } : {}
1020
+ }), y = m?.ppr === !0 && m.renderMode === "isr", b = (i, a) => ({
1008
1021
  status: 200,
1009
1022
  headers: {},
1010
1023
  body: "",
1011
1024
  stream: (o) => {
1012
- l().shellServes += 1, o.writeHead(200, {
1025
+ ie(p.route.pattern), o.writeHead(200, {
1013
1026
  "content-type": "text/html; charset=utf-8",
1014
1027
  "x-voltro-rendered-by": "isr",
1015
1028
  "x-voltro-ppr": "shell+holes",
1016
1029
  ...a
1017
- }), o.write(r), (async () => {
1030
+ }), o.write(i), (async () => {
1018
1031
  try {
1019
- let r = await ht({
1020
- provider: Y,
1032
+ let i = await yt({
1033
+ provider: q,
1021
1034
  root: t,
1022
- route: h.route,
1023
- params: h.params,
1024
- pathname: i,
1025
- dirs: K,
1026
- shellTemplate: et.get(h.route.pattern) ?? A,
1035
+ route: p.route,
1036
+ params: p.params,
1037
+ pathname: r,
1038
+ dirs: W,
1039
+ shellTemplate: Y.get(p.route.pattern) ?? w,
1027
1040
  requestHeaders: n,
1028
- apiOrigin: I,
1029
- apiName: L,
1030
- middlewares: B,
1031
- onCookieWarning: z,
1041
+ apiOrigin: P,
1042
+ apiName: F,
1043
+ middlewares: R,
1044
+ onCookieWarning: L,
1032
1045
  requestUrl: e,
1033
1046
  holesOnly: !0
1034
1047
  });
1035
- r !== null && "holes" in r ? await _e({
1036
- loader: r.holes.loader,
1037
- ctx: r.holes.ctx,
1048
+ i !== null && "holes" in i ? await be({
1049
+ loader: i.holes.loader,
1050
+ ctx: i.holes.ctx,
1038
1051
  res: o,
1039
- helpers: r.holes.helpers,
1040
- page: r.holes.page,
1041
- log: Q
1052
+ helpers: i.holes.helpers,
1053
+ page: i.holes.page,
1054
+ log: Z
1042
1055
  }) : o.writableEnded || o.end();
1043
1056
  } catch (e) {
1044
- Q.warn("ppr hole pass failed", { url: i }, e), o.writableEnded || o.end();
1057
+ Z.warn("ppr hole pass failed", { url: r }, e), o.writableEnded || o.end();
1045
1058
  }
1046
1059
  })();
1047
1060
  }
1048
- }), C = V.get(y), w = Date.now();
1049
- if (C && Pe(C, w)) return d.emit("cache", {
1061
+ }), x = z.get(_), S = Date.now();
1062
+ if (x && Le(x, S)) return f.emit("cache", {
1050
1063
  kind: "HIT",
1051
- key: y,
1052
- ageMs: w - C.renderedAt
1053
- }), b ? S(C.html, {
1064
+ key: _,
1065
+ ageMs: S - x.renderedAt
1066
+ }), y ? b(x.html, {
1054
1067
  "x-voltro-cache": "HIT",
1055
- "x-voltro-cache-key": y,
1056
- "x-voltro-cache-age-ms": String(w - C.renderedAt)
1068
+ "x-voltro-cache-key": _,
1069
+ "x-voltro-cache-age-ms": String(S - x.renderedAt)
1057
1070
  }) : {
1058
1071
  status: 200,
1059
1072
  headers: {
1060
1073
  "content-type": "text/html; charset=utf-8",
1061
1074
  "x-voltro-rendered-by": "isr",
1062
1075
  "x-voltro-cache": "HIT",
1063
- "x-voltro-cache-key": y,
1064
- "x-voltro-cache-age-ms": String(w - C.renderedAt)
1076
+ "x-voltro-cache-key": _,
1077
+ "x-voltro-cache-age-ms": String(S - x.renderedAt)
1065
1078
  },
1066
- body: C.html
1079
+ body: x.html
1067
1080
  };
1068
- if (C && je(C, w)) {
1069
- d.emit("cache", {
1081
+ if (x && Pe(x, S)) {
1082
+ f.emit("cache", {
1070
1083
  kind: "STALE",
1071
- key: y,
1072
- ageMs: w - C.renderedAt
1084
+ key: _,
1085
+ ageMs: S - x.renderedAt
1073
1086
  });
1074
- let r = V.generation(y);
1087
+ let i = z.generation(_);
1075
1088
  return (async () => {
1076
1089
  try {
1077
- let a = await ht({
1078
- provider: Y,
1090
+ let a = await yt({
1091
+ provider: q,
1079
1092
  root: t,
1080
- route: h.route,
1081
- params: h.params,
1082
- pathname: i,
1083
- dirs: K,
1084
- shellTemplate: et.get(h.route.pattern) ?? A,
1093
+ route: p.route,
1094
+ params: p.params,
1095
+ pathname: r,
1096
+ dirs: W,
1097
+ shellTemplate: Y.get(p.route.pattern) ?? w,
1085
1098
  requestHeaders: n,
1086
- apiOrigin: I,
1087
- apiName: L,
1088
- middlewares: B,
1089
- onCookieWarning: z,
1099
+ apiOrigin: P,
1100
+ apiName: F,
1101
+ middlewares: R,
1102
+ onCookieWarning: L,
1090
1103
  requestUrl: e,
1091
1104
  buffered: !0
1092
1105
  });
1093
1106
  if (a && "html" in a && a.renderMode === "isr" && a.revalidateMs !== null) {
1094
- let e = X.get(h.route.pattern)?.staleWhileRevalidateMs ?? 0, t = Date.now();
1095
- V.set(y, {
1107
+ let e = J.get(p.route.pattern)?.staleWhileRevalidateMs ?? 0, t = Date.now();
1108
+ z.set(_, {
1096
1109
  html: a.html,
1097
1110
  renderedAt: t,
1098
1111
  expiresAt: t + a.revalidateMs,
1099
1112
  servableUntil: t + a.revalidateMs + e,
1100
1113
  revalidateMs: a.revalidateMs,
1101
1114
  staleWhileRevalidateMs: e
1102
- }, { ifGeneration: r }) || Q.info("SWR refresh discarded — the entry was purged while it rendered", { key: y });
1115
+ }, { ifGeneration: i }) || Z.info("SWR refresh discarded — the entry was purged while it rendered", { key: _ });
1103
1116
  }
1104
1117
  } catch (e) {
1105
- Q.warn("background SWR refresh failed", { url: i }, e);
1118
+ Z.warn("background SWR refresh failed", { url: r }, e);
1106
1119
  }
1107
- })(), b ? S(C.html, {
1120
+ })(), y ? b(x.html, {
1108
1121
  "x-voltro-cache": "STALE",
1109
- "x-voltro-cache-key": y,
1110
- "x-voltro-cache-age-ms": String(w - C.renderedAt)
1122
+ "x-voltro-cache-key": _,
1123
+ "x-voltro-cache-age-ms": String(S - x.renderedAt)
1111
1124
  }) : {
1112
1125
  status: 200,
1113
1126
  headers: {
1114
1127
  "content-type": "text/html; charset=utf-8",
1115
1128
  "x-voltro-rendered-by": "isr",
1116
1129
  "x-voltro-cache": "STALE",
1117
- "x-voltro-cache-key": y,
1118
- "x-voltro-cache-age-ms": String(w - C.renderedAt)
1130
+ "x-voltro-cache-key": _,
1131
+ "x-voltro-cache-age-ms": String(S - x.renderedAt)
1119
1132
  },
1120
- body: C.html
1133
+ body: x.html
1121
1134
  };
1122
1135
  }
1123
1136
  try {
1124
- let r = V.generation(y), a = await ht({
1125
- provider: Y,
1137
+ let i = z.generation(_), a = await yt({
1138
+ provider: q,
1126
1139
  root: t,
1127
- route: h.route,
1128
- params: h.params,
1129
- pathname: i,
1130
- dirs: K,
1131
- shellTemplate: et.get(h.route.pattern) ?? A,
1140
+ route: p.route,
1141
+ params: p.params,
1142
+ pathname: r,
1143
+ dirs: W,
1144
+ shellTemplate: Y.get(p.route.pattern) ?? w,
1132
1145
  requestHeaders: n,
1133
- apiOrigin: I,
1134
- apiName: L,
1135
- middlewares: B,
1136
- onCookieWarning: z,
1146
+ apiOrigin: P,
1147
+ apiName: F,
1148
+ middlewares: R,
1149
+ onCookieWarning: L,
1137
1150
  requestUrl: e
1138
1151
  });
1139
1152
  if (!a) return {
@@ -1142,12 +1155,12 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
1142
1155
  "content-type": "text/html; charset=utf-8",
1143
1156
  "x-voltro-rendered-by": "spa-fallback"
1144
1157
  },
1145
- body: A
1158
+ body: w
1146
1159
  };
1147
1160
  let o = a.setCookies ?? [], s = a.responseHeaders ?? {}, c = (e) => ({
1148
1161
  ...s,
1149
1162
  ...e,
1150
- ...o.length === 0 ? {} : { "set-cookie": o.map(_) }
1163
+ ...o.length === 0 ? {} : { "set-cookie": o.map(v) }
1151
1164
  });
1152
1165
  if ("stream" in a) return {
1153
1166
  status: 200,
@@ -1176,34 +1189,34 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
1176
1189
  "x-voltro-rendered-by": a.renderMode
1177
1190
  });
1178
1191
  if (a.renderMode === "isr" && a.revalidateMs !== null) {
1179
- let e = Date.now(), t = X.get(h.route.pattern)?.staleWhileRevalidateMs ?? 0;
1180
- V.set(y, {
1192
+ let e = Date.now(), t = J.get(p.route.pattern)?.staleWhileRevalidateMs ?? 0;
1193
+ z.set(_, {
1181
1194
  html: a.html,
1182
1195
  renderedAt: e,
1183
1196
  expiresAt: e + a.revalidateMs,
1184
1197
  servableUntil: e + a.revalidateMs + t,
1185
1198
  revalidateMs: a.revalidateMs,
1186
1199
  staleWhileRevalidateMs: t
1187
- }, { ifGeneration: r }) || Q.info("miss fill discarded — the entry was purged while it rendered", { key: y }), l["x-voltro-cache"] = "MISS", l["x-voltro-cache-key"] = y, l["x-voltro-cache-revalidate-ms"] = String(a.revalidateMs), t > 0 && (l["x-voltro-cache-swr-ms"] = String(t)), d.emit("cache", {
1200
+ }, { ifGeneration: i }) || Z.info("miss fill discarded — the entry was purged while it rendered", { key: _ }), l["x-voltro-cache"] = "MISS", l["x-voltro-cache-key"] = _, l["x-voltro-cache-revalidate-ms"] = String(a.revalidateMs), t > 0 && (l["x-voltro-cache-swr-ms"] = String(t)), f.emit("cache", {
1188
1201
  kind: "MISS",
1189
- key: y,
1202
+ key: _,
1190
1203
  revalidateMs: a.revalidateMs,
1191
1204
  swrMs: t
1192
1205
  });
1193
- } else a.renderMode === "isr" && (l["x-voltro-cache"] = "BYPASS", d.emit("cache", {
1206
+ } else a.renderMode === "isr" && (l["x-voltro-cache"] = "BYPASS", f.emit("cache", {
1194
1207
  kind: "BYPASS",
1195
- key: y
1208
+ key: _
1196
1209
  }));
1197
- return b && a.renderMode === "isr" ? S(a.html, {
1210
+ return y && a.renderMode === "isr" ? b(a.html, {
1198
1211
  "x-voltro-cache": l["x-voltro-cache"] ?? "MISS",
1199
- "x-voltro-cache-key": y
1212
+ "x-voltro-cache-key": _
1200
1213
  }) : {
1201
1214
  status: 200,
1202
1215
  headers: l,
1203
1216
  body: a.html
1204
1217
  };
1205
1218
  } catch (e) {
1206
- return Q.error("render error", { url: i }, e), M(e) ? {
1219
+ return Z.error("render error", { url: r }, e), d(e) ? {
1207
1220
  status: 500,
1208
1221
  headers: {
1209
1222
  "content-type": "text/plain; charset=utf-8",
@@ -1223,78 +1236,82 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
1223
1236
  body: "server error"
1224
1237
  };
1225
1238
  }
1226
- }, Ot = !1, kt = le({
1227
- apiName: L,
1228
- apiOrigin: I,
1239
+ }, kt = !1, At = a({
1240
+ apiName: F,
1241
+ apiOrigin: P,
1229
1242
  loadDescriptors: async () => {
1230
- if (L === void 0) return;
1231
- let e = (await Y.getHelpers()).apiDescriptors?.[L];
1243
+ if (F === void 0) return;
1244
+ let e = (await q.getHelpers()).apiDescriptors?.[F];
1232
1245
  return e === void 0 ? void 0 : await e();
1233
1246
  },
1234
- rpcQuery: (e, t) => me(I, e, {
1235
- apiName: L,
1247
+ rpcQuery: (e, t) => _e(P, e, {
1248
+ apiName: F,
1236
1249
  headers: t
1237
1250
  }),
1251
+ resolveLocale: async (e, t) => {
1252
+ let n = await q.getHelpers(), r = k(t, n.i18n?.locales);
1253
+ return r === void 0 ? n.i18n?.resolve(e.cookie, e["accept-language"])?.locale ?? "en" : r;
1254
+ },
1238
1255
  renderErrorPage: async ({ path: e, headers: n, flash: r }) => {
1239
- let { pathname: i } = ie(e), a = pt(i, q);
1256
+ let { pathname: i } = se(e), a = ht(i, G);
1240
1257
  if (!a) return;
1241
- let o = await ht({
1242
- provider: Y,
1258
+ let o = await yt({
1259
+ provider: q,
1243
1260
  root: t,
1244
1261
  route: a.route,
1245
1262
  params: a.params,
1246
1263
  pathname: i,
1247
- dirs: K,
1248
- shellTemplate: A,
1264
+ dirs: W,
1265
+ shellTemplate: w,
1249
1266
  requestHeaders: n,
1250
- apiOrigin: I,
1251
- apiName: L,
1252
- middlewares: B,
1253
- onCookieWarning: z,
1267
+ apiOrigin: P,
1268
+ apiName: F,
1269
+ middlewares: R,
1270
+ onCookieWarning: L,
1254
1271
  requestUrl: e,
1255
1272
  formFlash: r,
1256
1273
  buffered: !0
1257
1274
  });
1258
1275
  return o !== null && "html" in o ? o.html : void 0;
1259
1276
  }
1260
- }), At = qe(async (e, t) => {
1277
+ }), jt = Xe(async (e, t) => {
1261
1278
  let n = e.url ?? "/", r = Date.now(), i = {};
1262
1279
  for (let [t, n] of Object.entries(e.headers)) n !== void 0 && (i[t.toLowerCase()] = Array.isArray(n) ? n.join(", ") : n);
1263
- let o = n.split("?")[0] ?? "/", s = (e.method ?? "GET").toUpperCase();
1264
- if (o === "/internal/liveness") {
1280
+ let a = n.split("?")[0] ?? "/", s = (e.method ?? "GET").toUpperCase();
1281
+ if (a === "/internal/liveness") {
1265
1282
  t.writeHead(200, {
1266
1283
  "content-type": "text/plain",
1267
1284
  "cache-control": "no-store"
1268
1285
  }), t.end("ok");
1269
1286
  return;
1270
1287
  }
1271
- if (o === "/internal/readiness") {
1272
- let e = Ot ? 200 : 503;
1288
+ if (a === "/internal/readiness") {
1289
+ let e = kt ? 200 : 503;
1273
1290
  t.writeHead(e, {
1274
1291
  "content-type": "text/plain",
1275
1292
  "cache-control": "no-store"
1276
- }), t.end(Ot ? "ready" : "not-ready");
1293
+ }), t.end(kt ? "ready" : "not-ready");
1277
1294
  return;
1278
1295
  }
1279
- if (!(o.startsWith(g) && await kt(e, t))) {
1280
- if (s === "OPTIONS" && o.startsWith("/_voltro/inspect")) {
1281
- let e = R(i.origin);
1296
+ if (!(a.startsWith(_) && await At(e, t))) {
1297
+ if (s === "OPTIONS" && a.startsWith("/_voltro/inspect")) {
1298
+ let e = Te(i.origin);
1282
1299
  t.writeHead(204, e), t.end();
1283
1300
  return;
1284
1301
  }
1285
- if (a.name === "voltroDashboard" && o === "/api/dashboard/proxy") {
1302
+ if (o.name === "voltroDashboard" && a === "/api/dashboard/proxy") {
1286
1303
  let r = new URL(n, "http://x").searchParams.get("target");
1287
1304
  if (!r) {
1288
1305
  t.writeHead(400, { "content-type": "text/plain" }), t.end("missing ?target=");
1289
1306
  return;
1290
1307
  }
1291
- if (!Ee(r)) {
1308
+ if (!ke(r)) {
1292
1309
  t.writeHead(400, { "content-type": "text/plain" }), t.end("target not allowed: must be loopback or an origin configured in VOLTRO_DASHBOARD_APPS");
1293
1310
  return;
1294
1311
  }
1295
1312
  try {
1296
1313
  let n = { accept: i.accept ?? "application/json" }, a = i.authorization;
1297
- a ? n.authorization = Array.isArray(a) ? a[0] : a : Te(r) && process.env.VOLTRO_INSPECT_TOKEN && (n.authorization = `Bearer ${process.env.VOLTRO_INSPECT_TOKEN}`);
1314
+ a ? n.authorization = Array.isArray(a) ? a[0] : a : Oe(r) && process.env.VOLTRO_INSPECT_TOKEN && (n.authorization = `Bearer ${process.env.VOLTRO_INSPECT_TOKEN}`);
1298
1315
  let o;
1299
1316
  if (s && s !== "GET" && s !== "HEAD") {
1300
1317
  let t = [];
@@ -1318,20 +1335,20 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
1318
1335
  }
1319
1336
  return;
1320
1337
  }
1321
- if (a.name === "voltroDashboard" && o === "/api/dashboard/proxy/stream") {
1338
+ if (o.name === "voltroDashboard" && a === "/api/dashboard/proxy/stream") {
1322
1339
  let r = new URL(n, "http://x").searchParams.get("target");
1323
1340
  if (!r) {
1324
1341
  t.writeHead(400, { "content-type": "text/plain" }), t.end("missing ?target=");
1325
1342
  return;
1326
1343
  }
1327
- if (!Ee(r)) {
1344
+ if (!ke(r)) {
1328
1345
  t.writeHead(400, { "content-type": "text/plain" }), t.end("target not allowed: must be loopback or an origin configured in VOLTRO_DASHBOARD_APPS");
1329
1346
  return;
1330
1347
  }
1331
1348
  let a = new AbortController();
1332
1349
  e.on("close", () => a.abort()), t.on("close", () => a.abort());
1333
1350
  try {
1334
- let e = i.authorization ?? (Te(r) && process.env.VOLTRO_INSPECT_TOKEN ? `Bearer ${process.env.VOLTRO_INSPECT_TOKEN}` : void 0), n = await fetch(r, {
1351
+ let e = i.authorization ?? (Oe(r) && process.env.VOLTRO_INSPECT_TOKEN ? `Bearer ${process.env.VOLTRO_INSPECT_TOKEN}` : void 0), n = await fetch(r, {
1335
1352
  redirect: "manual",
1336
1353
  method: "GET",
1337
1354
  headers: {
@@ -1365,16 +1382,16 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
1365
1382
  }
1366
1383
  return;
1367
1384
  }
1368
- if (o === "/_voltro/inspect/stream") {
1369
- let n = R(i.origin);
1370
- if (Se()) {
1385
+ if (a === "/_voltro/inspect/stream") {
1386
+ let n = Te(i.origin);
1387
+ if (I()) {
1371
1388
  t.writeHead(503, {
1372
1389
  "content-type": "application/json",
1373
1390
  ...n
1374
1391
  }), t.end(JSON.stringify({ error: "inspect disabled (VOLTRO_INSPECT=off)" }));
1375
1392
  return;
1376
1393
  }
1377
- let r = Ce(i, "GET");
1394
+ let r = Ee(i, "GET");
1378
1395
  if (!r.ok) {
1379
1396
  t.writeHead(401, {
1380
1397
  "content-type": "application/json",
@@ -1392,11 +1409,11 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
1392
1409
  "x-accel-buffering": "no",
1393
1410
  ...n
1394
1411
  }), t.flushHeaders(), t.write("retry: 5000\n\n");
1395
- for (let e of d.buffered()) t.write(D(e));
1396
- let a = d.subscribe((e) => {
1397
- t.write(D(e));
1412
+ for (let e of f.buffered()) t.write(ye(e));
1413
+ let a = f.subscribe((e) => {
1414
+ t.write(ye(e));
1398
1415
  }), o = setInterval(() => {
1399
- t.write(pe());
1416
+ t.write(he());
1400
1417
  }, 15e3), s = () => {
1401
1418
  clearInterval(o), a();
1402
1419
  };
@@ -1404,25 +1421,25 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
1404
1421
  return;
1405
1422
  }
1406
1423
  try {
1407
- let e = await Dt(n, i);
1408
- if (e.stream ? e.stream(t) : Ye({
1424
+ let e = await Ot(n, i);
1425
+ if (e.stream ? e.stream(t) : Qe({
1409
1426
  response: t,
1410
1427
  status: e.status,
1411
1428
  headers: e.headers,
1412
1429
  body: e.body,
1413
1430
  requestHeaders: i,
1414
- compression: he.compression
1415
- }) || (t.writeHead(e.status, e.headers), t.end(e.body)), !o.startsWith("/_voltro/inspect")) {
1431
+ compression: pe.compression
1432
+ }) || (t.writeHead(e.status, e.headers), t.end(e.body)), !a.startsWith("/_voltro/inspect")) {
1416
1433
  let t = Date.now() - r;
1417
- d.emit("request", {
1418
- url: o,
1434
+ f.emit("request", {
1435
+ url: a,
1419
1436
  status: e.status,
1420
1437
  durationMs: t,
1421
1438
  renderedBy: e.headers["x-voltro-rendered-by"],
1422
1439
  cache: e.headers["x-voltro-cache"]
1423
1440
  });
1424
- let n = pt(o, q)?.route.pattern ?? (e.status === 404 ? "<unmatched>" : "<asset>");
1425
- St.record({
1441
+ let n = ht(a, G)?.route.pattern ?? (e.status === 404 ? "<unmatched>" : "<asset>");
1442
+ Ct.record({
1426
1443
  kind: "request",
1427
1444
  tag: n,
1428
1445
  durationMs: t,
@@ -1434,77 +1451,77 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
1434
1451
  }
1435
1452
  }
1436
1453
  });
1437
- await new Promise((e) => At.listen(h, "::", e)), Ot = !0, i.mark("ready"), Q.info(`listening on http://localhost:${h}`, {
1438
- port: h,
1439
- distDir: x
1440
- }), Q.debug("dynamic + ssr/isr routes resolve via SSR loader");
1454
+ await new Promise((e) => jt.listen(p, "::", e)), kt = !0, i.mark("ready"), Z.info(`listening on http://localhost:${p}`, {
1455
+ port: p,
1456
+ distDir: h
1457
+ }), Z.debug("dynamic + ssr/isr routes resolve via SSR loader");
1441
1458
  try {
1442
- await Fe({
1443
- id: O,
1444
- name: E,
1459
+ await Re({
1460
+ id: S,
1461
+ name: b,
1445
1462
  kind: "web",
1446
- url: `http://localhost:${h}`,
1463
+ url: `http://localhost:${p}`,
1447
1464
  pid: process.pid,
1448
1465
  status: "live",
1449
- logFile: k.path
1466
+ logFile: C.path
1450
1467
  });
1451
- let e = P(t);
1468
+ let e = le(t);
1452
1469
  if (e) {
1453
- let t = await f({ dashboardAppPath: e });
1454
- 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 });
1470
+ let t = await r({ dashboardAppPath: e });
1471
+ t.status === "launched" ? Z.info(`dashboard launched at http://localhost:${t.port}`, { port: t.port }) : t.status === "already-running" && Z.debug(`dashboard already running on :${t.port}`, { port: t.port });
1455
1472
  }
1456
1473
  setInterval(() => {
1457
- Fe({
1458
- id: O,
1459
- name: E,
1474
+ Re({
1475
+ id: S,
1476
+ name: b,
1460
1477
  kind: "web",
1461
- url: `http://localhost:${h}`,
1478
+ url: `http://localhost:${p}`,
1462
1479
  pid: process.pid,
1463
1480
  status: "live",
1464
- logFile: k.path
1481
+ logFile: C.path
1465
1482
  }).catch(() => {});
1466
1483
  }, 1e4).unref();
1467
1484
  } catch (e) {
1468
- Q.warn("runtime-registry write failed", {}, e);
1485
+ Z.warn("runtime-registry write failed", {}, e);
1469
1486
  }
1470
- Ue({
1471
- app: a.name ?? "unnamed",
1487
+ Ke({
1488
+ app: o.name ?? "unnamed",
1472
1489
  kind: "web",
1473
- url: `http://localhost:${h}`,
1490
+ url: `http://localhost:${p}`,
1474
1491
  bootMs: i.total()
1475
1492
  });
1476
- let jt = i.phaseBreakdown();
1477
- Q.info(`start: ready in ${i.total()}ms`, {
1493
+ let Mt = i.phaseBreakdown();
1494
+ Z.info(`start: ready in ${i.total()}ms`, {
1478
1495
  bootMs: i.total(),
1479
- ...jt ? { phases: jt } : {}
1496
+ ...Mt ? { phases: Mt } : {}
1480
1497
  });
1481
- let Mt = !1, Nt = (e) => async () => {
1482
- if (!Mt) {
1483
- if (Mt = !0, Q.info(`received ${e}, shutting down`, { signal: e }), At.close(), await vt.stop(), bt) try {
1484
- bt();
1498
+ let Nt = !1, Pt = (e) => async () => {
1499
+ if (!Nt) {
1500
+ if (Nt = !0, Z.info(`received ${e}, shutting down`, { signal: e }), jt.close(), await vt.stop(), $) try {
1501
+ $();
1485
1502
  } catch {}
1486
- if (xt) try {
1487
- await We.runPromise(xt.close());
1503
+ if (St) try {
1504
+ await qe.runPromise(St.close());
1488
1505
  } catch {}
1489
- if (H) try {
1490
- await H.end();
1506
+ if (B) try {
1507
+ await B.end();
1491
1508
  } catch {}
1492
- await Y.close(), await Le(O), await k.dispose(), process.exit(0);
1509
+ await q.close(), await Be(S), await C.dispose(), process.exit(0);
1493
1510
  }
1494
1511
  };
1495
- process.on("SIGINT", Nt("SIGINT")), process.on("SIGTERM", Nt("SIGTERM"));
1496
- let Pt = process.ppid;
1497
- if (Pt > 1) {
1512
+ process.on("SIGINT", Pt("SIGINT")), process.on("SIGTERM", Pt("SIGTERM"));
1513
+ let Ft = process.ppid;
1514
+ if (Ft > 1) {
1498
1515
  let e = setInterval(() => {
1499
- (process.ppid !== Pt || process.ppid === 1) && (clearInterval(e), Nt("SIGTERM")());
1516
+ (process.ppid !== Ft || process.ppid === 1) && (clearInterval(e), Pt("SIGTERM")());
1500
1517
  }, 2e3);
1501
1518
  e.unref();
1502
1519
  }
1503
1520
  return new Promise(() => {});
1504
- }, yt = async (e) => {
1521
+ }, St = async (e) => {
1505
1522
  t("start");
1506
- let n = e.find((e) => !e.startsWith("-")) ?? process.cwd(), r = await vt(Ve(n));
1507
- return r.ran ? r.exitCode : (Q.error("no web app found at this path"), 1);
1523
+ let n = e.find((e) => !e.startsWith("-")) ?? process.cwd(), r = await $(We(n));
1524
+ return r.ran ? r.exitCode : (Z.error("no web app found at this path"), 1);
1508
1525
  };
1509
1526
  //#endregion
1510
- export { vt as n, yt as t };
1527
+ export { $ as n, St as t };