@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.
- package/CHANGELOG.md +424 -0
- package/THIRD-PARTY-NOTICES.md +8311 -3318
- package/dist/{agentsMd-0l980yhL.js → agentsMd-BaLC10Na.js} +110 -82
- package/dist/agentsMd-DCY1RSs8.js +2 -0
- package/dist/apiBuild-CeUN55uk.js +2 -0
- package/dist/{apiBuild-CSFI8QGq.js → apiBuild-DTWp0S_q.js} +11 -5
- package/dist/bin.js +1 -1
- package/dist/build-D4ygSbnV.js +843 -0
- package/dist/{checkCommand-COmqc2cB.js → checkCommand-Dg1G7Gwd.js} +6 -6
- package/dist/{checkCommand-2SbqzukH.js → checkCommand-L7DTlpIF.js} +1 -1
- package/dist/{cloudCmd-QUXh-b5w.js → cloudCmd-DzKcSYuy.js} +1 -1
- package/dist/{codegen-VF479Cnb.js → codegen-DSLM8Su9.js} +1 -1
- package/dist/codegen-DjgxEOnD.js +2 -0
- package/dist/codegenCommand-CG_Vx4lc.js +41 -0
- package/dist/{codemodRunner-r7J9lIa7.js → codemodRunner-Cd4xkC6u.js} +109 -11
- package/dist/{commands-Cc_nV8WI.js → commands-6Kzi92Np.js} +96 -73
- package/dist/{dashboardCommand-C-gKvwqh.js → dashboardCommand-Cq1PWvI1.js} +5 -5
- package/dist/{dataCommand-BgpBHnlB.js → dataCommand-DYzW8vkv.js} +3 -3
- package/dist/{dbCommand-sHedr-NJ.js → dbCommand-B4NWZtGL.js} +278 -237
- package/dist/dbCommand-CSFWs9ev.js +2 -0
- package/dist/{dev-CRHoCEiy.js → dev-CmuvUKRq.js} +2903 -2306
- package/dist/{dev--A3nsxA3.js → dev-cKUiZZsB.js} +1 -1
- package/dist/{doctorCommand-DtfJ3FA6.js → doctorCommand-DCiFVMtZ.js} +101 -69
- package/dist/doctorCommand-J3qu4E0Y.js +2 -0
- package/dist/{dormancyCommand-Drn7o0No.js → dormancyCommand-w1TrmgYP.js} +1 -1
- package/dist/{embeddingsCommand-Z-jO1fWN.js → embeddingsCommand-CMgPyRTr.js} +1 -1
- package/dist/{envCommand-D4gCrrTZ.js → envCommand-Cyynmcfa.js} +8 -8
- package/dist/{evolveCommand-CMROeKeA.js → evolveCommand-BwvQ8dVH.js} +2 -2
- package/dist/fileConventions-l-RIXbx8.js +36 -0
- package/dist/{fileTaxonomy-DvDUV9wq.js → fileTaxonomy-CbyMQYx_.js} +42 -42
- package/dist/fontPipeline-LxIHa1vo.js +2 -0
- package/dist/fontPipeline-Tsh8kZfA.js +152 -0
- package/dist/{frameworkTableAssembly-w-XnLa3q.js → frameworkTableAssembly-D7LJuALW.js} +5 -5
- package/dist/frameworkTableAssembly-IPD1pUnZ.js +2 -0
- package/dist/imagePipeline-B_GVJgm6.js +2 -0
- package/dist/imagePipeline-CBZmjT4i.js +127 -0
- package/dist/index.js +2 -2
- package/dist/{infoCommand-DXM868o_.js → infoCommand-DlYlUPqs.js} +1 -1
- package/dist/{inspect-CtL_xTbu.js → inspect-Bd8-9wsi.js} +1 -1
- package/dist/inspect-CuoDInfZ.js +2 -0
- package/dist/{inspectGateHint-BjnFubmH.js → inspectGateHint-4LxkNtrz.js} +1 -1
- package/dist/manifestBuild-C4-J1-m_.js +2 -0
- package/dist/{manifestBuild-CuU1VrSm.js → manifestBuild-Cqgsx2bM.js} +1 -1
- package/dist/{metaCommands-C6RFmF1r.js → metaCommands-x7RCi2AF.js} +9 -3
- package/dist/{migrate-D0F-eTlK.js → migrate-BK_Bbx-_.js} +2 -2
- package/dist/mobileCommand-D9O6iq3D.js +428 -0
- package/dist/mobileCommand-DAum7tsG.js +2 -0
- package/dist/{pageConvention-CzUiSbtU.js → pageConvention-CMpfDN6r.js} +1 -1
- package/dist/{privacyCommand-DGdopOI6.js → privacyCommand-BCa2OoZG.js} +1 -1
- package/dist/{probeCommand-C9gazU0H.js → probeCommand-_C0YU207.js} +83 -24
- package/dist/{projectScaffold-EzlErR4E.js → projectScaffold-CJfP-xbT.js} +1 -1
- package/dist/{projectScaffold-B4dmTlwT.js → projectScaffold-CSN0OzBV.js} +2 -2
- package/dist/renderModeScan-43yQ2opo.js +147 -0
- package/dist/{renderProfile-Ck32Fzxr.js → renderProfile-DvrhVJHa.js} +2 -2
- package/dist/{runtimeTrace-BPQyCmC5.js → runtimeTrace-CGWx1Q6l.js} +1 -1
- package/dist/{sdkgen-Se88ifTd.js → sdkgen-CDGHQUFj.js} +1 -1
- package/dist/serveCommand-BiPe8BJm.js +2 -0
- package/dist/{serveCommand-DkP3OT0W.js → serveCommand-Bje09q1v.js} +889 -825
- package/dist/serveEntry.js +1 -1
- package/dist/start-B0bnJgxI.js +3 -0
- package/dist/{start-jw89Xbqy.js → start-Clz-1BHB.js} +633 -455
- package/dist/startEntry.js +1 -1
- package/dist/{staticCommand-BwNEDlSU.js → staticCommand-ey0kYmOT.js} +1 -1
- package/dist/{subcommandNames-DpYs3DXr.js → subcommandNames-CDzfEtKV.js} +3 -3
- package/dist/{templates-BR-fb4SP.js → templates-BTWZkJJT.js} +41 -9
- package/dist/{test-f3amja6a.js → test-D_kW4KMj.js} +1 -1
- package/dist/updateCommand-CIoVDKnj.js +2 -0
- package/dist/{updateCommand-BMk2e4ky.js → updateCommand-CRJlAOaM.js} +139 -115
- package/dist/{webDev-BgWL9gKV.js → webDev-DSI9SOhs.js} +1598 -1028
- package/dist/webDev-DlvZO30c.js +2 -0
- package/dist/{webhooksCommand-CoIO3jbj.js → webhooksCommand-BvzXNHji.js} +1 -1
- package/dist/workspaceDeps-RKEkX92S.js +45 -0
- package/package.json +60 -19
- package/templates/AGENTS.core.md +2 -0
- package/templates/AGENTS.md +8 -4
- package/templates/agent-docs/_index.md +6 -4
- package/templates/agent-docs/_manifest.json +21 -5
- package/templates/agent-docs/ai.md +6 -6
- package/templates/agent-docs/authentication.md +73 -1
- package/templates/agent-docs/cli.md +6 -3
- package/templates/agent-docs/configuration.md +17 -0
- package/templates/agent-docs/data.md +522 -29
- package/templates/agent-docs/database/advancedqueries.md +8 -8
- package/templates/agent-docs/database/columntypes.md +2 -2
- package/templates/agent-docs/database/migrations.md +1 -1
- package/templates/agent-docs/database/querying.md +1 -1
- package/templates/agent-docs/database/schema.md +1 -1
- package/templates/agent-docs/database/seedsdialects.md +65 -3
- package/templates/agent-docs/database/transactions.md +3 -3
- package/templates/agent-docs/deployment.md +8 -0
- package/templates/agent-docs/internationalization.md +4 -2
- package/templates/agent-docs/introduction.md +32 -1
- package/templates/agent-docs/local-first-mobile.md +226 -30
- package/templates/agent-docs/observability.md +5 -1
- package/templates/agent-docs/plugins/atlassian.md +2 -2
- package/templates/agent-docs/plugins/audit.md +2 -2
- package/templates/agent-docs/plugins/auth.md +1 -1
- package/templates/agent-docs/plugins/billing.md +1 -1
- package/templates/agent-docs/plugins/cdc-out.md +8 -3
- package/templates/agent-docs/plugins/comments.md +164 -0
- package/templates/agent-docs/plugins/notifications.md +47 -4
- package/templates/agent-docs/plugins/presence.md +45 -3
- package/templates/agent-docs/plugins/prometheus.md +3 -1
- package/templates/agent-docs/plugins/queue.md +172 -0
- package/templates/agent-docs/plugins.md +17 -13
- package/templates/agent-docs/reference.md +35 -4
- package/templates/agent-docs/routing.md +585 -7
- package/templates/agent-docs/scheduling.md +1 -1
- package/templates/agent-docs/schema-driven-ui.md +226 -4
- package/templates/agent-docs/security.md +3 -3
- package/templates/agent-docs/templates/appshells.md +36 -4
- package/templates/agent-docs/whats-new.md +134 -66
- package/templates/apps/api-ai/package.json +6 -6
- package/templates/apps/api-auth/package.json +8 -8
- package/templates/apps/api-backend/package.json +7 -7
- package/templates/apps/api-backend-deactivation/package.json +7 -7
- package/templates/apps/api-backend-mail/package.json +8 -8
- package/templates/apps/api-backend-mariadb/package.json +9 -9
- package/templates/apps/api-backend-sqlite/package.json +8 -8
- package/templates/apps/api-backend-storage/package.json +8 -8
- package/templates/apps/api-cms/package.json +9 -9
- package/templates/apps/api-collab/README.md +3 -3
- package/templates/apps/api-collab/app.config.ts +1 -1
- package/templates/apps/api-collab/database/schema.ts +12 -8
- package/templates/apps/api-collab/mutations/documents.create.mutation.server.ts +1 -1
- package/templates/apps/api-collab/mutations/documents.setBody.mutation.server.ts +1 -1
- package/templates/apps/api-collab/mutations/documents.setBody.mutation.ts +1 -1
- package/templates/apps/api-collab/package.json +8 -8
- package/templates/apps/api-collab/template.json +1 -1
- package/templates/apps/api-collab/tests/documents.setBody.test.ts +10 -2
- package/templates/apps/api-data-advanced/package.json +8 -8
- package/templates/apps/api-durable/package.json +8 -8
- package/templates/apps/api-feature-flags/package.json +9 -9
- package/templates/apps/api-governance/package.json +8 -8
- package/templates/apps/api-kv/package.json +8 -8
- package/templates/apps/api-moderation/package.json +8 -8
- package/templates/apps/api-observability/package.json +8 -8
- package/templates/apps/api-ratelimit/package.json +8 -8
- package/templates/apps/api-rbac/package.json +8 -8
- package/templates/apps/api-rest/package.json +7 -7
- package/templates/apps/api-row-history/package.json +8 -8
- package/templates/apps/api-saas/package.json +11 -10
- package/templates/apps/api-saas-starter/package.json +10 -10
- package/templates/apps/api-search/package.json +8 -8
- package/templates/apps/api-status/package.json +8 -8
- package/templates/apps/api-webhooks/package.json +9 -9
- package/templates/apps/changelog/app.config.ts +26 -2
- package/templates/apps/changelog/content/releases/{0.1.0.mdx → v0-1-0.mdx} +0 -1
- package/templates/apps/changelog/content/releases/{0.2.0.mdx → v0-2-0.mdx} +0 -1
- package/templates/apps/changelog/package.json +9 -8
- package/templates/apps/changelog/src/collections/releases.collection.ts +48 -0
- package/templates/apps/changelog/src/globals.d.ts +1 -1
- package/templates/apps/changelog/src/locales/de.ts +1 -1
- package/templates/apps/changelog/src/locales/en.ts +1 -1
- package/templates/apps/changelog/src/pages/[locale]/[slug]/page.tsx +7 -4
- package/templates/apps/changelog/src/pages/[locale]/mirrors.test.tsx +13 -41
- package/templates/apps/changelog/src/pages/[slug]/page.test.tsx +26 -51
- package/templates/apps/changelog/src/pages/[slug]/page.tsx +21 -19
- package/templates/apps/changelog/src/pages/page.test.tsx +14 -37
- package/templates/apps/changelog/src/pages/page.tsx +18 -12
- package/templates/apps/edge-functions/package.json +2 -2
- package/templates/apps/frontend-admin/package.json +8 -8
- package/templates/apps/frontend-app/package.json +9 -9
- package/templates/apps/frontend-auth/package.json +8 -8
- package/templates/apps/frontend-blank/package.json +7 -7
- package/templates/apps/frontend-cms/package.json +9 -9
- package/templates/apps/frontend-collab/README.md +43 -24
- package/templates/apps/frontend-collab/app.config.ts +3 -3
- package/templates/apps/frontend-collab/package.json +14 -10
- package/templates/apps/frontend-collab/src/locales/de.ts +1 -2
- package/templates/apps/frontend-collab/src/locales/en.ts +1 -2
- package/templates/apps/frontend-collab/src/pages/page.test.tsx +72 -76
- package/templates/apps/frontend-collab/src/pages/page.tsx +45 -22
- package/templates/apps/frontend-collab/template.json +2 -2
- package/templates/apps/frontend-contact/package.json +7 -7
- package/templates/apps/frontend-dashboard/package.json +7 -7
- package/templates/apps/frontend-docs/content/docs/de/guides/first-page.md +4 -0
- package/templates/apps/frontend-docs/content/docs/de/intro/getting-started.md +4 -0
- package/templates/apps/frontend-docs/content/docs/en/guides/first-page.md +4 -0
- package/templates/apps/frontend-docs/content/docs/en/intro/getting-started.md +4 -0
- package/templates/apps/frontend-docs/package.json +9 -6
- package/templates/apps/frontend-docs/src/collections/docs.collection.ts +21 -0
- package/templates/apps/frontend-docs/src/locales/de.ts +0 -5
- package/templates/apps/frontend-docs/src/locales/en.ts +0 -5
- package/templates/apps/frontend-docs/src/pages/[locale]/docs/[...slug]/page.tsx +17 -9
- package/templates/apps/frontend-docs/src/pages/[locale]/mirrors.test.tsx +10 -5
- package/templates/apps/frontend-docs/src/pages/[locale]/page.tsx +8 -0
- package/templates/apps/frontend-docs/src/pages/docs/[...slug]/page.test.tsx +53 -15
- package/templates/apps/frontend-docs/src/pages/docs/[...slug]/page.tsx +27 -33
- package/templates/apps/frontend-docs/src/pages/page.test.tsx +17 -3
- package/templates/apps/frontend-docs/src/pages/page.tsx +16 -12
- package/templates/apps/frontend-i18n/package.json +6 -6
- package/templates/apps/frontend-landing/README.md +48 -0
- package/templates/apps/frontend-landing/app.config.ts +28 -0
- package/templates/apps/frontend-landing/package.json +7 -6
- package/templates/apps/frontend-landing/src/assets/hero.jpg +0 -0
- package/templates/apps/frontend-landing/src/fonts/Geist-Variable.woff2 +0 -0
- package/templates/apps/frontend-landing/src/fonts/LICENSE-Geist.txt +92 -0
- package/templates/apps/frontend-landing/src/globals.css +15 -0
- package/templates/apps/frontend-landing/src/globals.d.ts +17 -0
- package/templates/apps/frontend-landing/src/locales/de.ts +3 -2
- package/templates/apps/frontend-landing/src/locales/en.ts +5 -2
- package/templates/apps/frontend-landing/src/pages/page.test.tsx +79 -0
- package/templates/apps/frontend-landing/src/pages/page.tsx +26 -3
- package/templates/apps/frontend-landing/template.json +2 -2
- package/templates/apps/frontend-portal/package.json +8 -8
- package/templates/apps/frontend-saas/package.json +8 -8
- package/templates/apps/frontend-spa/package.json +7 -7
- package/templates/apps/frontend-ssr/package.json +7 -7
- package/templates/apps/frontend-ssr-api/package.json +8 -8
- package/templates/apps/frontend-static-blog/content/posts/cms-to-ssg.md +12 -0
- package/templates/apps/frontend-static-blog/content/posts/hello-static.md +12 -0
- package/templates/apps/frontend-static-blog/content/posts/islands-not-hydration.md +14 -0
- package/templates/apps/frontend-static-blog/package.json +9 -6
- package/templates/apps/frontend-static-blog/src/collections/posts.collection.ts +27 -0
- package/templates/apps/frontend-static-blog/src/pages/[locale]/blog/[slug]/page.tsx +7 -4
- package/templates/apps/frontend-static-blog/src/pages/[locale]/mirrors.test.tsx +7 -1
- package/templates/apps/frontend-static-blog/src/pages/blog/[slug]/page.test.tsx +19 -9
- package/templates/apps/frontend-static-blog/src/pages/blog/[slug]/page.tsx +19 -21
- package/templates/apps/frontend-static-blog/src/pages/page.test.tsx +18 -5
- package/templates/apps/frontend-static-blog/src/pages/page.tsx +21 -14
- package/templates/apps/frontend-status/package.json +8 -8
- package/templates/apps/mobile-app/package.json +12 -11
- package/templates/apps/mobile-app/src/lib/deeplinks.ts +29 -17
- package/templates/apps/mobile-app/tests/deeplinks.test.ts +16 -0
- package/dist/agentsMd-SDDSkyl4.js +0 -2
- package/dist/apiBuild-BYBpL7Pz.js +0 -2
- package/dist/build-CPgcMQug.js +0 -793
- package/dist/codegen-CctkDO-1.js +0 -2
- package/dist/codegenCommand-DCdG2JN-.js +0 -137
- package/dist/dbCommand-DNb6yeOG.js +0 -2
- package/dist/doctorCommand-CqoWA2p5.js +0 -2
- package/dist/fileConventions-DOqD3lPS.js +0 -34
- package/dist/frameworkTableAssembly-C6ETawPR.js +0 -2
- package/dist/inspect-CuGDYES0.js +0 -2
- package/dist/manifestBuild-CPjhvM62.js +0 -2
- package/dist/renderModeScan-CcH2X1_D.js +0 -120
- package/dist/serveCommand-DLc-BznW.js +0 -2
- package/dist/start-DfL3fOiN.js +0 -3
- package/dist/updateCommand-5gFVfK5q.js +0 -2
- package/dist/webDev-CZbTsDcH.js +0 -2
- package/templates/apps/changelog/scripts/generate-rss.mjs +0 -38
- package/templates/apps/changelog/src/lib/releases.ts +0 -21
- 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,
|
|
4
|
-
import { o as
|
|
5
|
-
import { A as
|
|
6
|
-
import { n as
|
|
7
|
-
import { a as
|
|
8
|
-
import { i as
|
|
9
|
-
import { n as
|
|
10
|
-
import { t as
|
|
11
|
-
import { dirname as
|
|
12
|
-
import { promises as
|
|
13
|
-
import { fileURLToPath as
|
|
14
|
-
import { createLogger as
|
|
15
|
-
import { Effect as
|
|
16
|
-
import { maybeCompress as
|
|
17
|
-
import { createHash as
|
|
18
|
-
import { resolveBroadcastProvider as
|
|
19
|
-
import { createServer as
|
|
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
|
|
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 =
|
|
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 =
|
|
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
|
-
}),
|
|
34
|
+
}), ee = {
|
|
35
35
|
...r,
|
|
36
36
|
...f.headers,
|
|
37
37
|
etag: u
|
|
38
38
|
};
|
|
39
|
-
return f.compressed && delete
|
|
40
|
-
},
|
|
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
|
-
},
|
|
52
|
-
let t = e.channel ?? "framework_changes", n = e.revalidateChannel ?? "voltro_revalidate", r =
|
|
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
|
|
57
|
-
let c =
|
|
58
|
-
if (!c && !o) return
|
|
59
|
-
if (!c) return
|
|
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
|
-
|
|
70
|
+
J.warn("bad CDC payload", {}, e);
|
|
71
71
|
return;
|
|
72
72
|
}
|
|
73
73
|
let o = r(a.table);
|
|
74
|
-
o > 0 &&
|
|
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
|
|
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
|
-
},
|
|
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
|
-
`,
|
|
111
|
-
let t = e.tableName ??
|
|
112
|
-
i || (i = !0, await n.query(
|
|
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
|
-
|
|
124
|
+
Y.warn("postgres bootstrap failed", {}, e);
|
|
125
125
|
}), o = (e, t) => {
|
|
126
126
|
a.then(() => n.query(e, t)).catch((e) => {
|
|
127
|
-
|
|
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
|
-
},
|
|
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
|
-
} : (
|
|
185
|
+
} : (Z.warn("bad revalidation payload (shape)", { payload: e }), null);
|
|
186
186
|
} catch {
|
|
187
|
-
return
|
|
187
|
+
return Z.warn("bad revalidation payload (not JSON)", { payload: e }), null;
|
|
188
188
|
}
|
|
189
|
-
},
|
|
189
|
+
}, it = (e, t) => {
|
|
190
190
|
if (t.kind === "table" || t.kind === "tag") {
|
|
191
191
|
let n = e.tableSink(t.value);
|
|
192
|
-
return
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
},
|
|
229
|
+
}, Q = G({ scope: "voltro:start" }), at = await (async () => {
|
|
230
230
|
try {
|
|
231
|
-
let e =
|
|
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
|
-
})(),
|
|
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
|
-
},
|
|
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
|
|
256
|
+
return await U.stat(e), !0;
|
|
257
257
|
} catch {
|
|
258
258
|
return !1;
|
|
259
259
|
}
|
|
260
|
-
},
|
|
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
|
-
},
|
|
270
|
-
let { regex: t, paramNames: n, priority: r } =
|
|
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),
|
|
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
|
-
},
|
|
292
|
-
let { provider: t, route: n, params: r, pathname: a, dirs:
|
|
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:
|
|
298
|
-
headers:
|
|
299
|
-
cookies:
|
|
297
|
+
search: v,
|
|
298
|
+
headers: h,
|
|
299
|
+
cookies: u(h.cookie),
|
|
300
300
|
route: n.pattern
|
|
301
|
-
}, e.onCookieWarning),
|
|
302
|
-
apiName:
|
|
303
|
-
headers:
|
|
304
|
-
})
|
|
305
|
-
if (
|
|
306
|
-
|
|
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:
|
|
309
|
-
entries:
|
|
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:
|
|
317
|
-
signal:
|
|
318
|
-
headers:
|
|
319
|
-
query:
|
|
338
|
+
search: v,
|
|
339
|
+
signal: de.signal,
|
|
340
|
+
headers: k,
|
|
341
|
+
query: D,
|
|
320
342
|
isServer: !0
|
|
321
343
|
}
|
|
322
|
-
}), typeof
|
|
344
|
+
}), typeof b.loader == "function" && !O && (le = await b.loader({
|
|
323
345
|
params: r,
|
|
324
346
|
pathname: a,
|
|
325
|
-
search:
|
|
326
|
-
signal:
|
|
327
|
-
headers:
|
|
328
|
-
query:
|
|
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 (
|
|
354
|
+
if (ot(e)) return {
|
|
333
355
|
control: "redirect",
|
|
334
356
|
status: e.status,
|
|
335
357
|
location: e.location,
|
|
336
|
-
setCookies:
|
|
337
|
-
responseHeaders:
|
|
358
|
+
setCookies: y.setCookies,
|
|
359
|
+
responseHeaders: y.responseHeaders
|
|
338
360
|
};
|
|
339
|
-
if (
|
|
361
|
+
if (st(e)) return {
|
|
340
362
|
control: "not-found",
|
|
341
|
-
setCookies:
|
|
342
|
-
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
|
-
|
|
348
|
-
pageMod:
|
|
369
|
+
O || await xe({
|
|
370
|
+
pageMod: b,
|
|
349
371
|
params: r,
|
|
350
|
-
query:
|
|
351
|
-
apiName:
|
|
372
|
+
query: D,
|
|
373
|
+
apiName: re,
|
|
352
374
|
seed: A.seedPreloadedSubscription,
|
|
353
375
|
seedFailure: A.seedPreloadedSubscriptionFailure,
|
|
354
|
-
onError: ({ tag: e, apiName: t }, n) =>
|
|
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
|
|
382
|
+
let me = {
|
|
361
383
|
pattern: n.pattern,
|
|
362
|
-
Component:
|
|
363
|
-
meta:
|
|
364
|
-
loader:
|
|
365
|
-
ErrorBoundary:
|
|
366
|
-
Pending:
|
|
367
|
-
renderMode:
|
|
368
|
-
chain:
|
|
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 (
|
|
371
|
-
let
|
|
372
|
-
cookies:
|
|
373
|
-
headers:
|
|
374
|
-
url:
|
|
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(
|
|
377
|
-
lang: j?.locale ??
|
|
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 =
|
|
381
|
-
if (
|
|
382
|
-
let e =
|
|
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:
|
|
410
|
+
descriptor: me,
|
|
389
411
|
params: r,
|
|
390
412
|
pathname: a,
|
|
391
|
-
search:
|
|
392
|
-
segmentLoaderData:
|
|
393
|
-
requestContext:
|
|
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) =>
|
|
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 =
|
|
428
|
+
let n = f({ shell: d });
|
|
407
429
|
return {
|
|
408
430
|
renderMode: "spa",
|
|
409
|
-
setCookies:
|
|
410
|
-
responseHeaders:
|
|
411
|
-
stream: (r) =>
|
|
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
|
-
...
|
|
438
|
+
...y.responseHeaders,
|
|
417
439
|
"content-type": "text/html; charset=utf-8",
|
|
418
440
|
"x-voltro-rendered-by": "spa",
|
|
419
|
-
...
|
|
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
|
-
|
|
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 =
|
|
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:
|
|
461
|
+
html: y.cspNonce === void 0 ? s : C(s, y.cspNonce),
|
|
438
462
|
renderMode: "spa",
|
|
439
463
|
revalidateMs: null,
|
|
440
|
-
setCookies:
|
|
441
|
-
responseHeaders:
|
|
464
|
+
setCookies: y.setCookies,
|
|
465
|
+
responseHeaders: y.responseHeaders
|
|
442
466
|
};
|
|
443
467
|
}
|
|
444
|
-
let P =
|
|
468
|
+
let P = m({
|
|
445
469
|
helpers: A,
|
|
446
470
|
page: n.pattern,
|
|
447
471
|
pathname: a,
|
|
448
|
-
renderMode:
|
|
472
|
+
renderMode: S,
|
|
449
473
|
interactive: N,
|
|
450
|
-
loaderData:
|
|
451
|
-
segmentLoaderData:
|
|
452
|
-
pageLoaderRan: typeof
|
|
453
|
-
|
|
454
|
-
|
|
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:
|
|
484
|
+
search: v,
|
|
458
485
|
loaderData: P.loaderData,
|
|
459
486
|
segmentLoaderData: P.segmentLoaderData,
|
|
460
|
-
requestContext:
|
|
487
|
+
requestContext: he,
|
|
461
488
|
...j ? {
|
|
462
489
|
outerWrap: j.outerWrap,
|
|
463
490
|
locale: j.locale
|
|
464
491
|
} : {}
|
|
465
|
-
},
|
|
466
|
-
|
|
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 (
|
|
472
|
-
let e =
|
|
506
|
+
if (S === "ssr" && N === "full" && e.buffered !== !0) {
|
|
507
|
+
let e = f({ shell: d });
|
|
473
508
|
return {
|
|
474
509
|
renderMode: "ssr",
|
|
475
|
-
setCookies:
|
|
476
|
-
stream: (t) =>
|
|
510
|
+
setCookies: y.setCookies,
|
|
511
|
+
stream: (t) => ae({
|
|
477
512
|
res: t,
|
|
478
513
|
shell: e,
|
|
479
514
|
documentAttrs: M,
|
|
480
515
|
headers: {
|
|
481
|
-
...
|
|
516
|
+
...y.responseHeaders,
|
|
482
517
|
"content-type": "text/html; charset=utf-8",
|
|
483
518
|
"x-voltro-rendered-by": "ssr",
|
|
484
|
-
...
|
|
519
|
+
...g(y.setCookies)
|
|
485
520
|
},
|
|
486
|
-
headInjection:
|
|
521
|
+
headInjection: ye,
|
|
522
|
+
...y.cspNonce === void 0 ? {} : { nonce: y.cspNonce },
|
|
487
523
|
render: (e) => A.renderPageToStream({
|
|
488
|
-
...
|
|
524
|
+
..._e,
|
|
489
525
|
...e,
|
|
490
|
-
...
|
|
526
|
+
...y.cspNonce === void 0 ? {} : { nonce: y.cspNonce }
|
|
491
527
|
}),
|
|
492
528
|
onShellError: (e) => {
|
|
493
|
-
|
|
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:
|
|
499
|
-
N === "none" && (
|
|
500
|
-
let
|
|
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:
|
|
503
|
-
renderMode:
|
|
504
|
-
revalidateMs:
|
|
505
|
-
setCookies:
|
|
506
|
-
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,
|
|
509
|
-
let t = await import(
|
|
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
|
-
},
|
|
539
|
-
let n = await
|
|
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
|
-
}),
|
|
557
|
-
limit:
|
|
558
|
-
onColdStart: (e) =>
|
|
559
|
-
onColdEnd: (e, { durationMs: t, failed: n }) =>
|
|
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
|
-
}),
|
|
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
|
|
604
|
+
return l(H(o, t));
|
|
569
605
|
},
|
|
570
606
|
async getLayout(e) {
|
|
571
|
-
return
|
|
607
|
+
return l(H(s(e), "layout.tsx"));
|
|
572
608
|
},
|
|
573
609
|
async getError(e) {
|
|
574
|
-
return
|
|
610
|
+
return l(H(s(e), "error.tsx"));
|
|
575
611
|
},
|
|
576
612
|
async getPending(e) {
|
|
577
|
-
return
|
|
613
|
+
return l(H(s(e), "loading.tsx"));
|
|
578
614
|
},
|
|
579
615
|
async getHelpers() {
|
|
580
|
-
return await
|
|
616
|
+
return await l("@voltro/web/ssr");
|
|
581
617
|
},
|
|
582
618
|
async close() {
|
|
583
|
-
await
|
|
619
|
+
await a.close();
|
|
584
620
|
}
|
|
585
621
|
};
|
|
586
|
-
},
|
|
587
|
-
let
|
|
588
|
-
if (!
|
|
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 (
|
|
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
|
-
|
|
597
|
-
|
|
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:
|
|
643
|
+
log: Q,
|
|
601
644
|
generateTypes: !1
|
|
602
|
-
}),
|
|
603
|
-
|
|
604
|
-
let
|
|
605
|
-
|
|
606
|
-
let
|
|
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:
|
|
651
|
+
configPort: o.port,
|
|
609
652
|
env: process.env,
|
|
610
|
-
dashboardPin: process.env[
|
|
653
|
+
dashboardPin: process.env[E] === "1"
|
|
611
654
|
});
|
|
612
|
-
for (let e of
|
|
613
|
-
let
|
|
614
|
-
if (!await
|
|
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
|
|
619
|
-
await
|
|
620
|
-
id:
|
|
621
|
-
name:
|
|
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:${
|
|
666
|
+
url: `http://localhost:${m}`,
|
|
624
667
|
pid: process.pid,
|
|
625
668
|
status: "booting",
|
|
626
|
-
logFile:
|
|
669
|
+
logFile: w.path
|
|
627
670
|
}).catch(() => {});
|
|
628
|
-
let
|
|
629
|
-
|
|
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
|
-
},
|
|
634
|
-
|
|
635
|
-
let
|
|
636
|
-
if (
|
|
637
|
-
else if (
|
|
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
|
|
640
|
-
|
|
641
|
-
} else
|
|
642
|
-
await
|
|
643
|
-
let
|
|
644
|
-
|
|
645
|
-
let q =
|
|
646
|
-
if (!
|
|
647
|
-
let J =
|
|
648
|
-
|
|
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
|
-
}),
|
|
652
|
-
let
|
|
653
|
-
|
|
654
|
-
|
|
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,
|
|
706
|
+
Y.set(e.pattern, Me(t, e.file)), tt++;
|
|
662
707
|
} catch (t) {
|
|
663
|
-
|
|
708
|
+
Q.warn("failed to load page metadata", { pattern: e.pattern }, t);
|
|
664
709
|
}
|
|
665
710
|
}
|
|
666
|
-
let
|
|
711
|
+
let X = /* @__PURE__ */ new Map();
|
|
667
712
|
for (let [e, t] of Y) {
|
|
668
713
|
if (t.interactive !== "islands") continue;
|
|
669
|
-
let n =
|
|
714
|
+
let n = H(g, "island-shells", `${S(e)}.html`);
|
|
670
715
|
try {
|
|
671
|
-
|
|
716
|
+
X.set(e, await U.readFile(n, "utf8"));
|
|
672
717
|
} catch {
|
|
673
|
-
|
|
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
|
-
|
|
724
|
+
Q.info(`registered ${Y.size} route(s)`, {
|
|
680
725
|
count: Y.size,
|
|
681
|
-
fromManifest: Y.size -
|
|
682
|
-
fromModules:
|
|
683
|
-
}),
|
|
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" &&
|
|
686
|
-
Z.size > 0 &&
|
|
687
|
-
let
|
|
688
|
-
for (let [e, t] of Y) t.cacheInvalidatesOn.length > 0 &&
|
|
689
|
-
let
|
|
690
|
-
for (let e of K)
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
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:
|
|
701
|
-
renderModeByPattern:
|
|
702
|
-
},
|
|
703
|
-
let t =
|
|
704
|
-
t &&
|
|
705
|
-
},
|
|
706
|
-
cache:
|
|
707
|
-
tableSubscriptionsByPattern:
|
|
708
|
-
regexByPattern:
|
|
709
|
-
...
|
|
710
|
-
}),
|
|
711
|
-
if (
|
|
712
|
-
let e =
|
|
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
|
-
|
|
715
|
-
let t =
|
|
716
|
-
|
|
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
|
-
|
|
782
|
+
Q.warn("revalidation broker subscribe failed — broker leg disabled", {}, e), St = null;
|
|
719
783
|
}
|
|
720
|
-
|
|
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
|
-
|
|
723
|
-
let
|
|
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
|
-
}),
|
|
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
|
-
})),
|
|
809
|
+
})), Et = V ? "postgres" : "memory", Dt = {
|
|
746
810
|
kind: "web",
|
|
747
811
|
meta: {
|
|
748
|
-
name:
|
|
749
|
-
voltroVersion:
|
|
750
|
-
port:
|
|
812
|
+
name: o.name ?? "(unnamed)",
|
|
813
|
+
voltroVersion: at,
|
|
814
|
+
port: m,
|
|
751
815
|
mode: "start",
|
|
752
|
-
apis: Object.entries(
|
|
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:
|
|
761
|
-
dirs:
|
|
824
|
+
routes: wt,
|
|
825
|
+
dirs: Tt,
|
|
762
826
|
cache: () => {
|
|
763
|
-
let e = Date.now(), t =
|
|
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:
|
|
775
|
-
size:
|
|
838
|
+
backend: Et,
|
|
839
|
+
size: B.size(),
|
|
776
840
|
entries: t
|
|
777
841
|
};
|
|
778
842
|
},
|
|
779
|
-
metrics: () =>
|
|
780
|
-
},
|
|
781
|
-
let
|
|
782
|
-
if (
|
|
783
|
-
let e = await
|
|
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 (
|
|
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 (
|
|
826
|
-
let t =
|
|
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
|
-
...
|
|
903
|
+
...we(n.origin)
|
|
832
904
|
},
|
|
833
905
|
body: t.body
|
|
834
906
|
};
|
|
835
907
|
}
|
|
836
|
-
if (
|
|
837
|
-
let t =
|
|
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
|
|
848
|
-
if (!
|
|
849
|
-
let t =
|
|
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:
|
|
923
|
+
pathname: r
|
|
852
924
|
});
|
|
853
925
|
if (t !== void 0) {
|
|
854
|
-
let
|
|
855
|
-
pathname:
|
|
856
|
-
search: e.slice(
|
|
926
|
+
let i = await ee(t, {
|
|
927
|
+
pathname: r,
|
|
928
|
+
search: e.slice(r.length),
|
|
857
929
|
headers: n,
|
|
858
|
-
cookies:
|
|
930
|
+
cookies: u(n.cookie),
|
|
859
931
|
route: void 0
|
|
860
932
|
});
|
|
861
|
-
|
|
933
|
+
c.push(...i.setCookies);
|
|
862
934
|
}
|
|
863
935
|
}
|
|
864
|
-
let
|
|
936
|
+
let l = (e) => c.length === 0 ? e : {
|
|
865
937
|
...e,
|
|
866
|
-
"set-cookie":
|
|
867
|
-
}, p =
|
|
868
|
-
if (!
|
|
869
|
-
let e = await
|
|
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:
|
|
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(
|
|
877
|
-
let e =
|
|
878
|
-
if (await
|
|
879
|
-
let t = await
|
|
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:
|
|
954
|
+
headers: l({ "content-type": lt(e) }),
|
|
883
955
|
body: t
|
|
884
956
|
};
|
|
885
957
|
}
|
|
886
958
|
}
|
|
887
|
-
let m =
|
|
888
|
-
if (!m)
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
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:
|
|
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":
|
|
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 &&
|
|
913
|
-
|
|
1071
|
+
if (S && Ne(S, C)) {
|
|
1072
|
+
f.emit("cache", {
|
|
914
1073
|
kind: "STALE",
|
|
915
|
-
key:
|
|
1074
|
+
key: v,
|
|
916
1075
|
ageMs: C - S.renderedAt
|
|
917
1076
|
});
|
|
918
|
-
let
|
|
1077
|
+
let i = B.generation(v);
|
|
919
1078
|
return (async () => {
|
|
920
1079
|
try {
|
|
921
|
-
let
|
|
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:
|
|
1085
|
+
pathname: r,
|
|
927
1086
|
dirs: G,
|
|
928
|
-
shellTemplate:
|
|
1087
|
+
shellTemplate: X.get(m.route.pattern) ?? T,
|
|
929
1088
|
requestHeaders: n,
|
|
930
|
-
apiOrigin:
|
|
931
|
-
apiName:
|
|
932
|
-
middlewares:
|
|
933
|
-
onCookieWarning:
|
|
1089
|
+
apiOrigin: F,
|
|
1090
|
+
apiName: I,
|
|
1091
|
+
middlewares: z,
|
|
1092
|
+
onCookieWarning: R,
|
|
934
1093
|
requestUrl: e,
|
|
935
1094
|
buffered: !0
|
|
936
1095
|
});
|
|
937
|
-
if (
|
|
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
|
-
|
|
940
|
-
html:
|
|
1098
|
+
B.set(v, {
|
|
1099
|
+
html: a.html,
|
|
941
1100
|
renderedAt: t,
|
|
942
|
-
expiresAt: t +
|
|
943
|
-
servableUntil: t +
|
|
944
|
-
revalidateMs:
|
|
1101
|
+
expiresAt: t + a.revalidateMs,
|
|
1102
|
+
servableUntil: t + a.revalidateMs + e,
|
|
1103
|
+
revalidateMs: a.revalidateMs,
|
|
945
1104
|
staleWhileRevalidateMs: e
|
|
946
|
-
}, { ifGeneration:
|
|
1105
|
+
}, { ifGeneration: i }) || Q.info("SWR refresh discarded — the entry was purged while it rendered", { key: v });
|
|
947
1106
|
}
|
|
948
1107
|
} catch (e) {
|
|
949
|
-
|
|
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":
|
|
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
|
|
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:
|
|
1132
|
+
pathname: r,
|
|
970
1133
|
dirs: G,
|
|
971
|
-
shellTemplate:
|
|
1134
|
+
shellTemplate: X.get(m.route.pattern) ?? T,
|
|
972
1135
|
requestHeaders: n,
|
|
973
|
-
apiOrigin:
|
|
974
|
-
apiName:
|
|
975
|
-
middlewares:
|
|
976
|
-
onCookieWarning:
|
|
1136
|
+
apiOrigin: F,
|
|
1137
|
+
apiName: I,
|
|
1138
|
+
middlewares: z,
|
|
1139
|
+
onCookieWarning: R,
|
|
977
1140
|
requestUrl: e
|
|
978
1141
|
});
|
|
979
|
-
if (!
|
|
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:
|
|
1148
|
+
body: T
|
|
986
1149
|
};
|
|
987
|
-
let o =
|
|
1150
|
+
let o = a.setCookies ?? [], s = a.responseHeaders ?? {}, c = (e) => ({
|
|
988
1151
|
...s,
|
|
989
1152
|
...e,
|
|
990
|
-
...o.length === 0 ? {} : { "set-cookie": o.map(
|
|
1153
|
+
...o.length === 0 ? {} : { "set-cookie": o.map(y) }
|
|
991
1154
|
});
|
|
992
|
-
if ("stream" in
|
|
1155
|
+
if ("stream" in a) return {
|
|
993
1156
|
status: 200,
|
|
994
|
-
headers: { "x-voltro-rendered-by":
|
|
1157
|
+
headers: { "x-voltro-rendered-by": a.renderMode },
|
|
995
1158
|
body: "",
|
|
996
|
-
stream:
|
|
1159
|
+
stream: a.stream
|
|
997
1160
|
};
|
|
998
|
-
if ("control" in
|
|
999
|
-
status:
|
|
1161
|
+
if ("control" in a) return a.control === "redirect" ? {
|
|
1162
|
+
status: a.status,
|
|
1000
1163
|
headers: c({
|
|
1001
|
-
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":
|
|
1179
|
+
"x-voltro-rendered-by": a.renderMode
|
|
1016
1180
|
});
|
|
1017
|
-
if (
|
|
1181
|
+
if (a.renderMode === "isr" && a.revalidateMs !== null) {
|
|
1018
1182
|
let e = Date.now(), t = Y.get(m.route.pattern)?.staleWhileRevalidateMs ?? 0;
|
|
1019
|
-
|
|
1020
|
-
html:
|
|
1183
|
+
B.set(v, {
|
|
1184
|
+
html: a.html,
|
|
1021
1185
|
renderedAt: e,
|
|
1022
|
-
expiresAt: e +
|
|
1023
|
-
servableUntil: e +
|
|
1024
|
-
revalidateMs:
|
|
1186
|
+
expiresAt: e + a.revalidateMs,
|
|
1187
|
+
servableUntil: e + a.revalidateMs + t,
|
|
1188
|
+
revalidateMs: a.revalidateMs,
|
|
1025
1189
|
staleWhileRevalidateMs: t
|
|
1026
|
-
}, { ifGeneration:
|
|
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:
|
|
1029
|
-
revalidateMs:
|
|
1192
|
+
key: v,
|
|
1193
|
+
revalidateMs: a.revalidateMs,
|
|
1030
1194
|
swrMs: t
|
|
1031
1195
|
});
|
|
1032
|
-
} else
|
|
1196
|
+
} else a.renderMode === "isr" && (l["x-voltro-cache"] = "BYPASS", f.emit("cache", {
|
|
1033
1197
|
kind: "BYPASS",
|
|
1034
|
-
key:
|
|
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:
|
|
1206
|
+
body: a.html
|
|
1040
1207
|
};
|
|
1041
1208
|
} catch (e) {
|
|
1042
|
-
return
|
|
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
|
-
},
|
|
1056
|
-
apiName:
|
|
1057
|
-
apiOrigin:
|
|
1229
|
+
}, kt = !1, At = a({
|
|
1230
|
+
apiName: I,
|
|
1231
|
+
apiOrigin: F,
|
|
1058
1232
|
loadDescriptors: async () => {
|
|
1059
|
-
if (
|
|
1060
|
-
let e = (await J.getHelpers()).apiDescriptors?.[
|
|
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) =>
|
|
1064
|
-
apiName:
|
|
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 } =
|
|
1246
|
+
let { pathname: i } = oe(e), a = mt(i, K);
|
|
1069
1247
|
if (!a) return;
|
|
1070
|
-
let o = await
|
|
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:
|
|
1255
|
+
shellTemplate: T,
|
|
1078
1256
|
requestHeaders: n,
|
|
1079
|
-
apiOrigin:
|
|
1080
|
-
apiName:
|
|
1081
|
-
middlewares:
|
|
1082
|
-
onCookieWarning:
|
|
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
|
-
}),
|
|
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] ?? "/",
|
|
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 =
|
|
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(
|
|
1283
|
+
}), t.end(kt ? "ready" : "not-ready");
|
|
1106
1284
|
return;
|
|
1107
1285
|
}
|
|
1108
|
-
if (!(a.startsWith(
|
|
1109
|
-
if (
|
|
1110
|
-
let e =
|
|
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 (
|
|
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 (!
|
|
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 :
|
|
1127
|
-
let
|
|
1128
|
-
if (
|
|
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
|
-
|
|
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:
|
|
1315
|
+
method: s,
|
|
1138
1316
|
headers: n,
|
|
1139
|
-
...
|
|
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 (
|
|
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 (!
|
|
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 ?? (
|
|
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 =
|
|
1199
|
-
if (
|
|
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 =
|
|
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
|
|
1225
|
-
let a =
|
|
1226
|
-
t.write(
|
|
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(
|
|
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
|
|
1237
|
-
if (e.stream ? e.stream(t) :
|
|
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:
|
|
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
|
-
|
|
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 =
|
|
1254
|
-
|
|
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) =>
|
|
1267
|
-
port:
|
|
1268
|
-
distDir:
|
|
1269
|
-
}),
|
|
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
|
|
1272
|
-
id:
|
|
1273
|
-
name:
|
|
1449
|
+
await Le({
|
|
1450
|
+
id: C,
|
|
1451
|
+
name: x,
|
|
1274
1452
|
kind: "web",
|
|
1275
|
-
url: `http://localhost:${
|
|
1453
|
+
url: `http://localhost:${m}`,
|
|
1276
1454
|
pid: process.pid,
|
|
1277
1455
|
status: "live",
|
|
1278
|
-
logFile:
|
|
1456
|
+
logFile: w.path
|
|
1279
1457
|
});
|
|
1280
|
-
let e =
|
|
1458
|
+
let e = ce(t);
|
|
1281
1459
|
if (e) {
|
|
1282
|
-
let t = await
|
|
1283
|
-
t.status === "launched" ?
|
|
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
|
-
|
|
1287
|
-
id:
|
|
1288
|
-
name:
|
|
1464
|
+
Le({
|
|
1465
|
+
id: C,
|
|
1466
|
+
name: x,
|
|
1289
1467
|
kind: "web",
|
|
1290
|
-
url: `http://localhost:${
|
|
1468
|
+
url: `http://localhost:${m}`,
|
|
1291
1469
|
pid: process.pid,
|
|
1292
1470
|
status: "live",
|
|
1293
|
-
logFile:
|
|
1471
|
+
logFile: w.path
|
|
1294
1472
|
}).catch(() => {});
|
|
1295
1473
|
}, 1e4).unref();
|
|
1296
1474
|
} catch (e) {
|
|
1297
|
-
|
|
1475
|
+
Q.warn("runtime-registry write failed", {}, e);
|
|
1298
1476
|
}
|
|
1299
|
-
|
|
1300
|
-
app:
|
|
1477
|
+
Ge({
|
|
1478
|
+
app: o.name ?? "unnamed",
|
|
1301
1479
|
kind: "web",
|
|
1302
|
-
url: `http://localhost:${
|
|
1303
|
-
bootMs:
|
|
1480
|
+
url: `http://localhost:${m}`,
|
|
1481
|
+
bootMs: i.total()
|
|
1304
1482
|
});
|
|
1305
|
-
let
|
|
1306
|
-
|
|
1307
|
-
bootMs:
|
|
1308
|
-
...
|
|
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
|
|
1311
|
-
if (!
|
|
1312
|
-
if (
|
|
1313
|
-
|
|
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 (
|
|
1316
|
-
await
|
|
1493
|
+
if (St) try {
|
|
1494
|
+
await Ke.runPromise(St.close());
|
|
1317
1495
|
} catch {}
|
|
1318
|
-
if (
|
|
1319
|
-
await
|
|
1496
|
+
if (V) try {
|
|
1497
|
+
await V.end();
|
|
1320
1498
|
} catch {}
|
|
1321
|
-
await J.close(), await
|
|
1499
|
+
await J.close(), await ze(C), await w.dispose(), process.exit(0);
|
|
1322
1500
|
}
|
|
1323
1501
|
};
|
|
1324
|
-
process.on("SIGINT",
|
|
1325
|
-
let
|
|
1326
|
-
if (
|
|
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 !==
|
|
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
|
-
},
|
|
1511
|
+
}, bt = async (e) => {
|
|
1334
1512
|
t("start");
|
|
1335
|
-
let n = e.find((e) => !e.startsWith("-")) ?? process.cwd(), r = await
|
|
1336
|
-
return r.ran ? r.exitCode : (
|
|
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 {
|
|
1517
|
+
export { yt as n, bt as t };
|