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