@voltro/cli 0.53.0 → 0.54.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 +195 -0
- package/dist/{agentsMd-0l980yhL.js → agentsMd-BaLC10Na.js} +110 -82
- package/dist/agentsMd-DCY1RSs8.js +2 -0
- package/dist/apiBuild-CeUN55uk.js +2 -0
- package/dist/{apiBuild-CaPfoWku.js → apiBuild-DTWp0S_q.js} +2 -2
- package/dist/bin.js +1 -1
- package/dist/{build-D-OnvNMf.js → build-D4ygSbnV.js} +114 -114
- package/dist/{checkCommand-C5elt0tW.js → checkCommand-Dg1G7Gwd.js} +6 -6
- package/dist/{checkCommand-D2ZduVlh.js → checkCommand-L7DTlpIF.js} +1 -1
- package/dist/{cloudCmd-QUXh-b5w.js → cloudCmd-DzKcSYuy.js} +1 -1
- package/dist/{codegen-FEk8AZHb.js → codegen-DSLM8Su9.js} +2 -2
- package/dist/codegen-DjgxEOnD.js +2 -0
- package/dist/codegenCommand-CG_Vx4lc.js +41 -0
- package/dist/{codemodRunner-BjtB2lq6.js → codemodRunner-Cd4xkC6u.js} +9 -9
- package/dist/{commands-DyxAmhP0.js → commands-6Kzi92Np.js} +96 -73
- package/dist/{dashboardCommand-BdKTyT13.js → dashboardCommand-Cq1PWvI1.js} +3 -3
- package/dist/{dataCommand-Bab9X7s8.js → dataCommand-DYzW8vkv.js} +3 -3
- package/dist/{dbCommand-06O2finM.js → dbCommand-B4NWZtGL.js} +3 -3
- package/dist/dbCommand-CSFWs9ev.js +2 -0
- package/dist/{dev-C6LGF4iY.js → dev-CmuvUKRq.js} +2236 -2219
- package/dist/{dev-GjJWAYo2.js → dev-cKUiZZsB.js} +1 -1
- package/dist/{doctorCommand-etMkflRc.js → doctorCommand-DCiFVMtZ.js} +21 -21
- package/dist/doctorCommand-J3qu4E0Y.js +2 -0
- package/dist/{dormancyCommand-UwZ1AZzB.js → dormancyCommand-w1TrmgYP.js} +1 -1
- package/dist/{embeddingsCommand-C70zWHwo.js → embeddingsCommand-CMgPyRTr.js} +1 -1
- package/dist/{envCommand-dSyKvRkM.js → envCommand-Cyynmcfa.js} +15 -15
- package/dist/{evolveCommand-CG0_ebO5.js → evolveCommand-BwvQ8dVH.js} +2 -2
- package/dist/fileConventions-l-RIXbx8.js +36 -0
- package/dist/{fileTaxonomy-B7uxipWS.js → fileTaxonomy-CbyMQYx_.js} +37 -37
- package/dist/{frameworkTableAssembly-DKx3ba3S.js → frameworkTableAssembly-D7LJuALW.js} +5 -5
- package/dist/frameworkTableAssembly-IPD1pUnZ.js +2 -0
- package/dist/index.js +2 -2
- package/dist/{infoCommand-_53iOc_j.js → infoCommand-DlYlUPqs.js} +1 -1
- package/dist/{metaCommands-Cn2oboG4.js → metaCommands-x7RCi2AF.js} +2 -2
- package/dist/{migrate-Cko9rswM.js → migrate-BK_Bbx-_.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-_C0YU207.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-CGWx1Q6l.js} +1 -1
- package/dist/{sdkgen-BiQCgIEr.js → sdkgen-CDGHQUFj.js} +1 -1
- package/dist/serveCommand-BiPe8BJm.js +2 -0
- package/dist/{serveCommand-CueKQgzl.js → serveCommand-Bje09q1v.js} +708 -708
- package/dist/serveEntry.js +1 -1
- package/dist/start-B0bnJgxI.js +3 -0
- package/dist/{start-ekPan8BT.js → start-Clz-1BHB.js} +511 -504
- 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-D_kW4KMj.js} +1 -1
- package/dist/updateCommand-CIoVDKnj.js +2 -0
- package/dist/{updateCommand-C_8I8Rzo.js → updateCommand-CRJlAOaM.js} +1 -1
- package/dist/{webDev-oczpugbx.js → webDev-DSI9SOhs.js} +1127 -1090
- package/dist/{webDev-C7jWJ5dX.js → webDev-DlvZO30c.js} +1 -1
- package/dist/{webhooksCommand-4SVPDjKg.js → webhooksCommand-BvzXNHji.js} +1 -1
- package/dist/workspaceDeps-RKEkX92S.js +45 -0
- package/package.json +19 -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 +72 -0
- package/templates/agent-docs/cli.md +4 -1
- package/templates/agent-docs/data.md +61 -12
- 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 +6 -6
- package/templates/agent-docs/reference.md +20 -1
- package/templates/agent-docs/routing.md +63 -9
- package/templates/agent-docs/scheduling.md +1 -1
- package/templates/agent-docs/schema-driven-ui.md +12 -1
- package/templates/agent-docs/templates/appshells.md +36 -4
- package/templates/agent-docs/whats-new.md +109 -135
- 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/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 p, K as m, Kt as h, L as te, M as g, Mt as _, N as ne, O as re, Ot as v, R as y, S as b, T as x, Tt as S, U as C, Ut as ie, V as w, W as ae, X as oe, Y as T, Z as E, at as D, bt as O, ct as se, et as ce, ht as le, i as ue, j as de, jt as k, k as fe, kt as A, l as pe, lt as me, m as he, mt as j, n as M, nt as N, o as ge, ot as P, p as _e, q as F, s as I, st as ve, w as ye, x as be, z as xe } from "./webDev-DSI9SOhs.js";
|
|
4
|
+
import { o as Se, t as Ce } from "./connectionConfig-Bk9IC7D0.js";
|
|
5
|
+
import { A as L, D as we, a as Te, h as Ee, j as De, k as Oe } from "./inspect-Bd8-9wsi.js";
|
|
6
|
+
import { n as ke, r as Ae, t as je } from "./inspectMetrics-CGF94puw.js";
|
|
7
|
+
import { a as Me, c as R, d as Ne, f as Pe, l as Fe, p as z, u as Ie } from "./renderModeScan-43yQ2opo.js";
|
|
8
|
+
import { i as Le, n as Re, r as ze, t as Be } from "./runtimeRegistry-DMeKfTHP.js";
|
|
9
|
+
import { n as Ve } from "./logFileSink-B4uP8pvf.js";
|
|
10
|
+
import { t as He } from "./bootTiming-BdyP9nYw.js";
|
|
11
|
+
import { dirname as B, extname as V, join as H, resolve as Ue } from "node:path";
|
|
12
|
+
import { promises as U } from "node:fs";
|
|
13
|
+
import { fileURLToPath as We, pathToFileURL as W } from "node:url";
|
|
14
|
+
import { createLogger as G, printReadyBlock as Ge } from "@voltro/logger";
|
|
15
|
+
import { Effect as Ke } from "effect";
|
|
16
|
+
import { maybeCompress as K, snapshotMetricsSync as qe } from "@voltro/runtime";
|
|
17
|
+
import { createHash as q } from "node:crypto";
|
|
18
|
+
import { resolveBroadcastProvider as Je } from "@voltro/plugin-broadcast";
|
|
19
|
+
import { createServer as Ye } from "node:http";
|
|
20
20
|
//#region src/httpResponseWrite.ts
|
|
21
|
-
var
|
|
21
|
+
var Xe = (e) => `W/"${q("md5").update(e).digest("hex")}"`, Ze = (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 = Xe(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 = K({
|
|
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
|
+
}, J = G({ scope: "voltro:start:cdc" }), Qe = (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
|
+
}, $e = () => Ce() ? Se() : null, et = (e) => {
|
|
52
|
+
let t = e.channel ?? "framework_changes", n = e.revalidateChannel ?? "voltro_revalidate", r = Qe(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 J.debug("skipped — no pages declare cacheInvalidatesOn and no revalidation handler is wired"), !1;
|
|
57
|
+
let c = $e();
|
|
58
|
+
if (!c && !o) return J.debug("no database configured — the revalidation LISTEN line is unavailable"), !1;
|
|
59
|
+
if (!c) return J.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
|
+
J.warn("bad CDC payload", {}, e);
|
|
71
71
|
return;
|
|
72
72
|
}
|
|
73
73
|
let o = r(a.table);
|
|
74
|
-
o > 0 &&
|
|
74
|
+
o > 0 && J.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 J.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
|
+
}, Y = G({ scope: "voltro:start:isr-cache" }), tt = "voltro_isr_cache", X = (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
|
+
`, nt = (e) => {
|
|
111
|
+
let t = e.tableName ?? tt, { client: n } = e, r = /* @__PURE__ */ new Map(), i = !1, a = (async () => {
|
|
112
|
+
i || (i = !0, await n.query(X(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
|
+
Y.warn("postgres bootstrap failed", {}, e);
|
|
125
125
|
}), o = (e, t) => {
|
|
126
126
|
a.then(() => n.query(e, t)).catch((e) => {
|
|
127
|
-
|
|
127
|
+
Y.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,7 +175,7 @@ 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
|
-
}, Z =
|
|
178
|
+
}, Z = G({ scope: "voltro:start:revalidate" }), rt = (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") ? {
|
|
@@ -186,7 +186,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
186
186
|
} catch {
|
|
187
187
|
return Z.warn("bad revalidation payload (not JSON)", { payload: e }), null;
|
|
188
188
|
}
|
|
189
|
-
},
|
|
189
|
+
}, it = (e, t) => {
|
|
190
190
|
if (t.kind === "table" || t.kind === "tag") {
|
|
191
191
|
let n = e.tableSink(t.value);
|
|
192
192
|
return Z.info(`revalidate ${t.kind} '${t.value}' → dropped ${n} cache entries`, {
|
|
@@ -226,14 +226,14 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
226
226
|
dropped: s,
|
|
227
227
|
...t.tenant === void 0 ? {} : { tenant: t.tenant }
|
|
228
228
|
}), s;
|
|
229
|
-
}, Q =
|
|
229
|
+
}, Q = G({ scope: "voltro:start" }), at = await (async () => {
|
|
230
230
|
try {
|
|
231
|
-
let e =
|
|
231
|
+
let e = H(B(We(import.meta.url)), "..", "package.json"), t = await U.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
|
+
})(), ot = (e) => e instanceof Error && e._voltroControl === "redirect" && typeof e.location == "string", st = (e) => e instanceof Error && e._voltroControl === "not-found", ct = {
|
|
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
|
+
}, lt = (e) => ct[V(e).toLowerCase()] ?? "application/octet-stream", ut = (e) => e.replace(/<script\b(?=[^>]*\btype="module")(?:(?!<\/script>).)*<\/script>/gi, "").replace(/<script\b(?=[^>]*\bsrc=)(?:(?!<\/script>).)*<\/script>/gi, "").replace(/<link\b[^>]*\brel="modulepreload"[^>]*>/gi, ""), dt = async (e) => {
|
|
255
255
|
try {
|
|
256
|
-
return await
|
|
256
|
+
return await U.stat(e), !0;
|
|
257
257
|
} catch {
|
|
258
258
|
return !1;
|
|
259
259
|
}
|
|
260
|
-
},
|
|
260
|
+
}, ft = (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
|
+
}, pt = (e) => e.map((e) => {
|
|
270
|
+
let { regex: t, paramNames: n, priority: r } = ft(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), mt = (e, t) => {
|
|
280
280
|
for (let n of t) {
|
|
281
281
|
let t = n.regex.exec(e);
|
|
282
282
|
if (!t) continue;
|
|
@@ -288,19 +288,19 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
288
288
|
};
|
|
289
289
|
}
|
|
290
290
|
return null;
|
|
291
|
-
},
|
|
292
|
-
let { provider: t, route: n, params: r, pathname: a, dirs: s, shellTemplate:
|
|
291
|
+
}, ht = null, gt = async (e) => {
|
|
292
|
+
let { provider: t, route: n, params: r, pathname: a, dirs: s, shellTemplate: d, requestHeaders: h, requestUrl: _ = "", apiOrigin: ne, apiName: re } = e, { search: v } = oe(_), y = await ee(te(e.middlewares ?? [], {
|
|
293
293
|
route: n.pattern,
|
|
294
294
|
pathname: a
|
|
295
295
|
}), {
|
|
296
296
|
pathname: a,
|
|
297
|
-
search:
|
|
298
|
-
headers:
|
|
299
|
-
cookies: u(
|
|
297
|
+
search: v,
|
|
298
|
+
headers: h,
|
|
299
|
+
cookies: u(h.cookie),
|
|
300
300
|
route: n.pattern
|
|
301
|
-
}, e.onCookieWarning), b = await t.getPage(n.pattern, n.file),
|
|
302
|
-
apiName:
|
|
303
|
-
headers:
|
|
301
|
+
}, e.onCookieWarning), b = await t.getPage(n.pattern, n.file), S = e.forceSsrRender === !0 ? "ssr" : R(b, n.file), ie = S === "isr" && b.ppr === !0, E = S === "isr" && e.holesOnly !== !0 ? i(y.headers) : y.headers, D = ge(ne, E.cookie, {
|
|
302
|
+
apiName: re,
|
|
303
|
+
headers: E
|
|
304
304
|
});
|
|
305
305
|
if (e.holesOnly === !0) {
|
|
306
306
|
if (typeof b.loader != "function") return null;
|
|
@@ -311,139 +311,141 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
311
311
|
ctx: {
|
|
312
312
|
params: r,
|
|
313
313
|
pathname: a,
|
|
314
|
-
search:
|
|
314
|
+
search: v,
|
|
315
315
|
signal: e.signal,
|
|
316
|
-
headers:
|
|
317
|
-
query:
|
|
316
|
+
headers: E,
|
|
317
|
+
query: D,
|
|
318
318
|
isServer: !0
|
|
319
319
|
},
|
|
320
320
|
helpers: await t.getHelpers(),
|
|
321
321
|
page: n.pattern
|
|
322
322
|
},
|
|
323
|
-
setCookies:
|
|
323
|
+
setCookies: y.setCookies
|
|
324
324
|
};
|
|
325
325
|
}
|
|
326
|
-
let
|
|
327
|
-
if (
|
|
328
|
-
let
|
|
326
|
+
let O = S === "spa" && pe(s, n.dirChain).some((e) => e.hasLayout);
|
|
327
|
+
if (S !== "ssr" && S !== "isr" && !O) return null;
|
|
328
|
+
let se = pe(s, n.dirChain), ce = {}, le = null, ue, de = new AbortController(), k = ie ? c(E, n.pattern) : E;
|
|
329
329
|
try {
|
|
330
|
-
(await t.getHelpers()).beginStoreSeeds(), {chain:
|
|
331
|
-
entries:
|
|
330
|
+
(await t.getHelpers()).beginStoreSeeds(), {chain: ue, segmentLoaderData: ce} = await I({
|
|
331
|
+
entries: se,
|
|
332
332
|
loadLayout: (e) => t.getLayout(e.dir),
|
|
333
333
|
loadError: (e) => t.getError(e.dir),
|
|
334
334
|
loadPending: (e) => t.getPending(e.dir),
|
|
335
335
|
ctx: {
|
|
336
336
|
params: r,
|
|
337
337
|
pathname: a,
|
|
338
|
-
search:
|
|
339
|
-
signal:
|
|
340
|
-
headers:
|
|
341
|
-
query:
|
|
338
|
+
search: v,
|
|
339
|
+
signal: de.signal,
|
|
340
|
+
headers: k,
|
|
341
|
+
query: D,
|
|
342
342
|
isServer: !0
|
|
343
343
|
}
|
|
344
|
-
}), typeof b.loader == "function" && !
|
|
344
|
+
}), typeof b.loader == "function" && !O && (le = await b.loader({
|
|
345
345
|
params: r,
|
|
346
346
|
pathname: a,
|
|
347
|
-
search:
|
|
348
|
-
signal:
|
|
349
|
-
headers:
|
|
350
|
-
query:
|
|
347
|
+
search: v,
|
|
348
|
+
signal: de.signal,
|
|
349
|
+
headers: k,
|
|
350
|
+
query: D,
|
|
351
351
|
isServer: !0
|
|
352
352
|
}));
|
|
353
353
|
} catch (e) {
|
|
354
|
-
if (
|
|
354
|
+
if (ot(e)) return {
|
|
355
355
|
control: "redirect",
|
|
356
356
|
status: e.status,
|
|
357
357
|
location: e.location,
|
|
358
|
-
setCookies:
|
|
359
|
-
responseHeaders:
|
|
358
|
+
setCookies: y.setCookies,
|
|
359
|
+
responseHeaders: y.responseHeaders
|
|
360
360
|
};
|
|
361
|
-
if (
|
|
361
|
+
if (st(e)) return {
|
|
362
362
|
control: "not-found",
|
|
363
|
-
setCookies:
|
|
364
|
-
responseHeaders:
|
|
363
|
+
setCookies: y.setCookies,
|
|
364
|
+
responseHeaders: y.responseHeaders
|
|
365
365
|
};
|
|
366
366
|
throw e;
|
|
367
367
|
}
|
|
368
|
-
let
|
|
369
|
-
|
|
368
|
+
let A = await t.getHelpers();
|
|
369
|
+
O || await xe({
|
|
370
370
|
pageMod: b,
|
|
371
371
|
params: r,
|
|
372
|
-
query:
|
|
373
|
-
apiName:
|
|
374
|
-
seed:
|
|
375
|
-
seedFailure:
|
|
372
|
+
query: D,
|
|
373
|
+
apiName: re,
|
|
374
|
+
seed: A.seedPreloadedSubscription,
|
|
375
|
+
seedFailure: A.seedPreloadedSubscriptionFailure,
|
|
376
376
|
onError: ({ tag: e, apiName: t }, n) => Q.warn("preload seed failed", {
|
|
377
377
|
tag: e,
|
|
378
378
|
apiName: t,
|
|
379
379
|
pathname: a
|
|
380
380
|
}, n)
|
|
381
381
|
});
|
|
382
|
-
let
|
|
382
|
+
let me = {
|
|
383
383
|
pattern: n.pattern,
|
|
384
384
|
Component: b.default,
|
|
385
385
|
meta: b.meta,
|
|
386
386
|
loader: b.loader,
|
|
387
387
|
ErrorBoundary: b.ErrorBoundary,
|
|
388
388
|
Pending: b.Pending,
|
|
389
|
-
renderMode:
|
|
390
|
-
chain:
|
|
389
|
+
renderMode: S,
|
|
390
|
+
chain: ue
|
|
391
391
|
};
|
|
392
|
-
if (
|
|
393
|
-
let
|
|
394
|
-
cookies:
|
|
395
|
-
headers:
|
|
396
|
-
url:
|
|
392
|
+
if (S === "isr" && y.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.`);
|
|
393
|
+
let he = {
|
|
394
|
+
cookies: ie ? l(fe(y.cookies), n.pattern) : S === "isr" ? fe(y.cookies) : y.cookies,
|
|
395
|
+
headers: k,
|
|
396
|
+
url: _,
|
|
397
397
|
...e.formFlash === void 0 ? {} : { formFlash: e.formFlash }
|
|
398
|
-
},
|
|
399
|
-
lang:
|
|
400
|
-
...
|
|
398
|
+
}, j = A.i18n?.resolve(E.cookie, E["accept-language"]), M = {
|
|
399
|
+
lang: j?.locale ?? he.cookies["voltro:locale"] ?? "en",
|
|
400
|
+
...j?.timeZone === void 0 ? {} : { timeZone: j.timeZone },
|
|
401
401
|
renderedAt: Date.now()
|
|
402
|
-
},
|
|
403
|
-
if (
|
|
404
|
-
let e =
|
|
405
|
-
helpers:
|
|
402
|
+
}, N = b.interactive ?? "full";
|
|
403
|
+
if (O) {
|
|
404
|
+
let e = F({
|
|
405
|
+
helpers: A,
|
|
406
406
|
page: n.pattern,
|
|
407
|
-
interactive:
|
|
407
|
+
interactive: N,
|
|
408
408
|
delivery: "stream",
|
|
409
409
|
renderInput: {
|
|
410
|
-
descriptor:
|
|
410
|
+
descriptor: me,
|
|
411
411
|
params: r,
|
|
412
412
|
pathname: a,
|
|
413
|
-
search:
|
|
414
|
-
segmentLoaderData:
|
|
415
|
-
requestContext:
|
|
416
|
-
...
|
|
417
|
-
outerWrap:
|
|
418
|
-
locale:
|
|
413
|
+
search: v,
|
|
414
|
+
segmentLoaderData: ce,
|
|
415
|
+
requestContext: he,
|
|
416
|
+
...j ? {
|
|
417
|
+
outerWrap: j.outerWrap,
|
|
418
|
+
locale: j.locale
|
|
419
419
|
} : {}
|
|
420
420
|
}
|
|
421
|
-
}), t = (t) =>
|
|
422
|
-
helpers:
|
|
421
|
+
}), t = (t) => T({
|
|
422
|
+
helpers: A,
|
|
423
423
|
prepared: e,
|
|
424
424
|
meta: t,
|
|
425
|
-
interactive:
|
|
425
|
+
interactive: N
|
|
426
426
|
});
|
|
427
427
|
if (e.hasDeferred) {
|
|
428
|
-
let n =
|
|
428
|
+
let n = f({ shell: d });
|
|
429
429
|
return {
|
|
430
430
|
renderMode: "spa",
|
|
431
|
-
setCookies:
|
|
432
|
-
responseHeaders:
|
|
433
|
-
stream: (r) =>
|
|
431
|
+
setCookies: y.setCookies,
|
|
432
|
+
responseHeaders: y.responseHeaders,
|
|
433
|
+
stream: (r) => ae({
|
|
434
434
|
res: r,
|
|
435
435
|
shell: n,
|
|
436
|
-
documentAttrs:
|
|
436
|
+
documentAttrs: M,
|
|
437
437
|
headers: {
|
|
438
|
-
...
|
|
438
|
+
...y.responseHeaders,
|
|
439
439
|
"content-type": "text/html; charset=utf-8",
|
|
440
440
|
"x-voltro-rendered-by": "spa",
|
|
441
|
-
...
|
|
441
|
+
...g(y.setCookies)
|
|
442
442
|
},
|
|
443
443
|
headInjection: t,
|
|
444
|
-
|
|
444
|
+
...y.cspNonce === void 0 ? {} : { nonce: y.cspNonce },
|
|
445
|
+
render: (t) => A.renderPageToStream({
|
|
445
446
|
...e.renderInput,
|
|
446
|
-
...t
|
|
447
|
+
...t,
|
|
448
|
+
...y.cspNonce === void 0 ? {} : { nonce: y.cspNonce }
|
|
447
449
|
}),
|
|
448
450
|
onShellError: (e) => {
|
|
449
451
|
Q.error("spa layout shell render failed", { pathname: a }, e), r.writeHead(500, { "content-type": "text/plain; charset=utf-8" }), r.end("server error");
|
|
@@ -451,76 +453,77 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
451
453
|
})
|
|
452
454
|
};
|
|
453
455
|
}
|
|
454
|
-
let i =
|
|
455
|
-
helpers:
|
|
456
|
+
let i = p({
|
|
457
|
+
helpers: A,
|
|
456
458
|
prepared: e
|
|
457
|
-
});
|
|
459
|
+
}), s = o(w(d.replace("<div id=\"root\"></div>", `<div id="root">${i.body}</div>`), t(i.meta)), M);
|
|
458
460
|
return {
|
|
459
|
-
html:
|
|
461
|
+
html: y.cspNonce === void 0 ? s : C(s, y.cspNonce),
|
|
460
462
|
renderMode: "spa",
|
|
461
463
|
revalidateMs: null,
|
|
462
|
-
setCookies:
|
|
463
|
-
responseHeaders:
|
|
464
|
+
setCookies: y.setCookies,
|
|
465
|
+
responseHeaders: y.responseHeaders
|
|
464
466
|
};
|
|
465
467
|
}
|
|
466
|
-
let
|
|
467
|
-
helpers:
|
|
468
|
+
let P = m({
|
|
469
|
+
helpers: A,
|
|
468
470
|
page: n.pattern,
|
|
469
471
|
pathname: a,
|
|
470
|
-
renderMode:
|
|
471
|
-
interactive:
|
|
472
|
-
loaderData:
|
|
473
|
-
segmentLoaderData:
|
|
472
|
+
renderMode: S,
|
|
473
|
+
interactive: N,
|
|
474
|
+
loaderData: le,
|
|
475
|
+
segmentLoaderData: ce,
|
|
474
476
|
pageLoaderRan: typeof b.loader == "function",
|
|
475
|
-
...
|
|
477
|
+
...ie ? { ppr: !0 } : {}
|
|
476
478
|
});
|
|
477
|
-
|
|
478
|
-
let
|
|
479
|
-
descriptor:
|
|
479
|
+
ie && x(P.stateInput, n.pattern);
|
|
480
|
+
let _e = {
|
|
481
|
+
descriptor: me,
|
|
480
482
|
params: r,
|
|
481
483
|
pathname: a,
|
|
482
|
-
search:
|
|
483
|
-
loaderData:
|
|
484
|
-
segmentLoaderData:
|
|
485
|
-
requestContext:
|
|
486
|
-
...
|
|
487
|
-
outerWrap:
|
|
488
|
-
locale:
|
|
484
|
+
search: v,
|
|
485
|
+
loaderData: P.loaderData,
|
|
486
|
+
segmentLoaderData: P.segmentLoaderData,
|
|
487
|
+
requestContext: he,
|
|
488
|
+
...j ? {
|
|
489
|
+
outerWrap: j.outerWrap,
|
|
490
|
+
locale: j.locale
|
|
489
491
|
} : {}
|
|
490
|
-
},
|
|
491
|
-
if (
|
|
492
|
-
let r =
|
|
492
|
+
}, ve = (t) => {
|
|
493
|
+
if (ht === null || S !== "ssr" && S !== "isr" || typeof b.ogImage != "function" || t.includes("og:image")) return "";
|
|
494
|
+
let r = E["x-tenant"], i = ht.signOgUrl({
|
|
493
495
|
pattern: n.pattern,
|
|
494
496
|
params: e.params,
|
|
495
497
|
...r === void 0 ? {} : { tenant: r }
|
|
496
498
|
});
|
|
497
499
|
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
|
-
|
|
500
|
+
}, ye = (e) => [
|
|
501
|
+
A.renderMetaToHtml(e) + ve(A.renderMetaToHtml(e)),
|
|
502
|
+
`<meta name="voltro-interactive" content="${N}" />`,
|
|
503
|
+
...P.hasDeferred ? [A.renderDeferredRegistryScript()] : [],
|
|
504
|
+
A.renderRouterStateScript(P.stateInput)
|
|
503
505
|
].filter((e) => e.length > 0).join("\n ");
|
|
504
|
-
if (
|
|
505
|
-
let e =
|
|
506
|
+
if (S === "ssr" && N === "full" && e.buffered !== !0) {
|
|
507
|
+
let e = f({ shell: d });
|
|
506
508
|
return {
|
|
507
509
|
renderMode: "ssr",
|
|
508
|
-
setCookies:
|
|
509
|
-
stream: (t) =>
|
|
510
|
+
setCookies: y.setCookies,
|
|
511
|
+
stream: (t) => ae({
|
|
510
512
|
res: t,
|
|
511
513
|
shell: e,
|
|
512
|
-
documentAttrs:
|
|
514
|
+
documentAttrs: M,
|
|
513
515
|
headers: {
|
|
514
|
-
...
|
|
516
|
+
...y.responseHeaders,
|
|
515
517
|
"content-type": "text/html; charset=utf-8",
|
|
516
518
|
"x-voltro-rendered-by": "ssr",
|
|
517
|
-
...
|
|
519
|
+
...g(y.setCookies)
|
|
518
520
|
},
|
|
519
|
-
headInjection:
|
|
520
|
-
|
|
521
|
-
|
|
521
|
+
headInjection: ye,
|
|
522
|
+
...y.cspNonce === void 0 ? {} : { nonce: y.cspNonce },
|
|
523
|
+
render: (e) => A.renderPageToStream({
|
|
524
|
+
..._e,
|
|
522
525
|
...e,
|
|
523
|
-
...
|
|
526
|
+
...y.cspNonce === void 0 ? {} : { nonce: y.cspNonce }
|
|
524
527
|
}),
|
|
525
528
|
onShellError: (e) => {
|
|
526
529
|
Q.error("ssr shell render failed", { pathname: a }, e), t.writeHead(500, { "content-type": "text/plain; charset=utf-8" }), t.end("server error");
|
|
@@ -528,18 +531,18 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
528
531
|
})
|
|
529
532
|
};
|
|
530
533
|
}
|
|
531
|
-
let { html: be, meta:
|
|
532
|
-
|
|
533
|
-
let
|
|
534
|
+
let { html: be, meta: Se } = A.renderPageToHtml(_e), Ce = ye(Se), L = o(w(d.replace("<div id=\"root\"></div>", `<div id="root">${be}</div>`), Ce), M);
|
|
535
|
+
N === "none" && (L = ut(L));
|
|
536
|
+
let we = S === "isr" ? z(b.revalidate) : null;
|
|
534
537
|
return {
|
|
535
|
-
html:
|
|
536
|
-
renderMode:
|
|
537
|
-
revalidateMs:
|
|
538
|
-
setCookies:
|
|
539
|
-
responseHeaders:
|
|
538
|
+
html: y.cspNonce === void 0 ? L : C(L, y.cspNonce),
|
|
539
|
+
renderMode: S,
|
|
540
|
+
revalidateMs: we,
|
|
541
|
+
setCookies: y.setCookies,
|
|
542
|
+
responseHeaders: y.responseHeaders
|
|
540
543
|
};
|
|
541
|
-
}, $ = (e) => e === "" ? "/" : e,
|
|
542
|
-
let t = await import(
|
|
544
|
+
}, $ = (e) => e === "" ? "/" : e, _t = async (e) => {
|
|
545
|
+
let t = await import(W(e).href);
|
|
543
546
|
return {
|
|
544
547
|
kind: "bundle",
|
|
545
548
|
getPageMeta: () => t.pageMeta,
|
|
@@ -568,8 +571,8 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
568
571
|
},
|
|
569
572
|
async close() {}
|
|
570
573
|
};
|
|
571
|
-
},
|
|
572
|
-
let n = await
|
|
574
|
+
}, vt = async (e, t) => {
|
|
575
|
+
let n = await h("vite", () => import("vite")), r = (await import("@vitejs/plugin-react")).default, i = (await import("@tailwindcss/vite")).default, a = await n.createServer({
|
|
573
576
|
root: t,
|
|
574
577
|
envPrefix: "__VOLTRO_VITE_ENV_DISABLED__",
|
|
575
578
|
plugins: [r(), i()],
|
|
@@ -586,131 +589,131 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
586
589
|
},
|
|
587
590
|
appType: "custom",
|
|
588
591
|
logLevel: "warn"
|
|
589
|
-
}),
|
|
590
|
-
limit:
|
|
592
|
+
}), o = H(e, "src", "pages"), s = (e) => e === "" ? o : H(o, e), c = k({
|
|
593
|
+
limit: _(),
|
|
591
594
|
onColdStart: (e) => Q.debug("ssr cold-compile start", { id: e }),
|
|
592
595
|
onColdEnd: (e, { durationMs: t, failed: n }) => Q.debug(`ssr cold-compile ${n ? "FAILED" : "end"} ${t}ms`, {
|
|
593
596
|
id: e,
|
|
594
597
|
ms: t,
|
|
595
598
|
...n ? { failed: !0 } : {}
|
|
596
599
|
})
|
|
597
|
-
}),
|
|
600
|
+
}), l = (e) => c.load(e, async () => await a.ssrLoadModule(e));
|
|
598
601
|
return {
|
|
599
602
|
kind: "middleware",
|
|
600
603
|
async getPage(e, t) {
|
|
601
|
-
return
|
|
604
|
+
return l(H(o, t));
|
|
602
605
|
},
|
|
603
606
|
async getLayout(e) {
|
|
604
|
-
return
|
|
607
|
+
return l(H(s(e), "layout.tsx"));
|
|
605
608
|
},
|
|
606
609
|
async getError(e) {
|
|
607
|
-
return
|
|
610
|
+
return l(H(s(e), "error.tsx"));
|
|
608
611
|
},
|
|
609
612
|
async getPending(e) {
|
|
610
|
-
return
|
|
613
|
+
return l(H(s(e), "loading.tsx"));
|
|
611
614
|
},
|
|
612
615
|
async getHelpers() {
|
|
613
|
-
return await
|
|
616
|
+
return await l("@voltro/web/ssr");
|
|
614
617
|
},
|
|
615
618
|
async close() {
|
|
616
|
-
await
|
|
619
|
+
await a.close();
|
|
617
620
|
}
|
|
618
621
|
};
|
|
619
|
-
},
|
|
620
|
-
let i =
|
|
621
|
-
if (!
|
|
622
|
+
}, yt = async (t) => {
|
|
623
|
+
let i = He(), o = await _e(t);
|
|
624
|
+
if (!o) return {
|
|
622
625
|
ran: !1,
|
|
623
626
|
exitCode: 0
|
|
624
627
|
};
|
|
625
|
-
if (
|
|
628
|
+
if (o.type !== "web") return Q.error("only web apps are supported by `voltro start`"), {
|
|
626
629
|
ran: !0,
|
|
627
630
|
exitCode: 1
|
|
628
631
|
};
|
|
629
632
|
{
|
|
630
|
-
let e =
|
|
633
|
+
let e = b(o);
|
|
631
634
|
if (e !== void 0) return Q.error(`voltro start: refusing to boot — ${e}`), {
|
|
632
635
|
ran: !0,
|
|
633
636
|
exitCode: 1
|
|
634
637
|
};
|
|
635
638
|
}
|
|
636
|
-
let { resolved:
|
|
637
|
-
rawEnv:
|
|
639
|
+
let { resolved: c } = await ie({
|
|
640
|
+
rawEnv: o.env,
|
|
638
641
|
appType: "web",
|
|
639
642
|
root: t,
|
|
640
643
|
log: Q,
|
|
641
644
|
generateTypes: !1
|
|
642
|
-
}),
|
|
645
|
+
}), l = c.publicValues;
|
|
643
646
|
i.mark("config");
|
|
644
|
-
let
|
|
645
|
-
|
|
647
|
+
let f = se();
|
|
648
|
+
D(f), Q.info("booting voltro start", { app: o.name ?? "(unnamed)" });
|
|
646
649
|
let p = n({
|
|
647
650
|
kind: "web",
|
|
648
|
-
configPort:
|
|
651
|
+
configPort: o.port,
|
|
649
652
|
env: process.env,
|
|
650
|
-
dashboardPin: process.env[
|
|
653
|
+
dashboardPin: process.env[E] === "1"
|
|
651
654
|
});
|
|
652
655
|
for (let e of p.warnings) Q.warn(e);
|
|
653
|
-
let
|
|
654
|
-
if (!await
|
|
656
|
+
let m = p.port, h = H(t, ".framework"), g = H(h, "dist"), _ = H(g, "index.html");
|
|
657
|
+
if (!await dt(_)) return Q.error("no built dist found — run `voltro build` first", { distDir: g }), {
|
|
655
658
|
ran: !0,
|
|
656
659
|
exitCode: 1
|
|
657
660
|
};
|
|
658
|
-
let
|
|
659
|
-
await
|
|
660
|
-
id:
|
|
661
|
-
name:
|
|
661
|
+
let x = o.name ?? "unnamed", C = Be("web", x, m), w = Ve(x);
|
|
662
|
+
await Le({
|
|
663
|
+
id: C,
|
|
664
|
+
name: x,
|
|
662
665
|
kind: "web",
|
|
663
|
-
url: `http://localhost:${
|
|
666
|
+
url: `http://localhost:${m}`,
|
|
664
667
|
pid: process.pid,
|
|
665
668
|
status: "booting",
|
|
666
|
-
logFile:
|
|
669
|
+
logFile: w.path
|
|
667
670
|
}).catch(() => {});
|
|
668
|
-
let
|
|
669
|
-
|
|
671
|
+
let ae = H(g, "_voltro", "shell.html"), T = await dt(ae) ? await U.readFile(ae, "utf8") : await U.readFile(_, "utf8"), k = await he(t, o), fe = ke(o), F = M(k[0]), I = k[0]?.name, xe = /* @__PURE__ */ new Set(), R = (e) => {
|
|
672
|
+
xe.has(e.name) || (xe.add(e.name), Q.warn(`middleware.ts wrote the cookie "${e.name}" with the HttpOnly default — a browser SDK cannot read it`, {
|
|
670
673
|
cookie: e.name,
|
|
671
674
|
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
675
|
}));
|
|
673
|
-
},
|
|
674
|
-
|
|
675
|
-
let
|
|
676
|
-
if (
|
|
677
|
-
else if (
|
|
676
|
+
}, z = await ne(t);
|
|
677
|
+
z.length > 0 && Q.info(`middleware.ts loaded — ${z.length} middleware(s): ` + z.map((e) => e.exportName).join(", "));
|
|
678
|
+
let B, V = null, Ue = process.env.SSR_CACHE === "postgres";
|
|
679
|
+
if (Ue && Ce()) V = new (await (import("pg"))).default.Client(Se()), await V.connect(), B = nt({ client: V }), Q.info("isr cache backend: postgres", { table: "voltro_isr_cache" });
|
|
680
|
+
else if (Ue) {
|
|
678
681
|
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
682
|
if (e()) throw Q.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");
|
|
680
|
-
|
|
681
|
-
} else
|
|
682
|
-
await s(t,
|
|
683
|
-
let
|
|
684
|
-
|
|
685
|
-
let
|
|
686
|
-
if (!
|
|
687
|
-
let
|
|
688
|
-
Q.info(`ssr loader: ${
|
|
689
|
-
kind:
|
|
690
|
-
...
|
|
683
|
+
B = Pe(), Q.warn(`${t} Falling back to the per-process memory cache — this would be a hard failure in production.`);
|
|
684
|
+
} else B = Pe(), Q.info("isr cache backend: memory (per-process)", { hint: "set SSR_CACHE=postgres for persistent storage" });
|
|
685
|
+
await s(t, o, k, l);
|
|
686
|
+
let We = H(t, "src", "pages"), { pages: W, dirs: G } = await be(We), K = pt(W);
|
|
687
|
+
de(z, K.map((e) => e.pattern)), i.mark("scan");
|
|
688
|
+
let q = H(g, "server", "ssrEntry.js"), Xe = await dt(q);
|
|
689
|
+
if (!Xe && process.env.NODE_ENV === "production") throw Q.fatal(`production \`voltro start\` requires a precompiled SSR bundle at ${q} 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 ${q}`);
|
|
690
|
+
let J = Xe ? await _t(q) : await vt(t, h);
|
|
691
|
+
Q.info(`ssr loader: ${J.kind}`, {
|
|
692
|
+
kind: J.kind,
|
|
693
|
+
...J.kind === "middleware" ? { hint: "no pre-built SSR bundle found; run `voltro build` to enable bundle mode" } : {}
|
|
691
694
|
}), i.mark("provider");
|
|
692
|
-
let
|
|
693
|
-
|
|
694
|
-
let
|
|
695
|
-
for (let e of
|
|
696
|
-
let t =
|
|
695
|
+
let $e = J.getPageMeta?.();
|
|
696
|
+
O(t);
|
|
697
|
+
let Y = /* @__PURE__ */ new Map(), tt = 0;
|
|
698
|
+
for (let e of W) {
|
|
699
|
+
let t = $e?.[e.pattern];
|
|
697
700
|
if (t) {
|
|
698
|
-
|
|
701
|
+
Y.set(e.pattern, t);
|
|
699
702
|
continue;
|
|
700
703
|
}
|
|
701
704
|
try {
|
|
702
|
-
let t = await
|
|
703
|
-
|
|
705
|
+
let t = await J.getPage(e.pattern, e.file);
|
|
706
|
+
Y.set(e.pattern, Me(t, e.file)), tt++;
|
|
704
707
|
} catch (t) {
|
|
705
708
|
Q.warn("failed to load page metadata", { pattern: e.pattern }, t);
|
|
706
709
|
}
|
|
707
710
|
}
|
|
708
|
-
let
|
|
709
|
-
for (let [e, t] of
|
|
711
|
+
let X = /* @__PURE__ */ new Map();
|
|
712
|
+
for (let [e, t] of Y) {
|
|
710
713
|
if (t.interactive !== "islands") continue;
|
|
711
|
-
let n =
|
|
714
|
+
let n = H(g, "island-shells", `${S(e)}.html`);
|
|
712
715
|
try {
|
|
713
|
-
|
|
716
|
+
X.set(e, await U.readFile(n, "utf8"));
|
|
714
717
|
} catch {
|
|
715
718
|
Q.warn("islands page has no built per-page shell — serving the full app shell", {
|
|
716
719
|
pattern: e,
|
|
@@ -718,71 +721,71 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
718
721
|
});
|
|
719
722
|
}
|
|
720
723
|
}
|
|
721
|
-
Q.info(`registered ${
|
|
722
|
-
count:
|
|
723
|
-
fromManifest:
|
|
724
|
-
fromModules:
|
|
724
|
+
Q.info(`registered ${Y.size} route(s)`, {
|
|
725
|
+
count: Y.size,
|
|
726
|
+
fromManifest: Y.size - tt,
|
|
727
|
+
fromModules: tt
|
|
725
728
|
}), i.mark("routes");
|
|
726
729
|
let Z = /* @__PURE__ */ new Set();
|
|
727
|
-
for (let e of
|
|
730
|
+
for (let e of K) Y.get(e.pattern)?.renderMode === "spa" && pe(G, e.dirChain).some((e) => e.hasLayout) && Z.add(e.pattern);
|
|
728
731
|
Z.size > 0 && Q.info(`${Z.size} spa route(s) render an SSR layout shell`, { patterns: [...Z] });
|
|
729
|
-
let at = /* @__PURE__ */ new Map();
|
|
730
|
-
for (let [e, t] of X) t.cacheInvalidatesOn.length > 0 && at.set(e, t.cacheInvalidatesOn);
|
|
731
732
|
let ot = /* @__PURE__ */ new Map();
|
|
732
|
-
for (let e of
|
|
733
|
+
for (let [e, t] of Y) t.cacheInvalidatesOn.length > 0 && ot.set(e, t.cacheInvalidatesOn);
|
|
734
|
+
let st = /* @__PURE__ */ new Map();
|
|
735
|
+
for (let e of K) st.set(e.pattern, e.regex);
|
|
733
736
|
{
|
|
734
|
-
let n = new Set([...
|
|
737
|
+
let n = new Set([...Y].filter(([, e]) => (e.renderMode === "ssr" || e.renderMode === "isr") && e.hasOgImage).map(([e]) => e));
|
|
735
738
|
if (n.size > 0) {
|
|
736
|
-
let { secret: r, fromEnv: i } =
|
|
739
|
+
let { secret: r, fromEnv: i } = le();
|
|
737
740
|
if (!i && e()) throw Q.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");
|
|
738
|
-
let
|
|
739
|
-
|
|
741
|
+
let a = new Map(W.map((e) => [e.pattern, e.file]));
|
|
742
|
+
ht = j({
|
|
740
743
|
root: t,
|
|
741
|
-
fonts:
|
|
742
|
-
cache:
|
|
744
|
+
fonts: o.fonts,
|
|
745
|
+
cache: B,
|
|
743
746
|
secret: r,
|
|
744
747
|
isOgSsrRoute: (e) => n.has(e),
|
|
745
748
|
getPageModule: async (e) => {
|
|
746
|
-
let t =
|
|
747
|
-
return t === void 0 ? null : await
|
|
749
|
+
let t = a.get(e);
|
|
750
|
+
return t === void 0 ? null : await J.getPage(e, t);
|
|
748
751
|
}
|
|
749
752
|
}), Q.info(`og route active for ${n.size} ssr route(s)`, { secret: i ? "env" : "per-boot" });
|
|
750
753
|
}
|
|
751
754
|
}
|
|
752
|
-
let
|
|
753
|
-
for (let [e, t] of
|
|
754
|
-
let
|
|
755
|
-
cache:
|
|
756
|
-
tableSink:
|
|
757
|
-
cache:
|
|
758
|
-
tableSubscriptionsByPattern:
|
|
759
|
-
regexByPattern:
|
|
755
|
+
let ct = /* @__PURE__ */ new Map();
|
|
756
|
+
for (let [e, t] of Y) ct.set(e, t.renderMode);
|
|
757
|
+
let ut = [...Y.values()].some((e) => e.renderMode === "isr"), ft = {
|
|
758
|
+
cache: B,
|
|
759
|
+
tableSink: Qe({
|
|
760
|
+
cache: B,
|
|
761
|
+
tableSubscriptionsByPattern: ot,
|
|
762
|
+
regexByPattern: st
|
|
760
763
|
}),
|
|
761
|
-
regexByPattern:
|
|
762
|
-
renderModeByPattern:
|
|
764
|
+
regexByPattern: st,
|
|
765
|
+
renderModeByPattern: ct
|
|
763
766
|
}, $ = (e) => {
|
|
764
|
-
let t =
|
|
765
|
-
t &&
|
|
766
|
-
},
|
|
767
|
-
cache:
|
|
768
|
-
tableSubscriptionsByPattern:
|
|
769
|
-
regexByPattern:
|
|
770
|
-
...
|
|
771
|
-
}),
|
|
772
|
-
if (
|
|
773
|
-
let e =
|
|
767
|
+
let t = rt(e);
|
|
768
|
+
t && it(ft, t);
|
|
769
|
+
}, yt = et({
|
|
770
|
+
cache: B,
|
|
771
|
+
tableSubscriptionsByPattern: ot,
|
|
772
|
+
regexByPattern: st,
|
|
773
|
+
...ut ? { onRevalidate: $ } : {}
|
|
774
|
+
}), bt = await yt.start(), xt = null, St = null;
|
|
775
|
+
if (ut) {
|
|
776
|
+
let e = Je({}, process.env);
|
|
774
777
|
if (e.crossReplica) try {
|
|
775
|
-
|
|
776
|
-
let t =
|
|
777
|
-
|
|
778
|
+
St = e.provider;
|
|
779
|
+
let t = Ae(process.env);
|
|
780
|
+
xt = await Ke.runPromise(e.provider.subscribe(t, $)), Q.info(`revalidation subscriber: broker (${e.provider.name})`, { channel: t });
|
|
778
781
|
} catch (e) {
|
|
779
|
-
Q.warn("revalidation broker subscribe failed — broker leg disabled", {}, e),
|
|
782
|
+
Q.warn("revalidation broker subscribe failed — broker leg disabled", {}, e), St = null;
|
|
780
783
|
}
|
|
781
|
-
|
|
784
|
+
bt && xt === null && Q.info("revalidation subscriber: postgres LISTEN (voltro_revalidate)"), !bt && xt === null && Q.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
785
|
}
|
|
783
786
|
i.mark("cdc");
|
|
784
|
-
let
|
|
785
|
-
let t =
|
|
787
|
+
let Ct = je(), wt = W.map((e) => {
|
|
788
|
+
let t = Y.get(e.pattern);
|
|
786
789
|
return {
|
|
787
790
|
pattern: e.pattern,
|
|
788
791
|
file: e.file,
|
|
@@ -797,20 +800,20 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
797
800
|
hasMeta: t?.hasMeta ?? !1,
|
|
798
801
|
hasGetStaticPaths: t?.hasGetStaticPaths ?? !1
|
|
799
802
|
};
|
|
800
|
-
}),
|
|
803
|
+
}), Tt = G.map((e) => ({
|
|
801
804
|
dir: e.dir,
|
|
802
805
|
hasLayout: e.hasLayout,
|
|
803
806
|
hasError: e.hasError,
|
|
804
807
|
hasPending: e.hasPending,
|
|
805
808
|
hasNotFound: e.hasNotFound
|
|
806
|
-
})),
|
|
809
|
+
})), Et = V ? "postgres" : "memory", Dt = {
|
|
807
810
|
kind: "web",
|
|
808
811
|
meta: {
|
|
809
|
-
name:
|
|
810
|
-
voltroVersion:
|
|
811
|
-
port:
|
|
812
|
+
name: o.name ?? "(unnamed)",
|
|
813
|
+
voltroVersion: at,
|
|
814
|
+
port: m,
|
|
812
815
|
mode: "start",
|
|
813
|
-
apis: Object.entries(
|
|
816
|
+
apis: Object.entries(o.apis ?? {}).map(([e, t]) => {
|
|
814
817
|
let n = {
|
|
815
818
|
name: e,
|
|
816
819
|
package: t.package
|
|
@@ -818,10 +821,10 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
818
821
|
return t.url !== void 0 && (n.url = t.url), n;
|
|
819
822
|
})
|
|
820
823
|
},
|
|
821
|
-
routes:
|
|
822
|
-
dirs:
|
|
824
|
+
routes: wt,
|
|
825
|
+
dirs: Tt,
|
|
823
826
|
cache: () => {
|
|
824
|
-
let e = Date.now(), t =
|
|
827
|
+
let e = Date.now(), t = B.snapshot().map(([t, n]) => ({
|
|
825
828
|
key: t,
|
|
826
829
|
renderedAt: n.renderedAt,
|
|
827
830
|
expiresAt: n.expiresAt,
|
|
@@ -832,16 +835,16 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
832
835
|
staleWhileRevalidateMs: n.staleWhileRevalidateMs
|
|
833
836
|
}));
|
|
834
837
|
return {
|
|
835
|
-
backend:
|
|
836
|
-
size:
|
|
838
|
+
backend: Et,
|
|
839
|
+
size: B.size(),
|
|
837
840
|
entries: t
|
|
838
841
|
};
|
|
839
842
|
},
|
|
840
|
-
metrics: () =>
|
|
841
|
-
},
|
|
842
|
-
let
|
|
843
|
-
if (
|
|
844
|
-
let e = await
|
|
843
|
+
metrics: () => qe()
|
|
844
|
+
}, Ot = async (e, n) => {
|
|
845
|
+
let r = e.split("?")[0] ?? "/";
|
|
846
|
+
if (o.name === "voltroDashboard" && r === "/api/dashboard/registry") try {
|
|
847
|
+
let e = await Re();
|
|
845
848
|
return {
|
|
846
849
|
status: 200,
|
|
847
850
|
headers: { "content-type": "application/json; charset=utf-8" },
|
|
@@ -854,7 +857,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
854
857
|
body: `registry read error: ${e.message}`
|
|
855
858
|
};
|
|
856
859
|
}
|
|
857
|
-
if (
|
|
860
|
+
if (o.name === "voltroDashboard" && r === "/api/dashboard/config") {
|
|
858
861
|
let e = process.env.VOLTRO_DASHBOARD_APPS, t = [];
|
|
859
862
|
if (e && e.trim().length > 0) {
|
|
860
863
|
let n;
|
|
@@ -883,27 +886,27 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
883
886
|
body: JSON.stringify({ apps: t })
|
|
884
887
|
};
|
|
885
888
|
}
|
|
886
|
-
if (
|
|
887
|
-
let t = await
|
|
889
|
+
if (ht !== null && r === "/_voltro/og") {
|
|
890
|
+
let t = await ht.handle(new URL(e, "http://localhost"));
|
|
888
891
|
if (t !== null) return {
|
|
889
892
|
status: t.status,
|
|
890
893
|
headers: { ...t.headers },
|
|
891
894
|
body: Buffer.from(t.body)
|
|
892
895
|
};
|
|
893
896
|
}
|
|
894
|
-
if (
|
|
895
|
-
let t =
|
|
897
|
+
if (r === "/_voltro/inspect/logs") {
|
|
898
|
+
let t = N(e, P(), n);
|
|
896
899
|
return {
|
|
897
900
|
status: t.status,
|
|
898
901
|
headers: {
|
|
899
902
|
"content-type": t.contentType,
|
|
900
|
-
...
|
|
903
|
+
...we(n.origin)
|
|
901
904
|
},
|
|
902
905
|
body: t.body
|
|
903
906
|
};
|
|
904
907
|
}
|
|
905
|
-
if (
|
|
906
|
-
let t =
|
|
908
|
+
if (r !== "/_voltro/inspect/stream") {
|
|
909
|
+
let t = Ee(e, Dt, n);
|
|
907
910
|
if (t !== null) return {
|
|
908
911
|
status: t.status,
|
|
909
912
|
headers: {
|
|
@@ -913,227 +916,227 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
913
916
|
body: t.body
|
|
914
917
|
};
|
|
915
918
|
}
|
|
916
|
-
let
|
|
917
|
-
if (!
|
|
918
|
-
let t = te(
|
|
919
|
+
let i = mt(r, K), a = i ? Y.get(i.route.pattern)?.renderMode : void 0, s = a === "ssr" || a === "isr" || (i ? Z.has(i.route.pattern) : !1), c = [];
|
|
920
|
+
if (!s && z.length > 0) {
|
|
921
|
+
let t = te(z, {
|
|
919
922
|
route: void 0,
|
|
920
|
-
pathname:
|
|
923
|
+
pathname: r
|
|
921
924
|
});
|
|
922
925
|
if (t !== void 0) {
|
|
923
|
-
let
|
|
924
|
-
pathname:
|
|
925
|
-
search: e.slice(
|
|
926
|
+
let i = await ee(t, {
|
|
927
|
+
pathname: r,
|
|
928
|
+
search: e.slice(r.length),
|
|
926
929
|
headers: n,
|
|
927
930
|
cookies: u(n.cookie),
|
|
928
931
|
route: void 0
|
|
929
932
|
});
|
|
930
|
-
|
|
933
|
+
c.push(...i.setCookies);
|
|
931
934
|
}
|
|
932
935
|
}
|
|
933
|
-
let
|
|
936
|
+
let l = (e) => c.length === 0 ? e : {
|
|
934
937
|
...e,
|
|
935
|
-
"set-cookie":
|
|
936
|
-
},
|
|
937
|
-
if (!
|
|
938
|
-
let e = await
|
|
938
|
+
"set-cookie": c.map(y)
|
|
939
|
+
}, p = r === "/" ? H(g, "index.html") : H(g, r.replace(/^\//, ""), "index.html");
|
|
940
|
+
if (!s && await dt(p)) {
|
|
941
|
+
let e = await U.readFile(p);
|
|
939
942
|
return {
|
|
940
943
|
status: 200,
|
|
941
|
-
headers:
|
|
944
|
+
headers: l({ "content-type": "text/html; charset=utf-8" }),
|
|
942
945
|
body: e
|
|
943
946
|
};
|
|
944
947
|
}
|
|
945
|
-
if (/\.[a-z0-9]+$/i.test(
|
|
946
|
-
let e =
|
|
947
|
-
if (await
|
|
948
|
-
let t = await
|
|
948
|
+
if (/\.[a-z0-9]+$/i.test(r)) {
|
|
949
|
+
let e = H(g, r.replace(/^\//, ""));
|
|
950
|
+
if (await dt(e)) {
|
|
951
|
+
let t = await U.readFile(e);
|
|
949
952
|
return {
|
|
950
953
|
status: 200,
|
|
951
|
-
headers:
|
|
954
|
+
headers: l({ "content-type": lt(e) }),
|
|
952
955
|
body: t
|
|
953
956
|
};
|
|
954
957
|
}
|
|
955
958
|
}
|
|
956
|
-
let
|
|
957
|
-
if (!
|
|
958
|
-
let
|
|
959
|
-
if (
|
|
960
|
-
let a = await
|
|
961
|
-
provider:
|
|
959
|
+
let m = mt(r, K);
|
|
960
|
+
if (!m) {
|
|
961
|
+
let i = ue(G, r);
|
|
962
|
+
if (i !== void 0) try {
|
|
963
|
+
let a = await gt({
|
|
964
|
+
provider: J,
|
|
962
965
|
root: t,
|
|
963
966
|
route: {
|
|
964
967
|
pattern: "<not-found>",
|
|
965
|
-
file:
|
|
966
|
-
dirChain:
|
|
968
|
+
file: i.dir === "" ? "not-found.tsx" : `${i.dir}/not-found.tsx`,
|
|
969
|
+
dirChain: i.chain,
|
|
967
970
|
regex: /^$/,
|
|
968
971
|
paramNames: [],
|
|
969
972
|
priority: 2 ** 53 - 1
|
|
970
973
|
},
|
|
971
974
|
params: {},
|
|
972
|
-
pathname:
|
|
973
|
-
dirs:
|
|
974
|
-
shellTemplate:
|
|
975
|
+
pathname: r,
|
|
976
|
+
dirs: G,
|
|
977
|
+
shellTemplate: T,
|
|
975
978
|
requestHeaders: n,
|
|
976
|
-
apiOrigin:
|
|
977
|
-
apiName:
|
|
978
|
-
middlewares:
|
|
979
|
-
onCookieWarning:
|
|
979
|
+
apiOrigin: F,
|
|
980
|
+
apiName: I,
|
|
981
|
+
middlewares: z,
|
|
982
|
+
onCookieWarning: R,
|
|
980
983
|
requestUrl: e,
|
|
981
984
|
buffered: !0,
|
|
982
985
|
forceSsrRender: !0
|
|
983
986
|
});
|
|
984
987
|
if (a && "html" in a && typeof a.html == "string") return {
|
|
985
988
|
status: 404,
|
|
986
|
-
headers:
|
|
989
|
+
headers: l({
|
|
987
990
|
"content-type": "text/html; charset=utf-8",
|
|
988
991
|
"x-voltro-rendered-by": "ssr-not-found"
|
|
989
992
|
}),
|
|
990
993
|
body: a.html
|
|
991
994
|
};
|
|
992
995
|
} catch (e) {
|
|
993
|
-
Q.warn("not-found.tsx failed to render — serving the plain 404", { pathname:
|
|
996
|
+
Q.warn("not-found.tsx failed to render — serving the plain 404", { pathname: r }, e instanceof Error ? e : Error(String(e)));
|
|
994
997
|
}
|
|
995
998
|
return {
|
|
996
999
|
status: 404,
|
|
997
|
-
headers:
|
|
1000
|
+
headers: l({
|
|
998
1001
|
"content-type": "text/plain",
|
|
999
1002
|
"x-voltro-rendered-by": "plain-not-found"
|
|
1000
1003
|
}),
|
|
1001
1004
|
body: "not found"
|
|
1002
1005
|
};
|
|
1003
1006
|
}
|
|
1004
|
-
let
|
|
1005
|
-
...
|
|
1006
|
-
...
|
|
1007
|
-
}), b =
|
|
1007
|
+
let h = Y.get(m.route.pattern), _ = n["x-tenant"] ?? "anonymous", ne = (await J.getHelpers()).i18n?.resolve(n.cookie, n["accept-language"])?.locale, v = Fe(r, {
|
|
1008
|
+
...h?.tenantAware ? { tenant: _ } : {},
|
|
1009
|
+
...ne ? { locale: ne } : {}
|
|
1010
|
+
}), b = h?.ppr === !0 && h.renderMode === "isr", x = (i, a) => ({
|
|
1008
1011
|
status: 200,
|
|
1009
1012
|
headers: {},
|
|
1010
1013
|
body: "",
|
|
1011
1014
|
stream: (o) => {
|
|
1012
|
-
|
|
1015
|
+
re(m.route.pattern), o.writeHead(200, {
|
|
1013
1016
|
"content-type": "text/html; charset=utf-8",
|
|
1014
1017
|
"x-voltro-rendered-by": "isr",
|
|
1015
1018
|
"x-voltro-ppr": "shell+holes",
|
|
1016
1019
|
...a
|
|
1017
|
-
}), o.write(
|
|
1020
|
+
}), o.write(i), (async () => {
|
|
1018
1021
|
try {
|
|
1019
|
-
let
|
|
1020
|
-
provider:
|
|
1022
|
+
let i = await gt({
|
|
1023
|
+
provider: J,
|
|
1021
1024
|
root: t,
|
|
1022
|
-
route:
|
|
1023
|
-
params:
|
|
1024
|
-
pathname:
|
|
1025
|
-
dirs:
|
|
1026
|
-
shellTemplate:
|
|
1025
|
+
route: m.route,
|
|
1026
|
+
params: m.params,
|
|
1027
|
+
pathname: r,
|
|
1028
|
+
dirs: G,
|
|
1029
|
+
shellTemplate: X.get(m.route.pattern) ?? T,
|
|
1027
1030
|
requestHeaders: n,
|
|
1028
|
-
apiOrigin:
|
|
1029
|
-
apiName:
|
|
1030
|
-
middlewares:
|
|
1031
|
-
onCookieWarning:
|
|
1031
|
+
apiOrigin: F,
|
|
1032
|
+
apiName: I,
|
|
1033
|
+
middlewares: z,
|
|
1034
|
+
onCookieWarning: R,
|
|
1032
1035
|
requestUrl: e,
|
|
1033
1036
|
holesOnly: !0
|
|
1034
1037
|
});
|
|
1035
|
-
|
|
1036
|
-
loader:
|
|
1037
|
-
ctx:
|
|
1038
|
+
i !== null && "holes" in i ? await ye({
|
|
1039
|
+
loader: i.holes.loader,
|
|
1040
|
+
ctx: i.holes.ctx,
|
|
1038
1041
|
res: o,
|
|
1039
|
-
helpers:
|
|
1040
|
-
page:
|
|
1042
|
+
helpers: i.holes.helpers,
|
|
1043
|
+
page: i.holes.page,
|
|
1041
1044
|
log: Q
|
|
1042
1045
|
}) : o.writableEnded || o.end();
|
|
1043
1046
|
} catch (e) {
|
|
1044
|
-
Q.warn("ppr hole pass failed", { url:
|
|
1047
|
+
Q.warn("ppr hole pass failed", { url: r }, e), o.writableEnded || o.end();
|
|
1045
1048
|
}
|
|
1046
1049
|
})();
|
|
1047
1050
|
}
|
|
1048
|
-
}),
|
|
1049
|
-
if (
|
|
1051
|
+
}), S = B.get(v), C = Date.now();
|
|
1052
|
+
if (S && Ie(S, C)) return f.emit("cache", {
|
|
1050
1053
|
kind: "HIT",
|
|
1051
|
-
key:
|
|
1052
|
-
ageMs:
|
|
1053
|
-
}), b ? S
|
|
1054
|
+
key: v,
|
|
1055
|
+
ageMs: C - S.renderedAt
|
|
1056
|
+
}), b ? x(S.html, {
|
|
1054
1057
|
"x-voltro-cache": "HIT",
|
|
1055
|
-
"x-voltro-cache-key":
|
|
1056
|
-
"x-voltro-cache-age-ms": String(
|
|
1058
|
+
"x-voltro-cache-key": v,
|
|
1059
|
+
"x-voltro-cache-age-ms": String(C - S.renderedAt)
|
|
1057
1060
|
}) : {
|
|
1058
1061
|
status: 200,
|
|
1059
1062
|
headers: {
|
|
1060
1063
|
"content-type": "text/html; charset=utf-8",
|
|
1061
1064
|
"x-voltro-rendered-by": "isr",
|
|
1062
1065
|
"x-voltro-cache": "HIT",
|
|
1063
|
-
"x-voltro-cache-key":
|
|
1064
|
-
"x-voltro-cache-age-ms": String(
|
|
1066
|
+
"x-voltro-cache-key": v,
|
|
1067
|
+
"x-voltro-cache-age-ms": String(C - S.renderedAt)
|
|
1065
1068
|
},
|
|
1066
|
-
body:
|
|
1069
|
+
body: S.html
|
|
1067
1070
|
};
|
|
1068
|
-
if (
|
|
1069
|
-
|
|
1071
|
+
if (S && Ne(S, C)) {
|
|
1072
|
+
f.emit("cache", {
|
|
1070
1073
|
kind: "STALE",
|
|
1071
|
-
key:
|
|
1072
|
-
ageMs:
|
|
1074
|
+
key: v,
|
|
1075
|
+
ageMs: C - S.renderedAt
|
|
1073
1076
|
});
|
|
1074
|
-
let
|
|
1077
|
+
let i = B.generation(v);
|
|
1075
1078
|
return (async () => {
|
|
1076
1079
|
try {
|
|
1077
|
-
let a = await
|
|
1078
|
-
provider:
|
|
1080
|
+
let a = await gt({
|
|
1081
|
+
provider: J,
|
|
1079
1082
|
root: t,
|
|
1080
|
-
route:
|
|
1081
|
-
params:
|
|
1082
|
-
pathname:
|
|
1083
|
-
dirs:
|
|
1084
|
-
shellTemplate:
|
|
1083
|
+
route: m.route,
|
|
1084
|
+
params: m.params,
|
|
1085
|
+
pathname: r,
|
|
1086
|
+
dirs: G,
|
|
1087
|
+
shellTemplate: X.get(m.route.pattern) ?? T,
|
|
1085
1088
|
requestHeaders: n,
|
|
1086
|
-
apiOrigin:
|
|
1087
|
-
apiName:
|
|
1088
|
-
middlewares:
|
|
1089
|
-
onCookieWarning:
|
|
1089
|
+
apiOrigin: F,
|
|
1090
|
+
apiName: I,
|
|
1091
|
+
middlewares: z,
|
|
1092
|
+
onCookieWarning: R,
|
|
1090
1093
|
requestUrl: e,
|
|
1091
1094
|
buffered: !0
|
|
1092
1095
|
});
|
|
1093
1096
|
if (a && "html" in a && a.renderMode === "isr" && a.revalidateMs !== null) {
|
|
1094
|
-
let e =
|
|
1095
|
-
|
|
1097
|
+
let e = Y.get(m.route.pattern)?.staleWhileRevalidateMs ?? 0, t = Date.now();
|
|
1098
|
+
B.set(v, {
|
|
1096
1099
|
html: a.html,
|
|
1097
1100
|
renderedAt: t,
|
|
1098
1101
|
expiresAt: t + a.revalidateMs,
|
|
1099
1102
|
servableUntil: t + a.revalidateMs + e,
|
|
1100
1103
|
revalidateMs: a.revalidateMs,
|
|
1101
1104
|
staleWhileRevalidateMs: e
|
|
1102
|
-
}, { ifGeneration:
|
|
1105
|
+
}, { ifGeneration: i }) || Q.info("SWR refresh discarded — the entry was purged while it rendered", { key: v });
|
|
1103
1106
|
}
|
|
1104
1107
|
} catch (e) {
|
|
1105
|
-
Q.warn("background SWR refresh failed", { url:
|
|
1108
|
+
Q.warn("background SWR refresh failed", { url: r }, e);
|
|
1106
1109
|
}
|
|
1107
|
-
})(), b ? S
|
|
1110
|
+
})(), b ? x(S.html, {
|
|
1108
1111
|
"x-voltro-cache": "STALE",
|
|
1109
|
-
"x-voltro-cache-key":
|
|
1110
|
-
"x-voltro-cache-age-ms": String(
|
|
1112
|
+
"x-voltro-cache-key": v,
|
|
1113
|
+
"x-voltro-cache-age-ms": String(C - S.renderedAt)
|
|
1111
1114
|
}) : {
|
|
1112
1115
|
status: 200,
|
|
1113
1116
|
headers: {
|
|
1114
1117
|
"content-type": "text/html; charset=utf-8",
|
|
1115
1118
|
"x-voltro-rendered-by": "isr",
|
|
1116
1119
|
"x-voltro-cache": "STALE",
|
|
1117
|
-
"x-voltro-cache-key":
|
|
1118
|
-
"x-voltro-cache-age-ms": String(
|
|
1120
|
+
"x-voltro-cache-key": v,
|
|
1121
|
+
"x-voltro-cache-age-ms": String(C - S.renderedAt)
|
|
1119
1122
|
},
|
|
1120
|
-
body:
|
|
1123
|
+
body: S.html
|
|
1121
1124
|
};
|
|
1122
1125
|
}
|
|
1123
1126
|
try {
|
|
1124
|
-
let
|
|
1125
|
-
provider:
|
|
1127
|
+
let i = B.generation(v), a = await gt({
|
|
1128
|
+
provider: J,
|
|
1126
1129
|
root: t,
|
|
1127
|
-
route:
|
|
1128
|
-
params:
|
|
1129
|
-
pathname:
|
|
1130
|
-
dirs:
|
|
1131
|
-
shellTemplate:
|
|
1130
|
+
route: m.route,
|
|
1131
|
+
params: m.params,
|
|
1132
|
+
pathname: r,
|
|
1133
|
+
dirs: G,
|
|
1134
|
+
shellTemplate: X.get(m.route.pattern) ?? T,
|
|
1132
1135
|
requestHeaders: n,
|
|
1133
|
-
apiOrigin:
|
|
1134
|
-
apiName:
|
|
1135
|
-
middlewares:
|
|
1136
|
-
onCookieWarning:
|
|
1136
|
+
apiOrigin: F,
|
|
1137
|
+
apiName: I,
|
|
1138
|
+
middlewares: z,
|
|
1139
|
+
onCookieWarning: R,
|
|
1137
1140
|
requestUrl: e
|
|
1138
1141
|
});
|
|
1139
1142
|
if (!a) return {
|
|
@@ -1142,12 +1145,12 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
1142
1145
|
"content-type": "text/html; charset=utf-8",
|
|
1143
1146
|
"x-voltro-rendered-by": "spa-fallback"
|
|
1144
1147
|
},
|
|
1145
|
-
body:
|
|
1148
|
+
body: T
|
|
1146
1149
|
};
|
|
1147
1150
|
let o = a.setCookies ?? [], s = a.responseHeaders ?? {}, c = (e) => ({
|
|
1148
1151
|
...s,
|
|
1149
1152
|
...e,
|
|
1150
|
-
...o.length === 0 ? {} : { "set-cookie": o.map(
|
|
1153
|
+
...o.length === 0 ? {} : { "set-cookie": o.map(y) }
|
|
1151
1154
|
});
|
|
1152
1155
|
if ("stream" in a) return {
|
|
1153
1156
|
status: 200,
|
|
@@ -1176,34 +1179,34 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
1176
1179
|
"x-voltro-rendered-by": a.renderMode
|
|
1177
1180
|
});
|
|
1178
1181
|
if (a.renderMode === "isr" && a.revalidateMs !== null) {
|
|
1179
|
-
let e = Date.now(), t =
|
|
1180
|
-
|
|
1182
|
+
let e = Date.now(), t = Y.get(m.route.pattern)?.staleWhileRevalidateMs ?? 0;
|
|
1183
|
+
B.set(v, {
|
|
1181
1184
|
html: a.html,
|
|
1182
1185
|
renderedAt: e,
|
|
1183
1186
|
expiresAt: e + a.revalidateMs,
|
|
1184
1187
|
servableUntil: e + a.revalidateMs + t,
|
|
1185
1188
|
revalidateMs: a.revalidateMs,
|
|
1186
1189
|
staleWhileRevalidateMs: t
|
|
1187
|
-
}, { ifGeneration:
|
|
1190
|
+
}, { ifGeneration: i }) || Q.info("miss fill discarded — the entry was purged while it rendered", { key: v }), l["x-voltro-cache"] = "MISS", l["x-voltro-cache-key"] = v, l["x-voltro-cache-revalidate-ms"] = String(a.revalidateMs), t > 0 && (l["x-voltro-cache-swr-ms"] = String(t)), f.emit("cache", {
|
|
1188
1191
|
kind: "MISS",
|
|
1189
|
-
key:
|
|
1192
|
+
key: v,
|
|
1190
1193
|
revalidateMs: a.revalidateMs,
|
|
1191
1194
|
swrMs: t
|
|
1192
1195
|
});
|
|
1193
|
-
} else a.renderMode === "isr" && (l["x-voltro-cache"] = "BYPASS",
|
|
1196
|
+
} else a.renderMode === "isr" && (l["x-voltro-cache"] = "BYPASS", f.emit("cache", {
|
|
1194
1197
|
kind: "BYPASS",
|
|
1195
|
-
key:
|
|
1198
|
+
key: v
|
|
1196
1199
|
}));
|
|
1197
|
-
return b && a.renderMode === "isr" ?
|
|
1200
|
+
return b && a.renderMode === "isr" ? x(a.html, {
|
|
1198
1201
|
"x-voltro-cache": l["x-voltro-cache"] ?? "MISS",
|
|
1199
|
-
"x-voltro-cache-key":
|
|
1202
|
+
"x-voltro-cache-key": v
|
|
1200
1203
|
}) : {
|
|
1201
1204
|
status: 200,
|
|
1202
1205
|
headers: l,
|
|
1203
1206
|
body: a.html
|
|
1204
1207
|
};
|
|
1205
1208
|
} catch (e) {
|
|
1206
|
-
return Q.error("render error", { url:
|
|
1209
|
+
return Q.error("render error", { url: r }, e), d(e) ? {
|
|
1207
1210
|
status: 500,
|
|
1208
1211
|
headers: {
|
|
1209
1212
|
"content-type": "text/plain; charset=utf-8",
|
|
@@ -1223,78 +1226,82 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
1223
1226
|
body: "server error"
|
|
1224
1227
|
};
|
|
1225
1228
|
}
|
|
1226
|
-
},
|
|
1227
|
-
apiName:
|
|
1228
|
-
apiOrigin:
|
|
1229
|
+
}, kt = !1, At = a({
|
|
1230
|
+
apiName: I,
|
|
1231
|
+
apiOrigin: F,
|
|
1229
1232
|
loadDescriptors: async () => {
|
|
1230
|
-
if (
|
|
1231
|
-
let e = (await
|
|
1233
|
+
if (I === void 0) return;
|
|
1234
|
+
let e = (await J.getHelpers()).apiDescriptors?.[I];
|
|
1232
1235
|
return e === void 0 ? void 0 : await e();
|
|
1233
1236
|
},
|
|
1234
|
-
rpcQuery: (e, t) =>
|
|
1235
|
-
apiName:
|
|
1237
|
+
rpcQuery: (e, t) => ge(F, e, {
|
|
1238
|
+
apiName: I,
|
|
1236
1239
|
headers: t
|
|
1237
1240
|
}),
|
|
1241
|
+
resolveLocale: async (e, t) => {
|
|
1242
|
+
let n = await J.getHelpers(), r = A(t, n.i18n?.locales);
|
|
1243
|
+
return r === void 0 ? n.i18n?.resolve(e.cookie, e["accept-language"])?.locale ?? "en" : r;
|
|
1244
|
+
},
|
|
1238
1245
|
renderErrorPage: async ({ path: e, headers: n, flash: r }) => {
|
|
1239
|
-
let { pathname: i } =
|
|
1246
|
+
let { pathname: i } = oe(e), a = mt(i, K);
|
|
1240
1247
|
if (!a) return;
|
|
1241
|
-
let o = await
|
|
1242
|
-
provider:
|
|
1248
|
+
let o = await gt({
|
|
1249
|
+
provider: J,
|
|
1243
1250
|
root: t,
|
|
1244
1251
|
route: a.route,
|
|
1245
1252
|
params: a.params,
|
|
1246
1253
|
pathname: i,
|
|
1247
|
-
dirs:
|
|
1248
|
-
shellTemplate:
|
|
1254
|
+
dirs: G,
|
|
1255
|
+
shellTemplate: T,
|
|
1249
1256
|
requestHeaders: n,
|
|
1250
|
-
apiOrigin:
|
|
1251
|
-
apiName:
|
|
1252
|
-
middlewares:
|
|
1253
|
-
onCookieWarning:
|
|
1257
|
+
apiOrigin: F,
|
|
1258
|
+
apiName: I,
|
|
1259
|
+
middlewares: z,
|
|
1260
|
+
onCookieWarning: R,
|
|
1254
1261
|
requestUrl: e,
|
|
1255
1262
|
formFlash: r,
|
|
1256
1263
|
buffered: !0
|
|
1257
1264
|
});
|
|
1258
1265
|
return o !== null && "html" in o ? o.html : void 0;
|
|
1259
1266
|
}
|
|
1260
|
-
}),
|
|
1267
|
+
}), jt = Ye(async (e, t) => {
|
|
1261
1268
|
let n = e.url ?? "/", r = Date.now(), i = {};
|
|
1262
1269
|
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 (
|
|
1270
|
+
let a = n.split("?")[0] ?? "/", s = (e.method ?? "GET").toUpperCase();
|
|
1271
|
+
if (a === "/internal/liveness") {
|
|
1265
1272
|
t.writeHead(200, {
|
|
1266
1273
|
"content-type": "text/plain",
|
|
1267
1274
|
"cache-control": "no-store"
|
|
1268
1275
|
}), t.end("ok");
|
|
1269
1276
|
return;
|
|
1270
1277
|
}
|
|
1271
|
-
if (
|
|
1272
|
-
let e =
|
|
1278
|
+
if (a === "/internal/readiness") {
|
|
1279
|
+
let e = kt ? 200 : 503;
|
|
1273
1280
|
t.writeHead(e, {
|
|
1274
1281
|
"content-type": "text/plain",
|
|
1275
1282
|
"cache-control": "no-store"
|
|
1276
|
-
}), t.end(
|
|
1283
|
+
}), t.end(kt ? "ready" : "not-ready");
|
|
1277
1284
|
return;
|
|
1278
1285
|
}
|
|
1279
|
-
if (!(
|
|
1280
|
-
if (s === "OPTIONS" &&
|
|
1281
|
-
let e =
|
|
1286
|
+
if (!(a.startsWith(v) && await At(e, t))) {
|
|
1287
|
+
if (s === "OPTIONS" && a.startsWith("/_voltro/inspect")) {
|
|
1288
|
+
let e = we(i.origin);
|
|
1282
1289
|
t.writeHead(204, e), t.end();
|
|
1283
1290
|
return;
|
|
1284
1291
|
}
|
|
1285
|
-
if (
|
|
1292
|
+
if (o.name === "voltroDashboard" && a === "/api/dashboard/proxy") {
|
|
1286
1293
|
let r = new URL(n, "http://x").searchParams.get("target");
|
|
1287
1294
|
if (!r) {
|
|
1288
1295
|
t.writeHead(400, { "content-type": "text/plain" }), t.end("missing ?target=");
|
|
1289
1296
|
return;
|
|
1290
1297
|
}
|
|
1291
|
-
if (!
|
|
1298
|
+
if (!Oe(r)) {
|
|
1292
1299
|
t.writeHead(400, { "content-type": "text/plain" }), t.end("target not allowed: must be loopback or an origin configured in VOLTRO_DASHBOARD_APPS");
|
|
1293
1300
|
return;
|
|
1294
1301
|
}
|
|
1295
1302
|
try {
|
|
1296
1303
|
let n = { accept: i.accept ?? "application/json" }, a = i.authorization;
|
|
1297
|
-
a ? n.authorization = Array.isArray(a) ? a[0] : a :
|
|
1304
|
+
a ? n.authorization = Array.isArray(a) ? a[0] : a : De(r) && process.env.VOLTRO_INSPECT_TOKEN && (n.authorization = `Bearer ${process.env.VOLTRO_INSPECT_TOKEN}`);
|
|
1298
1305
|
let o;
|
|
1299
1306
|
if (s && s !== "GET" && s !== "HEAD") {
|
|
1300
1307
|
let t = [];
|
|
@@ -1318,20 +1325,20 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
1318
1325
|
}
|
|
1319
1326
|
return;
|
|
1320
1327
|
}
|
|
1321
|
-
if (
|
|
1328
|
+
if (o.name === "voltroDashboard" && a === "/api/dashboard/proxy/stream") {
|
|
1322
1329
|
let r = new URL(n, "http://x").searchParams.get("target");
|
|
1323
1330
|
if (!r) {
|
|
1324
1331
|
t.writeHead(400, { "content-type": "text/plain" }), t.end("missing ?target=");
|
|
1325
1332
|
return;
|
|
1326
1333
|
}
|
|
1327
|
-
if (!
|
|
1334
|
+
if (!Oe(r)) {
|
|
1328
1335
|
t.writeHead(400, { "content-type": "text/plain" }), t.end("target not allowed: must be loopback or an origin configured in VOLTRO_DASHBOARD_APPS");
|
|
1329
1336
|
return;
|
|
1330
1337
|
}
|
|
1331
1338
|
let a = new AbortController();
|
|
1332
1339
|
e.on("close", () => a.abort()), t.on("close", () => a.abort());
|
|
1333
1340
|
try {
|
|
1334
|
-
let e = i.authorization ?? (
|
|
1341
|
+
let e = i.authorization ?? (De(r) && process.env.VOLTRO_INSPECT_TOKEN ? `Bearer ${process.env.VOLTRO_INSPECT_TOKEN}` : void 0), n = await fetch(r, {
|
|
1335
1342
|
redirect: "manual",
|
|
1336
1343
|
method: "GET",
|
|
1337
1344
|
headers: {
|
|
@@ -1365,16 +1372,16 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
1365
1372
|
}
|
|
1366
1373
|
return;
|
|
1367
1374
|
}
|
|
1368
|
-
if (
|
|
1369
|
-
let n =
|
|
1370
|
-
if (
|
|
1375
|
+
if (a === "/_voltro/inspect/stream") {
|
|
1376
|
+
let n = we(i.origin);
|
|
1377
|
+
if (L()) {
|
|
1371
1378
|
t.writeHead(503, {
|
|
1372
1379
|
"content-type": "application/json",
|
|
1373
1380
|
...n
|
|
1374
1381
|
}), t.end(JSON.stringify({ error: "inspect disabled (VOLTRO_INSPECT=off)" }));
|
|
1375
1382
|
return;
|
|
1376
1383
|
}
|
|
1377
|
-
let r =
|
|
1384
|
+
let r = Te(i, "GET");
|
|
1378
1385
|
if (!r.ok) {
|
|
1379
1386
|
t.writeHead(401, {
|
|
1380
1387
|
"content-type": "application/json",
|
|
@@ -1392,11 +1399,11 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
1392
1399
|
"x-accel-buffering": "no",
|
|
1393
1400
|
...n
|
|
1394
1401
|
}), t.flushHeaders(), t.write("retry: 5000\n\n");
|
|
1395
|
-
for (let e of
|
|
1396
|
-
let a =
|
|
1397
|
-
t.write(
|
|
1402
|
+
for (let e of f.buffered()) t.write(ve(e));
|
|
1403
|
+
let a = f.subscribe((e) => {
|
|
1404
|
+
t.write(ve(e));
|
|
1398
1405
|
}), o = setInterval(() => {
|
|
1399
|
-
t.write(
|
|
1406
|
+
t.write(me());
|
|
1400
1407
|
}, 15e3), s = () => {
|
|
1401
1408
|
clearInterval(o), a();
|
|
1402
1409
|
};
|
|
@@ -1404,25 +1411,25 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
1404
1411
|
return;
|
|
1405
1412
|
}
|
|
1406
1413
|
try {
|
|
1407
|
-
let e = await
|
|
1408
|
-
if (e.stream ? e.stream(t) :
|
|
1414
|
+
let e = await Ot(n, i);
|
|
1415
|
+
if (e.stream ? e.stream(t) : Ze({
|
|
1409
1416
|
response: t,
|
|
1410
1417
|
status: e.status,
|
|
1411
1418
|
headers: e.headers,
|
|
1412
1419
|
body: e.body,
|
|
1413
1420
|
requestHeaders: i,
|
|
1414
|
-
compression:
|
|
1415
|
-
}) || (t.writeHead(e.status, e.headers), t.end(e.body)), !
|
|
1421
|
+
compression: fe.compression
|
|
1422
|
+
}) || (t.writeHead(e.status, e.headers), t.end(e.body)), !a.startsWith("/_voltro/inspect")) {
|
|
1416
1423
|
let t = Date.now() - r;
|
|
1417
|
-
|
|
1418
|
-
url:
|
|
1424
|
+
f.emit("request", {
|
|
1425
|
+
url: a,
|
|
1419
1426
|
status: e.status,
|
|
1420
1427
|
durationMs: t,
|
|
1421
1428
|
renderedBy: e.headers["x-voltro-rendered-by"],
|
|
1422
1429
|
cache: e.headers["x-voltro-cache"]
|
|
1423
1430
|
});
|
|
1424
|
-
let n =
|
|
1425
|
-
|
|
1431
|
+
let n = mt(a, K)?.route.pattern ?? (e.status === 404 ? "<unmatched>" : "<asset>");
|
|
1432
|
+
Ct.record({
|
|
1426
1433
|
kind: "request",
|
|
1427
1434
|
tag: n,
|
|
1428
1435
|
durationMs: t,
|
|
@@ -1434,77 +1441,77 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
1434
1441
|
}
|
|
1435
1442
|
}
|
|
1436
1443
|
});
|
|
1437
|
-
await new Promise((e) =>
|
|
1438
|
-
port:
|
|
1439
|
-
distDir:
|
|
1444
|
+
await new Promise((e) => jt.listen(m, "::", e)), kt = !0, i.mark("ready"), Q.info(`listening on http://localhost:${m}`, {
|
|
1445
|
+
port: m,
|
|
1446
|
+
distDir: g
|
|
1440
1447
|
}), Q.debug("dynamic + ssr/isr routes resolve via SSR loader");
|
|
1441
1448
|
try {
|
|
1442
|
-
await
|
|
1443
|
-
id:
|
|
1444
|
-
name:
|
|
1449
|
+
await Le({
|
|
1450
|
+
id: C,
|
|
1451
|
+
name: x,
|
|
1445
1452
|
kind: "web",
|
|
1446
|
-
url: `http://localhost:${
|
|
1453
|
+
url: `http://localhost:${m}`,
|
|
1447
1454
|
pid: process.pid,
|
|
1448
1455
|
status: "live",
|
|
1449
|
-
logFile:
|
|
1456
|
+
logFile: w.path
|
|
1450
1457
|
});
|
|
1451
|
-
let e =
|
|
1458
|
+
let e = ce(t);
|
|
1452
1459
|
if (e) {
|
|
1453
|
-
let t = await
|
|
1460
|
+
let t = await r({ dashboardAppPath: e });
|
|
1454
1461
|
t.status === "launched" ? Q.info(`dashboard launched at http://localhost:${t.port}`, { port: t.port }) : t.status === "already-running" && Q.debug(`dashboard already running on :${t.port}`, { port: t.port });
|
|
1455
1462
|
}
|
|
1456
1463
|
setInterval(() => {
|
|
1457
|
-
|
|
1458
|
-
id:
|
|
1459
|
-
name:
|
|
1464
|
+
Le({
|
|
1465
|
+
id: C,
|
|
1466
|
+
name: x,
|
|
1460
1467
|
kind: "web",
|
|
1461
|
-
url: `http://localhost:${
|
|
1468
|
+
url: `http://localhost:${m}`,
|
|
1462
1469
|
pid: process.pid,
|
|
1463
1470
|
status: "live",
|
|
1464
|
-
logFile:
|
|
1471
|
+
logFile: w.path
|
|
1465
1472
|
}).catch(() => {});
|
|
1466
1473
|
}, 1e4).unref();
|
|
1467
1474
|
} catch (e) {
|
|
1468
1475
|
Q.warn("runtime-registry write failed", {}, e);
|
|
1469
1476
|
}
|
|
1470
|
-
|
|
1471
|
-
app:
|
|
1477
|
+
Ge({
|
|
1478
|
+
app: o.name ?? "unnamed",
|
|
1472
1479
|
kind: "web",
|
|
1473
|
-
url: `http://localhost:${
|
|
1480
|
+
url: `http://localhost:${m}`,
|
|
1474
1481
|
bootMs: i.total()
|
|
1475
1482
|
});
|
|
1476
|
-
let
|
|
1483
|
+
let Mt = i.phaseBreakdown();
|
|
1477
1484
|
Q.info(`start: ready in ${i.total()}ms`, {
|
|
1478
1485
|
bootMs: i.total(),
|
|
1479
|
-
...
|
|
1486
|
+
...Mt ? { phases: Mt } : {}
|
|
1480
1487
|
});
|
|
1481
|
-
let
|
|
1482
|
-
if (!
|
|
1483
|
-
if (
|
|
1484
|
-
|
|
1488
|
+
let Nt = !1, Pt = (e) => async () => {
|
|
1489
|
+
if (!Nt) {
|
|
1490
|
+
if (Nt = !0, Q.info(`received ${e}, shutting down`, { signal: e }), jt.close(), await yt.stop(), xt) try {
|
|
1491
|
+
xt();
|
|
1485
1492
|
} catch {}
|
|
1486
|
-
if (
|
|
1487
|
-
await
|
|
1493
|
+
if (St) try {
|
|
1494
|
+
await Ke.runPromise(St.close());
|
|
1488
1495
|
} catch {}
|
|
1489
|
-
if (
|
|
1490
|
-
await
|
|
1496
|
+
if (V) try {
|
|
1497
|
+
await V.end();
|
|
1491
1498
|
} catch {}
|
|
1492
|
-
await
|
|
1499
|
+
await J.close(), await ze(C), await w.dispose(), process.exit(0);
|
|
1493
1500
|
}
|
|
1494
1501
|
};
|
|
1495
|
-
process.on("SIGINT",
|
|
1496
|
-
let
|
|
1497
|
-
if (
|
|
1502
|
+
process.on("SIGINT", Pt("SIGINT")), process.on("SIGTERM", Pt("SIGTERM"));
|
|
1503
|
+
let Ft = process.ppid;
|
|
1504
|
+
if (Ft > 1) {
|
|
1498
1505
|
let e = setInterval(() => {
|
|
1499
|
-
(process.ppid !==
|
|
1506
|
+
(process.ppid !== Ft || process.ppid === 1) && (clearInterval(e), Pt("SIGTERM")());
|
|
1500
1507
|
}, 2e3);
|
|
1501
1508
|
e.unref();
|
|
1502
1509
|
}
|
|
1503
1510
|
return new Promise(() => {});
|
|
1504
|
-
},
|
|
1511
|
+
}, bt = async (e) => {
|
|
1505
1512
|
t("start");
|
|
1506
|
-
let n = e.find((e) => !e.startsWith("-")) ?? process.cwd(), r = await
|
|
1513
|
+
let n = e.find((e) => !e.startsWith("-")) ?? process.cwd(), r = await yt(Ue(n));
|
|
1507
1514
|
return r.ran ? r.exitCode : (Q.error("no web app found at this path"), 1);
|
|
1508
1515
|
};
|
|
1509
1516
|
//#endregion
|
|
1510
|
-
export {
|
|
1517
|
+
export { yt as n, bt as t };
|