@voltro/cli 0.53.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 +335 -0
- package/dist/{agentsMd-0l980yhL.js → agentsMd-BaLC10Na.js} +110 -82
- package/dist/agentsMd-DCY1RSs8.js +2 -0
- package/dist/{apiBuild-CaPfoWku.js → apiBuild-CMvLJM_K.js} +2 -2
- package/dist/apiBuild-Cl0IDx8c.js +2 -0
- package/dist/bin.js +1 -1
- package/dist/{build-D-OnvNMf.js → build-S0QOzqPT.js} +115 -115
- package/dist/{checkCommand-D2ZduVlh.js → checkCommand-DNkY5kwF.js} +1 -1
- package/dist/{checkCommand-C5elt0tW.js → checkCommand-fbj9GDjN.js} +6 -6
- package/dist/{cloudCmd-QUXh-b5w.js → cloudCmd-DzKcSYuy.js} +1 -1
- package/dist/codegen-CN6vMM4J.js +2 -0
- package/dist/{codegen-FEk8AZHb.js → codegen-SIepQtUl.js} +76 -65
- package/dist/codegenCommand-3TDJezom.js +42 -0
- package/dist/{codemodRunner-BjtB2lq6.js → codemodRunner-C2zxZUIw.js} +64 -9
- package/dist/{commands-DyxAmhP0.js → commands-BBYJ7Q3B.js} +96 -73
- package/dist/{dashboardCommand-BdKTyT13.js → dashboardCommand-D2kmyCLL.js} +3 -3
- package/dist/{dataCommand-Bab9X7s8.js → dataCommand-BEPPQiTl.js} +267 -195
- package/dist/dbCommand-BTyBGhIA.js +2 -0
- package/dist/{dbCommand-06O2finM.js → dbCommand-DZTmOFT4.js} +3 -3
- package/dist/{dev-C6LGF4iY.js → dev-Ca_A_S9v.js} +2439 -2397
- package/dist/{dev-GjJWAYo2.js → dev-DfVZaoys.js} +1 -1
- package/dist/{doctorCommand-etMkflRc.js → doctorCommand-CGZJK_4o.js} +21 -21
- package/dist/doctorCommand-djmqEcDC.js +2 -0
- package/dist/{dormancyCommand-UwZ1AZzB.js → dormancyCommand-DY2rYpTa.js} +1 -1
- package/dist/{embeddingsCommand-C70zWHwo.js → embeddingsCommand-BoCqZsgp.js} +1 -1
- package/dist/{envCommand-dSyKvRkM.js → envCommand-Bxy2fOjc.js} +15 -15
- package/dist/{evolveCommand-CG0_ebO5.js → evolveCommand-BsbZ-XDg.js} +2 -2
- package/dist/fileConventions-l-RIXbx8.js +36 -0
- package/dist/{fileTaxonomy-B7uxipWS.js → fileTaxonomy-CbyMQYx_.js} +37 -37
- package/dist/frameworkTableAssembly-Df2Ymp2f.js +2 -0
- package/dist/{frameworkTableAssembly-DKx3ba3S.js → frameworkTableAssembly-Do-cf6RJ.js} +96 -102
- package/dist/index.js +2 -2
- package/dist/{infoCommand-_53iOc_j.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/{metaCommands-Cn2oboG4.js → metaCommands-x7RCi2AF.js} +2 -2
- package/dist/{migrate-Cko9rswM.js → migrate-CGFZS-1a.js} +2 -2
- package/dist/mobileCommand-D9O6iq3D.js +428 -0
- package/dist/mobileCommand-DAum7tsG.js +2 -0
- package/dist/{pageConvention-C938S8oC.js → pageConvention-CMpfDN6r.js} +1 -1
- package/dist/{privacyCommand-DWTQMC6R.js → privacyCommand-BCa2OoZG.js} +2 -2
- package/dist/{probeCommand-DkGGLknv.js → probeCommand-Bs3iVBSL.js} +1 -1
- package/dist/{projectScaffold-EzlErR4E.js → projectScaffold-CJfP-xbT.js} +1 -1
- package/dist/{projectScaffold-B4dmTlwT.js → projectScaffold-CSN0OzBV.js} +2 -2
- package/dist/renderModeScan-43yQ2opo.js +147 -0
- package/dist/{renderProfile-CskIgAfn.js → renderProfile-DvrhVJHa.js} +2 -2
- package/dist/{runtimeTrace-c0APJz7E.js → runtimeTrace-C1BTpHGQ.js} +1 -1
- package/dist/{sdkgen-BiQCgIEr.js → sdkgen-CXMwLg9n.js} +1 -1
- package/dist/{serveCommand-CueKQgzl.js → serveCommand-C7IrCD58.js} +899 -897
- package/dist/serveCommand-Cjt5S9hD.js +2 -0
- package/dist/serveEntry.js +1 -1
- package/dist/start-DH7cat4-.js +3 -0
- package/dist/{start-ekPan8BT.js → start-EOV7s1NZ.js} +544 -527
- package/dist/startEntry.js +1 -1
- package/dist/{staticCommand-xlSL-IWk.js → staticCommand-ey0kYmOT.js} +1 -1
- package/dist/{subcommandNames-DpYs3DXr.js → subcommandNames-CDzfEtKV.js} +3 -3
- package/dist/{templates-BR-fb4SP.js → templates-BTWZkJJT.js} +41 -9
- package/dist/{test-BWPQcRoB.js → test-DO27-x2P.js} +1 -1
- package/dist/{updateCommand-C_8I8Rzo.js → updateCommand-C_jN1w18.js} +1 -1
- package/dist/updateCommand-nnFjDbl4.js +2 -0
- package/dist/{webDev-C7jWJ5dX.js → webDev-1XpVnYkW.js} +1 -1
- package/dist/{webDev-oczpugbx.js → webDev-B7vNj4Bq.js} +1231 -1186
- package/dist/{webhooksCommand-4SVPDjKg.js → webhooksCommand-B1LVcyO3.js} +1 -1
- package/dist/workspaceDeps-RKEkX92S.js +45 -0
- package/package.json +31 -19
- package/templates/AGENTS.core.md +2 -0
- package/templates/AGENTS.md +4 -2
- package/templates/agent-docs/_index.md +2 -2
- package/templates/agent-docs/_manifest.json +1 -1
- package/templates/agent-docs/ai.md +4 -4
- package/templates/agent-docs/authentication.md +115 -0
- package/templates/agent-docs/cli.md +98 -12
- package/templates/agent-docs/data.md +121 -21
- package/templates/agent-docs/database/advancedqueries.md +1 -1
- package/templates/agent-docs/database/migrations.md +1 -1
- package/templates/agent-docs/database/seedsdialects.md +64 -2
- package/templates/agent-docs/internationalization.md +2 -0
- package/templates/agent-docs/introduction.md +25 -0
- package/templates/agent-docs/local-first-mobile.md +139 -41
- package/templates/agent-docs/observability.md +4 -2
- package/templates/agent-docs/plugins/atlassian.md +2 -2
- package/templates/agent-docs/plugins/audit.md +2 -2
- package/templates/agent-docs/plugins/billing.md +1 -1
- package/templates/agent-docs/plugins/cdc-out.md +8 -3
- package/templates/agent-docs/plugins/comments.md +22 -0
- package/templates/agent-docs/plugins/presence.md +32 -3
- package/templates/agent-docs/plugins/prometheus.md +2 -0
- package/templates/agent-docs/plugins/queue.md +47 -4
- package/templates/agent-docs/plugins.md +52 -14
- package/templates/agent-docs/reference.md +25 -4
- package/templates/agent-docs/routing.md +81 -9
- package/templates/agent-docs/scheduling.md +1 -1
- package/templates/agent-docs/schema-driven-ui.md +137 -1
- package/templates/agent-docs/templates/appshells.md +36 -4
- package/templates/agent-docs/whats-new.md +75 -158
- 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/README.md +3 -3
- package/templates/apps/api-collab/app.config.ts +1 -1
- package/templates/apps/api-collab/database/schema.ts +12 -8
- package/templates/apps/api-collab/mutations/documents.create.mutation.server.ts +1 -1
- package/templates/apps/api-collab/mutations/documents.setBody.mutation.server.ts +1 -1
- package/templates/apps/api-collab/mutations/documents.setBody.mutation.ts +1 -1
- package/templates/apps/api-collab/package.json +8 -8
- package/templates/apps/api-collab/template.json +1 -1
- package/templates/apps/api-collab/tests/documents.setBody.test.ts +10 -2
- 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 -10
- 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 -6
- 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/README.md +43 -24
- package/templates/apps/frontend-collab/app.config.ts +3 -3
- package/templates/apps/frontend-collab/package.json +14 -10
- package/templates/apps/frontend-collab/src/locales/de.ts +1 -2
- package/templates/apps/frontend-collab/src/locales/en.ts +1 -2
- package/templates/apps/frontend-collab/src/pages/page.test.tsx +72 -76
- package/templates/apps/frontend-collab/src/pages/page.tsx +45 -22
- package/templates/apps/frontend-collab/template.json +2 -2
- 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 -7
- package/templates/apps/frontend-i18n/package.json +6 -6
- package/templates/apps/frontend-landing/README.md +48 -0
- package/templates/apps/frontend-landing/app.config.ts +28 -0
- package/templates/apps/frontend-landing/package.json +7 -6
- package/templates/apps/frontend-landing/src/assets/hero.jpg +0 -0
- package/templates/apps/frontend-landing/src/fonts/Geist-Variable.woff2 +0 -0
- package/templates/apps/frontend-landing/src/fonts/LICENSE-Geist.txt +92 -0
- package/templates/apps/frontend-landing/src/globals.css +15 -0
- package/templates/apps/frontend-landing/src/globals.d.ts +17 -0
- package/templates/apps/frontend-landing/src/locales/de.ts +3 -2
- package/templates/apps/frontend-landing/src/locales/en.ts +5 -2
- package/templates/apps/frontend-landing/src/pages/page.test.tsx +79 -0
- package/templates/apps/frontend-landing/src/pages/page.tsx +26 -3
- package/templates/apps/frontend-landing/template.json +2 -2
- 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 -7
- package/templates/apps/frontend-status/package.json +8 -8
- package/templates/apps/mobile-app/package.json +12 -11
- package/templates/apps/mobile-app/src/lib/deeplinks.ts +29 -17
- package/templates/apps/mobile-app/tests/deeplinks.test.ts +16 -0
- package/dist/agentsMd-SDDSkyl4.js +0 -2
- package/dist/apiBuild-DHtLXYx9.js +0 -2
- package/dist/codegen-BWpt3VgF.js +0 -2
- package/dist/codegenCommand-BOiWQ5hz.js +0 -137
- package/dist/dbCommand-B1EXBC6f.js +0 -2
- package/dist/doctorCommand-B0hX0tdz.js +0 -2
- package/dist/fileConventions-DASGEmj-.js +0 -35
- package/dist/frameworkTableAssembly-C_7Z-rMs.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/renderModeScan-CUbOeOAg.js +0 -122
- package/dist/serveCommand-DsnrVN3U.js +0 -2
- package/dist/start-BJzZLbt8.js +0 -3
- package/dist/updateCommand-Bqql_rsQ.js +0 -2
|
@@ -1,43 +1,43 @@
|
|
|
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,
|
|
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
|
|
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"],
|
|
33
33
|
options: e.compression
|
|
34
|
-
}),
|
|
34
|
+
}), ee = {
|
|
35
35
|
...r,
|
|
36
|
-
...
|
|
36
|
+
...f.headers,
|
|
37
37
|
etag: u
|
|
38
38
|
};
|
|
39
|
-
return
|
|
40
|
-
},
|
|
39
|
+
return f.compressed && delete ee["content-length"], t.writeHead(n, ee), t.end(Buffer.from(f.bytes)), !0;
|
|
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 Je = (e) => `W/"${J("md5").update(e).digest("hex")}"`, Ye = (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 Je = (e) => `W/"${J("md5").update(e).digest("hex")}"`, Ye = (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 Je = (e) => `W/"${J("md5").update(e).digest("hex")}"`, Ye = (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,33 +288,43 @@ 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
307
|
search: _,
|
|
298
|
-
headers:
|
|
299
|
-
cookies: u(
|
|
308
|
+
headers: m,
|
|
309
|
+
cookies: u(m.cookie),
|
|
300
310
|
route: n.pattern
|
|
301
|
-
}, e.onCookieWarning),
|
|
302
|
-
apiName:
|
|
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,
|
|
303
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
324
|
search: _,
|
|
315
325
|
signal: e.signal,
|
|
316
326
|
headers: T,
|
|
317
|
-
query:
|
|
327
|
+
query: E,
|
|
318
328
|
isServer: !0
|
|
319
329
|
},
|
|
320
330
|
helpers: await t.getHelpers(),
|
|
@@ -323,12 +333,12 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
323
333
|
setCookies: v.setCookies
|
|
324
334
|
};
|
|
325
335
|
}
|
|
326
|
-
let D =
|
|
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),
|
|
@@ -336,210 +346,213 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
336
346
|
params: r,
|
|
337
347
|
pathname: a,
|
|
338
348
|
search: _,
|
|
339
|
-
signal:
|
|
340
|
-
headers:
|
|
341
|
-
query:
|
|
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
357
|
search: _,
|
|
348
|
-
signal:
|
|
349
|
-
headers:
|
|
350
|
-
query:
|
|
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
368
|
setCookies: v.setCookies,
|
|
359
369
|
responseHeaders: v.responseHeaders
|
|
360
370
|
};
|
|
361
|
-
if (
|
|
371
|
+
if (ct(e)) return {
|
|
362
372
|
control: "not-found",
|
|
363
373
|
setCookies: v.setCookies,
|
|
364
374
|
responseHeaders: v.responseHeaders
|
|
365
375
|
};
|
|
366
376
|
throw e;
|
|
367
377
|
}
|
|
368
|
-
let
|
|
369
|
-
D || await
|
|
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
|
-
},
|
|
412
|
+
}, M = y.interactive ?? "full";
|
|
403
413
|
if (D) {
|
|
404
|
-
let e =
|
|
405
|
-
helpers:
|
|
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
423
|
search: _,
|
|
414
|
-
segmentLoaderData:
|
|
415
|
-
requestContext:
|
|
416
|
-
...
|
|
417
|
-
outerWrap:
|
|
418
|
-
locale:
|
|
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
|
-
let n =
|
|
438
|
+
let n = f({ shell: d });
|
|
429
439
|
return {
|
|
430
440
|
renderMode: "spa",
|
|
431
441
|
setCookies: v.setCookies,
|
|
432
442
|
responseHeaders: v.responseHeaders,
|
|
433
|
-
stream: (r) =>
|
|
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
|
-
|
|
454
|
+
...v.cspNonce === void 0 ? {} : { nonce: v.cspNonce },
|
|
455
|
+
render: (t) => k.renderPageToStream({
|
|
445
456
|
...e.renderInput,
|
|
446
|
-
...t
|
|
457
|
+
...t,
|
|
458
|
+
...v.cspNonce === void 0 ? {} : { nonce: v.cspNonce }
|
|
447
459
|
}),
|
|
448
460
|
onShellError: (e) => {
|
|
449
|
-
|
|
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");
|
|
450
462
|
}
|
|
451
463
|
})
|
|
452
464
|
};
|
|
453
465
|
}
|
|
454
|
-
let i =
|
|
455
|
-
helpers:
|
|
466
|
+
let i = te({
|
|
467
|
+
helpers: k,
|
|
456
468
|
prepared: e
|
|
457
|
-
});
|
|
469
|
+
}), s = o(C(d.replace("<div id=\"root\"></div>", `<div id="root">${i.body}</div>`), t(i.meta)), j);
|
|
458
470
|
return {
|
|
459
|
-
html:
|
|
471
|
+
html: v.cspNonce === void 0 ? s : S(s, v.cspNonce),
|
|
460
472
|
renderMode: "spa",
|
|
461
473
|
revalidateMs: null,
|
|
462
474
|
setCookies: v.setCookies,
|
|
463
475
|
responseHeaders: v.responseHeaders
|
|
464
476
|
};
|
|
465
477
|
}
|
|
466
|
-
let
|
|
467
|
-
helpers:
|
|
478
|
+
let N = p({
|
|
479
|
+
helpers: k,
|
|
468
480
|
page: n.pattern,
|
|
469
481
|
pathname: a,
|
|
470
|
-
renderMode:
|
|
471
|
-
interactive:
|
|
472
|
-
loaderData:
|
|
473
|
-
segmentLoaderData:
|
|
474
|
-
pageLoaderRan: typeof
|
|
475
|
-
...
|
|
482
|
+
renderMode: x,
|
|
483
|
+
interactive: M,
|
|
484
|
+
loaderData: ue,
|
|
485
|
+
segmentLoaderData: le,
|
|
486
|
+
pageLoaderRan: typeof y.loader == "function",
|
|
487
|
+
...ae ? { ppr: !0 } : {}
|
|
476
488
|
});
|
|
477
|
-
|
|
478
|
-
let
|
|
479
|
-
descriptor:
|
|
489
|
+
ae && b(N.stateInput, n.pattern);
|
|
490
|
+
let ve = {
|
|
491
|
+
descriptor: he,
|
|
480
492
|
params: r,
|
|
481
493
|
pathname: a,
|
|
482
494
|
search: _,
|
|
483
|
-
loaderData:
|
|
484
|
-
segmentLoaderData:
|
|
485
|
-
requestContext:
|
|
486
|
-
...
|
|
487
|
-
outerWrap:
|
|
488
|
-
locale:
|
|
495
|
+
loaderData: N.loaderData,
|
|
496
|
+
segmentLoaderData: N.segmentLoaderData,
|
|
497
|
+
requestContext: ge,
|
|
498
|
+
...A ? {
|
|
499
|
+
outerWrap: A.outerWrap,
|
|
500
|
+
locale: A.locale
|
|
489
501
|
} : {}
|
|
490
|
-
},
|
|
491
|
-
if (
|
|
492
|
-
let r = T["x-tenant"], i =
|
|
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({
|
|
493
505
|
pattern: n.pattern,
|
|
494
506
|
params: e.params,
|
|
495
507
|
...r === void 0 ? {} : { tenant: r }
|
|
496
508
|
});
|
|
497
509
|
return `<meta property="og:image" content="${i}" /><meta name="twitter:image" content="${i}" /><meta name="twitter:card" content="summary_large_image" />`;
|
|
498
|
-
},
|
|
499
|
-
|
|
500
|
-
`<meta name="voltro-interactive" content="${
|
|
501
|
-
...
|
|
502
|
-
|
|
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)
|
|
503
515
|
].filter((e) => e.length > 0).join("\n ");
|
|
504
|
-
if (
|
|
505
|
-
let e =
|
|
516
|
+
if (x === "ssr" && M === "full" && e.buffered !== !0) {
|
|
517
|
+
let e = f({ shell: d });
|
|
506
518
|
return {
|
|
507
519
|
renderMode: "ssr",
|
|
508
520
|
setCookies: v.setCookies,
|
|
509
|
-
stream: (t) =>
|
|
521
|
+
stream: (t) => oe({
|
|
510
522
|
res: t,
|
|
511
523
|
shell: e,
|
|
512
|
-
documentAttrs:
|
|
524
|
+
documentAttrs: j,
|
|
513
525
|
headers: {
|
|
514
526
|
...v.responseHeaders,
|
|
515
527
|
"content-type": "text/html; charset=utf-8",
|
|
516
528
|
"x-voltro-rendered-by": "ssr",
|
|
517
|
-
...
|
|
529
|
+
...h(v.setCookies)
|
|
518
530
|
},
|
|
519
|
-
headInjection:
|
|
520
|
-
|
|
521
|
-
|
|
531
|
+
headInjection: be,
|
|
532
|
+
...v.cspNonce === void 0 ? {} : { nonce: v.cspNonce },
|
|
533
|
+
render: (e) => k.renderPageToStream({
|
|
534
|
+
...ve,
|
|
522
535
|
...e,
|
|
523
536
|
...v.cspNonce === void 0 ? {} : { nonce: v.cspNonce }
|
|
524
537
|
}),
|
|
525
538
|
onShellError: (e) => {
|
|
526
|
-
|
|
539
|
+
Z.error("ssr shell render failed", { pathname: a }, e), t.writeHead(500, { "content-type": "text/plain; charset=utf-8" }), t.end("server error");
|
|
527
540
|
}
|
|
528
541
|
})
|
|
529
542
|
};
|
|
530
543
|
}
|
|
531
|
-
let { html:
|
|
532
|
-
|
|
533
|
-
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;
|
|
534
547
|
return {
|
|
535
|
-
html: v.cspNonce === void 0 ?
|
|
536
|
-
renderMode:
|
|
537
|
-
revalidateMs:
|
|
548
|
+
html: v.cspNonce === void 0 ? I : S(I, v.cspNonce),
|
|
549
|
+
renderMode: x,
|
|
550
|
+
revalidateMs: Te,
|
|
538
551
|
setCookies: v.setCookies,
|
|
539
552
|
responseHeaders: v.responseHeaders
|
|
540
553
|
};
|
|
541
|
-
},
|
|
542
|
-
let t = await import(
|
|
554
|
+
}, Q = (e) => e === "" ? "/" : e, bt = async (e) => {
|
|
555
|
+
let t = await import(U(e).href);
|
|
543
556
|
return {
|
|
544
557
|
kind: "bundle",
|
|
545
558
|
getPageMeta: () => t.pageMeta,
|
|
@@ -549,18 +562,18 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
549
562
|
return typeof r == "function" ? await r() : r;
|
|
550
563
|
},
|
|
551
564
|
async getLayout(e) {
|
|
552
|
-
let n = t.layouts[
|
|
553
|
-
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)}`);
|
|
554
567
|
return typeof n == "function" ? await n() : n;
|
|
555
568
|
},
|
|
556
569
|
async getError(e) {
|
|
557
|
-
let n = t.errors[
|
|
558
|
-
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)}`);
|
|
559
572
|
return typeof n == "function" ? await n() : n;
|
|
560
573
|
},
|
|
561
574
|
async getPending(e) {
|
|
562
|
-
let n = t.pendings[
|
|
563
|
-
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)}`);
|
|
564
577
|
return typeof n == "function" ? await n() : n;
|
|
565
578
|
},
|
|
566
579
|
async getHelpers() {
|
|
@@ -568,8 +581,8 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
568
581
|
},
|
|
569
582
|
async close() {}
|
|
570
583
|
};
|
|
571
|
-
},
|
|
572
|
-
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({
|
|
573
586
|
root: t,
|
|
574
587
|
envPrefix: "__VOLTRO_VITE_ENV_DISABLED__",
|
|
575
588
|
plugins: [r(), i()],
|
|
@@ -586,203 +599,203 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
586
599
|
},
|
|
587
600
|
appType: "custom",
|
|
588
601
|
logLevel: "warn"
|
|
589
|
-
}),
|
|
590
|
-
limit:
|
|
591
|
-
onColdStart: (e) =>
|
|
592
|
-
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`, {
|
|
593
606
|
id: e,
|
|
594
607
|
ms: t,
|
|
595
608
|
...n ? { failed: !0 } : {}
|
|
596
609
|
})
|
|
597
|
-
}),
|
|
610
|
+
}), l = (e) => c.load(e, async () => await a.ssrLoadModule(e));
|
|
598
611
|
return {
|
|
599
612
|
kind: "middleware",
|
|
600
613
|
async getPage(e, t) {
|
|
601
|
-
return
|
|
614
|
+
return l(V(o, t));
|
|
602
615
|
},
|
|
603
616
|
async getLayout(e) {
|
|
604
|
-
return
|
|
617
|
+
return l(V(s(e), "layout.tsx"));
|
|
605
618
|
},
|
|
606
619
|
async getError(e) {
|
|
607
|
-
return
|
|
620
|
+
return l(V(s(e), "error.tsx"));
|
|
608
621
|
},
|
|
609
622
|
async getPending(e) {
|
|
610
|
-
return
|
|
623
|
+
return l(V(s(e), "loading.tsx"));
|
|
611
624
|
},
|
|
612
625
|
async getHelpers() {
|
|
613
|
-
return await
|
|
626
|
+
return await l("@voltro/web/ssr");
|
|
614
627
|
},
|
|
615
628
|
async close() {
|
|
616
|
-
await
|
|
629
|
+
await a.close();
|
|
617
630
|
}
|
|
618
631
|
};
|
|
619
|
-
},
|
|
620
|
-
let i =
|
|
621
|
-
if (!
|
|
632
|
+
}, $ = async (t) => {
|
|
633
|
+
let i = Ue(), o = await ve(t);
|
|
634
|
+
if (!o) return {
|
|
622
635
|
ran: !1,
|
|
623
636
|
exitCode: 0
|
|
624
637
|
};
|
|
625
|
-
if (
|
|
638
|
+
if (o.type !== "web") return Z.error("only web apps are supported by `voltro start`"), {
|
|
626
639
|
ran: !0,
|
|
627
640
|
exitCode: 1
|
|
628
641
|
};
|
|
629
642
|
{
|
|
630
|
-
let e =
|
|
631
|
-
if (e !== void 0) return
|
|
643
|
+
let e = y(o);
|
|
644
|
+
if (e !== void 0) return Z.error(`voltro start: refusing to boot — ${e}`), {
|
|
632
645
|
ran: !0,
|
|
633
646
|
exitCode: 1
|
|
634
647
|
};
|
|
635
648
|
}
|
|
636
|
-
let { resolved:
|
|
637
|
-
rawEnv:
|
|
649
|
+
let { resolved: c } = await ae({
|
|
650
|
+
rawEnv: o.env,
|
|
638
651
|
appType: "web",
|
|
639
652
|
root: t,
|
|
640
|
-
log:
|
|
653
|
+
log: Z,
|
|
641
654
|
generateTypes: !1
|
|
642
|
-
}),
|
|
655
|
+
}), l = c.publicValues;
|
|
643
656
|
i.mark("config");
|
|
644
|
-
let
|
|
645
|
-
|
|
646
|
-
let
|
|
657
|
+
let f = ce();
|
|
658
|
+
E(f), Z.info("booting voltro start", { app: o.name ?? "(unnamed)" });
|
|
659
|
+
let te = n({
|
|
647
660
|
kind: "web",
|
|
648
|
-
configPort:
|
|
661
|
+
configPort: o.port,
|
|
649
662
|
env: process.env,
|
|
650
|
-
dashboardPin: process.env[
|
|
663
|
+
dashboardPin: process.env[T] === "1"
|
|
651
664
|
});
|
|
652
|
-
for (let e of
|
|
653
|
-
let
|
|
654
|
-
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 }), {
|
|
655
668
|
ran: !0,
|
|
656
669
|
exitCode: 1
|
|
657
670
|
};
|
|
658
|
-
let
|
|
659
|
-
await
|
|
660
|
-
id:
|
|
661
|
-
name:
|
|
671
|
+
let b = o.name ?? "unnamed", S = Ve("web", b, p), C = He(b);
|
|
672
|
+
await Re({
|
|
673
|
+
id: S,
|
|
674
|
+
name: b,
|
|
662
675
|
kind: "web",
|
|
663
|
-
url: `http://localhost:${
|
|
676
|
+
url: `http://localhost:${p}`,
|
|
664
677
|
pid: process.pid,
|
|
665
678
|
status: "booting",
|
|
666
|
-
logFile:
|
|
679
|
+
logFile: C.path
|
|
667
680
|
}).catch(() => {});
|
|
668
|
-
let
|
|
669
|
-
|
|
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`, {
|
|
670
683
|
cookie: e.name,
|
|
671
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."
|
|
672
685
|
}));
|
|
673
|
-
},
|
|
674
|
-
|
|
675
|
-
let
|
|
676
|
-
if (
|
|
677
|
-
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) {
|
|
678
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).";
|
|
679
|
-
if (e()) throw
|
|
680
|
-
|
|
681
|
-
} else
|
|
682
|
-
await s(t,
|
|
683
|
-
let
|
|
684
|
-
|
|
685
|
-
let
|
|
686
|
-
if (!
|
|
687
|
-
let
|
|
688
|
-
|
|
689
|
-
kind:
|
|
690
|
-
...
|
|
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" } : {}
|
|
691
704
|
}), i.mark("provider");
|
|
692
|
-
let
|
|
693
|
-
|
|
694
|
-
let
|
|
695
|
-
for (let e of
|
|
696
|
-
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];
|
|
697
710
|
if (t) {
|
|
698
|
-
|
|
711
|
+
J.set(e.pattern, t);
|
|
699
712
|
continue;
|
|
700
713
|
}
|
|
701
714
|
try {
|
|
702
|
-
let t = await
|
|
703
|
-
|
|
715
|
+
let t = await q.getPage(e.pattern, e.file);
|
|
716
|
+
J.set(e.pattern, Ne(t, e.file)), nt++;
|
|
704
717
|
} catch (t) {
|
|
705
|
-
|
|
718
|
+
Z.warn("failed to load page metadata", { pattern: e.pattern }, t);
|
|
706
719
|
}
|
|
707
720
|
}
|
|
708
|
-
let
|
|
709
|
-
for (let [e, t] of
|
|
721
|
+
let Y = /* @__PURE__ */ new Map();
|
|
722
|
+
for (let [e, t] of J) {
|
|
710
723
|
if (t.interactive !== "islands") continue;
|
|
711
|
-
let n =
|
|
724
|
+
let n = V(h, "island-shells", `${x(e)}.html`);
|
|
712
725
|
try {
|
|
713
|
-
|
|
726
|
+
Y.set(e, await H.readFile(n, "utf8"));
|
|
714
727
|
} catch {
|
|
715
|
-
|
|
728
|
+
Z.warn("islands page has no built per-page shell — serving the full app shell", {
|
|
716
729
|
pattern: e,
|
|
717
730
|
expected: n
|
|
718
731
|
});
|
|
719
732
|
}
|
|
720
733
|
}
|
|
721
|
-
|
|
722
|
-
count:
|
|
723
|
-
fromManifest:
|
|
724
|
-
fromModules:
|
|
734
|
+
Z.info(`registered ${J.size} route(s)`, {
|
|
735
|
+
count: J.size,
|
|
736
|
+
fromManifest: J.size - nt,
|
|
737
|
+
fromModules: nt
|
|
725
738
|
}), i.mark("routes");
|
|
726
|
-
let
|
|
727
|
-
for (let e of
|
|
728
|
-
|
|
729
|
-
let
|
|
730
|
-
for (let [e, t] of
|
|
731
|
-
let
|
|
732
|
-
for (let e of
|
|
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] });
|
|
742
|
+
let st = /* @__PURE__ */ new Map();
|
|
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);
|
|
733
746
|
{
|
|
734
|
-
let n = new Set([...
|
|
747
|
+
let n = new Set([...J].filter(([, e]) => (e.renderMode === "ssr" || e.renderMode === "isr") && e.hasOgImage).map(([e]) => e));
|
|
735
748
|
if (n.size > 0) {
|
|
736
|
-
let { secret: r, fromEnv: i } =
|
|
737
|
-
if (!i && e()) throw
|
|
738
|
-
let
|
|
739
|
-
|
|
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({
|
|
740
753
|
root: t,
|
|
741
|
-
fonts:
|
|
742
|
-
cache:
|
|
754
|
+
fonts: o.fonts,
|
|
755
|
+
cache: z,
|
|
743
756
|
secret: r,
|
|
744
757
|
isOgSsrRoute: (e) => n.has(e),
|
|
745
758
|
getPageModule: async (e) => {
|
|
746
|
-
let t =
|
|
747
|
-
return t === void 0 ? null : await
|
|
759
|
+
let t = a.get(e);
|
|
760
|
+
return t === void 0 ? null : await q.getPage(e, t);
|
|
748
761
|
}
|
|
749
|
-
}),
|
|
762
|
+
}), Z.info(`og route active for ${n.size} ssr route(s)`, { secret: i ? "env" : "per-boot" });
|
|
750
763
|
}
|
|
751
764
|
}
|
|
752
|
-
let
|
|
753
|
-
for (let [e, t] of
|
|
754
|
-
let
|
|
755
|
-
cache:
|
|
756
|
-
tableSink:
|
|
757
|
-
cache:
|
|
758
|
-
tableSubscriptionsByPattern:
|
|
759
|
-
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
|
|
760
773
|
}),
|
|
761
|
-
regexByPattern:
|
|
762
|
-
renderModeByPattern:
|
|
763
|
-
},
|
|
764
|
-
let t =
|
|
765
|
-
t &&
|
|
766
|
-
}, vt =
|
|
767
|
-
cache:
|
|
768
|
-
tableSubscriptionsByPattern:
|
|
769
|
-
regexByPattern:
|
|
770
|
-
...
|
|
771
|
-
}),
|
|
772
|
-
if (
|
|
773
|
-
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);
|
|
774
787
|
if (e.crossReplica) try {
|
|
775
|
-
|
|
776
|
-
let t =
|
|
777
|
-
|
|
788
|
+
St = e.provider;
|
|
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 });
|
|
778
791
|
} catch (e) {
|
|
779
|
-
|
|
792
|
+
Z.warn("revalidation broker subscribe failed — broker leg disabled", {}, e), St = null;
|
|
780
793
|
}
|
|
781
|
-
|
|
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.");
|
|
782
795
|
}
|
|
783
796
|
i.mark("cdc");
|
|
784
|
-
let
|
|
785
|
-
let t =
|
|
797
|
+
let Ct = Me(), wt = U.map((e) => {
|
|
798
|
+
let t = J.get(e.pattern);
|
|
786
799
|
return {
|
|
787
800
|
pattern: e.pattern,
|
|
788
801
|
file: e.file,
|
|
@@ -797,20 +810,20 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
797
810
|
hasMeta: t?.hasMeta ?? !1,
|
|
798
811
|
hasGetStaticPaths: t?.hasGetStaticPaths ?? !1
|
|
799
812
|
};
|
|
800
|
-
}),
|
|
813
|
+
}), Tt = W.map((e) => ({
|
|
801
814
|
dir: e.dir,
|
|
802
815
|
hasLayout: e.hasLayout,
|
|
803
816
|
hasError: e.hasError,
|
|
804
817
|
hasPending: e.hasPending,
|
|
805
818
|
hasNotFound: e.hasNotFound
|
|
806
|
-
})),
|
|
819
|
+
})), Et = B ? "postgres" : "memory", Dt = {
|
|
807
820
|
kind: "web",
|
|
808
821
|
meta: {
|
|
809
|
-
name:
|
|
810
|
-
voltroVersion:
|
|
811
|
-
port:
|
|
822
|
+
name: o.name ?? "(unnamed)",
|
|
823
|
+
voltroVersion: ot,
|
|
824
|
+
port: p,
|
|
812
825
|
mode: "start",
|
|
813
|
-
apis: Object.entries(
|
|
826
|
+
apis: Object.entries(o.apis ?? {}).map(([e, t]) => {
|
|
814
827
|
let n = {
|
|
815
828
|
name: e,
|
|
816
829
|
package: t.package
|
|
@@ -818,10 +831,10 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
818
831
|
return t.url !== void 0 && (n.url = t.url), n;
|
|
819
832
|
})
|
|
820
833
|
},
|
|
821
|
-
routes:
|
|
822
|
-
dirs:
|
|
834
|
+
routes: wt,
|
|
835
|
+
dirs: Tt,
|
|
823
836
|
cache: () => {
|
|
824
|
-
let e = Date.now(), t =
|
|
837
|
+
let e = Date.now(), t = z.snapshot().map(([t, n]) => ({
|
|
825
838
|
key: t,
|
|
826
839
|
renderedAt: n.renderedAt,
|
|
827
840
|
expiresAt: n.expiresAt,
|
|
@@ -832,16 +845,16 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
832
845
|
staleWhileRevalidateMs: n.staleWhileRevalidateMs
|
|
833
846
|
}));
|
|
834
847
|
return {
|
|
835
|
-
backend:
|
|
836
|
-
size:
|
|
848
|
+
backend: Et,
|
|
849
|
+
size: z.size(),
|
|
837
850
|
entries: t
|
|
838
851
|
};
|
|
839
852
|
},
|
|
840
|
-
metrics: () =>
|
|
841
|
-
},
|
|
842
|
-
let
|
|
843
|
-
if (
|
|
844
|
-
let e = await
|
|
853
|
+
metrics: () => Je()
|
|
854
|
+
}, Ot = async (e, n) => {
|
|
855
|
+
let r = e.split("?")[0] ?? "/";
|
|
856
|
+
if (o.name === "voltroDashboard" && r === "/api/dashboard/registry") try {
|
|
857
|
+
let e = await ze();
|
|
845
858
|
return {
|
|
846
859
|
status: 200,
|
|
847
860
|
headers: { "content-type": "application/json; charset=utf-8" },
|
|
@@ -854,7 +867,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
854
867
|
body: `registry read error: ${e.message}`
|
|
855
868
|
};
|
|
856
869
|
}
|
|
857
|
-
if (
|
|
870
|
+
if (o.name === "voltroDashboard" && r === "/api/dashboard/config") {
|
|
858
871
|
let e = process.env.VOLTRO_DASHBOARD_APPS, t = [];
|
|
859
872
|
if (e && e.trim().length > 0) {
|
|
860
873
|
let n;
|
|
@@ -883,27 +896,27 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
883
896
|
body: JSON.stringify({ apps: t })
|
|
884
897
|
};
|
|
885
898
|
}
|
|
886
|
-
if (
|
|
887
|
-
let t = await
|
|
899
|
+
if (gt !== null && r === "/_voltro/og") {
|
|
900
|
+
let t = await gt.handle(new URL(e, "http://localhost"));
|
|
888
901
|
if (t !== null) return {
|
|
889
902
|
status: t.status,
|
|
890
903
|
headers: { ...t.headers },
|
|
891
904
|
body: Buffer.from(t.body)
|
|
892
905
|
};
|
|
893
906
|
}
|
|
894
|
-
if (
|
|
895
|
-
let t =
|
|
907
|
+
if (r === "/_voltro/inspect/logs") {
|
|
908
|
+
let t = M(e, N(), n);
|
|
896
909
|
return {
|
|
897
910
|
status: t.status,
|
|
898
911
|
headers: {
|
|
899
912
|
"content-type": t.contentType,
|
|
900
|
-
...
|
|
913
|
+
...Te(n.origin)
|
|
901
914
|
},
|
|
902
915
|
body: t.body
|
|
903
916
|
};
|
|
904
917
|
}
|
|
905
|
-
if (
|
|
906
|
-
let t =
|
|
918
|
+
if (r !== "/_voltro/inspect/stream") {
|
|
919
|
+
let t = De(e, Dt, n);
|
|
907
920
|
if (t !== null) return {
|
|
908
921
|
status: t.status,
|
|
909
922
|
headers: {
|
|
@@ -913,227 +926,227 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
913
926
|
body: t.body
|
|
914
927
|
};
|
|
915
928
|
}
|
|
916
|
-
let
|
|
917
|
-
if (!
|
|
918
|
-
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, {
|
|
919
932
|
route: void 0,
|
|
920
|
-
pathname:
|
|
933
|
+
pathname: r
|
|
921
934
|
});
|
|
922
935
|
if (t !== void 0) {
|
|
923
|
-
let
|
|
924
|
-
pathname:
|
|
925
|
-
search: e.slice(
|
|
936
|
+
let i = await ee(t, {
|
|
937
|
+
pathname: r,
|
|
938
|
+
search: e.slice(r.length),
|
|
926
939
|
headers: n,
|
|
927
940
|
cookies: u(n.cookie),
|
|
928
941
|
route: void 0
|
|
929
942
|
});
|
|
930
|
-
|
|
943
|
+
c.push(...i.setCookies);
|
|
931
944
|
}
|
|
932
945
|
}
|
|
933
|
-
let
|
|
946
|
+
let l = (e) => c.length === 0 ? e : {
|
|
934
947
|
...e,
|
|
935
|
-
"set-cookie":
|
|
936
|
-
},
|
|
937
|
-
if (!
|
|
938
|
-
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);
|
|
939
952
|
return {
|
|
940
953
|
status: 200,
|
|
941
|
-
headers:
|
|
954
|
+
headers: l({ "content-type": "text/html; charset=utf-8" }),
|
|
942
955
|
body: e
|
|
943
956
|
};
|
|
944
957
|
}
|
|
945
|
-
if (/\.[a-z0-9]+$/i.test(
|
|
946
|
-
let e =
|
|
947
|
-
if (await
|
|
948
|
-
let t = await
|
|
958
|
+
if (/\.[a-z0-9]+$/i.test(r)) {
|
|
959
|
+
let e = V(h, r.replace(/^\//, ""));
|
|
960
|
+
if (await ft(e)) {
|
|
961
|
+
let t = await H.readFile(e);
|
|
949
962
|
return {
|
|
950
963
|
status: 200,
|
|
951
|
-
headers:
|
|
964
|
+
headers: l({ "content-type": ut(e) }),
|
|
952
965
|
body: t
|
|
953
966
|
};
|
|
954
967
|
}
|
|
955
968
|
}
|
|
956
|
-
let
|
|
957
|
-
if (!
|
|
958
|
-
let
|
|
959
|
-
if (
|
|
960
|
-
let a = await
|
|
961
|
-
provider:
|
|
969
|
+
let p = ht(r, G);
|
|
970
|
+
if (!p) {
|
|
971
|
+
let i = de(W, r);
|
|
972
|
+
if (i !== void 0) try {
|
|
973
|
+
let a = await yt({
|
|
974
|
+
provider: q,
|
|
962
975
|
root: t,
|
|
963
976
|
route: {
|
|
964
977
|
pattern: "<not-found>",
|
|
965
|
-
file:
|
|
966
|
-
dirChain:
|
|
978
|
+
file: i.dir === "" ? "not-found.tsx" : `${i.dir}/not-found.tsx`,
|
|
979
|
+
dirChain: i.chain,
|
|
967
980
|
regex: /^$/,
|
|
968
981
|
paramNames: [],
|
|
969
982
|
priority: 2 ** 53 - 1
|
|
970
983
|
},
|
|
971
984
|
params: {},
|
|
972
|
-
pathname:
|
|
973
|
-
dirs:
|
|
974
|
-
shellTemplate:
|
|
985
|
+
pathname: r,
|
|
986
|
+
dirs: W,
|
|
987
|
+
shellTemplate: w,
|
|
975
988
|
requestHeaders: n,
|
|
976
|
-
apiOrigin:
|
|
977
|
-
apiName:
|
|
978
|
-
middlewares:
|
|
979
|
-
onCookieWarning:
|
|
989
|
+
apiOrigin: P,
|
|
990
|
+
apiName: F,
|
|
991
|
+
middlewares: R,
|
|
992
|
+
onCookieWarning: L,
|
|
980
993
|
requestUrl: e,
|
|
981
994
|
buffered: !0,
|
|
982
995
|
forceSsrRender: !0
|
|
983
996
|
});
|
|
984
997
|
if (a && "html" in a && typeof a.html == "string") return {
|
|
985
998
|
status: 404,
|
|
986
|
-
headers:
|
|
999
|
+
headers: l({
|
|
987
1000
|
"content-type": "text/html; charset=utf-8",
|
|
988
1001
|
"x-voltro-rendered-by": "ssr-not-found"
|
|
989
1002
|
}),
|
|
990
1003
|
body: a.html
|
|
991
1004
|
};
|
|
992
1005
|
} catch (e) {
|
|
993
|
-
|
|
1006
|
+
Z.warn("not-found.tsx failed to render — serving the plain 404", { pathname: r }, e instanceof Error ? e : Error(String(e)));
|
|
994
1007
|
}
|
|
995
1008
|
return {
|
|
996
1009
|
status: 404,
|
|
997
|
-
headers:
|
|
1010
|
+
headers: l({
|
|
998
1011
|
"content-type": "text/plain",
|
|
999
1012
|
"x-voltro-rendered-by": "plain-not-found"
|
|
1000
1013
|
}),
|
|
1001
1014
|
body: "not found"
|
|
1002
1015
|
};
|
|
1003
1016
|
}
|
|
1004
|
-
let
|
|
1005
|
-
...
|
|
1006
|
-
...
|
|
1007
|
-
}),
|
|
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) => ({
|
|
1008
1021
|
status: 200,
|
|
1009
1022
|
headers: {},
|
|
1010
1023
|
body: "",
|
|
1011
1024
|
stream: (o) => {
|
|
1012
|
-
|
|
1025
|
+
ie(p.route.pattern), o.writeHead(200, {
|
|
1013
1026
|
"content-type": "text/html; charset=utf-8",
|
|
1014
1027
|
"x-voltro-rendered-by": "isr",
|
|
1015
1028
|
"x-voltro-ppr": "shell+holes",
|
|
1016
1029
|
...a
|
|
1017
|
-
}), o.write(
|
|
1030
|
+
}), o.write(i), (async () => {
|
|
1018
1031
|
try {
|
|
1019
|
-
let
|
|
1020
|
-
provider:
|
|
1032
|
+
let i = await yt({
|
|
1033
|
+
provider: q,
|
|
1021
1034
|
root: t,
|
|
1022
|
-
route:
|
|
1023
|
-
params:
|
|
1024
|
-
pathname:
|
|
1025
|
-
dirs:
|
|
1026
|
-
shellTemplate:
|
|
1035
|
+
route: p.route,
|
|
1036
|
+
params: p.params,
|
|
1037
|
+
pathname: r,
|
|
1038
|
+
dirs: W,
|
|
1039
|
+
shellTemplate: Y.get(p.route.pattern) ?? w,
|
|
1027
1040
|
requestHeaders: n,
|
|
1028
|
-
apiOrigin:
|
|
1029
|
-
apiName:
|
|
1030
|
-
middlewares:
|
|
1031
|
-
onCookieWarning:
|
|
1041
|
+
apiOrigin: P,
|
|
1042
|
+
apiName: F,
|
|
1043
|
+
middlewares: R,
|
|
1044
|
+
onCookieWarning: L,
|
|
1032
1045
|
requestUrl: e,
|
|
1033
1046
|
holesOnly: !0
|
|
1034
1047
|
});
|
|
1035
|
-
|
|
1036
|
-
loader:
|
|
1037
|
-
ctx:
|
|
1048
|
+
i !== null && "holes" in i ? await be({
|
|
1049
|
+
loader: i.holes.loader,
|
|
1050
|
+
ctx: i.holes.ctx,
|
|
1038
1051
|
res: o,
|
|
1039
|
-
helpers:
|
|
1040
|
-
page:
|
|
1041
|
-
log:
|
|
1052
|
+
helpers: i.holes.helpers,
|
|
1053
|
+
page: i.holes.page,
|
|
1054
|
+
log: Z
|
|
1042
1055
|
}) : o.writableEnded || o.end();
|
|
1043
1056
|
} catch (e) {
|
|
1044
|
-
|
|
1057
|
+
Z.warn("ppr hole pass failed", { url: r }, e), o.writableEnded || o.end();
|
|
1045
1058
|
}
|
|
1046
1059
|
})();
|
|
1047
1060
|
}
|
|
1048
|
-
}),
|
|
1049
|
-
if (
|
|
1061
|
+
}), x = z.get(_), S = Date.now();
|
|
1062
|
+
if (x && Le(x, S)) return f.emit("cache", {
|
|
1050
1063
|
kind: "HIT",
|
|
1051
|
-
key:
|
|
1052
|
-
ageMs:
|
|
1053
|
-
}),
|
|
1064
|
+
key: _,
|
|
1065
|
+
ageMs: S - x.renderedAt
|
|
1066
|
+
}), y ? b(x.html, {
|
|
1054
1067
|
"x-voltro-cache": "HIT",
|
|
1055
|
-
"x-voltro-cache-key":
|
|
1056
|
-
"x-voltro-cache-age-ms": String(
|
|
1068
|
+
"x-voltro-cache-key": _,
|
|
1069
|
+
"x-voltro-cache-age-ms": String(S - x.renderedAt)
|
|
1057
1070
|
}) : {
|
|
1058
1071
|
status: 200,
|
|
1059
1072
|
headers: {
|
|
1060
1073
|
"content-type": "text/html; charset=utf-8",
|
|
1061
1074
|
"x-voltro-rendered-by": "isr",
|
|
1062
1075
|
"x-voltro-cache": "HIT",
|
|
1063
|
-
"x-voltro-cache-key":
|
|
1064
|
-
"x-voltro-cache-age-ms": String(
|
|
1076
|
+
"x-voltro-cache-key": _,
|
|
1077
|
+
"x-voltro-cache-age-ms": String(S - x.renderedAt)
|
|
1065
1078
|
},
|
|
1066
|
-
body:
|
|
1079
|
+
body: x.html
|
|
1067
1080
|
};
|
|
1068
|
-
if (
|
|
1069
|
-
|
|
1081
|
+
if (x && Pe(x, S)) {
|
|
1082
|
+
f.emit("cache", {
|
|
1070
1083
|
kind: "STALE",
|
|
1071
|
-
key:
|
|
1072
|
-
ageMs:
|
|
1084
|
+
key: _,
|
|
1085
|
+
ageMs: S - x.renderedAt
|
|
1073
1086
|
});
|
|
1074
|
-
let
|
|
1087
|
+
let i = z.generation(_);
|
|
1075
1088
|
return (async () => {
|
|
1076
1089
|
try {
|
|
1077
|
-
let a = await
|
|
1078
|
-
provider:
|
|
1090
|
+
let a = await yt({
|
|
1091
|
+
provider: q,
|
|
1079
1092
|
root: t,
|
|
1080
|
-
route:
|
|
1081
|
-
params:
|
|
1082
|
-
pathname:
|
|
1083
|
-
dirs:
|
|
1084
|
-
shellTemplate:
|
|
1093
|
+
route: p.route,
|
|
1094
|
+
params: p.params,
|
|
1095
|
+
pathname: r,
|
|
1096
|
+
dirs: W,
|
|
1097
|
+
shellTemplate: Y.get(p.route.pattern) ?? w,
|
|
1085
1098
|
requestHeaders: n,
|
|
1086
|
-
apiOrigin:
|
|
1087
|
-
apiName:
|
|
1088
|
-
middlewares:
|
|
1089
|
-
onCookieWarning:
|
|
1099
|
+
apiOrigin: P,
|
|
1100
|
+
apiName: F,
|
|
1101
|
+
middlewares: R,
|
|
1102
|
+
onCookieWarning: L,
|
|
1090
1103
|
requestUrl: e,
|
|
1091
1104
|
buffered: !0
|
|
1092
1105
|
});
|
|
1093
1106
|
if (a && "html" in a && a.renderMode === "isr" && a.revalidateMs !== null) {
|
|
1094
|
-
let e =
|
|
1095
|
-
|
|
1107
|
+
let e = J.get(p.route.pattern)?.staleWhileRevalidateMs ?? 0, t = Date.now();
|
|
1108
|
+
z.set(_, {
|
|
1096
1109
|
html: a.html,
|
|
1097
1110
|
renderedAt: t,
|
|
1098
1111
|
expiresAt: t + a.revalidateMs,
|
|
1099
1112
|
servableUntil: t + a.revalidateMs + e,
|
|
1100
1113
|
revalidateMs: a.revalidateMs,
|
|
1101
1114
|
staleWhileRevalidateMs: e
|
|
1102
|
-
}, { ifGeneration:
|
|
1115
|
+
}, { ifGeneration: i }) || Z.info("SWR refresh discarded — the entry was purged while it rendered", { key: _ });
|
|
1103
1116
|
}
|
|
1104
1117
|
} catch (e) {
|
|
1105
|
-
|
|
1118
|
+
Z.warn("background SWR refresh failed", { url: r }, e);
|
|
1106
1119
|
}
|
|
1107
|
-
})(),
|
|
1120
|
+
})(), y ? b(x.html, {
|
|
1108
1121
|
"x-voltro-cache": "STALE",
|
|
1109
|
-
"x-voltro-cache-key":
|
|
1110
|
-
"x-voltro-cache-age-ms": String(
|
|
1122
|
+
"x-voltro-cache-key": _,
|
|
1123
|
+
"x-voltro-cache-age-ms": String(S - x.renderedAt)
|
|
1111
1124
|
}) : {
|
|
1112
1125
|
status: 200,
|
|
1113
1126
|
headers: {
|
|
1114
1127
|
"content-type": "text/html; charset=utf-8",
|
|
1115
1128
|
"x-voltro-rendered-by": "isr",
|
|
1116
1129
|
"x-voltro-cache": "STALE",
|
|
1117
|
-
"x-voltro-cache-key":
|
|
1118
|
-
"x-voltro-cache-age-ms": String(
|
|
1130
|
+
"x-voltro-cache-key": _,
|
|
1131
|
+
"x-voltro-cache-age-ms": String(S - x.renderedAt)
|
|
1119
1132
|
},
|
|
1120
|
-
body:
|
|
1133
|
+
body: x.html
|
|
1121
1134
|
};
|
|
1122
1135
|
}
|
|
1123
1136
|
try {
|
|
1124
|
-
let
|
|
1125
|
-
provider:
|
|
1137
|
+
let i = z.generation(_), a = await yt({
|
|
1138
|
+
provider: q,
|
|
1126
1139
|
root: t,
|
|
1127
|
-
route:
|
|
1128
|
-
params:
|
|
1129
|
-
pathname:
|
|
1130
|
-
dirs:
|
|
1131
|
-
shellTemplate:
|
|
1140
|
+
route: p.route,
|
|
1141
|
+
params: p.params,
|
|
1142
|
+
pathname: r,
|
|
1143
|
+
dirs: W,
|
|
1144
|
+
shellTemplate: Y.get(p.route.pattern) ?? w,
|
|
1132
1145
|
requestHeaders: n,
|
|
1133
|
-
apiOrigin:
|
|
1134
|
-
apiName:
|
|
1135
|
-
middlewares:
|
|
1136
|
-
onCookieWarning:
|
|
1146
|
+
apiOrigin: P,
|
|
1147
|
+
apiName: F,
|
|
1148
|
+
middlewares: R,
|
|
1149
|
+
onCookieWarning: L,
|
|
1137
1150
|
requestUrl: e
|
|
1138
1151
|
});
|
|
1139
1152
|
if (!a) return {
|
|
@@ -1142,12 +1155,12 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
1142
1155
|
"content-type": "text/html; charset=utf-8",
|
|
1143
1156
|
"x-voltro-rendered-by": "spa-fallback"
|
|
1144
1157
|
},
|
|
1145
|
-
body:
|
|
1158
|
+
body: w
|
|
1146
1159
|
};
|
|
1147
1160
|
let o = a.setCookies ?? [], s = a.responseHeaders ?? {}, c = (e) => ({
|
|
1148
1161
|
...s,
|
|
1149
1162
|
...e,
|
|
1150
|
-
...o.length === 0 ? {} : { "set-cookie": o.map(
|
|
1163
|
+
...o.length === 0 ? {} : { "set-cookie": o.map(v) }
|
|
1151
1164
|
});
|
|
1152
1165
|
if ("stream" in a) return {
|
|
1153
1166
|
status: 200,
|
|
@@ -1176,34 +1189,34 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
1176
1189
|
"x-voltro-rendered-by": a.renderMode
|
|
1177
1190
|
});
|
|
1178
1191
|
if (a.renderMode === "isr" && a.revalidateMs !== null) {
|
|
1179
|
-
let e = Date.now(), t =
|
|
1180
|
-
|
|
1192
|
+
let e = Date.now(), t = J.get(p.route.pattern)?.staleWhileRevalidateMs ?? 0;
|
|
1193
|
+
z.set(_, {
|
|
1181
1194
|
html: a.html,
|
|
1182
1195
|
renderedAt: e,
|
|
1183
1196
|
expiresAt: e + a.revalidateMs,
|
|
1184
1197
|
servableUntil: e + a.revalidateMs + t,
|
|
1185
1198
|
revalidateMs: a.revalidateMs,
|
|
1186
1199
|
staleWhileRevalidateMs: t
|
|
1187
|
-
}, { ifGeneration:
|
|
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", {
|
|
1188
1201
|
kind: "MISS",
|
|
1189
|
-
key:
|
|
1202
|
+
key: _,
|
|
1190
1203
|
revalidateMs: a.revalidateMs,
|
|
1191
1204
|
swrMs: t
|
|
1192
1205
|
});
|
|
1193
|
-
} else a.renderMode === "isr" && (l["x-voltro-cache"] = "BYPASS",
|
|
1206
|
+
} else a.renderMode === "isr" && (l["x-voltro-cache"] = "BYPASS", f.emit("cache", {
|
|
1194
1207
|
kind: "BYPASS",
|
|
1195
|
-
key:
|
|
1208
|
+
key: _
|
|
1196
1209
|
}));
|
|
1197
|
-
return
|
|
1210
|
+
return y && a.renderMode === "isr" ? b(a.html, {
|
|
1198
1211
|
"x-voltro-cache": l["x-voltro-cache"] ?? "MISS",
|
|
1199
|
-
"x-voltro-cache-key":
|
|
1212
|
+
"x-voltro-cache-key": _
|
|
1200
1213
|
}) : {
|
|
1201
1214
|
status: 200,
|
|
1202
1215
|
headers: l,
|
|
1203
1216
|
body: a.html
|
|
1204
1217
|
};
|
|
1205
1218
|
} catch (e) {
|
|
1206
|
-
return
|
|
1219
|
+
return Z.error("render error", { url: r }, e), d(e) ? {
|
|
1207
1220
|
status: 500,
|
|
1208
1221
|
headers: {
|
|
1209
1222
|
"content-type": "text/plain; charset=utf-8",
|
|
@@ -1223,78 +1236,82 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
1223
1236
|
body: "server error"
|
|
1224
1237
|
};
|
|
1225
1238
|
}
|
|
1226
|
-
},
|
|
1227
|
-
apiName:
|
|
1228
|
-
apiOrigin:
|
|
1239
|
+
}, kt = !1, At = a({
|
|
1240
|
+
apiName: F,
|
|
1241
|
+
apiOrigin: P,
|
|
1229
1242
|
loadDescriptors: async () => {
|
|
1230
|
-
if (
|
|
1231
|
-
let e = (await
|
|
1243
|
+
if (F === void 0) return;
|
|
1244
|
+
let e = (await q.getHelpers()).apiDescriptors?.[F];
|
|
1232
1245
|
return e === void 0 ? void 0 : await e();
|
|
1233
1246
|
},
|
|
1234
|
-
rpcQuery: (e, t) =>
|
|
1235
|
-
apiName:
|
|
1247
|
+
rpcQuery: (e, t) => _e(P, e, {
|
|
1248
|
+
apiName: F,
|
|
1236
1249
|
headers: t
|
|
1237
1250
|
}),
|
|
1251
|
+
resolveLocale: async (e, t) => {
|
|
1252
|
+
let n = await q.getHelpers(), r = k(t, n.i18n?.locales);
|
|
1253
|
+
return r === void 0 ? n.i18n?.resolve(e.cookie, e["accept-language"])?.locale ?? "en" : r;
|
|
1254
|
+
},
|
|
1238
1255
|
renderErrorPage: async ({ path: e, headers: n, flash: r }) => {
|
|
1239
|
-
let { pathname: i } =
|
|
1256
|
+
let { pathname: i } = se(e), a = ht(i, G);
|
|
1240
1257
|
if (!a) return;
|
|
1241
|
-
let o = await
|
|
1242
|
-
provider:
|
|
1258
|
+
let o = await yt({
|
|
1259
|
+
provider: q,
|
|
1243
1260
|
root: t,
|
|
1244
1261
|
route: a.route,
|
|
1245
1262
|
params: a.params,
|
|
1246
1263
|
pathname: i,
|
|
1247
|
-
dirs:
|
|
1248
|
-
shellTemplate:
|
|
1264
|
+
dirs: W,
|
|
1265
|
+
shellTemplate: w,
|
|
1249
1266
|
requestHeaders: n,
|
|
1250
|
-
apiOrigin:
|
|
1251
|
-
apiName:
|
|
1252
|
-
middlewares:
|
|
1253
|
-
onCookieWarning:
|
|
1267
|
+
apiOrigin: P,
|
|
1268
|
+
apiName: F,
|
|
1269
|
+
middlewares: R,
|
|
1270
|
+
onCookieWarning: L,
|
|
1254
1271
|
requestUrl: e,
|
|
1255
1272
|
formFlash: r,
|
|
1256
1273
|
buffered: !0
|
|
1257
1274
|
});
|
|
1258
1275
|
return o !== null && "html" in o ? o.html : void 0;
|
|
1259
1276
|
}
|
|
1260
|
-
}),
|
|
1277
|
+
}), jt = Xe(async (e, t) => {
|
|
1261
1278
|
let n = e.url ?? "/", r = Date.now(), i = {};
|
|
1262
1279
|
for (let [t, n] of Object.entries(e.headers)) n !== void 0 && (i[t.toLowerCase()] = Array.isArray(n) ? n.join(", ") : n);
|
|
1263
|
-
let
|
|
1264
|
-
if (
|
|
1280
|
+
let a = n.split("?")[0] ?? "/", s = (e.method ?? "GET").toUpperCase();
|
|
1281
|
+
if (a === "/internal/liveness") {
|
|
1265
1282
|
t.writeHead(200, {
|
|
1266
1283
|
"content-type": "text/plain",
|
|
1267
1284
|
"cache-control": "no-store"
|
|
1268
1285
|
}), t.end("ok");
|
|
1269
1286
|
return;
|
|
1270
1287
|
}
|
|
1271
|
-
if (
|
|
1272
|
-
let e =
|
|
1288
|
+
if (a === "/internal/readiness") {
|
|
1289
|
+
let e = kt ? 200 : 503;
|
|
1273
1290
|
t.writeHead(e, {
|
|
1274
1291
|
"content-type": "text/plain",
|
|
1275
1292
|
"cache-control": "no-store"
|
|
1276
|
-
}), t.end(
|
|
1293
|
+
}), t.end(kt ? "ready" : "not-ready");
|
|
1277
1294
|
return;
|
|
1278
1295
|
}
|
|
1279
|
-
if (!(
|
|
1280
|
-
if (s === "OPTIONS" &&
|
|
1281
|
-
let e =
|
|
1296
|
+
if (!(a.startsWith(_) && await At(e, t))) {
|
|
1297
|
+
if (s === "OPTIONS" && a.startsWith("/_voltro/inspect")) {
|
|
1298
|
+
let e = Te(i.origin);
|
|
1282
1299
|
t.writeHead(204, e), t.end();
|
|
1283
1300
|
return;
|
|
1284
1301
|
}
|
|
1285
|
-
if (
|
|
1302
|
+
if (o.name === "voltroDashboard" && a === "/api/dashboard/proxy") {
|
|
1286
1303
|
let r = new URL(n, "http://x").searchParams.get("target");
|
|
1287
1304
|
if (!r) {
|
|
1288
1305
|
t.writeHead(400, { "content-type": "text/plain" }), t.end("missing ?target=");
|
|
1289
1306
|
return;
|
|
1290
1307
|
}
|
|
1291
|
-
if (!
|
|
1308
|
+
if (!ke(r)) {
|
|
1292
1309
|
t.writeHead(400, { "content-type": "text/plain" }), t.end("target not allowed: must be loopback or an origin configured in VOLTRO_DASHBOARD_APPS");
|
|
1293
1310
|
return;
|
|
1294
1311
|
}
|
|
1295
1312
|
try {
|
|
1296
1313
|
let n = { accept: i.accept ?? "application/json" }, a = i.authorization;
|
|
1297
|
-
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}`);
|
|
1298
1315
|
let o;
|
|
1299
1316
|
if (s && s !== "GET" && s !== "HEAD") {
|
|
1300
1317
|
let t = [];
|
|
@@ -1318,20 +1335,20 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
1318
1335
|
}
|
|
1319
1336
|
return;
|
|
1320
1337
|
}
|
|
1321
|
-
if (
|
|
1338
|
+
if (o.name === "voltroDashboard" && a === "/api/dashboard/proxy/stream") {
|
|
1322
1339
|
let r = new URL(n, "http://x").searchParams.get("target");
|
|
1323
1340
|
if (!r) {
|
|
1324
1341
|
t.writeHead(400, { "content-type": "text/plain" }), t.end("missing ?target=");
|
|
1325
1342
|
return;
|
|
1326
1343
|
}
|
|
1327
|
-
if (!
|
|
1344
|
+
if (!ke(r)) {
|
|
1328
1345
|
t.writeHead(400, { "content-type": "text/plain" }), t.end("target not allowed: must be loopback or an origin configured in VOLTRO_DASHBOARD_APPS");
|
|
1329
1346
|
return;
|
|
1330
1347
|
}
|
|
1331
1348
|
let a = new AbortController();
|
|
1332
1349
|
e.on("close", () => a.abort()), t.on("close", () => a.abort());
|
|
1333
1350
|
try {
|
|
1334
|
-
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, {
|
|
1335
1352
|
redirect: "manual",
|
|
1336
1353
|
method: "GET",
|
|
1337
1354
|
headers: {
|
|
@@ -1365,16 +1382,16 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
1365
1382
|
}
|
|
1366
1383
|
return;
|
|
1367
1384
|
}
|
|
1368
|
-
if (
|
|
1369
|
-
let n =
|
|
1370
|
-
if (
|
|
1385
|
+
if (a === "/_voltro/inspect/stream") {
|
|
1386
|
+
let n = Te(i.origin);
|
|
1387
|
+
if (I()) {
|
|
1371
1388
|
t.writeHead(503, {
|
|
1372
1389
|
"content-type": "application/json",
|
|
1373
1390
|
...n
|
|
1374
1391
|
}), t.end(JSON.stringify({ error: "inspect disabled (VOLTRO_INSPECT=off)" }));
|
|
1375
1392
|
return;
|
|
1376
1393
|
}
|
|
1377
|
-
let r =
|
|
1394
|
+
let r = Ee(i, "GET");
|
|
1378
1395
|
if (!r.ok) {
|
|
1379
1396
|
t.writeHead(401, {
|
|
1380
1397
|
"content-type": "application/json",
|
|
@@ -1392,11 +1409,11 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
1392
1409
|
"x-accel-buffering": "no",
|
|
1393
1410
|
...n
|
|
1394
1411
|
}), t.flushHeaders(), t.write("retry: 5000\n\n");
|
|
1395
|
-
for (let e of
|
|
1396
|
-
let a =
|
|
1397
|
-
t.write(
|
|
1412
|
+
for (let e of f.buffered()) t.write(ye(e));
|
|
1413
|
+
let a = f.subscribe((e) => {
|
|
1414
|
+
t.write(ye(e));
|
|
1398
1415
|
}), o = setInterval(() => {
|
|
1399
|
-
t.write(
|
|
1416
|
+
t.write(he());
|
|
1400
1417
|
}, 15e3), s = () => {
|
|
1401
1418
|
clearInterval(o), a();
|
|
1402
1419
|
};
|
|
@@ -1404,25 +1421,25 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
1404
1421
|
return;
|
|
1405
1422
|
}
|
|
1406
1423
|
try {
|
|
1407
|
-
let e = await
|
|
1408
|
-
if (e.stream ? e.stream(t) :
|
|
1424
|
+
let e = await Ot(n, i);
|
|
1425
|
+
if (e.stream ? e.stream(t) : Qe({
|
|
1409
1426
|
response: t,
|
|
1410
1427
|
status: e.status,
|
|
1411
1428
|
headers: e.headers,
|
|
1412
1429
|
body: e.body,
|
|
1413
1430
|
requestHeaders: i,
|
|
1414
|
-
compression:
|
|
1415
|
-
}) || (t.writeHead(e.status, e.headers), t.end(e.body)), !
|
|
1431
|
+
compression: pe.compression
|
|
1432
|
+
}) || (t.writeHead(e.status, e.headers), t.end(e.body)), !a.startsWith("/_voltro/inspect")) {
|
|
1416
1433
|
let t = Date.now() - r;
|
|
1417
|
-
|
|
1418
|
-
url:
|
|
1434
|
+
f.emit("request", {
|
|
1435
|
+
url: a,
|
|
1419
1436
|
status: e.status,
|
|
1420
1437
|
durationMs: t,
|
|
1421
1438
|
renderedBy: e.headers["x-voltro-rendered-by"],
|
|
1422
1439
|
cache: e.headers["x-voltro-cache"]
|
|
1423
1440
|
});
|
|
1424
|
-
let n =
|
|
1425
|
-
|
|
1441
|
+
let n = ht(a, G)?.route.pattern ?? (e.status === 404 ? "<unmatched>" : "<asset>");
|
|
1442
|
+
Ct.record({
|
|
1426
1443
|
kind: "request",
|
|
1427
1444
|
tag: n,
|
|
1428
1445
|
durationMs: t,
|
|
@@ -1434,77 +1451,77 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
1434
1451
|
}
|
|
1435
1452
|
}
|
|
1436
1453
|
});
|
|
1437
|
-
await new Promise((e) =>
|
|
1438
|
-
port:
|
|
1439
|
-
distDir:
|
|
1440
|
-
}),
|
|
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");
|
|
1441
1458
|
try {
|
|
1442
|
-
await
|
|
1443
|
-
id:
|
|
1444
|
-
name:
|
|
1459
|
+
await Re({
|
|
1460
|
+
id: S,
|
|
1461
|
+
name: b,
|
|
1445
1462
|
kind: "web",
|
|
1446
|
-
url: `http://localhost:${
|
|
1463
|
+
url: `http://localhost:${p}`,
|
|
1447
1464
|
pid: process.pid,
|
|
1448
1465
|
status: "live",
|
|
1449
|
-
logFile:
|
|
1466
|
+
logFile: C.path
|
|
1450
1467
|
});
|
|
1451
|
-
let e =
|
|
1468
|
+
let e = le(t);
|
|
1452
1469
|
if (e) {
|
|
1453
|
-
let t = await
|
|
1454
|
-
t.status === "launched" ?
|
|
1470
|
+
let t = await r({ dashboardAppPath: e });
|
|
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 });
|
|
1455
1472
|
}
|
|
1456
1473
|
setInterval(() => {
|
|
1457
|
-
|
|
1458
|
-
id:
|
|
1459
|
-
name:
|
|
1474
|
+
Re({
|
|
1475
|
+
id: S,
|
|
1476
|
+
name: b,
|
|
1460
1477
|
kind: "web",
|
|
1461
|
-
url: `http://localhost:${
|
|
1478
|
+
url: `http://localhost:${p}`,
|
|
1462
1479
|
pid: process.pid,
|
|
1463
1480
|
status: "live",
|
|
1464
|
-
logFile:
|
|
1481
|
+
logFile: C.path
|
|
1465
1482
|
}).catch(() => {});
|
|
1466
1483
|
}, 1e4).unref();
|
|
1467
1484
|
} catch (e) {
|
|
1468
|
-
|
|
1485
|
+
Z.warn("runtime-registry write failed", {}, e);
|
|
1469
1486
|
}
|
|
1470
|
-
|
|
1471
|
-
app:
|
|
1487
|
+
Ke({
|
|
1488
|
+
app: o.name ?? "unnamed",
|
|
1472
1489
|
kind: "web",
|
|
1473
|
-
url: `http://localhost:${
|
|
1490
|
+
url: `http://localhost:${p}`,
|
|
1474
1491
|
bootMs: i.total()
|
|
1475
1492
|
});
|
|
1476
|
-
let
|
|
1477
|
-
|
|
1493
|
+
let Mt = i.phaseBreakdown();
|
|
1494
|
+
Z.info(`start: ready in ${i.total()}ms`, {
|
|
1478
1495
|
bootMs: i.total(),
|
|
1479
|
-
...
|
|
1496
|
+
...Mt ? { phases: Mt } : {}
|
|
1480
1497
|
});
|
|
1481
|
-
let
|
|
1482
|
-
if (!
|
|
1483
|
-
if (
|
|
1484
|
-
|
|
1498
|
+
let Nt = !1, Pt = (e) => async () => {
|
|
1499
|
+
if (!Nt) {
|
|
1500
|
+
if (Nt = !0, Z.info(`received ${e}, shutting down`, { signal: e }), jt.close(), await vt.stop(), $) try {
|
|
1501
|
+
$();
|
|
1485
1502
|
} catch {}
|
|
1486
|
-
if (
|
|
1487
|
-
await
|
|
1503
|
+
if (St) try {
|
|
1504
|
+
await qe.runPromise(St.close());
|
|
1488
1505
|
} catch {}
|
|
1489
|
-
if (
|
|
1490
|
-
await
|
|
1506
|
+
if (B) try {
|
|
1507
|
+
await B.end();
|
|
1491
1508
|
} catch {}
|
|
1492
|
-
await
|
|
1509
|
+
await q.close(), await Be(S), await C.dispose(), process.exit(0);
|
|
1493
1510
|
}
|
|
1494
1511
|
};
|
|
1495
|
-
process.on("SIGINT",
|
|
1496
|
-
let
|
|
1497
|
-
if (
|
|
1512
|
+
process.on("SIGINT", Pt("SIGINT")), process.on("SIGTERM", Pt("SIGTERM"));
|
|
1513
|
+
let Ft = process.ppid;
|
|
1514
|
+
if (Ft > 1) {
|
|
1498
1515
|
let e = setInterval(() => {
|
|
1499
|
-
(process.ppid !==
|
|
1516
|
+
(process.ppid !== Ft || process.ppid === 1) && (clearInterval(e), Pt("SIGTERM")());
|
|
1500
1517
|
}, 2e3);
|
|
1501
1518
|
e.unref();
|
|
1502
1519
|
}
|
|
1503
1520
|
return new Promise(() => {});
|
|
1504
|
-
},
|
|
1521
|
+
}, St = async (e) => {
|
|
1505
1522
|
t("start");
|
|
1506
|
-
let n = e.find((e) => !e.startsWith("-")) ?? process.cwd(), r = await
|
|
1507
|
-
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);
|
|
1508
1525
|
};
|
|
1509
1526
|
//#endregion
|
|
1510
|
-
export {
|
|
1527
|
+
export { $ as n, St as t };
|