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