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