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