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