@voltro/cli 0.60.0 → 0.62.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 +43 -0
- package/dist/apiBuild-Dl-djDc_.js +2 -0
- package/dist/{apiBuild-BU5cd-Fn.js → apiBuild-DwhySM-6.js} +2 -2
- package/dist/bin.js +1 -1
- package/dist/{build-BxAsLzyU.js → build-B43mm2g2.js} +7 -7
- package/dist/{checkCommand-C1CQc8lD.js → checkCommand-nB68vIo_.js} +1 -1
- package/dist/{checkCommand-DC7k1_hP.js → checkCommand-zGYZtIkJ.js} +3 -3
- package/dist/{codegenCommand-kS3Twuc9.js → codegenCommand-YvqhgQBj.js} +1 -1
- package/dist/{codemodRunner-ClUqkhvR.js → codemodRunner-D90bexh4.js} +233 -159
- package/dist/{commands-Ro4hYBHD.js → commands-Dd6Cp7qs.js} +21 -21
- package/dist/{dashboardCommand-t8Qsebjr.js → dashboardCommand-BsDfQa-g.js} +3 -3
- package/dist/{dataCommand-hNOGKz4K.js → dataCommand-Cgdcl5M0.js} +1 -1
- package/dist/{dev-Ce2gEziv.js → dev-BfUG0jrD.js} +32 -12
- package/dist/{dev-Dff_pdik.js → dev-BpMSAjMk.js} +1 -1
- package/dist/doctorCommand-PHcqxpnx.js +2 -0
- package/dist/{doctorCommand-CGjefPmk.js → doctorCommand-pxYq2bH5.js} +13 -13
- package/dist/{dormancyCommand-DYgI0Kf-.js → dormancyCommand-DZpSCWy9.js} +1 -1
- package/dist/{embeddingsCommand-yJivQSrI.js → embeddingsCommand-YR5Eif0k.js} +1 -1
- package/dist/{envCommand-ORJUf8r_.js → envCommand-Yl4TGM4h.js} +2 -2
- package/dist/{evolveCommand-CThb0EZZ.js → evolveCommand-B2iYAC9t.js} +2 -2
- package/dist/index.js +1 -1
- package/dist/{infoCommand-a0WkKcUY.js → infoCommand-DjtMWLZl.js} +1 -1
- package/dist/{probeCommand-BUYzc0CT.js → probeCommand-Dsu5if_4.js} +1 -1
- package/dist/{runtimeTrace-DDuKJgVi.js → runtimeTrace-CQcn26bI.js} +1 -1
- package/dist/{sdkgen-vq1fF9D_.js → sdkgen-DJvyVw7B.js} +1 -1
- package/dist/serveCommand-CZ0kgfIX.js +2 -0
- package/dist/{serveCommand-Dr4KXmTS.js → serveCommand-CaLTTh68.js} +3 -3
- package/dist/serveEntry.js +1 -1
- package/dist/{start-BhoDQ25C.js → start-DE4ixCTi.js} +1 -1
- package/dist/{start-CcdPRG8L.js → start-bqT4GRH0.js} +427 -418
- package/dist/startEntry.js +1 -1
- package/dist/updateCommand-DA4OMF7u.js +2 -0
- package/dist/{updateCommand-D9avpQFT.js → updateCommand-F6HFgz0i.js} +1 -1
- package/dist/{webDev-CBN9KkyQ.js → webDev-CYjhmOTZ.js} +1 -1
- package/dist/{webDev-Bzb8ZFus.js → webDev-CuG3Ged-.js} +1 -1
- package/dist/{webhooksCommand-BPJQOGTe.js → webhooksCommand-Bgdli8dI.js} +1 -1
- package/package.json +37 -19
- package/templates/AGENTS.md +2 -2
- package/templates/agent-docs/_index.md +2 -2
- package/templates/agent-docs/_manifest.json +1 -1
- package/templates/agent-docs/ai.md +32 -0
- package/templates/agent-docs/data.md +10 -2
- package/templates/agent-docs/observability.md +17 -2
- package/templates/agent-docs/plugins/sentry.md +29 -12
- package/templates/agent-docs/schema-driven-ui.md +38 -10
- package/templates/agent-docs/whats-new.md +5 -45
- package/templates/agent-docs/workflows.md +7 -2
- 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-B9OvhITV.js +0 -2
- package/dist/doctorCommand-DXnNpKQT.js +0 -2
- package/dist/serveCommand-1R52mo6F.js +0 -2
- package/dist/updateCommand-QMOirvXC.js +0 -2
|
@@ -1,29 +1,29 @@
|
|
|
1
1
|
import { i as e, t } from "./nodeEnvironment-cGFAj1J8.js";
|
|
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 S, Qt as C, R as
|
|
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 { createRequire as
|
|
20
|
-
import { createHash as
|
|
21
|
-
import { resolveBroadcastProvider as
|
|
22
|
-
import { createServer as
|
|
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 S, Qt as C, R as ne, 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-CYjhmOTZ.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 { createRequire as W } from "node:module";
|
|
20
|
+
import { createHash as lt } from "node:crypto";
|
|
21
|
+
import { resolveBroadcastProvider as ut } from "@voltro/plugin-broadcast";
|
|
22
|
+
import { createServer as dt } from "node:http";
|
|
23
23
|
//#region src/inertPublicEnv.ts
|
|
24
|
-
var
|
|
24
|
+
var ft = "VOLTRO_PUBLIC_", pt = (e, t) => {
|
|
25
25
|
let n = [];
|
|
26
|
-
for (let [r, i] of Object.entries(e)) if (r.startsWith(
|
|
26
|
+
for (let [r, i] of Object.entries(e)) if (r.startsWith(ft) && i !== void 0 && i !== "") {
|
|
27
27
|
if (t === void 0 || !(r in t)) {
|
|
28
28
|
n.push({
|
|
29
29
|
key: r,
|
|
@@ -37,15 +37,15 @@ var dt = "VOLTRO_PUBLIC_", ft = (e, t) => {
|
|
|
37
37
|
});
|
|
38
38
|
}
|
|
39
39
|
return n.sort((e, t) => e.key.localeCompare(t.key));
|
|
40
|
-
},
|
|
40
|
+
}, mt = (e) => {
|
|
41
41
|
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`);
|
|
42
42
|
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
|
|
43
43
|
readable in a browser — so they must exist when the bundle is BUILT, not when it runs.
|
|
44
44
|
→ pass them to the build (a Docker build-arg / CI build step), not as deployment env.`;
|
|
45
|
-
},
|
|
45
|
+
}, ht = (e) => `W/"${lt("md5").update(e).digest("hex")}"`, gt = (e) => {
|
|
46
46
|
let { response: t, status: n, headers: r, body: i, requestHeaders: a } = e, o = r["cache-control"], s = (typeof o == "string" ? o : "").toLowerCase();
|
|
47
47
|
if (i === void 0 || n !== 200 || s.includes("no-store")) return !1;
|
|
48
|
-
let c = r["content-type"], l = typeof c == "string" ? c : void 0, u = r.etag, d = typeof u == "string" ? u :
|
|
48
|
+
let c = r["content-type"], l = typeof c == "string" ? c : void 0, u = r.etag, d = typeof u == "string" ? u : ht(i), ee = a["if-none-match"];
|
|
49
49
|
if (ee !== void 0 && ee.split(",").some((e) => e.trim() === d)) return t.writeHead(304, {
|
|
50
50
|
...r,
|
|
51
51
|
etag: d
|
|
@@ -54,7 +54,7 @@ var dt = "VOLTRO_PUBLIC_", ft = (e, t) => {
|
|
|
54
54
|
...r,
|
|
55
55
|
etag: d
|
|
56
56
|
}), t.end(i), !0;
|
|
57
|
-
let f =
|
|
57
|
+
let f = U({
|
|
58
58
|
body: typeof i == "string" ? new TextEncoder().encode(i) : new Uint8Array(i),
|
|
59
59
|
contentType: l,
|
|
60
60
|
acceptEncoding: a["accept-encoding"],
|
|
@@ -65,7 +65,7 @@ var dt = "VOLTRO_PUBLIC_", ft = (e, t) => {
|
|
|
65
65
|
etag: d
|
|
66
66
|
};
|
|
67
67
|
return f.compressed && delete p["content-length"], t.writeHead(n, p), t.end(Buffer.from(f.bytes)), !0;
|
|
68
|
-
},
|
|
68
|
+
}, G = H({ scope: "voltro:start:cdc" }), _t = (e) => (t) => {
|
|
69
69
|
let n = 0;
|
|
70
70
|
for (let [r, i] of e.tableSubscriptionsByPattern) {
|
|
71
71
|
if (!i.includes(t)) continue;
|
|
@@ -76,15 +76,15 @@ var dt = "VOLTRO_PUBLIC_", ft = (e, t) => {
|
|
|
76
76
|
}));
|
|
77
77
|
}
|
|
78
78
|
return n;
|
|
79
|
-
},
|
|
80
|
-
let t = e.channel ?? "framework_changes", n = e.revalidateChannel ?? "voltro_revalidate", r =
|
|
79
|
+
}, vt = () => Pe() ? Ne() : null, yt = (e) => {
|
|
80
|
+
let t = e.channel ?? "framework_changes", n = e.revalidateChannel ?? "voltro_revalidate", r = _t(e), i = null, a = null;
|
|
81
81
|
return {
|
|
82
82
|
start: async () => {
|
|
83
83
|
let o = e.tableSubscriptionsByPattern.size > 0, s = e.onRevalidate !== void 0;
|
|
84
|
-
if (!o && !s) return
|
|
85
|
-
let c =
|
|
86
|
-
if (!c && !o) return
|
|
87
|
-
if (!c) return
|
|
84
|
+
if (!o && !s) return G.debug("skipped — no pages declare cacheInvalidatesOn and no revalidation handler is wired"), !1;
|
|
85
|
+
let c = vt();
|
|
86
|
+
if (!c && !o) return G.debug("no database configured — the revalidation LISTEN line is unavailable"), !1;
|
|
87
|
+
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;
|
|
88
88
|
i = new (await (import("pg"))).default.Client(c), await i.connect(), a = (i) => {
|
|
89
89
|
if (i.channel === n && i.payload && e.onRevalidate) {
|
|
90
90
|
e.onRevalidate(i.payload);
|
|
@@ -95,18 +95,18 @@ var dt = "VOLTRO_PUBLIC_", ft = (e, t) => {
|
|
|
95
95
|
try {
|
|
96
96
|
a = JSON.parse(i.payload);
|
|
97
97
|
} catch (e) {
|
|
98
|
-
|
|
98
|
+
G.warn("bad CDC payload", {}, e);
|
|
99
99
|
return;
|
|
100
100
|
}
|
|
101
101
|
let o = r(a.table);
|
|
102
|
-
o > 0 &&
|
|
102
|
+
o > 0 && G.info(`${a.op} on '${a.table}' → dropped ${o} cache entries`, {
|
|
103
103
|
op: a.op,
|
|
104
104
|
table: a.table,
|
|
105
105
|
dropped: o
|
|
106
106
|
});
|
|
107
107
|
}, i.on("notification", a), o && await i.query(`LISTEN ${t}`), s && await i.query(`LISTEN ${n}`);
|
|
108
108
|
let l = [...o ? [t] : [], ...s ? [n] : []];
|
|
109
|
-
return
|
|
109
|
+
return G.info(`LISTEN ${l.join(", ")}`, {
|
|
110
110
|
channels: l,
|
|
111
111
|
..."connectionString" in c ? { target: c.connectionString.replace(/\/\/[^@/]*@/, "//") } : {
|
|
112
112
|
host: c.host,
|
|
@@ -124,7 +124,7 @@ var dt = "VOLTRO_PUBLIC_", ft = (e, t) => {
|
|
|
124
124
|
}
|
|
125
125
|
}
|
|
126
126
|
};
|
|
127
|
-
},
|
|
127
|
+
}, K = H({ scope: "voltro:start:isr-cache" }), bt = "voltro_isr_cache", xt = (e) => `
|
|
128
128
|
CREATE TABLE IF NOT EXISTS ${e} (
|
|
129
129
|
cache_key TEXT PRIMARY KEY,
|
|
130
130
|
html TEXT NOT NULL,
|
|
@@ -135,9 +135,9 @@ CREATE TABLE IF NOT EXISTS ${e} (
|
|
|
135
135
|
stale_while_revalidate_ms BIGINT NOT NULL DEFAULT 0
|
|
136
136
|
);
|
|
137
137
|
CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
138
|
-
`,
|
|
139
|
-
let t = e.tableName ??
|
|
140
|
-
i || (i = !0, await n.query(
|
|
138
|
+
`, St = (e) => {
|
|
139
|
+
let t = e.tableName ?? bt, { client: n } = e, r = /* @__PURE__ */ new Map(), i = !1, a = (async () => {
|
|
140
|
+
i || (i = !0, await n.query(xt(t)));
|
|
141
141
|
})().then(async () => {
|
|
142
142
|
let e = await n.query(`SELECT * FROM ${t}`);
|
|
143
143
|
for (let t of e.rows) r.set(t.cache_key, {
|
|
@@ -149,10 +149,10 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
149
149
|
staleWhileRevalidateMs: Number(t.stale_while_revalidate_ms)
|
|
150
150
|
});
|
|
151
151
|
}).catch((e) => {
|
|
152
|
-
|
|
152
|
+
K.warn("postgres bootstrap failed", {}, e);
|
|
153
153
|
}), o = (e, t) => {
|
|
154
154
|
a.then(() => n.query(e, t)).catch((e) => {
|
|
155
|
-
|
|
155
|
+
K.warn("postgres write failed", {}, e);
|
|
156
156
|
});
|
|
157
157
|
}, s = /* @__PURE__ */ new Map(), c = (e) => {
|
|
158
158
|
s.set(e, (s.get(e) ?? 0) + 1);
|
|
@@ -203,21 +203,21 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
203
203
|
return Array.from(r.entries());
|
|
204
204
|
}
|
|
205
205
|
};
|
|
206
|
-
},
|
|
206
|
+
}, q = H({ scope: "voltro:start:revalidate" }), Ct = (e) => {
|
|
207
207
|
try {
|
|
208
208
|
let t = JSON.parse(e);
|
|
209
209
|
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") ? {
|
|
210
210
|
kind: t.kind,
|
|
211
211
|
value: t.value,
|
|
212
212
|
...t.tenant === void 0 ? {} : { tenant: t.tenant }
|
|
213
|
-
} : (
|
|
213
|
+
} : (q.warn("bad revalidation payload (shape)", { payload: e }), null);
|
|
214
214
|
} catch {
|
|
215
|
-
return
|
|
215
|
+
return q.warn("bad revalidation payload (not JSON)", { payload: e }), null;
|
|
216
216
|
}
|
|
217
|
-
},
|
|
217
|
+
}, wt = (e, t) => {
|
|
218
218
|
if (t.kind === "table" || t.kind === "tag") {
|
|
219
219
|
let n = e.tableSink(t.value);
|
|
220
|
-
return
|
|
220
|
+
return q.info(`revalidate ${t.kind} '${t.value}' → dropped ${n} cache entries`, {
|
|
221
221
|
kind: t.kind,
|
|
222
222
|
value: t.value,
|
|
223
223
|
dropped: n
|
|
@@ -226,7 +226,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
226
226
|
let n = t.value, r = (e) => t.tenant === void 0 || e.split("|").includes(`tenant=${t.tenant}`), i = e.regexByPattern.get(n);
|
|
227
227
|
if (i !== void 0) {
|
|
228
228
|
let a = e.renderModeByPattern.get(n);
|
|
229
|
-
if (a !== "isr") return
|
|
229
|
+
if (a !== "isr") return q.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.`, {
|
|
230
230
|
path: n,
|
|
231
231
|
renderMode: a ?? "unknown"
|
|
232
232
|
}), 0;
|
|
@@ -234,42 +234,42 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
234
234
|
let t = e.split("|")[0] ?? e;
|
|
235
235
|
return i.test(t) && r(e);
|
|
236
236
|
});
|
|
237
|
-
return
|
|
237
|
+
return q.info(`revalidate path pattern '${n}' → dropped ${o} cache entries`, {
|
|
238
238
|
path: n,
|
|
239
239
|
dropped: o,
|
|
240
240
|
...t.tenant === void 0 ? {} : { tenant: t.tenant }
|
|
241
241
|
}), o;
|
|
242
242
|
}
|
|
243
243
|
let a = [...e.regexByPattern.entries()].find(([, e]) => e.test(n));
|
|
244
|
-
if (a === void 0) return
|
|
244
|
+
if (a === void 0) return q.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;
|
|
245
245
|
let o = e.renderModeByPattern.get(a[0]);
|
|
246
|
-
if (o !== "isr") return
|
|
246
|
+
if (o !== "isr") return q.error(`revalidatePath('${n}') targets a '${o ?? "unknown"}' route (${a[0]}) — only \`renderMode: 'isr'\` routes have cache entries to drop.`, {
|
|
247
247
|
path: n,
|
|
248
248
|
route: a[0],
|
|
249
249
|
renderMode: o ?? "unknown"
|
|
250
250
|
}), 0;
|
|
251
251
|
let s = e.cache.invalidateBy((e) => (e.split("|")[0] ?? e) === n && r(e));
|
|
252
|
-
return
|
|
252
|
+
return q.info(`revalidate path '${n}' → dropped ${s} cache entries`, {
|
|
253
253
|
path: n,
|
|
254
254
|
dropped: s,
|
|
255
255
|
...t.tenant === void 0 ? {} : { tenant: t.tenant }
|
|
256
256
|
}), s;
|
|
257
|
-
},
|
|
258
|
-
let t =
|
|
257
|
+
}, Tt = async (e) => {
|
|
258
|
+
let t = W(R(e, "package.json")), n;
|
|
259
259
|
try {
|
|
260
260
|
n = t.resolve("@voltro/plugin-sentry/server");
|
|
261
261
|
} catch {
|
|
262
262
|
return { reason: "SENTRY_DSN is set but `@voltro/plugin-sentry` is not installed in this app — the web server cannot report SSR errors. → `pnpm add @voltro/plugin-sentry` in the web app." };
|
|
263
263
|
}
|
|
264
264
|
try {
|
|
265
|
-
return await import(
|
|
265
|
+
return await import(V(n).href);
|
|
266
266
|
} catch (e) {
|
|
267
267
|
return { reason: `@voltro/plugin-sentry/server resolved but could not be loaded: ${e instanceof Error ? e.message : String(e)}` };
|
|
268
268
|
}
|
|
269
|
-
},
|
|
269
|
+
}, Et = async (e, t, n, r = {}) => {
|
|
270
270
|
let i = t.SENTRY_DSN;
|
|
271
271
|
if (i === void 0 || i === "") return;
|
|
272
|
-
let a = await (r.load ??
|
|
272
|
+
let a = await (r.load ?? Tt)(e);
|
|
273
273
|
if ("reason" in a) {
|
|
274
274
|
n.warn(a.reason);
|
|
275
275
|
return;
|
|
@@ -294,7 +294,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
294
294
|
});
|
|
295
295
|
} catch {}
|
|
296
296
|
};
|
|
297
|
-
},
|
|
297
|
+
}, J = H({ scope: "voltro:start" }), Dt = nt() ?? "unknown", Ot = (e) => e instanceof Error && e._voltroControl === "redirect" && typeof e.location == "string", kt = (e) => e instanceof Error && e._voltroControl === "not-found", At = {
|
|
298
298
|
".html": "text/html; charset=utf-8",
|
|
299
299
|
".js": "application/javascript",
|
|
300
300
|
".mjs": "application/javascript",
|
|
@@ -312,13 +312,13 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
312
312
|
".woff": "font/woff",
|
|
313
313
|
".woff2": "font/woff2",
|
|
314
314
|
".txt": "text/plain; charset=utf-8"
|
|
315
|
-
},
|
|
315
|
+
}, jt = (e) => At[L(e).toLowerCase()] ?? "application/octet-stream", Mt = (e) => e.replace(/<script\b(?=[^>]*\btype="module")(?:(?!<\/script>).)*<\/script>/gi, "").replace(/<script\b(?=[^>]*\bsrc=)(?:(?!<\/script>).)*<\/script>/gi, "").replace(/<link\b[^>]*\brel="modulepreload"[^>]*>/gi, ""), Y = async (e) => {
|
|
316
316
|
try {
|
|
317
|
-
return await
|
|
317
|
+
return await B.stat(e), !0;
|
|
318
318
|
} catch {
|
|
319
319
|
return !1;
|
|
320
320
|
}
|
|
321
|
-
},
|
|
321
|
+
}, Nt = (e) => {
|
|
322
322
|
let t = [], n = 0, r = e.split("/").filter(Boolean), i = [];
|
|
323
323
|
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, "\\$&"));
|
|
324
324
|
let a = i.join("/");
|
|
@@ -327,8 +327,8 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
327
327
|
paramNames: t,
|
|
328
328
|
priority: n
|
|
329
329
|
};
|
|
330
|
-
},
|
|
331
|
-
let { regex: t, paramNames: n, priority: r } =
|
|
330
|
+
}, Pt = (e) => e.map((e) => {
|
|
331
|
+
let { regex: t, paramNames: n, priority: r } = Nt(e.pattern);
|
|
332
332
|
return {
|
|
333
333
|
pattern: e.pattern,
|
|
334
334
|
file: e.file,
|
|
@@ -337,7 +337,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
337
337
|
paramNames: n,
|
|
338
338
|
priority: r
|
|
339
339
|
};
|
|
340
|
-
}).slice().sort((e, t) => e.priority - t.priority),
|
|
340
|
+
}).slice().sort((e, t) => e.priority - t.priority), Ft = (e, t) => {
|
|
341
341
|
for (let n of t) {
|
|
342
342
|
let t = n.regex.exec(e);
|
|
343
343
|
if (!t) continue;
|
|
@@ -349,7 +349,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
349
349
|
};
|
|
350
350
|
}
|
|
351
351
|
return null;
|
|
352
|
-
},
|
|
352
|
+
}, X = null, It, Lt = (e, t) => t === void 0 ? Promise.resolve() : (It ??= (async () => {
|
|
353
353
|
try {
|
|
354
354
|
let n = await e.getHelpers(), r = n.apiDescriptors?.[t];
|
|
355
355
|
if (r === void 0) return;
|
|
@@ -357,10 +357,10 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
357
357
|
if (i === void 0) return;
|
|
358
358
|
i(t, await r());
|
|
359
359
|
} catch {}
|
|
360
|
-
})(),
|
|
360
|
+
})(), It), Rt = async (e) => {
|
|
361
361
|
let { provider: t, route: r, params: i, pathname: a, dirs: o, shellTemplate: s, requestHeaders: c, requestUrl: l = "", apiOrigin: u, apiName: d } = e;
|
|
362
|
-
await
|
|
363
|
-
let { search: p } =
|
|
362
|
+
await Lt(t, d);
|
|
363
|
+
let { search: p } = be(l), g = await ie(ae(e.middlewares ?? [], {
|
|
364
364
|
route: r.pattern,
|
|
365
365
|
pathname: a
|
|
366
366
|
}), {
|
|
@@ -369,7 +369,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
369
369
|
headers: c,
|
|
370
370
|
cookies: ee(c.cookie),
|
|
371
371
|
route: r.pattern
|
|
372
|
-
}, e.onCookieWarning), y = await t.getPage(r.pattern, r.file), x = e.forceSsrRender === !0 ? "ssr" :
|
|
372
|
+
}, e.onCookieWarning), y = await t.getPage(r.pattern, r.file), x = e.forceSsrRender === !0 ? "ssr" : ze(y, r.file), S = x === "isr" && y.ppr === !0, C = x === "isr" && e.holesOnly !== !0 ? h(g.headers) : g.headers, ne = xe(u, C.cookie, {
|
|
373
373
|
apiName: d,
|
|
374
374
|
headers: C
|
|
375
375
|
});
|
|
@@ -385,7 +385,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
385
385
|
search: p,
|
|
386
386
|
signal: e.signal,
|
|
387
387
|
headers: C,
|
|
388
|
-
query:
|
|
388
|
+
query: ne,
|
|
389
389
|
isServer: !0
|
|
390
390
|
},
|
|
391
391
|
helpers: await t.getHelpers(),
|
|
@@ -394,12 +394,12 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
394
394
|
setCookies: g.setCookies
|
|
395
395
|
};
|
|
396
396
|
}
|
|
397
|
-
let
|
|
398
|
-
if (x !== "ssr" && x !== "isr" && !
|
|
399
|
-
let
|
|
397
|
+
let w = x === "spa" && we(o, r.dirChain).some((e) => e.hasLayout);
|
|
398
|
+
if (x !== "ssr" && x !== "isr" && !w) return null;
|
|
399
|
+
let re = we(o, r.dirChain), oe = {}, ce = null, le, ue = new AbortController(), fe = S ? b(C, r.pattern) : C;
|
|
400
400
|
try {
|
|
401
|
-
(await t.getHelpers()).beginStoreSeeds(), {chain:
|
|
402
|
-
entries:
|
|
401
|
+
(await t.getHelpers()).beginStoreSeeds(), {chain: le, segmentLoaderData: oe} = await D({
|
|
402
|
+
entries: re,
|
|
403
403
|
loadLayout: (e) => t.getLayout(e.dir),
|
|
404
404
|
loadError: (e) => t.getError(e.dir),
|
|
405
405
|
loadPending: (e) => t.getPending(e.dir),
|
|
@@ -407,50 +407,50 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
407
407
|
params: i,
|
|
408
408
|
pathname: a,
|
|
409
409
|
search: p,
|
|
410
|
-
signal:
|
|
411
|
-
headers:
|
|
412
|
-
query:
|
|
410
|
+
signal: ue.signal,
|
|
411
|
+
headers: fe,
|
|
412
|
+
query: ne,
|
|
413
413
|
isServer: !0
|
|
414
414
|
}
|
|
415
|
-
}), typeof y.loader == "function" && !
|
|
415
|
+
}), typeof y.loader == "function" && !w && (ce = await y.loader({
|
|
416
416
|
params: i,
|
|
417
417
|
pathname: a,
|
|
418
418
|
search: p,
|
|
419
|
-
signal:
|
|
420
|
-
headers:
|
|
421
|
-
query:
|
|
419
|
+
signal: ue.signal,
|
|
420
|
+
headers: fe,
|
|
421
|
+
query: ne,
|
|
422
422
|
isServer: !0
|
|
423
423
|
}));
|
|
424
424
|
} catch (e) {
|
|
425
|
-
if (
|
|
425
|
+
if (Ot(e)) return {
|
|
426
426
|
control: "redirect",
|
|
427
427
|
status: e.status,
|
|
428
428
|
location: e.location,
|
|
429
429
|
setCookies: g.setCookies,
|
|
430
430
|
responseHeaders: g.responseHeaders
|
|
431
431
|
};
|
|
432
|
-
if (
|
|
432
|
+
if (kt(e)) return {
|
|
433
433
|
control: "not-found",
|
|
434
434
|
setCookies: g.setCookies,
|
|
435
435
|
responseHeaders: g.responseHeaders
|
|
436
436
|
};
|
|
437
437
|
throw e;
|
|
438
438
|
}
|
|
439
|
-
let
|
|
440
|
-
|
|
439
|
+
let O = await t.getHelpers();
|
|
440
|
+
w || await te({
|
|
441
441
|
pageMod: y,
|
|
442
442
|
params: i,
|
|
443
|
-
query:
|
|
443
|
+
query: ne,
|
|
444
444
|
apiName: d,
|
|
445
|
-
seed:
|
|
446
|
-
seedFailure:
|
|
447
|
-
onError: ({ tag: e, apiName: t }, n) =>
|
|
445
|
+
seed: O.seedPreloadedSubscription,
|
|
446
|
+
seedFailure: O.seedPreloadedSubscriptionFailure,
|
|
447
|
+
onError: ({ tag: e, apiName: t }, n) => J.warn("preload seed failed", {
|
|
448
448
|
tag: e,
|
|
449
449
|
apiName: t,
|
|
450
450
|
pathname: a
|
|
451
451
|
}, n)
|
|
452
452
|
});
|
|
453
|
-
let
|
|
453
|
+
let pe = {
|
|
454
454
|
pattern: r.pattern,
|
|
455
455
|
Component: y.default,
|
|
456
456
|
meta: y.meta,
|
|
@@ -458,68 +458,68 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
458
458
|
ErrorBoundary: y.ErrorBoundary,
|
|
459
459
|
Pending: y.Pending,
|
|
460
460
|
renderMode: x,
|
|
461
|
-
chain:
|
|
461
|
+
chain: le
|
|
462
462
|
};
|
|
463
463
|
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.`);
|
|
464
|
-
let
|
|
464
|
+
let me = {
|
|
465
465
|
cookies: S ? v(f(g.cookies), r.pattern) : x === "isr" ? f(g.cookies) : g.cookies,
|
|
466
|
-
headers:
|
|
466
|
+
headers: fe,
|
|
467
467
|
url: l,
|
|
468
468
|
...e.formFlash === void 0 ? {} : { formFlash: e.formFlash }
|
|
469
|
-
},
|
|
470
|
-
lang:
|
|
471
|
-
...
|
|
469
|
+
}, k = O.i18n?.resolve(C.cookie, C["accept-language"]), he = {
|
|
470
|
+
lang: k?.locale ?? me.cookies["voltro:locale"] ?? "en",
|
|
471
|
+
...k?.timeZone === void 0 ? {} : { timeZone: k.timeZone },
|
|
472
472
|
renderedAt: Date.now()
|
|
473
|
-
},
|
|
474
|
-
if (
|
|
475
|
-
let e =
|
|
476
|
-
helpers:
|
|
473
|
+
}, A = y.interactive ?? "full";
|
|
474
|
+
if (w) {
|
|
475
|
+
let e = de({
|
|
476
|
+
helpers: O,
|
|
477
477
|
page: r.pattern,
|
|
478
|
-
interactive:
|
|
478
|
+
interactive: A,
|
|
479
479
|
delivery: "stream",
|
|
480
480
|
renderInput: {
|
|
481
|
-
descriptor:
|
|
481
|
+
descriptor: pe,
|
|
482
482
|
params: i,
|
|
483
483
|
pathname: a,
|
|
484
484
|
search: p,
|
|
485
|
-
segmentLoaderData:
|
|
486
|
-
requestContext:
|
|
487
|
-
...
|
|
488
|
-
outerWrap:
|
|
489
|
-
locale:
|
|
485
|
+
segmentLoaderData: oe,
|
|
486
|
+
requestContext: me,
|
|
487
|
+
...k ? {
|
|
488
|
+
outerWrap: k.outerWrap,
|
|
489
|
+
locale: k.locale
|
|
490
490
|
} : {}
|
|
491
491
|
}
|
|
492
|
-
}), t = (t) =>
|
|
493
|
-
helpers:
|
|
492
|
+
}), t = (t) => ve({
|
|
493
|
+
helpers: O,
|
|
494
494
|
prepared: e,
|
|
495
495
|
meta: t,
|
|
496
|
-
interactive:
|
|
496
|
+
interactive: A
|
|
497
497
|
});
|
|
498
498
|
if (e.hasDeferred) {
|
|
499
|
-
let n =
|
|
499
|
+
let n = E({ shell: s });
|
|
500
500
|
return {
|
|
501
501
|
renderMode: "spa",
|
|
502
502
|
setCookies: g.setCookies,
|
|
503
503
|
responseHeaders: g.responseHeaders,
|
|
504
|
-
stream: (r) =>
|
|
504
|
+
stream: (r) => se({
|
|
505
505
|
res: r,
|
|
506
506
|
shell: n,
|
|
507
|
-
documentAttrs:
|
|
507
|
+
documentAttrs: he,
|
|
508
508
|
headers: {
|
|
509
509
|
...g.responseHeaders,
|
|
510
510
|
"content-type": "text/html; charset=utf-8",
|
|
511
511
|
"x-voltro-rendered-by": "spa",
|
|
512
|
-
...
|
|
512
|
+
...P(g.setCookies)
|
|
513
513
|
},
|
|
514
514
|
headInjection: t,
|
|
515
515
|
...g.cspNonce === void 0 ? {} : { nonce: g.cspNonce },
|
|
516
|
-
render: (t) =>
|
|
516
|
+
render: (t) => O.renderPageToStream({
|
|
517
517
|
...e.renderInput,
|
|
518
518
|
...t,
|
|
519
519
|
...g.cspNonce === void 0 ? {} : { nonce: g.cspNonce }
|
|
520
520
|
}),
|
|
521
521
|
onShellError: (e) => {
|
|
522
|
-
|
|
522
|
+
J.error("spa layout shell render failed", { pathname: a }, e), Q?.(e, {
|
|
523
523
|
stage: "spa-layout-shell",
|
|
524
524
|
pathname: a
|
|
525
525
|
}), r.writeHead(500, { "content-type": "text/plain; charset=utf-8" }), r.end("server error");
|
|
@@ -527,80 +527,80 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
527
527
|
})
|
|
528
528
|
};
|
|
529
529
|
}
|
|
530
|
-
let n =
|
|
531
|
-
helpers:
|
|
530
|
+
let n = N({
|
|
531
|
+
helpers: O,
|
|
532
532
|
prepared: e
|
|
533
|
-
}), o =
|
|
533
|
+
}), o = M(m(s.replace("<div id=\"root\"></div>", `<div id="root">${n.body}</div>`), t(n.meta)), he);
|
|
534
534
|
return {
|
|
535
|
-
html: g.cspNonce === void 0 ? o :
|
|
535
|
+
html: g.cspNonce === void 0 ? o : T(o, g.cspNonce),
|
|
536
536
|
renderMode: "spa",
|
|
537
537
|
revalidateMs: null,
|
|
538
538
|
setCookies: g.setCookies,
|
|
539
539
|
responseHeaders: g.responseHeaders
|
|
540
540
|
};
|
|
541
541
|
}
|
|
542
|
-
let
|
|
543
|
-
helpers:
|
|
542
|
+
let j = n({
|
|
543
|
+
helpers: O,
|
|
544
544
|
page: r.pattern,
|
|
545
545
|
pathname: a,
|
|
546
546
|
renderMode: x,
|
|
547
|
-
interactive:
|
|
548
|
-
loaderData:
|
|
549
|
-
segmentLoaderData:
|
|
547
|
+
interactive: A,
|
|
548
|
+
loaderData: ce,
|
|
549
|
+
segmentLoaderData: oe,
|
|
550
550
|
pageLoaderRan: typeof y.loader == "function",
|
|
551
551
|
...S ? { ppr: !0 } : {}
|
|
552
552
|
});
|
|
553
|
-
S && _(
|
|
554
|
-
let
|
|
555
|
-
descriptor:
|
|
553
|
+
S && _(j.stateInput, r.pattern);
|
|
554
|
+
let ge = {
|
|
555
|
+
descriptor: pe,
|
|
556
556
|
params: i,
|
|
557
557
|
pathname: a,
|
|
558
558
|
search: p,
|
|
559
|
-
loaderData:
|
|
560
|
-
segmentLoaderData:
|
|
561
|
-
requestContext:
|
|
562
|
-
...
|
|
563
|
-
outerWrap:
|
|
564
|
-
locale:
|
|
559
|
+
loaderData: j.loaderData,
|
|
560
|
+
segmentLoaderData: j.segmentLoaderData,
|
|
561
|
+
requestContext: me,
|
|
562
|
+
...k ? {
|
|
563
|
+
outerWrap: k.outerWrap,
|
|
564
|
+
locale: k.locale
|
|
565
565
|
} : {}
|
|
566
|
-
},
|
|
567
|
-
if (
|
|
568
|
-
let n = C["x-tenant"], i =
|
|
566
|
+
}, _e = (t) => {
|
|
567
|
+
if (X === null || x !== "ssr" && x !== "isr" || typeof y.ogImage != "function" || t.includes("og:image")) return "";
|
|
568
|
+
let n = C["x-tenant"], i = X.signOgUrl({
|
|
569
569
|
pattern: r.pattern,
|
|
570
570
|
params: e.params,
|
|
571
571
|
...n === void 0 ? {} : { tenant: n }
|
|
572
572
|
});
|
|
573
573
|
return `<meta property="og:image" content="${i}" /><meta name="twitter:image" content="${i}" /><meta name="twitter:card" content="summary_large_image" />`;
|
|
574
|
-
},
|
|
575
|
-
|
|
576
|
-
`<meta name="voltro-interactive" content="${
|
|
577
|
-
...
|
|
578
|
-
|
|
574
|
+
}, ye = (e) => [
|
|
575
|
+
O.renderMetaToHtml(e) + _e(O.renderMetaToHtml(e)),
|
|
576
|
+
`<meta name="voltro-interactive" content="${A}" />`,
|
|
577
|
+
...j.hasDeferred ? [O.renderDeferredRegistryScript()] : [],
|
|
578
|
+
O.renderRouterStateScript(j.stateInput)
|
|
579
579
|
].filter((e) => e.length > 0).join("\n ");
|
|
580
|
-
if (x === "ssr" &&
|
|
581
|
-
let e =
|
|
580
|
+
if (x === "ssr" && A === "full" && e.buffered !== !0) {
|
|
581
|
+
let e = E({ shell: s });
|
|
582
582
|
return {
|
|
583
583
|
renderMode: "ssr",
|
|
584
584
|
setCookies: g.setCookies,
|
|
585
|
-
stream: (t) =>
|
|
585
|
+
stream: (t) => se({
|
|
586
586
|
res: t,
|
|
587
587
|
shell: e,
|
|
588
|
-
documentAttrs:
|
|
588
|
+
documentAttrs: he,
|
|
589
589
|
headers: {
|
|
590
590
|
...g.responseHeaders,
|
|
591
591
|
"content-type": "text/html; charset=utf-8",
|
|
592
592
|
"x-voltro-rendered-by": "ssr",
|
|
593
|
-
...
|
|
593
|
+
...P(g.setCookies)
|
|
594
594
|
},
|
|
595
|
-
headInjection:
|
|
595
|
+
headInjection: ye,
|
|
596
596
|
...g.cspNonce === void 0 ? {} : { nonce: g.cspNonce },
|
|
597
|
-
render: (e) =>
|
|
598
|
-
...
|
|
597
|
+
render: (e) => O.renderPageToStream({
|
|
598
|
+
...ge,
|
|
599
599
|
...e,
|
|
600
600
|
...g.cspNonce === void 0 ? {} : { nonce: g.cspNonce }
|
|
601
601
|
}),
|
|
602
602
|
onShellError: (e) => {
|
|
603
|
-
|
|
603
|
+
J.error("ssr shell render failed", { pathname: a }, e), Q?.(e, {
|
|
604
604
|
stage: "ssr-shell",
|
|
605
605
|
pathname: a
|
|
606
606
|
}), t.writeHead(500, { "content-type": "text/plain; charset=utf-8" }), t.end("server error");
|
|
@@ -608,18 +608,18 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
608
608
|
})
|
|
609
609
|
};
|
|
610
610
|
}
|
|
611
|
-
let { html:
|
|
612
|
-
|
|
613
|
-
let
|
|
611
|
+
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);
|
|
612
|
+
A === "none" && (F = Mt(F));
|
|
613
|
+
let Ee = x === "isr" ? I(y.revalidate) : null;
|
|
614
614
|
return {
|
|
615
|
-
html: g.cspNonce === void 0 ?
|
|
615
|
+
html: g.cspNonce === void 0 ? F : T(F, g.cspNonce),
|
|
616
616
|
renderMode: x,
|
|
617
|
-
revalidateMs:
|
|
617
|
+
revalidateMs: Ee,
|
|
618
618
|
setCookies: g.setCookies,
|
|
619
619
|
responseHeaders: g.responseHeaders
|
|
620
620
|
};
|
|
621
|
-
},
|
|
622
|
-
let t = await import(
|
|
621
|
+
}, Z = (e) => e === "" ? "/" : e, zt = async (e) => {
|
|
622
|
+
let t = await import(V(e).href);
|
|
623
623
|
return {
|
|
624
624
|
kind: "bundle",
|
|
625
625
|
getPageMeta: () => t.pageMeta,
|
|
@@ -629,18 +629,18 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
629
629
|
return typeof r == "function" ? await r() : r;
|
|
630
630
|
},
|
|
631
631
|
async getLayout(e) {
|
|
632
|
-
let n = t.layouts[
|
|
633
|
-
if (!n) throw Error(`[voltro start] ssr bundle missing layout for dir ${
|
|
632
|
+
let n = t.layouts[Z(e)];
|
|
633
|
+
if (!n) throw Error(`[voltro start] ssr bundle missing layout for dir ${Z(e)}`);
|
|
634
634
|
return typeof n == "function" ? await n() : n;
|
|
635
635
|
},
|
|
636
636
|
async getError(e) {
|
|
637
|
-
let n = t.errors[
|
|
638
|
-
if (!n) throw Error(`[voltro start] ssr bundle missing error for dir ${
|
|
637
|
+
let n = t.errors[Z(e)];
|
|
638
|
+
if (!n) throw Error(`[voltro start] ssr bundle missing error for dir ${Z(e)}`);
|
|
639
639
|
return typeof n == "function" ? await n() : n;
|
|
640
640
|
},
|
|
641
641
|
async getPending(e) {
|
|
642
|
-
let n = t.pendings[
|
|
643
|
-
if (!n) throw Error(`[voltro start] ssr bundle missing pending for dir ${
|
|
642
|
+
let n = t.pendings[Z(e)];
|
|
643
|
+
if (!n) throw Error(`[voltro start] ssr bundle missing pending for dir ${Z(e)}`);
|
|
644
644
|
return typeof n == "function" ? await n() : n;
|
|
645
645
|
},
|
|
646
646
|
async getHelpers() {
|
|
@@ -648,7 +648,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
648
648
|
},
|
|
649
649
|
async close() {}
|
|
650
650
|
};
|
|
651
|
-
},
|
|
651
|
+
}, Bt = async (e, t) => {
|
|
652
652
|
let n = await C("vite", () => import("vite")), r = (await import("@vitejs/plugin-react")).default, i = (await import("@tailwindcss/vite")).default, a = await n.createServer({
|
|
653
653
|
root: t,
|
|
654
654
|
envPrefix: "__VOLTRO_VITE_ENV_DISABLED__",
|
|
@@ -666,10 +666,10 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
666
666
|
},
|
|
667
667
|
appType: "custom",
|
|
668
668
|
logLevel: "warn"
|
|
669
|
-
}), o =
|
|
670
|
-
limit:
|
|
671
|
-
onColdStart: (e) =>
|
|
672
|
-
onColdEnd: (e, { durationMs: t, failed: n }) =>
|
|
669
|
+
}), o = R(e, "src", "pages"), s = (e) => e === "" ? o : R(o, e), c = g({
|
|
670
|
+
limit: w(),
|
|
671
|
+
onColdStart: (e) => J.debug("ssr cold-compile start", { id: e }),
|
|
672
|
+
onColdEnd: (e, { durationMs: t, failed: n }) => J.debug(`ssr cold-compile ${n ? "FAILED" : "end"} ${t}ms`, {
|
|
673
673
|
id: e,
|
|
674
674
|
ms: t,
|
|
675
675
|
...n ? { failed: !0 } : {}
|
|
@@ -678,16 +678,16 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
678
678
|
return {
|
|
679
679
|
kind: "middleware",
|
|
680
680
|
async getPage(e, t) {
|
|
681
|
-
return l(
|
|
681
|
+
return l(R(o, t));
|
|
682
682
|
},
|
|
683
683
|
async getLayout(e) {
|
|
684
|
-
return l(
|
|
684
|
+
return l(R(s(e), "layout.tsx"));
|
|
685
685
|
},
|
|
686
686
|
async getError(e) {
|
|
687
|
-
return l(
|
|
687
|
+
return l(R(s(e), "error.tsx"));
|
|
688
688
|
},
|
|
689
689
|
async getPending(e) {
|
|
690
|
-
return l(
|
|
690
|
+
return l(R(s(e), "loading.tsx"));
|
|
691
691
|
},
|
|
692
692
|
async getHelpers() {
|
|
693
693
|
return await l("@voltro/web/ssr");
|
|
@@ -696,185 +696,185 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
696
696
|
await a.close();
|
|
697
697
|
}
|
|
698
698
|
};
|
|
699
|
-
},
|
|
700
|
-
let n =
|
|
699
|
+
}, Q, $ = async (t) => {
|
|
700
|
+
let n = Ye(), f = await j(t);
|
|
701
701
|
if (!f) return {
|
|
702
702
|
ran: !1,
|
|
703
703
|
exitCode: 0
|
|
704
704
|
};
|
|
705
|
-
if (f.type !== "web") return
|
|
705
|
+
if (f.type !== "web") return J.error("only web apps are supported by `voltro start`"), {
|
|
706
706
|
ran: !0,
|
|
707
707
|
exitCode: 1
|
|
708
708
|
};
|
|
709
|
-
|
|
709
|
+
Q = await Et(t, process.env, J);
|
|
710
710
|
{
|
|
711
711
|
let e = s(f);
|
|
712
|
-
if (e !== void 0) return
|
|
712
|
+
if (e !== void 0) return J.error(`voltro start: refusing to boot — ${e}`), {
|
|
713
713
|
ran: !0,
|
|
714
714
|
exitCode: 1
|
|
715
715
|
};
|
|
716
716
|
}
|
|
717
|
-
let { resolved: m } = await
|
|
717
|
+
let { resolved: m } = await oe({
|
|
718
718
|
rawEnv: f.env,
|
|
719
719
|
appType: "web",
|
|
720
720
|
root: t,
|
|
721
|
-
log:
|
|
721
|
+
log: J,
|
|
722
722
|
generateTypes: !1
|
|
723
723
|
}), te = m.publicValues;
|
|
724
724
|
n.mark("config");
|
|
725
|
-
let h =
|
|
726
|
-
|
|
727
|
-
let g =
|
|
725
|
+
let h = ue();
|
|
726
|
+
fe(h), J.info("booting voltro start", { app: f.name ?? "(unnamed)" });
|
|
727
|
+
let g = Me({
|
|
728
728
|
kind: "web",
|
|
729
729
|
configPort: f.port,
|
|
730
730
|
env: process.env,
|
|
731
|
-
dashboardPin: process.env[
|
|
731
|
+
dashboardPin: process.env[pe] === "1"
|
|
732
732
|
});
|
|
733
|
-
for (let e of g.warnings)
|
|
734
|
-
let _ = g.port, v =
|
|
733
|
+
for (let e of g.warnings) J.warn(e);
|
|
734
|
+
let _ = g.port, v = R(t, ".framework");
|
|
735
735
|
{
|
|
736
736
|
let e;
|
|
737
737
|
try {
|
|
738
|
-
e = JSON.parse(await
|
|
738
|
+
e = JSON.parse(await B.readFile(R(v, "env.public.json"), "utf8"));
|
|
739
739
|
} catch {
|
|
740
740
|
e = void 0;
|
|
741
741
|
}
|
|
742
|
-
let t =
|
|
743
|
-
t.length > 0 &&
|
|
742
|
+
let t = pt(process.env, e);
|
|
743
|
+
t.length > 0 && J.warn(mt(t));
|
|
744
744
|
}
|
|
745
|
-
let b =
|
|
746
|
-
if (!await
|
|
745
|
+
let b = R(v, "dist"), C = R(b, "index.html");
|
|
746
|
+
if (!await Y(C)) return J.error("no built dist found — run `voltro build` first", { distDir: b }), {
|
|
747
747
|
ran: !0,
|
|
748
748
|
exitCode: 1
|
|
749
749
|
};
|
|
750
|
-
let
|
|
751
|
-
await
|
|
752
|
-
id:
|
|
753
|
-
name:
|
|
750
|
+
let w = f.name ?? "unnamed", T = qe("web", w, _), E = Je(w);
|
|
751
|
+
await We({
|
|
752
|
+
id: T,
|
|
753
|
+
name: w,
|
|
754
754
|
kind: "web",
|
|
755
755
|
url: `http://localhost:${_}`,
|
|
756
756
|
pid: process.pid,
|
|
757
757
|
status: "booting",
|
|
758
|
-
logFile:
|
|
758
|
+
logFile: E.path
|
|
759
759
|
}).catch(() => {});
|
|
760
|
-
let
|
|
761
|
-
|
|
760
|
+
let se = R(b, "_voltro", "shell.html"), D = await Y(se) ? await B.readFile(se, "utf8") : await B.readFile(C, "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) => {
|
|
761
|
+
ze.has(e.name) || (ze.add(e.name), J.warn(`middleware.ts wrote the cookie "${e.name}" with the HttpOnly default — a browser SDK cannot read it`, {
|
|
762
762
|
cookie: e.name,
|
|
763
763
|
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."
|
|
764
764
|
}));
|
|
765
|
-
},
|
|
766
|
-
|
|
767
|
-
let
|
|
768
|
-
if (
|
|
769
|
-
else if (
|
|
765
|
+
}, L = await a(t);
|
|
766
|
+
L.length > 0 && J.info(`middleware.ts loaded — ${L.length} middleware(s): ` + L.map((e) => e.exportName).join(", "));
|
|
767
|
+
let z, V = null, H = process.env.SSR_CACHE === "postgres";
|
|
768
|
+
if (H && Pe()) V = new (await (import("pg"))).default.Client(Ne()), await V.connect(), z = St({ client: V }), J.info("isr cache backend: postgres", { table: "voltro_isr_cache" });
|
|
769
|
+
else if (H) {
|
|
770
770
|
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).";
|
|
771
|
-
if (e()) throw
|
|
772
|
-
|
|
773
|
-
} else
|
|
774
|
-
await o(t, f,
|
|
775
|
-
let
|
|
776
|
-
|
|
777
|
-
let
|
|
778
|
-
if (!
|
|
779
|
-
let
|
|
780
|
-
|
|
781
|
-
kind:
|
|
782
|
-
...
|
|
771
|
+
if (e()) throw J.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");
|
|
772
|
+
z = Ve(), J.warn(`${t} Falling back to the per-process memory cache — this would be a hard failure in production.`);
|
|
773
|
+
} else z = Ve(), J.info("isr cache backend: memory (per-process)", { hint: "set SSR_CACHE=postgres for persistent storage" });
|
|
774
|
+
await o(t, f, de, te);
|
|
775
|
+
let nt = R(t, "src", "pages"), { pages: rt, dirs: U } = await re(nt), W = Pt(rt);
|
|
776
|
+
ne(L, W.map((e) => e.pattern)), n.mark("scan");
|
|
777
|
+
let lt = R(b, "server", "ssrEntry.js"), ft = await Y(lt);
|
|
778
|
+
if (!ft && process.env.NODE_ENV === "production") throw J.fatal(`production \`voltro start\` requires a precompiled SSR bundle at ${lt} 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 ${lt}`);
|
|
779
|
+
let G = ft ? await zt(lt) : await Bt(t, v);
|
|
780
|
+
J.info(`ssr loader: ${G.kind}`, {
|
|
781
|
+
kind: G.kind,
|
|
782
|
+
...G.kind === "middleware" ? { hint: "no pre-built SSR bundle found; run `voltro build` to enable bundle mode" } : {}
|
|
783
783
|
}), n.mark("provider");
|
|
784
|
-
let
|
|
784
|
+
let vt = G.getPageMeta?.();
|
|
785
785
|
c(t);
|
|
786
|
-
let
|
|
787
|
-
for (let e of
|
|
788
|
-
let t =
|
|
786
|
+
let K = /* @__PURE__ */ new Map(), bt = 0;
|
|
787
|
+
for (let e of rt) {
|
|
788
|
+
let t = vt?.[e.pattern];
|
|
789
789
|
if (t) {
|
|
790
|
-
|
|
790
|
+
K.set(e.pattern, t);
|
|
791
791
|
continue;
|
|
792
792
|
}
|
|
793
793
|
try {
|
|
794
|
-
let t = await
|
|
795
|
-
|
|
794
|
+
let t = await G.getPage(e.pattern, e.file);
|
|
795
|
+
K.set(e.pattern, Re(t, e.file)), bt++;
|
|
796
796
|
} catch (t) {
|
|
797
|
-
|
|
797
|
+
J.warn("failed to load page metadata", { pattern: e.pattern }, t);
|
|
798
798
|
}
|
|
799
799
|
}
|
|
800
|
-
let
|
|
801
|
-
for (let [e, t] of
|
|
800
|
+
let xt = /* @__PURE__ */ new Map();
|
|
801
|
+
for (let [e, t] of K) {
|
|
802
802
|
if (t.interactive !== "islands") continue;
|
|
803
|
-
let n =
|
|
803
|
+
let n = R(b, "island-shells", `${k(e)}.html`);
|
|
804
804
|
try {
|
|
805
|
-
|
|
805
|
+
xt.set(e, await B.readFile(n, "utf8"));
|
|
806
806
|
} catch {
|
|
807
|
-
|
|
807
|
+
J.warn("islands page has no built per-page shell — serving the full app shell", {
|
|
808
808
|
pattern: e,
|
|
809
809
|
expected: n
|
|
810
810
|
});
|
|
811
811
|
}
|
|
812
812
|
}
|
|
813
|
-
|
|
814
|
-
count:
|
|
815
|
-
fromManifest:
|
|
816
|
-
fromModules:
|
|
813
|
+
J.info(`registered ${K.size} route(s)`, {
|
|
814
|
+
count: K.size,
|
|
815
|
+
fromManifest: K.size - bt,
|
|
816
|
+
fromModules: bt
|
|
817
817
|
}), n.mark("routes");
|
|
818
|
-
let
|
|
819
|
-
for (let e of
|
|
820
|
-
|
|
821
|
-
let
|
|
822
|
-
for (let [e, t] of
|
|
823
|
-
let
|
|
824
|
-
for (let e of
|
|
818
|
+
let q = /* @__PURE__ */ new Set();
|
|
819
|
+
for (let e of W) K.get(e.pattern)?.renderMode === "spa" && we(U, e.dirChain).some((e) => e.hasLayout) && q.add(e.pattern);
|
|
820
|
+
q.size > 0 && J.info(`${q.size} spa route(s) render an SSR layout shell`, { patterns: [...q] });
|
|
821
|
+
let Tt = /* @__PURE__ */ new Map();
|
|
822
|
+
for (let [e, t] of K) t.cacheInvalidatesOn.length > 0 && Tt.set(e, t.cacheInvalidatesOn);
|
|
823
|
+
let Ot = /* @__PURE__ */ new Map();
|
|
824
|
+
for (let e of W) Ot.set(e.pattern, e.regex);
|
|
825
825
|
{
|
|
826
|
-
let n = new Set([...
|
|
826
|
+
let n = new Set([...K].filter(([, e]) => (e.renderMode === "ssr" || e.renderMode === "isr") && e.hasOgImage).map(([e]) => e));
|
|
827
827
|
if (n.size > 0) {
|
|
828
|
-
let { secret: r, fromEnv: i } =
|
|
829
|
-
if (!i && e()) throw
|
|
830
|
-
let a = new Map(
|
|
831
|
-
|
|
828
|
+
let { secret: r, fromEnv: i } = Te();
|
|
829
|
+
if (!i && e()) throw J.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");
|
|
830
|
+
let a = new Map(rt.map((e) => [e.pattern, e.file]));
|
|
831
|
+
X = le({
|
|
832
832
|
root: t,
|
|
833
833
|
fonts: f.fonts,
|
|
834
|
-
cache:
|
|
834
|
+
cache: z,
|
|
835
835
|
secret: r,
|
|
836
836
|
isOgSsrRoute: (e) => n.has(e),
|
|
837
837
|
getPageModule: async (e) => {
|
|
838
838
|
let t = a.get(e);
|
|
839
|
-
return t === void 0 ? null : await
|
|
839
|
+
return t === void 0 ? null : await G.getPage(e, t);
|
|
840
840
|
}
|
|
841
|
-
}),
|
|
841
|
+
}), J.info(`og route active for ${n.size} ssr route(s)`, { secret: i ? "env" : "per-boot" });
|
|
842
842
|
}
|
|
843
843
|
}
|
|
844
|
-
let
|
|
845
|
-
for (let [e, t] of
|
|
846
|
-
let
|
|
847
|
-
cache:
|
|
848
|
-
tableSink:
|
|
849
|
-
cache:
|
|
850
|
-
tableSubscriptionsByPattern:
|
|
851
|
-
regexByPattern:
|
|
844
|
+
let kt = /* @__PURE__ */ new Map();
|
|
845
|
+
for (let [e, t] of K) kt.set(e, t.renderMode);
|
|
846
|
+
let At = [...K.values()].some((e) => e.renderMode === "isr"), Mt = {
|
|
847
|
+
cache: z,
|
|
848
|
+
tableSink: _t({
|
|
849
|
+
cache: z,
|
|
850
|
+
tableSubscriptionsByPattern: Tt,
|
|
851
|
+
regexByPattern: Ot
|
|
852
852
|
}),
|
|
853
|
-
regexByPattern:
|
|
854
|
-
renderModeByPattern:
|
|
855
|
-
},
|
|
856
|
-
let t =
|
|
857
|
-
t &&
|
|
858
|
-
},
|
|
859
|
-
cache:
|
|
860
|
-
tableSubscriptionsByPattern:
|
|
861
|
-
regexByPattern:
|
|
862
|
-
...
|
|
863
|
-
}),
|
|
864
|
-
if (
|
|
865
|
-
let e =
|
|
853
|
+
regexByPattern: Ot,
|
|
854
|
+
renderModeByPattern: kt
|
|
855
|
+
}, Nt = (e) => {
|
|
856
|
+
let t = Ct(e);
|
|
857
|
+
t && wt(Mt, t);
|
|
858
|
+
}, It = yt({
|
|
859
|
+
cache: z,
|
|
860
|
+
tableSubscriptionsByPattern: Tt,
|
|
861
|
+
regexByPattern: Ot,
|
|
862
|
+
...At ? { onRevalidate: Nt } : {}
|
|
863
|
+
}), Lt = await It.start(), Z = null, $ = null;
|
|
864
|
+
if (At) {
|
|
865
|
+
let e = ut({}, process.env);
|
|
866
866
|
if (e.crossReplica) try {
|
|
867
867
|
$ = e.provider;
|
|
868
|
-
let t =
|
|
869
|
-
|
|
868
|
+
let t = Ie(process.env);
|
|
869
|
+
Z = await ct.runPromise(e.provider.subscribe(t, Nt)), J.info(`revalidation subscriber: broker (${e.provider.name})`, { channel: t });
|
|
870
870
|
} catch (e) {
|
|
871
|
-
|
|
871
|
+
J.warn("revalidation broker subscribe failed — broker leg disabled", {}, e), $ = null;
|
|
872
872
|
}
|
|
873
|
-
|
|
873
|
+
Lt && Z === null && J.info("revalidation subscriber: postgres LISTEN (voltro_revalidate)"), !Lt && Z === null && J.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.");
|
|
874
874
|
}
|
|
875
875
|
n.mark("cdc");
|
|
876
|
-
let Vt =
|
|
877
|
-
let t =
|
|
876
|
+
let Vt = Le(), Ht = rt.map((e) => {
|
|
877
|
+
let t = K.get(e.pattern);
|
|
878
878
|
return {
|
|
879
879
|
pattern: e.pattern,
|
|
880
880
|
file: e.file,
|
|
@@ -889,19 +889,19 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
889
889
|
hasMeta: t?.hasMeta ?? !1,
|
|
890
890
|
hasGetStaticPaths: t?.hasGetStaticPaths ?? !1
|
|
891
891
|
};
|
|
892
|
-
}), Ut =
|
|
892
|
+
}), Ut = U.map((e) => ({
|
|
893
893
|
dir: e.dir,
|
|
894
894
|
hasLayout: e.hasLayout,
|
|
895
895
|
hasError: e.hasError,
|
|
896
896
|
hasPending: e.hasPending,
|
|
897
897
|
hasNotFound: e.hasNotFound
|
|
898
|
-
})), Wt =
|
|
898
|
+
})), Wt = V ? "postgres" : "memory", Gt = {
|
|
899
899
|
kind: "web",
|
|
900
900
|
meta: {
|
|
901
901
|
name: f.name ?? "(unnamed)",
|
|
902
|
-
voltroVersion:
|
|
902
|
+
voltroVersion: Dt,
|
|
903
903
|
port: _,
|
|
904
|
-
mode:
|
|
904
|
+
mode: tt(),
|
|
905
905
|
apis: Object.entries(f.apis ?? {}).map(([e, t]) => {
|
|
906
906
|
let n = {
|
|
907
907
|
name: e,
|
|
@@ -913,7 +913,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
913
913
|
routes: Ht,
|
|
914
914
|
dirs: Ut,
|
|
915
915
|
cache: () => {
|
|
916
|
-
let e = Date.now(), t =
|
|
916
|
+
let e = Date.now(), t = z.snapshot().map(([t, n]) => ({
|
|
917
917
|
key: t,
|
|
918
918
|
renderedAt: n.renderedAt,
|
|
919
919
|
expiresAt: n.expiresAt,
|
|
@@ -925,15 +925,15 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
925
925
|
}));
|
|
926
926
|
return {
|
|
927
927
|
backend: Wt,
|
|
928
|
-
size:
|
|
928
|
+
size: z.size(),
|
|
929
929
|
entries: t
|
|
930
930
|
};
|
|
931
931
|
},
|
|
932
|
-
metrics: () =>
|
|
932
|
+
metrics: () => st()
|
|
933
933
|
}, Kt = async (e, n) => {
|
|
934
934
|
let r = e.split("?")[0] ?? "/";
|
|
935
935
|
if (f.name === "voltroDashboard" && r === "/api/dashboard/registry") try {
|
|
936
|
-
let e = await
|
|
936
|
+
let e = await Ge();
|
|
937
937
|
return {
|
|
938
938
|
status: 200,
|
|
939
939
|
headers: { "content-type": "application/json; charset=utf-8" },
|
|
@@ -975,8 +975,8 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
975
975
|
body: JSON.stringify({ apps: t })
|
|
976
976
|
};
|
|
977
977
|
}
|
|
978
|
-
if (
|
|
979
|
-
let t = await
|
|
978
|
+
if (X !== null && r === "/_voltro/og") {
|
|
979
|
+
let t = await X.handle(new URL(e, "http://localhost"));
|
|
980
980
|
if (t !== null) return {
|
|
981
981
|
status: t.status,
|
|
982
982
|
headers: { ...t.headers },
|
|
@@ -984,18 +984,18 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
984
984
|
};
|
|
985
985
|
}
|
|
986
986
|
if (r === "/_voltro/inspect/logs") {
|
|
987
|
-
let t =
|
|
987
|
+
let t = A(e, ge(), n);
|
|
988
988
|
return {
|
|
989
989
|
status: t.status,
|
|
990
990
|
headers: {
|
|
991
991
|
"content-type": t.contentType,
|
|
992
|
-
...
|
|
992
|
+
...Oe(n.origin)
|
|
993
993
|
},
|
|
994
994
|
body: t.body
|
|
995
995
|
};
|
|
996
996
|
}
|
|
997
997
|
if (r !== "/_voltro/inspect/stream") {
|
|
998
|
-
let t =
|
|
998
|
+
let t = ke(e, Gt, n);
|
|
999
999
|
if (t !== null) return {
|
|
1000
1000
|
status: t.status,
|
|
1001
1001
|
headers: {
|
|
@@ -1005,14 +1005,14 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
1005
1005
|
body: t.body
|
|
1006
1006
|
};
|
|
1007
1007
|
}
|
|
1008
|
-
let i =
|
|
1009
|
-
if (!o &&
|
|
1010
|
-
let t =
|
|
1008
|
+
let i = Ft(r, W), a = i ? K.get(i.route.pattern)?.renderMode : void 0, o = a === "ssr" || a === "isr" || (i ? q.has(i.route.pattern) : !1), s = [];
|
|
1009
|
+
if (!o && L.length > 0) {
|
|
1010
|
+
let t = ae(L, {
|
|
1011
1011
|
route: void 0,
|
|
1012
1012
|
pathname: r
|
|
1013
1013
|
});
|
|
1014
1014
|
if (t !== void 0) {
|
|
1015
|
-
let i = await
|
|
1015
|
+
let i = await ie(t, {
|
|
1016
1016
|
pathname: r,
|
|
1017
1017
|
search: e.slice(r.length),
|
|
1018
1018
|
headers: n,
|
|
@@ -1025,14 +1025,14 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
1025
1025
|
let c = (e) => s.length === 0 ? e : {
|
|
1026
1026
|
...e,
|
|
1027
1027
|
"set-cookie": s.map(d)
|
|
1028
|
-
}, u = r === "/" ?
|
|
1029
|
-
if (!o && await
|
|
1030
|
-
let e = await
|
|
1028
|
+
}, u = r === "/" ? R(b, "index.html") : R(b, r.replace(/^\//, ""), "index.html");
|
|
1029
|
+
if (!o && await Y(u)) {
|
|
1030
|
+
let e = await B.readFile(u);
|
|
1031
1031
|
return {
|
|
1032
1032
|
status: 200,
|
|
1033
1033
|
headers: c({
|
|
1034
1034
|
"content-type": "text/html; charset=utf-8",
|
|
1035
|
-
"cache-control":
|
|
1035
|
+
"cache-control": Qe(M)
|
|
1036
1036
|
}),
|
|
1037
1037
|
body: e
|
|
1038
1038
|
};
|
|
@@ -1043,40 +1043,40 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
1043
1043
|
body: "not found"
|
|
1044
1044
|
};
|
|
1045
1045
|
if (/\.[a-z0-9]+$/i.test(r)) {
|
|
1046
|
-
let e =
|
|
1047
|
-
if (await
|
|
1048
|
-
let t =
|
|
1049
|
-
if (a !== void 0 && await
|
|
1050
|
-
let n = await
|
|
1046
|
+
let e = R(b, r.replace(/^\//, ""));
|
|
1047
|
+
if (await Y(e)) {
|
|
1048
|
+
let t = $e(r, M), i = at(n["accept-encoding"]), a = i === "br" ? `${e}.br` : i === "gzip" ? `${e}.gz` : void 0;
|
|
1049
|
+
if (a !== void 0 && await Y(a)) {
|
|
1050
|
+
let n = await B.readFile(e);
|
|
1051
1051
|
return {
|
|
1052
1052
|
status: 200,
|
|
1053
1053
|
headers: c({
|
|
1054
|
-
"content-type":
|
|
1054
|
+
"content-type": jt(e),
|
|
1055
1055
|
"cache-control": t,
|
|
1056
1056
|
"content-encoding": i === "br" ? "br" : "gzip",
|
|
1057
1057
|
vary: "Accept-Encoding",
|
|
1058
|
-
etag:
|
|
1058
|
+
etag: ht(n)
|
|
1059
1059
|
}),
|
|
1060
|
-
body: await
|
|
1060
|
+
body: await B.readFile(a)
|
|
1061
1061
|
};
|
|
1062
1062
|
}
|
|
1063
|
-
let o = await
|
|
1063
|
+
let o = await B.readFile(e);
|
|
1064
1064
|
return {
|
|
1065
1065
|
status: 200,
|
|
1066
1066
|
headers: c({
|
|
1067
|
-
"content-type":
|
|
1067
|
+
"content-type": jt(e),
|
|
1068
1068
|
"cache-control": t
|
|
1069
1069
|
}),
|
|
1070
1070
|
body: o
|
|
1071
1071
|
};
|
|
1072
1072
|
}
|
|
1073
1073
|
}
|
|
1074
|
-
let p =
|
|
1074
|
+
let p = Ft(r, W);
|
|
1075
1075
|
if (!p) {
|
|
1076
|
-
let i =
|
|
1076
|
+
let i = ce(U, r);
|
|
1077
1077
|
if (i !== void 0) try {
|
|
1078
|
-
let a = await
|
|
1079
|
-
provider:
|
|
1078
|
+
let a = await Rt({
|
|
1079
|
+
provider: G,
|
|
1080
1080
|
root: t,
|
|
1081
1081
|
route: {
|
|
1082
1082
|
pattern: "<not-found>",
|
|
@@ -1088,13 +1088,13 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
1088
1088
|
},
|
|
1089
1089
|
params: {},
|
|
1090
1090
|
pathname: r,
|
|
1091
|
-
dirs:
|
|
1092
|
-
shellTemplate:
|
|
1091
|
+
dirs: U,
|
|
1092
|
+
shellTemplate: D,
|
|
1093
1093
|
requestHeaders: n,
|
|
1094
|
-
apiOrigin:
|
|
1095
|
-
apiName:
|
|
1096
|
-
middlewares:
|
|
1097
|
-
onCookieWarning:
|
|
1094
|
+
apiOrigin: N,
|
|
1095
|
+
apiName: P,
|
|
1096
|
+
middlewares: L,
|
|
1097
|
+
onCookieWarning: I,
|
|
1098
1098
|
requestUrl: e,
|
|
1099
1099
|
buffered: !0,
|
|
1100
1100
|
forceSsrRender: !0
|
|
@@ -1108,7 +1108,10 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
1108
1108
|
body: a.html
|
|
1109
1109
|
};
|
|
1110
1110
|
} catch (e) {
|
|
1111
|
-
|
|
1111
|
+
J.warn("not-found.tsx failed to render — serving the plain 404", { pathname: r }, e instanceof Error ? e : Error(String(e))), Q?.(e, {
|
|
1112
|
+
stage: "not-found-render",
|
|
1113
|
+
pathname: r
|
|
1114
|
+
});
|
|
1112
1115
|
}
|
|
1113
1116
|
return {
|
|
1114
1117
|
status: 404,
|
|
@@ -1119,7 +1122,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
1119
1122
|
body: "not found"
|
|
1120
1123
|
};
|
|
1121
1124
|
}
|
|
1122
|
-
let m =
|
|
1125
|
+
let m = K.get(p.route.pattern), te = n["x-tenant"] ?? "anonymous", g = (await G.getHelpers()).i18n?.resolve(n.cookie, n["accept-language"])?.locale, _ = He(r, {
|
|
1123
1126
|
...m?.tenantAware ? { tenant: te } : {},
|
|
1124
1127
|
...g ? { locale: g } : {}
|
|
1125
1128
|
}), v = m?.ppr === !0 && m.renderMode === "isr", y = (i, a) => ({
|
|
@@ -1134,42 +1137,45 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
1134
1137
|
...a
|
|
1135
1138
|
}), o.write(i), (async () => {
|
|
1136
1139
|
try {
|
|
1137
|
-
let i = await
|
|
1138
|
-
provider:
|
|
1140
|
+
let i = await Rt({
|
|
1141
|
+
provider: G,
|
|
1139
1142
|
root: t,
|
|
1140
1143
|
route: p.route,
|
|
1141
1144
|
params: p.params,
|
|
1142
1145
|
pathname: r,
|
|
1143
|
-
dirs:
|
|
1144
|
-
shellTemplate:
|
|
1146
|
+
dirs: U,
|
|
1147
|
+
shellTemplate: xt.get(p.route.pattern) ?? D,
|
|
1145
1148
|
requestHeaders: n,
|
|
1146
|
-
apiOrigin:
|
|
1147
|
-
apiName:
|
|
1148
|
-
middlewares:
|
|
1149
|
-
onCookieWarning:
|
|
1149
|
+
apiOrigin: N,
|
|
1150
|
+
apiName: P,
|
|
1151
|
+
middlewares: L,
|
|
1152
|
+
onCookieWarning: I,
|
|
1150
1153
|
requestUrl: e,
|
|
1151
1154
|
holesOnly: !0
|
|
1152
1155
|
});
|
|
1153
|
-
i !== null && "holes" in i ? await
|
|
1156
|
+
i !== null && "holes" in i ? await me({
|
|
1154
1157
|
loader: i.holes.loader,
|
|
1155
1158
|
ctx: i.holes.ctx,
|
|
1156
1159
|
res: o,
|
|
1157
1160
|
helpers: i.holes.helpers,
|
|
1158
1161
|
page: i.holes.page,
|
|
1159
|
-
log:
|
|
1162
|
+
log: J
|
|
1160
1163
|
}) : o.writableEnded || o.end();
|
|
1161
1164
|
} catch (e) {
|
|
1162
|
-
|
|
1165
|
+
J.warn("ppr hole pass failed", { url: r }, e), Q?.(e, {
|
|
1166
|
+
stage: "ppr-holes",
|
|
1167
|
+
pathname: r
|
|
1168
|
+
}), o.writableEnded || o.end();
|
|
1163
1169
|
}
|
|
1164
1170
|
})();
|
|
1165
1171
|
}
|
|
1166
|
-
}), x =
|
|
1167
|
-
if (x &&
|
|
1172
|
+
}), x = z.get(_), C = Date.now();
|
|
1173
|
+
if (x && Ue(x, C)) return h.emit("cache", {
|
|
1168
1174
|
kind: "HIT",
|
|
1169
1175
|
key: _,
|
|
1170
1176
|
ageMs: C - x.renderedAt
|
|
1171
1177
|
}), v ? y(x.html, {
|
|
1172
|
-
"cache-control":
|
|
1178
|
+
"cache-control": Ze(M, x.revalidateMs, x.staleWhileRevalidateMs),
|
|
1173
1179
|
"x-voltro-cache": "HIT",
|
|
1174
1180
|
"x-voltro-cache-key": _,
|
|
1175
1181
|
"x-voltro-cache-age-ms": String(C - x.renderedAt)
|
|
@@ -1177,7 +1183,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
1177
1183
|
status: 200,
|
|
1178
1184
|
headers: {
|
|
1179
1185
|
"content-type": "text/html; charset=utf-8",
|
|
1180
|
-
"cache-control":
|
|
1186
|
+
"cache-control": Ze(M, x.revalidateMs, x.staleWhileRevalidateMs),
|
|
1181
1187
|
"x-voltro-rendered-by": "isr",
|
|
1182
1188
|
"x-voltro-cache": "HIT",
|
|
1183
1189
|
"x-voltro-cache-key": _,
|
|
@@ -1185,47 +1191,50 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
1185
1191
|
},
|
|
1186
1192
|
body: x.html
|
|
1187
1193
|
};
|
|
1188
|
-
if (x &&
|
|
1194
|
+
if (x && Be(x, C)) {
|
|
1189
1195
|
h.emit("cache", {
|
|
1190
1196
|
kind: "STALE",
|
|
1191
1197
|
key: _,
|
|
1192
1198
|
ageMs: C - x.renderedAt
|
|
1193
1199
|
});
|
|
1194
|
-
let i =
|
|
1200
|
+
let i = z.generation(_);
|
|
1195
1201
|
return (async () => {
|
|
1196
1202
|
try {
|
|
1197
|
-
let a = await
|
|
1198
|
-
provider:
|
|
1203
|
+
let a = await Rt({
|
|
1204
|
+
provider: G,
|
|
1199
1205
|
root: t,
|
|
1200
1206
|
route: p.route,
|
|
1201
1207
|
params: p.params,
|
|
1202
1208
|
pathname: r,
|
|
1203
|
-
dirs:
|
|
1204
|
-
shellTemplate:
|
|
1209
|
+
dirs: U,
|
|
1210
|
+
shellTemplate: xt.get(p.route.pattern) ?? D,
|
|
1205
1211
|
requestHeaders: n,
|
|
1206
|
-
apiOrigin:
|
|
1207
|
-
apiName:
|
|
1208
|
-
middlewares:
|
|
1209
|
-
onCookieWarning:
|
|
1212
|
+
apiOrigin: N,
|
|
1213
|
+
apiName: P,
|
|
1214
|
+
middlewares: L,
|
|
1215
|
+
onCookieWarning: I,
|
|
1210
1216
|
requestUrl: e,
|
|
1211
1217
|
buffered: !0
|
|
1212
1218
|
});
|
|
1213
1219
|
if (a && "html" in a && a.renderMode === "isr" && a.revalidateMs !== null) {
|
|
1214
|
-
let e =
|
|
1215
|
-
|
|
1220
|
+
let e = K.get(p.route.pattern)?.staleWhileRevalidateMs ?? 0, t = Date.now();
|
|
1221
|
+
z.set(_, {
|
|
1216
1222
|
html: a.html,
|
|
1217
1223
|
renderedAt: t,
|
|
1218
1224
|
expiresAt: t + a.revalidateMs,
|
|
1219
1225
|
servableUntil: t + a.revalidateMs + e,
|
|
1220
1226
|
revalidateMs: a.revalidateMs,
|
|
1221
1227
|
staleWhileRevalidateMs: e
|
|
1222
|
-
}, { ifGeneration: i }) ||
|
|
1228
|
+
}, { ifGeneration: i }) || J.info("SWR refresh discarded — the entry was purged while it rendered", { key: _ });
|
|
1223
1229
|
}
|
|
1224
1230
|
} catch (e) {
|
|
1225
|
-
|
|
1231
|
+
J.warn("background SWR refresh failed", { url: r }, e), Q?.(e, {
|
|
1232
|
+
stage: "swr-refresh",
|
|
1233
|
+
pathname: r
|
|
1234
|
+
});
|
|
1226
1235
|
}
|
|
1227
1236
|
})(), v ? y(x.html, {
|
|
1228
|
-
"cache-control":
|
|
1237
|
+
"cache-control": Ze(M, x.revalidateMs, x.staleWhileRevalidateMs),
|
|
1229
1238
|
"x-voltro-cache": "STALE",
|
|
1230
1239
|
"x-voltro-cache-key": _,
|
|
1231
1240
|
"x-voltro-cache-age-ms": String(C - x.renderedAt)
|
|
@@ -1233,7 +1242,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
1233
1242
|
status: 200,
|
|
1234
1243
|
headers: {
|
|
1235
1244
|
"content-type": "text/html; charset=utf-8",
|
|
1236
|
-
"cache-control":
|
|
1245
|
+
"cache-control": Ze(M, x.revalidateMs, x.staleWhileRevalidateMs),
|
|
1237
1246
|
"x-voltro-rendered-by": "isr",
|
|
1238
1247
|
"x-voltro-cache": "STALE",
|
|
1239
1248
|
"x-voltro-cache-key": _,
|
|
@@ -1243,19 +1252,19 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
1243
1252
|
};
|
|
1244
1253
|
}
|
|
1245
1254
|
try {
|
|
1246
|
-
let i =
|
|
1247
|
-
provider:
|
|
1255
|
+
let i = z.generation(_), a = await Rt({
|
|
1256
|
+
provider: G,
|
|
1248
1257
|
root: t,
|
|
1249
1258
|
route: p.route,
|
|
1250
1259
|
params: p.params,
|
|
1251
1260
|
pathname: r,
|
|
1252
|
-
dirs:
|
|
1253
|
-
shellTemplate:
|
|
1261
|
+
dirs: U,
|
|
1262
|
+
shellTemplate: xt.get(p.route.pattern) ?? D,
|
|
1254
1263
|
requestHeaders: n,
|
|
1255
|
-
apiOrigin:
|
|
1256
|
-
apiName:
|
|
1257
|
-
middlewares:
|
|
1258
|
-
onCookieWarning:
|
|
1264
|
+
apiOrigin: N,
|
|
1265
|
+
apiName: P,
|
|
1266
|
+
middlewares: L,
|
|
1267
|
+
onCookieWarning: I,
|
|
1259
1268
|
requestUrl: e
|
|
1260
1269
|
});
|
|
1261
1270
|
if (!a) return {
|
|
@@ -1264,7 +1273,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
1264
1273
|
"content-type": "text/html; charset=utf-8",
|
|
1265
1274
|
"x-voltro-rendered-by": "spa-fallback"
|
|
1266
1275
|
},
|
|
1267
|
-
body:
|
|
1276
|
+
body: D
|
|
1268
1277
|
};
|
|
1269
1278
|
let o = a.setCookies ?? [], s = a.responseHeaders ?? {}, c = (e) => ({
|
|
1270
1279
|
...s,
|
|
@@ -1298,15 +1307,15 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
1298
1307
|
"x-voltro-rendered-by": a.renderMode
|
|
1299
1308
|
});
|
|
1300
1309
|
if (a.renderMode === "isr" && a.revalidateMs !== null) {
|
|
1301
|
-
let e = Date.now(), t =
|
|
1302
|
-
|
|
1310
|
+
let e = Date.now(), t = K.get(p.route.pattern)?.staleWhileRevalidateMs ?? 0;
|
|
1311
|
+
z.set(_, {
|
|
1303
1312
|
html: a.html,
|
|
1304
1313
|
renderedAt: e,
|
|
1305
1314
|
expiresAt: e + a.revalidateMs,
|
|
1306
1315
|
servableUntil: e + a.revalidateMs + t,
|
|
1307
1316
|
revalidateMs: a.revalidateMs,
|
|
1308
1317
|
staleWhileRevalidateMs: t
|
|
1309
|
-
}, { ifGeneration: i }) ||
|
|
1318
|
+
}, { ifGeneration: i }) || J.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", {
|
|
1310
1319
|
kind: "MISS",
|
|
1311
1320
|
key: _,
|
|
1312
1321
|
revalidateMs: a.revalidateMs,
|
|
@@ -1325,7 +1334,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
1325
1334
|
body: a.html
|
|
1326
1335
|
};
|
|
1327
1336
|
} catch (e) {
|
|
1328
|
-
return
|
|
1337
|
+
return J.error("render error", { url: r }, e), Q?.(e, {
|
|
1329
1338
|
stage: "render",
|
|
1330
1339
|
pathname: r
|
|
1331
1340
|
}), S(e) ? {
|
|
@@ -1349,47 +1358,47 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
1349
1358
|
};
|
|
1350
1359
|
}
|
|
1351
1360
|
}, qt = !1, Jt = i(f.health, () => qt), Yt = p({
|
|
1352
|
-
apiName:
|
|
1353
|
-
apiOrigin:
|
|
1361
|
+
apiName: P,
|
|
1362
|
+
apiOrigin: N,
|
|
1354
1363
|
loadDescriptors: async () => {
|
|
1355
|
-
if (
|
|
1356
|
-
let e = (await
|
|
1364
|
+
if (P === void 0) return;
|
|
1365
|
+
let e = (await G.getHelpers()).apiDescriptors?.[P];
|
|
1357
1366
|
return e === void 0 ? void 0 : await e();
|
|
1358
1367
|
},
|
|
1359
|
-
rpcQuery: (e, t) =>
|
|
1360
|
-
apiName:
|
|
1368
|
+
rpcQuery: (e, t) => xe(N, e, {
|
|
1369
|
+
apiName: P,
|
|
1361
1370
|
headers: t
|
|
1362
1371
|
}),
|
|
1363
1372
|
resolveLocale: async (e, t) => {
|
|
1364
|
-
let n = await
|
|
1373
|
+
let n = await G.getHelpers(), r = u(t, n.i18n?.locales);
|
|
1365
1374
|
return r === void 0 ? n.i18n?.resolve(e.cookie, e["accept-language"])?.locale ?? "en" : r;
|
|
1366
1375
|
},
|
|
1367
1376
|
renderErrorPage: async ({ path: e, headers: n, flash: r }) => {
|
|
1368
|
-
let { pathname: i } =
|
|
1377
|
+
let { pathname: i } = be(e), a = Ft(i, W);
|
|
1369
1378
|
if (!a) return;
|
|
1370
|
-
let o = await
|
|
1371
|
-
provider:
|
|
1379
|
+
let o = await Rt({
|
|
1380
|
+
provider: G,
|
|
1372
1381
|
root: t,
|
|
1373
1382
|
route: a.route,
|
|
1374
1383
|
params: a.params,
|
|
1375
1384
|
pathname: i,
|
|
1376
|
-
dirs:
|
|
1377
|
-
shellTemplate:
|
|
1385
|
+
dirs: U,
|
|
1386
|
+
shellTemplate: D,
|
|
1378
1387
|
requestHeaders: n,
|
|
1379
|
-
apiOrigin:
|
|
1380
|
-
apiName:
|
|
1381
|
-
middlewares:
|
|
1382
|
-
onCookieWarning:
|
|
1388
|
+
apiOrigin: N,
|
|
1389
|
+
apiName: P,
|
|
1390
|
+
middlewares: L,
|
|
1391
|
+
onCookieWarning: I,
|
|
1383
1392
|
requestUrl: e,
|
|
1384
1393
|
formFlash: r,
|
|
1385
1394
|
buffered: !0
|
|
1386
1395
|
});
|
|
1387
1396
|
return o !== null && "html" in o ? o.html : void 0;
|
|
1388
1397
|
}
|
|
1389
|
-
}), Xt =
|
|
1398
|
+
}), Xt = ot(f), Zt = dt(async (e, t) => {
|
|
1390
1399
|
let n = e.url ?? "/", i = Date.now(), a = {};
|
|
1391
1400
|
for (let [t, n] of Object.entries(e.headers)) n !== void 0 && (a[t.toLowerCase()] = Array.isArray(n) ? n.join(", ") : n);
|
|
1392
|
-
let o = n.split("?")[0] ?? "/", s = (e.method ?? "GET").toUpperCase(), c =
|
|
1401
|
+
let o = n.split("?")[0] ?? "/", s = (e.method ?? "GET").toUpperCase(), c = he(Jt, o);
|
|
1393
1402
|
if (c !== void 0) {
|
|
1394
1403
|
let e = await y(Jt, c);
|
|
1395
1404
|
t.writeHead(e.status, {
|
|
@@ -1400,7 +1409,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
1400
1409
|
}
|
|
1401
1410
|
if (!(o.startsWith(x) && await Yt(e, t))) {
|
|
1402
1411
|
if (s === "OPTIONS" && o.startsWith("/_voltro/inspect")) {
|
|
1403
|
-
let e =
|
|
1412
|
+
let e = Oe(a.origin);
|
|
1404
1413
|
t.writeHead(204, e), t.end();
|
|
1405
1414
|
return;
|
|
1406
1415
|
}
|
|
@@ -1410,13 +1419,13 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
1410
1419
|
t.writeHead(400, { "content-type": "text/plain" }), t.end("missing ?target=");
|
|
1411
1420
|
return;
|
|
1412
1421
|
}
|
|
1413
|
-
if (!
|
|
1422
|
+
if (!F(r)) {
|
|
1414
1423
|
t.writeHead(400, { "content-type": "text/plain" }), t.end("target not allowed: must be loopback or an origin configured in VOLTRO_DASHBOARD_APPS");
|
|
1415
1424
|
return;
|
|
1416
1425
|
}
|
|
1417
1426
|
try {
|
|
1418
1427
|
let n = { accept: a.accept ?? "application/json" }, i = a.authorization;
|
|
1419
|
-
i ? n.authorization = Array.isArray(i) ? i[0] : i :
|
|
1428
|
+
i ? n.authorization = Array.isArray(i) ? i[0] : i : De(r) && process.env.VOLTRO_INSPECT_TOKEN && (n.authorization = `Bearer ${process.env.VOLTRO_INSPECT_TOKEN}`);
|
|
1420
1429
|
let o;
|
|
1421
1430
|
if (s && s !== "GET" && s !== "HEAD") {
|
|
1422
1431
|
let t = [];
|
|
@@ -1446,14 +1455,14 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
1446
1455
|
t.writeHead(400, { "content-type": "text/plain" }), t.end("missing ?target=");
|
|
1447
1456
|
return;
|
|
1448
1457
|
}
|
|
1449
|
-
if (!
|
|
1458
|
+
if (!F(r)) {
|
|
1450
1459
|
t.writeHead(400, { "content-type": "text/plain" }), t.end("target not allowed: must be loopback or an origin configured in VOLTRO_DASHBOARD_APPS");
|
|
1451
1460
|
return;
|
|
1452
1461
|
}
|
|
1453
1462
|
let i = new AbortController();
|
|
1454
1463
|
e.on("close", () => i.abort()), t.on("close", () => i.abort());
|
|
1455
1464
|
try {
|
|
1456
|
-
let e =
|
|
1465
|
+
let e = Ee(a, r), n = await fetch(r, {
|
|
1457
1466
|
redirect: "manual",
|
|
1458
1467
|
method: "GET",
|
|
1459
1468
|
headers: {
|
|
@@ -1488,15 +1497,15 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
1488
1497
|
return;
|
|
1489
1498
|
}
|
|
1490
1499
|
if (o === "/_voltro/inspect/stream") {
|
|
1491
|
-
let n =
|
|
1492
|
-
if (
|
|
1500
|
+
let n = Oe(a.origin);
|
|
1501
|
+
if (Ae()) {
|
|
1493
1502
|
t.writeHead(503, {
|
|
1494
1503
|
"content-type": "application/json",
|
|
1495
1504
|
...n
|
|
1496
1505
|
}), t.end(JSON.stringify({ error: "inspect disabled (VOLTRO_INSPECT=off)" }));
|
|
1497
1506
|
return;
|
|
1498
1507
|
}
|
|
1499
|
-
let i =
|
|
1508
|
+
let i = je(a, "GET");
|
|
1500
1509
|
if (!i.ok) {
|
|
1501
1510
|
t.writeHead(401, {
|
|
1502
1511
|
"content-type": "application/json",
|
|
@@ -1518,7 +1527,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
1518
1527
|
let o = h.subscribe((e) => {
|
|
1519
1528
|
t.write(r(e));
|
|
1520
1529
|
}), s = setInterval(() => {
|
|
1521
|
-
t.write(
|
|
1530
|
+
t.write(Ce());
|
|
1522
1531
|
}, 15e3), c = () => {
|
|
1523
1532
|
clearInterval(s), o();
|
|
1524
1533
|
};
|
|
@@ -1527,13 +1536,13 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
1527
1536
|
}
|
|
1528
1537
|
try {
|
|
1529
1538
|
let e = await Kt(n, a);
|
|
1530
|
-
if (e.stream ? e.stream(t) :
|
|
1539
|
+
if (e.stream ? e.stream(t) : gt({
|
|
1531
1540
|
response: t,
|
|
1532
1541
|
status: e.status,
|
|
1533
1542
|
headers: e.headers,
|
|
1534
1543
|
body: e.body,
|
|
1535
1544
|
requestHeaders: a,
|
|
1536
|
-
compression:
|
|
1545
|
+
compression: ve.compression
|
|
1537
1546
|
}) || (t.writeHead(e.status, e.headers), t.end(e.body)), !o.startsWith("/_voltro/inspect")) {
|
|
1538
1547
|
let t = Date.now() - i;
|
|
1539
1548
|
h.emit("request", {
|
|
@@ -1543,7 +1552,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
1543
1552
|
renderedBy: e.headers["x-voltro-rendered-by"],
|
|
1544
1553
|
cache: e.headers["x-voltro-cache"]
|
|
1545
1554
|
});
|
|
1546
|
-
let n =
|
|
1555
|
+
let n = Ft(o, W)?.route.pattern ?? (e.status === 404 ? "<unmatched>" : "<asset>");
|
|
1547
1556
|
Vt.record({
|
|
1548
1557
|
kind: "request",
|
|
1549
1558
|
tag: n,
|
|
@@ -1556,62 +1565,62 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
1556
1565
|
}
|
|
1557
1566
|
}
|
|
1558
1567
|
});
|
|
1559
|
-
await new Promise((e) => Zt.listen(_, "::", e)), qt = !0, n.mark("ready"),
|
|
1568
|
+
await new Promise((e) => Zt.listen(_, "::", e)), qt = !0, n.mark("ready"), it(Zt, Xt), J.info(`listening on http://localhost:${_}`, {
|
|
1560
1569
|
port: _,
|
|
1561
1570
|
distDir: b
|
|
1562
|
-
}),
|
|
1571
|
+
}), J.debug("dynamic + ssr/isr routes resolve via SSR loader");
|
|
1563
1572
|
try {
|
|
1564
|
-
await
|
|
1565
|
-
id:
|
|
1566
|
-
name:
|
|
1573
|
+
await We({
|
|
1574
|
+
id: T,
|
|
1575
|
+
name: w,
|
|
1567
1576
|
kind: "web",
|
|
1568
1577
|
url: `http://localhost:${_}`,
|
|
1569
1578
|
pid: process.pid,
|
|
1570
1579
|
status: "live",
|
|
1571
|
-
logFile:
|
|
1580
|
+
logFile: E.path
|
|
1572
1581
|
});
|
|
1573
|
-
let e =
|
|
1582
|
+
let e = Se(t);
|
|
1574
1583
|
if (e) {
|
|
1575
|
-
let t = await
|
|
1576
|
-
t.status === "launched" ?
|
|
1584
|
+
let t = await ye({ dashboardAppPath: e });
|
|
1585
|
+
t.status === "launched" ? J.info(`dashboard launched at http://localhost:${t.port}`, { port: t.port }) : t.status === "already-running" && J.debug(`dashboard already running on :${t.port}`, { port: t.port });
|
|
1577
1586
|
}
|
|
1578
1587
|
setInterval(() => {
|
|
1579
|
-
|
|
1580
|
-
id:
|
|
1581
|
-
name:
|
|
1588
|
+
We({
|
|
1589
|
+
id: T,
|
|
1590
|
+
name: w,
|
|
1582
1591
|
kind: "web",
|
|
1583
1592
|
url: `http://localhost:${_}`,
|
|
1584
1593
|
pid: process.pid,
|
|
1585
1594
|
status: "live",
|
|
1586
|
-
logFile:
|
|
1595
|
+
logFile: E.path
|
|
1587
1596
|
}).catch(() => {});
|
|
1588
1597
|
}, 1e4).unref();
|
|
1589
1598
|
} catch (e) {
|
|
1590
|
-
|
|
1599
|
+
J.warn("runtime-registry write failed", {}, e);
|
|
1591
1600
|
}
|
|
1592
|
-
|
|
1601
|
+
et({
|
|
1593
1602
|
app: f.name ?? "unnamed",
|
|
1594
1603
|
kind: "web",
|
|
1595
1604
|
url: `http://localhost:${_}`,
|
|
1596
1605
|
bootMs: n.total()
|
|
1597
1606
|
});
|
|
1598
1607
|
let Qt = n.phaseBreakdown();
|
|
1599
|
-
|
|
1608
|
+
J.info(`start: ready in ${n.total()}ms`, {
|
|
1600
1609
|
bootMs: n.total(),
|
|
1601
1610
|
...Qt ? { phases: Qt } : {}
|
|
1602
1611
|
});
|
|
1603
1612
|
let $t = !1, en = (e) => async () => {
|
|
1604
1613
|
if (!$t) {
|
|
1605
|
-
if ($t = !0,
|
|
1606
|
-
|
|
1614
|
+
if ($t = !0, J.info(`received ${e}, shutting down`, { signal: e }), Zt.close(), await It.stop(), Z) try {
|
|
1615
|
+
Z();
|
|
1607
1616
|
} catch {}
|
|
1608
1617
|
if ($) try {
|
|
1609
|
-
await
|
|
1618
|
+
await ct.runPromise($.close());
|
|
1610
1619
|
} catch {}
|
|
1611
|
-
if (
|
|
1612
|
-
await
|
|
1620
|
+
if (V) try {
|
|
1621
|
+
await V.end();
|
|
1613
1622
|
} catch {}
|
|
1614
|
-
await
|
|
1623
|
+
await G.close(), await Ke(T), await E.dispose(), process.exit(0);
|
|
1615
1624
|
}
|
|
1616
1625
|
};
|
|
1617
1626
|
process.on("SIGINT", en("SIGINT")), process.on("SIGTERM", en("SIGTERM"));
|
|
@@ -1624,9 +1633,9 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
1624
1633
|
}
|
|
1625
1634
|
return new Promise(() => {});
|
|
1626
1635
|
}, Vt = async (e) => {
|
|
1627
|
-
|
|
1628
|
-
let n = e.find((e) => !e.startsWith("-")) ?? process.cwd(), r = await $(
|
|
1629
|
-
return r.ran ? r.exitCode : (
|
|
1636
|
+
rt("start"), t("start");
|
|
1637
|
+
let n = e.find((e) => !e.startsWith("-")) ?? process.cwd(), r = await $(z(n));
|
|
1638
|
+
return r.ran ? r.exitCode : (J.error("no web app found at this path"), 1);
|
|
1630
1639
|
};
|
|
1631
1640
|
//#endregion
|
|
1632
1641
|
export { $ as n, Vt as t };
|