@voltro/cli 0.30.1 → 0.31.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 +163 -0
- package/dist/apiBuild-BOqL1dlg.js +2 -0
- package/dist/{apiBuild-DmkzRyv7.js → apiBuild-CLPt-pX6.js} +2 -2
- package/dist/appGraph-CvQCte0z.js +2 -0
- package/dist/appGraph-gQ_6GkQQ.js +110 -0
- package/dist/bin.js +3 -3
- package/dist/checkCommand-ClRvH_SN.js +2 -0
- package/dist/{checkCommand-C4konUy9.js → checkCommand-D7r6_pk7.js} +439 -530
- package/dist/{commands-BkJft9K2.js → commands-CNVVv03h.js} +1941 -1880
- package/dist/{dbCommand-qn__kLEt.js → dbCommand-BH8GAYuf.js} +76 -19
- package/dist/dbCommand-BwQ_Jl98.js +2 -0
- package/dist/{dev-DXhhZ7-f.js → dev-DOZVMVfi.js} +1 -1
- package/dist/{dev-C_NPcLDp.js → dev-DdQEn2Ia.js} +1986 -1967
- package/dist/{frameworkTableAssembly-Cpgn2e88.js → frameworkTableAssembly-BwIrO5nv.js} +122 -103
- package/dist/frameworkTableAssembly-D-EebUQX.js +2 -0
- package/dist/index.js +1 -1
- package/dist/{inspectMetrics-CkB2J0Zn.js → inspectMetrics-BeEAnjqw.js} +774 -527
- package/dist/{sdkgen-wsWLrq4l.js → sdkgen-v9WV8zRi.js} +1 -1
- package/dist/{serveCommand-HtI4X5kj.js → serveCommand-KsKXXWn4.js} +294 -293
- package/dist/serveEntry.js +2 -2
- package/dist/{start-egkbpugc.js → start-CI2QdKy9.js} +351 -346
- package/dist/startEntry.js +2 -2
- package/package.json +17 -17
- package/templates/AGENTS.md +43 -43
- package/templates/agent-docs/_index.md +43 -43
- package/templates/agent-docs/_manifest.json +84 -42
- package/templates/agent-docs/cli.md +4 -2
- package/templates/agent-docs/database/migrations.md +14 -1
- package/templates/agent-docs/internationalization.md +54 -3
- package/templates/agent-docs/plugins/ai-flows.md +148 -0
- package/templates/agent-docs/plugins/analytics-postgres.md +90 -0
- package/templates/agent-docs/plugins/atlassian.md +378 -0
- package/templates/agent-docs/plugins/audit.md +324 -0
- package/templates/agent-docs/plugins/auth-auth0.md +92 -0
- package/templates/agent-docs/plugins/auth-clerk.md +90 -0
- package/templates/agent-docs/plugins/auth-kinde.md +88 -0
- package/templates/agent-docs/plugins/auth-oidc.md +95 -0
- package/templates/agent-docs/plugins/auth-supabase.md +103 -0
- package/templates/agent-docs/plugins/auth-workos.md +105 -0
- package/templates/agent-docs/plugins/auth.md +227 -0
- package/templates/agent-docs/plugins/billing.md +324 -0
- package/templates/agent-docs/plugins/broadcast.md +144 -0
- package/templates/agent-docs/plugins/cdc-out.md +116 -0
- package/templates/agent-docs/plugins/clickhouse.md +91 -0
- package/templates/agent-docs/plugins/datadog.md +105 -0
- package/templates/agent-docs/plugins/deactivation.md +114 -0
- package/templates/agent-docs/plugins/duckdb.md +82 -0
- package/templates/agent-docs/plugins/flags.md +146 -0
- package/templates/agent-docs/plugins/governance.md +143 -0
- package/templates/agent-docs/plugins/licensing.md +74 -0
- package/templates/agent-docs/plugins/logship.md +56 -0
- package/templates/agent-docs/plugins/mail.md +334 -0
- package/templates/agent-docs/plugins/moderation.md +65 -0
- package/templates/agent-docs/plugins/multitenancy.md +99 -0
- package/templates/agent-docs/plugins/notifications.md +252 -0
- package/templates/agent-docs/plugins/openapi.md +94 -0
- package/templates/agent-docs/plugins/postgis.md +140 -0
- package/templates/agent-docs/plugins/posthog.md +91 -0
- package/templates/agent-docs/plugins/presence.md +115 -0
- package/templates/agent-docs/plugins/prometheus.md +124 -0
- package/templates/agent-docs/plugins/ratelimit.md +274 -0
- package/templates/agent-docs/plugins/rbac.md +270 -0
- package/templates/agent-docs/plugins/scim.md +63 -0
- package/templates/agent-docs/plugins/search.md +116 -0
- package/templates/agent-docs/plugins/sentry.md +192 -0
- package/templates/agent-docs/plugins/soft-delete.md +72 -0
- package/templates/agent-docs/plugins/sso-saml.md +132 -0
- package/templates/agent-docs/plugins/storage.md +709 -0
- package/templates/agent-docs/plugins/tinybird.md +92 -0
- package/templates/agent-docs/plugins/versioning.md +226 -0
- package/templates/agent-docs/plugins/webhooks.md +585 -0
- package/templates/agent-docs/security.md +12 -1
- package/templates/agent-docs/whats-new.md +81 -37
- package/templates/apps/api-ai/package.json +7 -7
- 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 +10 -10
- package/templates/apps/api-collab/package.json +8 -8
- package/templates/apps/api-data-advanced/package.json +8 -8
- package/templates/apps/api-durable/package.json +8 -8
- package/templates/apps/api-feature-flags/package.json +9 -9
- package/templates/apps/api-governance/package.json +8 -8
- package/templates/apps/api-kv/package.json +8 -8
- package/templates/apps/api-moderation/package.json +8 -8
- package/templates/apps/api-observability/package.json +8 -8
- package/templates/apps/api-ratelimit/package.json +8 -8
- package/templates/apps/api-rbac/package.json +8 -8
- package/templates/apps/api-rest/package.json +7 -7
- package/templates/apps/api-saas/package.json +11 -11
- package/templates/apps/api-saas-starter/package.json +10 -10
- package/templates/apps/api-search/package.json +8 -8
- package/templates/apps/api-status/package.json +8 -8
- package/templates/apps/api-versioning/package.json +8 -8
- package/templates/apps/api-webhooks/package.json +9 -9
- package/templates/apps/changelog/package.json +6 -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 +8 -8
- package/templates/apps/frontend-auth/package.json +8 -8
- package/templates/apps/frontend-blank/package.json +7 -7
- package/templates/apps/frontend-cms/package.json +9 -9
- package/templates/apps/frontend-collab/package.json +9 -9
- 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 +7 -7
- package/templates/apps/frontend-i18n/package.json +6 -6
- package/templates/apps/frontend-landing/package.json +7 -7
- package/templates/apps/frontend-portal/package.json +8 -8
- package/templates/apps/frontend-saas/package.json +8 -8
- package/templates/apps/frontend-spa/package.json +7 -7
- package/templates/apps/frontend-ssr/package.json +7 -7
- package/templates/apps/frontend-ssr-api/package.json +8 -8
- package/templates/apps/frontend-static-blog/package.json +6 -6
- package/templates/apps/frontend-status/package.json +8 -8
- package/templates/apps/mobile-app/package.json +2 -2
- package/dist/apiBuild-Ca6Sq5jy.js +0 -2
- package/dist/checkCommand-DHD0aBeR.js +0 -2
- package/dist/dbCommand-wfGi3FgG.js +0 -2
- package/dist/frameworkTableAssembly-Bn_c4Mnl.js +0 -2
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { A as
|
|
1
|
+
import { $ as e, C as t, Ct as n, D as r, E as i, G as a, J as o, K as s, L as c, P as l, Q as u, S as d, St as ee, Tt as f, V as p, W as m, _ as h, _t as g, a as _, b as v, bt as y, c as b, dt as te, f as x, ft as S, g as C, h as w, i as T, k as E, m as D, mt as O, o as ne, p as re, pt as k, q as ie, r as A, s as j, t as M, ut as N, v as ae, wt as oe, x as P, y as F } from "./inspectMetrics-BeEAnjqw.js";
|
|
2
|
+
import { A as se, E as I, O as ce, a as le, k as L, m as ue } from "./inspect-BUUjt773.js";
|
|
3
3
|
import { t as de } from "./bootTiming-BdyP9nYw.js";
|
|
4
|
-
import { dirname as
|
|
5
|
-
import { fileURLToPath as
|
|
6
|
-
import { createLogger as
|
|
7
|
-
import { promises as
|
|
4
|
+
import { dirname as fe, extname as pe, join as R, resolve as z } from "node:path";
|
|
5
|
+
import { fileURLToPath as B, pathToFileURL as V } from "node:url";
|
|
6
|
+
import { createLogger as H, printReadyBlock as me } from "@voltro/logger";
|
|
7
|
+
import { promises as U } from "node:fs";
|
|
8
8
|
import { snapshotMetricsSync as he } from "@voltro/runtime";
|
|
9
9
|
import { createServer as ge } from "node:http";
|
|
10
10
|
//#region src/isrCdcInvalidator.ts
|
|
11
|
-
var
|
|
11
|
+
var W = H({ scope: "voltro:start:cdc" }), G = (e) => (t) => {
|
|
12
12
|
let n = 0;
|
|
13
13
|
for (let [r, i] of e.tableSubscriptionsByPattern) {
|
|
14
14
|
if (!i.includes(t)) continue;
|
|
@@ -19,23 +19,23 @@ var U = V({ scope: "voltro:start:cdc" }), W = (e) => (t) => {
|
|
|
19
19
|
}));
|
|
20
20
|
}
|
|
21
21
|
return n;
|
|
22
|
-
},
|
|
22
|
+
}, _e = () => !process.env.PG_HOST && !process.env.PG_DATABASE ? null : {
|
|
23
23
|
host: process.env.PG_HOST ?? "localhost",
|
|
24
24
|
port: Number(process.env.PG_PORT ?? 5432),
|
|
25
25
|
user: process.env.PG_USER ?? "app",
|
|
26
26
|
password: process.env.PG_PASSWORD ?? "app",
|
|
27
27
|
database: process.env.PG_DATABASE ?? "app"
|
|
28
|
-
},
|
|
29
|
-
let t = e.channel ?? "framework_changes", n =
|
|
28
|
+
}, ve = (e) => {
|
|
29
|
+
let t = e.channel ?? "framework_changes", n = G(e), r = null, i = null;
|
|
30
30
|
return {
|
|
31
31
|
start: async () => {
|
|
32
|
-
let a =
|
|
32
|
+
let a = _e();
|
|
33
33
|
if (!a) {
|
|
34
|
-
|
|
34
|
+
W.debug("skipped — no PG_* env vars set");
|
|
35
35
|
return;
|
|
36
36
|
}
|
|
37
37
|
if (e.tableSubscriptionsByPattern.size === 0) {
|
|
38
|
-
|
|
38
|
+
W.debug("skipped — no pages declare cacheInvalidatesOn");
|
|
39
39
|
return;
|
|
40
40
|
}
|
|
41
41
|
r = new (await (import("pg"))).default.Client(a), await r.connect(), i = (e) => {
|
|
@@ -44,16 +44,16 @@ var U = V({ scope: "voltro:start:cdc" }), W = (e) => (t) => {
|
|
|
44
44
|
try {
|
|
45
45
|
r = JSON.parse(e.payload);
|
|
46
46
|
} catch (e) {
|
|
47
|
-
|
|
47
|
+
W.warn("bad CDC payload", {}, e);
|
|
48
48
|
return;
|
|
49
49
|
}
|
|
50
50
|
let i = n(r.table);
|
|
51
|
-
i > 0 &&
|
|
51
|
+
i > 0 && W.info(`${r.op} on '${r.table}' → dropped ${i} cache entries`, {
|
|
52
52
|
op: r.op,
|
|
53
53
|
table: r.table,
|
|
54
54
|
dropped: i
|
|
55
55
|
});
|
|
56
|
-
}, r.on("notification", i), await r.query(`LISTEN ${t}`),
|
|
56
|
+
}, r.on("notification", i), await r.query(`LISTEN ${t}`), W.info(`LISTEN ${t}`, {
|
|
57
57
|
channel: t,
|
|
58
58
|
host: a.host,
|
|
59
59
|
port: a.port,
|
|
@@ -69,7 +69,7 @@ var U = V({ scope: "voltro:start:cdc" }), W = (e) => (t) => {
|
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
71
|
};
|
|
72
|
-
}, K =
|
|
72
|
+
}, K = H({ scope: "voltro:start:isr-cache" }), ye = "voltro_isr_cache", q = (e) => `
|
|
73
73
|
CREATE TABLE IF NOT EXISTS ${e} (
|
|
74
74
|
cache_key TEXT PRIMARY KEY,
|
|
75
75
|
html TEXT NOT NULL,
|
|
@@ -80,9 +80,9 @@ CREATE TABLE IF NOT EXISTS ${e} (
|
|
|
80
80
|
stale_while_revalidate_ms BIGINT NOT NULL DEFAULT 0
|
|
81
81
|
);
|
|
82
82
|
CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
83
|
-
`,
|
|
84
|
-
let t = e.tableName ??
|
|
85
|
-
i || (i = !0, await n.query(
|
|
83
|
+
`, be = (e) => {
|
|
84
|
+
let t = e.tableName ?? ye, { client: n } = e, r = /* @__PURE__ */ new Map(), i = !1, a = (async () => {
|
|
85
|
+
i || (i = !0, await n.query(q(t)));
|
|
86
86
|
})().then(async () => {
|
|
87
87
|
let e = await n.query(`SELECT * FROM ${t}`);
|
|
88
88
|
for (let t of e.rows) r.set(t.cache_key, {
|
|
@@ -142,14 +142,14 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
142
142
|
return Array.from(r.entries());
|
|
143
143
|
}
|
|
144
144
|
};
|
|
145
|
-
}, J =
|
|
145
|
+
}, J = H({ scope: "voltro:start" }), xe = await (async () => {
|
|
146
146
|
try {
|
|
147
|
-
let e = R(
|
|
147
|
+
let e = R(fe(B(import.meta.url)), "..", "package.json"), t = await U.readFile(e, "utf8");
|
|
148
148
|
return JSON.parse(t).version ?? "0.0.0";
|
|
149
149
|
} catch {
|
|
150
150
|
return "0.0.0";
|
|
151
151
|
}
|
|
152
|
-
})(), Y = (e) => e instanceof Error && e._voltroControl === "redirect" && typeof e.location == "string", X = (e) => e instanceof Error && e._voltroControl === "not-found",
|
|
152
|
+
})(), Y = (e) => e instanceof Error && e._voltroControl === "redirect" && typeof e.location == "string", X = (e) => e instanceof Error && e._voltroControl === "not-found", Se = {
|
|
153
153
|
".html": "text/html; charset=utf-8",
|
|
154
154
|
".js": "application/javascript",
|
|
155
155
|
".mjs": "application/javascript",
|
|
@@ -167,13 +167,13 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
167
167
|
".woff": "font/woff",
|
|
168
168
|
".woff2": "font/woff2",
|
|
169
169
|
".txt": "text/plain; charset=utf-8"
|
|
170
|
-
},
|
|
170
|
+
}, Ce = (e) => Se[pe(e).toLowerCase()] ?? "application/octet-stream", we = (e) => e.replace(/<script\b(?=[^>]*\btype="module")(?:(?!<\/script>).)*<\/script>/gi, "").replace(/<script\b(?=[^>]*\bsrc=)(?:(?!<\/script>).)*<\/script>/gi, "").replace(/<link\b[^>]*\brel="modulepreload"[^>]*>/gi, ""), Z = async (e) => {
|
|
171
171
|
try {
|
|
172
|
-
return await
|
|
172
|
+
return await U.stat(e), !0;
|
|
173
173
|
} catch {
|
|
174
174
|
return !1;
|
|
175
175
|
}
|
|
176
|
-
},
|
|
176
|
+
}, Q = (e) => {
|
|
177
177
|
let t = [], n = 0, r = e.split("/").filter(Boolean), i = [];
|
|
178
178
|
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, "\\$&"));
|
|
179
179
|
let a = i.join("/");
|
|
@@ -182,8 +182,8 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
182
182
|
paramNames: t,
|
|
183
183
|
priority: n
|
|
184
184
|
};
|
|
185
|
-
},
|
|
186
|
-
let { regex: t, paramNames: n, priority: r } =
|
|
185
|
+
}, Te = (e) => e.map((e) => {
|
|
186
|
+
let { regex: t, paramNames: n, priority: r } = Q(e.pattern);
|
|
187
187
|
return {
|
|
188
188
|
pattern: e.pattern,
|
|
189
189
|
file: e.file,
|
|
@@ -192,7 +192,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
192
192
|
paramNames: n,
|
|
193
193
|
priority: r
|
|
194
194
|
};
|
|
195
|
-
}).slice().sort((e, t) => e.priority - t.priority),
|
|
195
|
+
}).slice().sort((e, t) => e.priority - t.priority), Ee = (e, t) => {
|
|
196
196
|
for (let n of t) {
|
|
197
197
|
let t = n.regex.exec(e);
|
|
198
198
|
if (!t) continue;
|
|
@@ -204,31 +204,31 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
204
204
|
};
|
|
205
205
|
}
|
|
206
206
|
return null;
|
|
207
|
-
},
|
|
208
|
-
let { provider:
|
|
209
|
-
if (
|
|
210
|
-
let
|
|
207
|
+
}, De = async (e) => {
|
|
208
|
+
let { provider: n, route: r, params: i, pathname: a, dirs: o, shellTemplate: s, requestHeaders: l, requestUrl: u = "", apiOrigin: ee, apiName: f } = e, { search: p } = t(u), m = T(ee, l.cookie, { apiName: f }), g = await n.getPage(r.pattern, r.file), y = c(g, r.file), b = y === "spa" && ne(o, r.dirChain).some((e) => e.hasLayout);
|
|
209
|
+
if (y !== "ssr" && y !== "isr" && !b) return null;
|
|
210
|
+
let te = ne(o, r.dirChain), x = {}, S = null, E, re = new AbortController();
|
|
211
211
|
try {
|
|
212
|
-
(await
|
|
213
|
-
entries:
|
|
214
|
-
loadLayout: (e) =>
|
|
215
|
-
loadError: (e) =>
|
|
216
|
-
loadPending: (e) =>
|
|
212
|
+
(await n.getHelpers()).beginStoreSeeds(), {chain: E, segmentLoaderData: x} = await _({
|
|
213
|
+
entries: te,
|
|
214
|
+
loadLayout: (e) => n.getLayout(e.dir),
|
|
215
|
+
loadError: (e) => n.getError(e.dir),
|
|
216
|
+
loadPending: (e) => n.getPending(e.dir),
|
|
217
217
|
ctx: {
|
|
218
218
|
params: i,
|
|
219
219
|
pathname: a,
|
|
220
|
-
search:
|
|
221
|
-
signal:
|
|
220
|
+
search: p,
|
|
221
|
+
signal: re.signal,
|
|
222
222
|
headers: l,
|
|
223
|
-
query:
|
|
223
|
+
query: m
|
|
224
224
|
}
|
|
225
|
-
}), typeof
|
|
225
|
+
}), typeof g.loader == "function" && !b && (S = await g.loader({
|
|
226
226
|
params: i,
|
|
227
227
|
pathname: a,
|
|
228
|
-
search:
|
|
229
|
-
signal:
|
|
228
|
+
search: p,
|
|
229
|
+
signal: re.signal,
|
|
230
230
|
headers: l,
|
|
231
|
-
query:
|
|
231
|
+
query: m
|
|
232
232
|
}));
|
|
233
233
|
} catch (e) {
|
|
234
234
|
if (Y(e)) return {
|
|
@@ -239,71 +239,71 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
239
239
|
if (X(e)) return { control: "not-found" };
|
|
240
240
|
throw e;
|
|
241
241
|
}
|
|
242
|
-
let
|
|
243
|
-
|
|
244
|
-
pageMod:
|
|
242
|
+
let k = await n.getHelpers();
|
|
243
|
+
b || await D({
|
|
244
|
+
pageMod: g,
|
|
245
245
|
params: i,
|
|
246
|
-
query:
|
|
247
|
-
apiName:
|
|
248
|
-
seed:
|
|
246
|
+
query: m,
|
|
247
|
+
apiName: f,
|
|
248
|
+
seed: k.seedPreloadedSubscription,
|
|
249
249
|
onError: ({ tag: e, apiName: t }, n) => J.warn("preload seed failed", {
|
|
250
250
|
tag: e,
|
|
251
251
|
apiName: t,
|
|
252
252
|
pathname: a
|
|
253
253
|
}, n)
|
|
254
254
|
});
|
|
255
|
-
let
|
|
256
|
-
pattern:
|
|
257
|
-
Component:
|
|
258
|
-
meta:
|
|
259
|
-
loader:
|
|
260
|
-
ErrorBoundary:
|
|
261
|
-
Pending:
|
|
262
|
-
renderMode:
|
|
263
|
-
chain:
|
|
264
|
-
},
|
|
265
|
-
cookies:
|
|
255
|
+
let ie = {
|
|
256
|
+
pattern: r.pattern,
|
|
257
|
+
Component: g.default,
|
|
258
|
+
meta: g.meta,
|
|
259
|
+
loader: g.loader,
|
|
260
|
+
ErrorBoundary: g.ErrorBoundary,
|
|
261
|
+
Pending: g.Pending,
|
|
262
|
+
renderMode: y,
|
|
263
|
+
chain: E
|
|
264
|
+
}, A = {
|
|
265
|
+
cookies: k.parseCookieHeader(l.cookie),
|
|
266
266
|
headers: l,
|
|
267
267
|
url: u
|
|
268
|
-
},
|
|
269
|
-
if (
|
|
270
|
-
let e =
|
|
271
|
-
helpers:
|
|
272
|
-
page:
|
|
273
|
-
interactive:
|
|
268
|
+
}, j = k.i18n?.resolve(l.cookie, l["accept-language"]), M = g.interactive ?? "full";
|
|
269
|
+
if (b) {
|
|
270
|
+
let e = v({
|
|
271
|
+
helpers: k,
|
|
272
|
+
page: r.pattern,
|
|
273
|
+
interactive: M,
|
|
274
274
|
delivery: "stream",
|
|
275
275
|
renderInput: {
|
|
276
|
-
descriptor:
|
|
276
|
+
descriptor: ie,
|
|
277
277
|
params: i,
|
|
278
278
|
pathname: a,
|
|
279
|
-
search:
|
|
279
|
+
search: p,
|
|
280
280
|
segmentLoaderData: x,
|
|
281
|
-
requestContext:
|
|
282
|
-
...
|
|
283
|
-
outerWrap:
|
|
284
|
-
locale:
|
|
281
|
+
requestContext: A,
|
|
282
|
+
...j ? {
|
|
283
|
+
outerWrap: j.outerWrap,
|
|
284
|
+
locale: j.locale
|
|
285
285
|
} : {}
|
|
286
286
|
}
|
|
287
|
-
}), t =
|
|
288
|
-
helpers:
|
|
287
|
+
}), t = j?.locale ?? A.cookies["voltro:locale"] ?? "en", n = (t) => d({
|
|
288
|
+
helpers: k,
|
|
289
289
|
prepared: e,
|
|
290
290
|
meta: t,
|
|
291
|
-
interactive:
|
|
291
|
+
interactive: M
|
|
292
292
|
});
|
|
293
293
|
if (e.hasDeferred) {
|
|
294
|
-
let
|
|
294
|
+
let r = C({ shell: s });
|
|
295
295
|
return {
|
|
296
296
|
renderMode: "spa",
|
|
297
|
-
stream: (i) =>
|
|
297
|
+
stream: (i) => h({
|
|
298
298
|
res: i,
|
|
299
|
-
shell:
|
|
299
|
+
shell: r,
|
|
300
300
|
htmlLang: t,
|
|
301
301
|
headers: {
|
|
302
302
|
"content-type": "text/html; charset=utf-8",
|
|
303
303
|
"x-voltro-rendered-by": "spa"
|
|
304
304
|
},
|
|
305
|
-
headInjection:
|
|
306
|
-
render: (t) =>
|
|
305
|
+
headInjection: n,
|
|
306
|
+
render: (t) => k.renderPageToStream({
|
|
307
307
|
...e.renderInput,
|
|
308
308
|
...t
|
|
309
309
|
}),
|
|
@@ -313,48 +313,48 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
313
313
|
})
|
|
314
314
|
};
|
|
315
315
|
}
|
|
316
|
-
let o =
|
|
317
|
-
helpers:
|
|
316
|
+
let o = P({
|
|
317
|
+
helpers: k,
|
|
318
318
|
prepared: e
|
|
319
319
|
});
|
|
320
320
|
return {
|
|
321
|
-
html: s.replace("<div id=\"root\"></div>", `<div id="root">${o.body}</div>`)
|
|
321
|
+
html: w(s.replace("<div id=\"root\"></div>", `<div id="root">${o.body}</div>`), n(o.meta)).replace(/<html(\s+lang="[^"]*")?/i, `<html lang="${t}"`),
|
|
322
322
|
renderMode: "spa",
|
|
323
323
|
revalidateMs: null
|
|
324
324
|
};
|
|
325
325
|
}
|
|
326
|
-
let
|
|
327
|
-
helpers:
|
|
328
|
-
page:
|
|
326
|
+
let N = F({
|
|
327
|
+
helpers: k,
|
|
328
|
+
page: r.pattern,
|
|
329
329
|
pathname: a,
|
|
330
|
-
renderMode:
|
|
331
|
-
interactive:
|
|
332
|
-
loaderData:
|
|
330
|
+
renderMode: y,
|
|
331
|
+
interactive: M,
|
|
332
|
+
loaderData: S,
|
|
333
333
|
segmentLoaderData: x,
|
|
334
|
-
pageLoaderRan: typeof
|
|
335
|
-
}),
|
|
336
|
-
descriptor:
|
|
334
|
+
pageLoaderRan: typeof g.loader == "function"
|
|
335
|
+
}), ae = {
|
|
336
|
+
descriptor: ie,
|
|
337
337
|
params: i,
|
|
338
338
|
pathname: a,
|
|
339
|
-
search:
|
|
340
|
-
loaderData:
|
|
341
|
-
segmentLoaderData:
|
|
342
|
-
requestContext:
|
|
343
|
-
...
|
|
344
|
-
outerWrap:
|
|
345
|
-
locale:
|
|
339
|
+
search: p,
|
|
340
|
+
loaderData: N.loaderData,
|
|
341
|
+
segmentLoaderData: N.segmentLoaderData,
|
|
342
|
+
requestContext: A,
|
|
343
|
+
...j ? {
|
|
344
|
+
outerWrap: j.outerWrap,
|
|
345
|
+
locale: j.locale
|
|
346
346
|
} : {}
|
|
347
|
-
},
|
|
348
|
-
|
|
349
|
-
`<meta name="voltro-interactive" content="${
|
|
350
|
-
...
|
|
351
|
-
|
|
347
|
+
}, oe = (e) => [
|
|
348
|
+
k.renderMetaToHtml(e),
|
|
349
|
+
`<meta name="voltro-interactive" content="${M}" />`,
|
|
350
|
+
...N.hasDeferred ? [k.renderDeferredRegistryScript()] : [],
|
|
351
|
+
k.renderRouterStateScript(N.stateInput)
|
|
352
352
|
].filter((e) => e.length > 0).join("\n ");
|
|
353
|
-
if (
|
|
354
|
-
let e =
|
|
353
|
+
if (y === "ssr" && M === "full" && e.buffered !== !0) {
|
|
354
|
+
let e = j?.locale ?? A.cookies["voltro:locale"] ?? "en", t = C({ shell: s });
|
|
355
355
|
return {
|
|
356
356
|
renderMode: "ssr",
|
|
357
|
-
stream: (n) =>
|
|
357
|
+
stream: (n) => h({
|
|
358
358
|
res: n,
|
|
359
359
|
shell: t,
|
|
360
360
|
htmlLang: e,
|
|
@@ -362,9 +362,9 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
362
362
|
"content-type": "text/html; charset=utf-8",
|
|
363
363
|
"x-voltro-rendered-by": "ssr"
|
|
364
364
|
},
|
|
365
|
-
headInjection:
|
|
366
|
-
render: (e) =>
|
|
367
|
-
...
|
|
365
|
+
headInjection: oe,
|
|
366
|
+
render: (e) => k.renderPageToStream({
|
|
367
|
+
...ae,
|
|
368
368
|
...e
|
|
369
369
|
}),
|
|
370
370
|
onShellError: (e) => {
|
|
@@ -373,16 +373,16 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
373
373
|
})
|
|
374
374
|
};
|
|
375
375
|
}
|
|
376
|
-
let { html:
|
|
377
|
-
|
|
378
|
-
let ue =
|
|
376
|
+
let { html: se, meta: I } = k.renderPageToHtml(ae), ce = oe(I), le = j?.locale ?? A.cookies["voltro:locale"] ?? "en", L = w(s.replace("<div id=\"root\"></div>", `<div id="root">${se}</div>`), ce).replace(/<html(\s+lang="[^"]*")?/i, `<html lang="${le}"`);
|
|
377
|
+
M === "none" && (L = we(L));
|
|
378
|
+
let ue = y === "isr" ? O(g.revalidate) : null;
|
|
379
379
|
return {
|
|
380
|
-
html:
|
|
381
|
-
renderMode:
|
|
380
|
+
html: L,
|
|
381
|
+
renderMode: y,
|
|
382
382
|
revalidateMs: ue
|
|
383
383
|
};
|
|
384
|
-
}, $ = (e) => e === "" ? "/" : e,
|
|
385
|
-
let t = await import(
|
|
384
|
+
}, $ = (e) => e === "" ? "/" : e, Oe = async (e) => {
|
|
385
|
+
let t = await import(V(e).href);
|
|
386
386
|
return {
|
|
387
387
|
kind: "bundle",
|
|
388
388
|
getPageMeta: () => t.pageMeta,
|
|
@@ -411,51 +411,56 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
411
411
|
},
|
|
412
412
|
async close() {}
|
|
413
413
|
};
|
|
414
|
-
},
|
|
415
|
-
let
|
|
416
|
-
root:
|
|
414
|
+
}, ke = async (t, n) => {
|
|
415
|
+
let r = await y("vite", () => import("vite")), i = (await import("@vitejs/plugin-react")).default, a = (await import("@tailwindcss/vite")).default, o = await r.createServer({
|
|
416
|
+
root: n,
|
|
417
417
|
envPrefix: "__VOLTRO_VITE_ENV_DISABLED__",
|
|
418
|
-
plugins: [
|
|
419
|
-
resolve: { dedupe: [
|
|
420
|
-
|
|
418
|
+
plugins: [i(), a()],
|
|
419
|
+
resolve: { dedupe: [
|
|
420
|
+
"react",
|
|
421
|
+
"react-dom",
|
|
422
|
+
"react-intl",
|
|
423
|
+
"@voltro/i18n"
|
|
424
|
+
] },
|
|
425
|
+
ssr: { noExternal: ["react-intl", "@voltro/i18n"] },
|
|
421
426
|
server: {
|
|
422
427
|
middlewareMode: !0,
|
|
423
428
|
hmr: !1
|
|
424
429
|
},
|
|
425
430
|
appType: "custom",
|
|
426
431
|
logLevel: "warn"
|
|
427
|
-
}),
|
|
428
|
-
limit:
|
|
432
|
+
}), s = R(t, "src", "pages"), c = (e) => e === "" ? s : R(s, e), l = u({
|
|
433
|
+
limit: e(),
|
|
429
434
|
onColdStart: (e) => J.debug("ssr cold-compile start", { id: e }),
|
|
430
435
|
onColdEnd: (e, { durationMs: t, failed: n }) => J.debug(`ssr cold-compile ${n ? "FAILED" : "end"} ${t}ms`, {
|
|
431
436
|
id: e,
|
|
432
437
|
ms: t,
|
|
433
438
|
...n ? { failed: !0 } : {}
|
|
434
439
|
})
|
|
435
|
-
}),
|
|
440
|
+
}), d = (e) => l.load(e, async () => await o.ssrLoadModule(e));
|
|
436
441
|
return {
|
|
437
442
|
kind: "middleware",
|
|
438
443
|
async getPage(e, t) {
|
|
439
|
-
return
|
|
444
|
+
return d(R(s, t));
|
|
440
445
|
},
|
|
441
446
|
async getLayout(e) {
|
|
442
|
-
return
|
|
447
|
+
return d(R(c(e), "layout.tsx"));
|
|
443
448
|
},
|
|
444
449
|
async getError(e) {
|
|
445
|
-
return
|
|
450
|
+
return d(R(c(e), "error.tsx"));
|
|
446
451
|
},
|
|
447
452
|
async getPending(e) {
|
|
448
|
-
return
|
|
453
|
+
return d(R(c(e), "loading.tsx"));
|
|
449
454
|
},
|
|
450
455
|
async getHelpers() {
|
|
451
|
-
return await
|
|
456
|
+
return await d("@voltro/web/ssr");
|
|
452
457
|
},
|
|
453
458
|
async close() {
|
|
454
|
-
await
|
|
459
|
+
await o.close();
|
|
455
460
|
}
|
|
456
461
|
};
|
|
457
|
-
},
|
|
458
|
-
let
|
|
462
|
+
}, Ae = async (e) => {
|
|
463
|
+
let t = de(), c = await j(e);
|
|
459
464
|
if (!c) return {
|
|
460
465
|
ran: !1,
|
|
461
466
|
exitCode: 0
|
|
@@ -464,89 +469,89 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
464
469
|
ran: !0,
|
|
465
470
|
exitCode: 1
|
|
466
471
|
};
|
|
467
|
-
let { resolved:
|
|
472
|
+
let { resolved: u } = await g({
|
|
468
473
|
rawEnv: c.env,
|
|
469
474
|
appType: "web",
|
|
470
|
-
root:
|
|
475
|
+
root: e,
|
|
471
476
|
log: J,
|
|
472
477
|
generateTypes: !1
|
|
473
|
-
}),
|
|
474
|
-
|
|
475
|
-
let
|
|
476
|
-
|
|
477
|
-
let
|
|
478
|
+
}), d = u.publicValues;
|
|
479
|
+
t.mark("config");
|
|
480
|
+
let h = ie();
|
|
481
|
+
m(h), J.info("booting voltro start", { app: c.name ?? "(unnamed)" });
|
|
482
|
+
let _ = (() => {
|
|
478
483
|
if (process.env.VOLTRO_IS_DASHBOARD === "1" && process.env.VOLTRO_DASHBOARD_PORT) return Number(process.env.VOLTRO_DASHBOARD_PORT);
|
|
479
484
|
if (process.env.PORT) {
|
|
480
485
|
let e = Number(process.env.PORT);
|
|
481
486
|
if (Number.isFinite(e) && e > 0) return e;
|
|
482
487
|
}
|
|
483
488
|
return c.port ?? 5173;
|
|
484
|
-
})(),
|
|
485
|
-
if (!await
|
|
489
|
+
})(), v = R(e, ".framework"), y = R(v, "dist"), C = R(y, "index.html");
|
|
490
|
+
if (!await Z(C)) return J.error("no built dist found — run `voltro build` first", { distDir: y }), {
|
|
486
491
|
ran: !0,
|
|
487
492
|
exitCode: 1
|
|
488
493
|
};
|
|
489
|
-
let
|
|
490
|
-
await
|
|
494
|
+
let w = c.name ?? "unnamed", T = ee("web", w, _), D = E(w);
|
|
495
|
+
await f({
|
|
491
496
|
id: T,
|
|
492
|
-
name:
|
|
497
|
+
name: w,
|
|
493
498
|
kind: "web",
|
|
494
|
-
url: `http://localhost:${
|
|
499
|
+
url: `http://localhost:${_}`,
|
|
495
500
|
pid: process.pid,
|
|
496
501
|
status: "booting",
|
|
497
|
-
logFile:
|
|
502
|
+
logFile: D.path
|
|
498
503
|
}).catch(() => {});
|
|
499
|
-
let
|
|
504
|
+
let O = R(y, "_voltro", "shell.html"), P = await Z(O) ? await U.readFile(O, "utf8") : await U.readFile(C, "utf8"), F = await b(e, c), fe = A(F[0]), pe = F[0]?.name, z, B = null;
|
|
500
505
|
process.env.SSR_CACHE === "postgres" && process.env.PG_HOST ? (B = new (await (import("pg"))).default.Client({
|
|
501
506
|
host: process.env.PG_HOST,
|
|
502
507
|
port: Number(process.env.PG_PORT ?? 5432),
|
|
503
508
|
user: process.env.PG_USER ?? "app",
|
|
504
509
|
password: process.env.PG_PASSWORD ?? "app",
|
|
505
510
|
database: process.env.PG_DATABASE ?? "app"
|
|
506
|
-
}), await B.connect(), z =
|
|
507
|
-
let { pages: V, dirs:
|
|
508
|
-
|
|
509
|
-
let G = R(
|
|
510
|
-
if (!
|
|
511
|
-
let
|
|
512
|
-
J.info(`ssr loader: ${
|
|
513
|
-
kind:
|
|
514
|
-
...
|
|
515
|
-
}),
|
|
516
|
-
let
|
|
511
|
+
}), await B.connect(), z = be({ client: B }), J.info("isr cache backend: postgres", { table: "voltro_isr_cache" })) : (z = k(), J.info("isr cache backend: memory (per-process)", { hint: "set SSR_CACHE=postgres for persistent storage" })), await re(e, c, F, d);
|
|
512
|
+
let { pages: V, dirs: H } = await x(R(e, "src", "pages")), W = Te(V);
|
|
513
|
+
t.mark("scan");
|
|
514
|
+
let G = R(y, "server", "ssrEntry.js"), _e = await Z(G);
|
|
515
|
+
if (!_e && process.env.NODE_ENV === "production") throw J.fatal(`production \`voltro start\` requires a precompiled SSR bundle at ${G} 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 ${G}`);
|
|
516
|
+
let K = _e ? await Oe(G) : await ke(e, v);
|
|
517
|
+
J.info(`ssr loader: ${K.kind}`, {
|
|
518
|
+
kind: K.kind,
|
|
519
|
+
...K.kind === "middleware" ? { hint: "no pre-built SSR bundle found; run `voltro build` to enable bundle mode" } : {}
|
|
520
|
+
}), t.mark("provider");
|
|
521
|
+
let ye = K.getPageMeta?.(), q = /* @__PURE__ */ new Map(), Y = 0;
|
|
517
522
|
for (let e of V) {
|
|
518
|
-
let t =
|
|
523
|
+
let t = ye?.[e.pattern];
|
|
519
524
|
if (t) {
|
|
520
|
-
|
|
525
|
+
q.set(e.pattern, t);
|
|
521
526
|
continue;
|
|
522
527
|
}
|
|
523
528
|
try {
|
|
524
|
-
let t = await
|
|
525
|
-
|
|
529
|
+
let t = await K.getPage(e.pattern, e.file);
|
|
530
|
+
q.set(e.pattern, l(t, e.file)), Y++;
|
|
526
531
|
} catch (t) {
|
|
527
532
|
J.warn("failed to load page metadata", { pattern: e.pattern }, t);
|
|
528
533
|
}
|
|
529
534
|
}
|
|
530
|
-
J.info(`registered ${
|
|
531
|
-
count:
|
|
532
|
-
fromManifest:
|
|
533
|
-
fromModules:
|
|
534
|
-
}),
|
|
535
|
-
let
|
|
536
|
-
for (let e of W)
|
|
537
|
-
|
|
535
|
+
J.info(`registered ${q.size} route(s)`, {
|
|
536
|
+
count: q.size,
|
|
537
|
+
fromManifest: q.size - Y,
|
|
538
|
+
fromModules: Y
|
|
539
|
+
}), t.mark("routes");
|
|
540
|
+
let X = /* @__PURE__ */ new Set();
|
|
541
|
+
for (let e of W) q.get(e.pattern)?.renderMode === "spa" && ne(H, e.dirChain).some((e) => e.hasLayout) && X.add(e.pattern);
|
|
542
|
+
X.size > 0 && J.info(`${X.size} spa route(s) render an SSR layout shell`, { patterns: [...X] });
|
|
538
543
|
let Se = /* @__PURE__ */ new Map();
|
|
539
|
-
for (let [e, t] of
|
|
540
|
-
let
|
|
541
|
-
for (let e of W)
|
|
542
|
-
let
|
|
544
|
+
for (let [e, t] of q) t.cacheInvalidatesOn.length > 0 && Se.set(e, t.cacheInvalidatesOn);
|
|
545
|
+
let we = /* @__PURE__ */ new Map();
|
|
546
|
+
for (let e of W) we.set(e.pattern, e.regex);
|
|
547
|
+
let Q = ve({
|
|
543
548
|
cache: z,
|
|
544
549
|
tableSubscriptionsByPattern: Se,
|
|
545
|
-
regexByPattern:
|
|
550
|
+
regexByPattern: we
|
|
546
551
|
});
|
|
547
|
-
await
|
|
548
|
-
let
|
|
549
|
-
let t =
|
|
552
|
+
await Q.start(), t.mark("cdc");
|
|
553
|
+
let $ = M(), Ae = V.map((e) => {
|
|
554
|
+
let t = q.get(e.pattern);
|
|
550
555
|
return {
|
|
551
556
|
pattern: e.pattern,
|
|
552
557
|
file: e.file,
|
|
@@ -561,7 +566,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
561
566
|
hasMeta: t?.hasMeta ?? !1,
|
|
562
567
|
hasGetStaticPaths: t?.hasGetStaticPaths ?? !1
|
|
563
568
|
};
|
|
564
|
-
}), je =
|
|
569
|
+
}), je = H.map((e) => ({
|
|
565
570
|
dir: e.dir,
|
|
566
571
|
hasLayout: e.hasLayout,
|
|
567
572
|
hasError: e.hasError,
|
|
@@ -571,8 +576,8 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
571
576
|
kind: "web",
|
|
572
577
|
meta: {
|
|
573
578
|
name: c.name ?? "(unnamed)",
|
|
574
|
-
voltroVersion:
|
|
575
|
-
port:
|
|
579
|
+
voltroVersion: xe,
|
|
580
|
+
port: _,
|
|
576
581
|
mode: "start",
|
|
577
582
|
apis: Object.entries(c.apis ?? {}).map(([e, t]) => {
|
|
578
583
|
let n = {
|
|
@@ -602,10 +607,10 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
602
607
|
};
|
|
603
608
|
},
|
|
604
609
|
metrics: () => he()
|
|
605
|
-
}, Pe = async (t,
|
|
610
|
+
}, Pe = async (t, r) => {
|
|
606
611
|
let i = t.split("?")[0] ?? "/";
|
|
607
612
|
if (c.name === "voltroDashboard" && i === "/api/dashboard/registry") try {
|
|
608
|
-
let e = await
|
|
613
|
+
let e = await n();
|
|
609
614
|
return {
|
|
610
615
|
status: 200,
|
|
611
616
|
headers: { "content-type": "application/json; charset=utf-8" },
|
|
@@ -648,18 +653,18 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
648
653
|
};
|
|
649
654
|
}
|
|
650
655
|
if (i === "/_voltro/inspect/logs") {
|
|
651
|
-
let
|
|
656
|
+
let e = p(t, a(), r);
|
|
652
657
|
return {
|
|
653
|
-
status:
|
|
658
|
+
status: e.status,
|
|
654
659
|
headers: {
|
|
655
|
-
"content-type":
|
|
656
|
-
...
|
|
660
|
+
"content-type": e.contentType,
|
|
661
|
+
...I(r.origin)
|
|
657
662
|
},
|
|
658
|
-
body:
|
|
663
|
+
body: e.body
|
|
659
664
|
};
|
|
660
665
|
}
|
|
661
666
|
if (i !== "/_voltro/inspect/stream") {
|
|
662
|
-
let e = ue(t, Ne,
|
|
667
|
+
let e = ue(t, Ne, r);
|
|
663
668
|
if (e !== null) return {
|
|
664
669
|
status: e.status,
|
|
665
670
|
headers: {
|
|
@@ -669,36 +674,36 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
669
674
|
body: e.body
|
|
670
675
|
};
|
|
671
676
|
}
|
|
672
|
-
let
|
|
673
|
-
if (!
|
|
677
|
+
let o = Ee(i, W), s = o ? q.get(o.route.pattern)?.renderMode : void 0, l = s === "ssr" || s === "isr" || (o ? X.has(o.route.pattern) : !1), u = i === "/" ? R(y, "index.html") : R(y, i.replace(/^\//, ""), "index.html");
|
|
678
|
+
if (!l && await Z(u)) return {
|
|
674
679
|
status: 200,
|
|
675
680
|
headers: { "content-type": "text/html; charset=utf-8" },
|
|
676
|
-
body: await
|
|
681
|
+
body: await U.readFile(u)
|
|
677
682
|
};
|
|
678
683
|
if (/\.[a-z0-9]+$/i.test(i)) {
|
|
679
|
-
let e = R(
|
|
680
|
-
if (await
|
|
681
|
-
let t = await
|
|
684
|
+
let e = R(y, i.replace(/^\//, ""));
|
|
685
|
+
if (await Z(e)) {
|
|
686
|
+
let t = await U.readFile(e);
|
|
682
687
|
return {
|
|
683
688
|
status: 200,
|
|
684
|
-
headers: { "content-type":
|
|
689
|
+
headers: { "content-type": Ce(e) },
|
|
685
690
|
body: t
|
|
686
691
|
};
|
|
687
692
|
}
|
|
688
693
|
}
|
|
689
|
-
let
|
|
690
|
-
if (!
|
|
694
|
+
let d = Ee(i, W);
|
|
695
|
+
if (!d) return {
|
|
691
696
|
status: 404,
|
|
692
697
|
headers: { "content-type": "text/plain" },
|
|
693
698
|
body: "not found"
|
|
694
699
|
};
|
|
695
|
-
let
|
|
696
|
-
...
|
|
700
|
+
let ee = q.get(d.route.pattern), f = r["x-tenant"] ?? "anonymous", m = (await K.getHelpers()).i18n?.resolve(r.cookie, r["accept-language"])?.locale, g = N(i, {
|
|
701
|
+
...ee?.tenantAware ? { tenant: f } : {},
|
|
697
702
|
...m ? { locale: m } : {}
|
|
698
|
-
}), _ = z.get(
|
|
699
|
-
if (_ &&
|
|
703
|
+
}), _ = z.get(g), v = Date.now();
|
|
704
|
+
if (_ && te(_, v)) return h.emit("cache", {
|
|
700
705
|
kind: "HIT",
|
|
701
|
-
key:
|
|
706
|
+
key: g,
|
|
702
707
|
ageMs: v - _.renderedAt
|
|
703
708
|
}), {
|
|
704
709
|
status: 200,
|
|
@@ -706,40 +711,40 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
706
711
|
"content-type": "text/html; charset=utf-8",
|
|
707
712
|
"x-voltro-rendered-by": "isr",
|
|
708
713
|
"x-voltro-cache": "HIT",
|
|
709
|
-
"x-voltro-cache-key":
|
|
714
|
+
"x-voltro-cache-key": g,
|
|
710
715
|
"x-voltro-cache-age-ms": String(v - _.renderedAt)
|
|
711
716
|
},
|
|
712
717
|
body: _.html
|
|
713
718
|
};
|
|
714
|
-
if (_ &&
|
|
719
|
+
if (_ && S(_, v)) return h.emit("cache", {
|
|
715
720
|
kind: "STALE",
|
|
716
|
-
key:
|
|
721
|
+
key: g,
|
|
717
722
|
ageMs: v - _.renderedAt
|
|
718
723
|
}), (async () => {
|
|
719
724
|
try {
|
|
720
|
-
let
|
|
721
|
-
provider:
|
|
722
|
-
root:
|
|
723
|
-
route:
|
|
724
|
-
params:
|
|
725
|
+
let n = await De({
|
|
726
|
+
provider: K,
|
|
727
|
+
root: e,
|
|
728
|
+
route: d.route,
|
|
729
|
+
params: d.params,
|
|
725
730
|
pathname: i,
|
|
726
|
-
dirs:
|
|
727
|
-
shellTemplate:
|
|
728
|
-
requestHeaders:
|
|
731
|
+
dirs: H,
|
|
732
|
+
shellTemplate: P,
|
|
733
|
+
requestHeaders: r,
|
|
729
734
|
apiOrigin: fe,
|
|
730
735
|
apiName: pe,
|
|
731
736
|
requestUrl: t,
|
|
732
737
|
buffered: !0
|
|
733
738
|
});
|
|
734
|
-
if (
|
|
735
|
-
let
|
|
736
|
-
z.set(
|
|
737
|
-
html:
|
|
738
|
-
renderedAt:
|
|
739
|
-
expiresAt:
|
|
740
|
-
servableUntil:
|
|
741
|
-
revalidateMs:
|
|
742
|
-
staleWhileRevalidateMs:
|
|
739
|
+
if (n && "html" in n && n.renderMode === "isr" && n.revalidateMs !== null) {
|
|
740
|
+
let e = q.get(d.route.pattern)?.staleWhileRevalidateMs ?? 0, t = Date.now();
|
|
741
|
+
z.set(g, {
|
|
742
|
+
html: n.html,
|
|
743
|
+
renderedAt: t,
|
|
744
|
+
expiresAt: t + n.revalidateMs,
|
|
745
|
+
servableUntil: t + n.revalidateMs + e,
|
|
746
|
+
revalidateMs: n.revalidateMs,
|
|
747
|
+
staleWhileRevalidateMs: e
|
|
743
748
|
});
|
|
744
749
|
}
|
|
745
750
|
} catch (e) {
|
|
@@ -751,43 +756,43 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
751
756
|
"content-type": "text/html; charset=utf-8",
|
|
752
757
|
"x-voltro-rendered-by": "isr",
|
|
753
758
|
"x-voltro-cache": "STALE",
|
|
754
|
-
"x-voltro-cache-key":
|
|
759
|
+
"x-voltro-cache-key": g,
|
|
755
760
|
"x-voltro-cache-age-ms": String(v - _.renderedAt)
|
|
756
761
|
},
|
|
757
762
|
body: _.html
|
|
758
763
|
};
|
|
759
764
|
try {
|
|
760
|
-
let
|
|
761
|
-
provider:
|
|
762
|
-
root:
|
|
763
|
-
route:
|
|
764
|
-
params:
|
|
765
|
+
let n = await De({
|
|
766
|
+
provider: K,
|
|
767
|
+
root: e,
|
|
768
|
+
route: d.route,
|
|
769
|
+
params: d.params,
|
|
765
770
|
pathname: i,
|
|
766
|
-
dirs:
|
|
767
|
-
shellTemplate:
|
|
768
|
-
requestHeaders:
|
|
771
|
+
dirs: H,
|
|
772
|
+
shellTemplate: P,
|
|
773
|
+
requestHeaders: r,
|
|
769
774
|
apiOrigin: fe,
|
|
770
775
|
apiName: pe,
|
|
771
776
|
requestUrl: t
|
|
772
777
|
});
|
|
773
|
-
if (!
|
|
778
|
+
if (!n) return {
|
|
774
779
|
status: 200,
|
|
775
780
|
headers: {
|
|
776
781
|
"content-type": "text/html; charset=utf-8",
|
|
777
782
|
"x-voltro-rendered-by": "spa-fallback"
|
|
778
783
|
},
|
|
779
|
-
body:
|
|
784
|
+
body: P
|
|
780
785
|
};
|
|
781
|
-
if ("stream" in
|
|
786
|
+
if ("stream" in n) return {
|
|
782
787
|
status: 200,
|
|
783
|
-
headers: { "x-voltro-rendered-by":
|
|
788
|
+
headers: { "x-voltro-rendered-by": n.renderMode },
|
|
784
789
|
body: "",
|
|
785
|
-
stream:
|
|
790
|
+
stream: n.stream
|
|
786
791
|
};
|
|
787
|
-
if ("control" in
|
|
788
|
-
status:
|
|
792
|
+
if ("control" in n) return n.control === "redirect" ? {
|
|
793
|
+
status: n.status,
|
|
789
794
|
headers: {
|
|
790
|
-
location:
|
|
795
|
+
location: n.location,
|
|
791
796
|
"x-voltro-rendered-by": "loader-redirect"
|
|
792
797
|
},
|
|
793
798
|
body: ""
|
|
@@ -801,34 +806,34 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
801
806
|
};
|
|
802
807
|
let a = {
|
|
803
808
|
"content-type": "text/html; charset=utf-8",
|
|
804
|
-
"x-voltro-rendered-by":
|
|
809
|
+
"x-voltro-rendered-by": n.renderMode
|
|
805
810
|
};
|
|
806
|
-
if (
|
|
807
|
-
let
|
|
808
|
-
z.set(
|
|
809
|
-
html:
|
|
810
|
-
renderedAt:
|
|
811
|
-
expiresAt:
|
|
812
|
-
servableUntil:
|
|
813
|
-
revalidateMs:
|
|
814
|
-
staleWhileRevalidateMs:
|
|
815
|
-
}), a["x-voltro-cache"] = "MISS", a["x-voltro-cache-key"] =
|
|
811
|
+
if (n.renderMode === "isr" && n.revalidateMs !== null) {
|
|
812
|
+
let e = Date.now(), t = q.get(d.route.pattern)?.staleWhileRevalidateMs ?? 0;
|
|
813
|
+
z.set(g, {
|
|
814
|
+
html: n.html,
|
|
815
|
+
renderedAt: e,
|
|
816
|
+
expiresAt: e + n.revalidateMs,
|
|
817
|
+
servableUntil: e + n.revalidateMs + t,
|
|
818
|
+
revalidateMs: n.revalidateMs,
|
|
819
|
+
staleWhileRevalidateMs: t
|
|
820
|
+
}), a["x-voltro-cache"] = "MISS", a["x-voltro-cache-key"] = g, a["x-voltro-cache-revalidate-ms"] = String(n.revalidateMs), t > 0 && (a["x-voltro-cache-swr-ms"] = String(t)), h.emit("cache", {
|
|
816
821
|
kind: "MISS",
|
|
817
|
-
key:
|
|
818
|
-
revalidateMs:
|
|
819
|
-
swrMs:
|
|
822
|
+
key: g,
|
|
823
|
+
revalidateMs: n.revalidateMs,
|
|
824
|
+
swrMs: t
|
|
820
825
|
});
|
|
821
|
-
} else
|
|
826
|
+
} else n.renderMode === "isr" && (a["x-voltro-cache"] = "BYPASS", h.emit("cache", {
|
|
822
827
|
kind: "BYPASS",
|
|
823
|
-
key:
|
|
828
|
+
key: g
|
|
824
829
|
}));
|
|
825
830
|
return {
|
|
826
831
|
status: 200,
|
|
827
832
|
headers: a,
|
|
828
|
-
body:
|
|
833
|
+
body: n.html
|
|
829
834
|
};
|
|
830
835
|
} catch (e) {
|
|
831
|
-
return J.error("render error", { url: i }, e),
|
|
836
|
+
return J.error("render error", { url: i }, e), ae(e) ? {
|
|
832
837
|
status: 500,
|
|
833
838
|
headers: {
|
|
834
839
|
"content-type": "text/plain; charset=utf-8",
|
|
@@ -842,17 +847,17 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
842
847
|
};
|
|
843
848
|
}
|
|
844
849
|
}, Fe = !1, Ie = ge(async (e, t) => {
|
|
845
|
-
let
|
|
846
|
-
for (let [t, n] of Object.entries(e.headers)) n !== void 0 && (
|
|
847
|
-
let
|
|
848
|
-
if (
|
|
850
|
+
let n = e.url ?? "/", r = Date.now(), i = {};
|
|
851
|
+
for (let [t, n] of Object.entries(e.headers)) n !== void 0 && (i[t.toLowerCase()] = Array.isArray(n) ? n.join(", ") : n);
|
|
852
|
+
let a = n.split("?")[0] ?? "/", l = (e.method ?? "GET").toUpperCase();
|
|
853
|
+
if (a === "/internal/liveness") {
|
|
849
854
|
t.writeHead(200, {
|
|
850
855
|
"content-type": "text/plain",
|
|
851
856
|
"cache-control": "no-store"
|
|
852
857
|
}), t.end("ok");
|
|
853
858
|
return;
|
|
854
859
|
}
|
|
855
|
-
if (
|
|
860
|
+
if (a === "/internal/readiness") {
|
|
856
861
|
let e = Fe ? 200 : 503;
|
|
857
862
|
t.writeHead(e, {
|
|
858
863
|
"content-type": "text/plain",
|
|
@@ -860,71 +865,71 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
860
865
|
}), t.end(Fe ? "ready" : "not-ready");
|
|
861
866
|
return;
|
|
862
867
|
}
|
|
863
|
-
if (
|
|
864
|
-
let e =
|
|
868
|
+
if (l === "OPTIONS" && a.startsWith("/_voltro/inspect")) {
|
|
869
|
+
let e = I(i.origin);
|
|
865
870
|
t.writeHead(204, e), t.end();
|
|
866
871
|
return;
|
|
867
872
|
}
|
|
868
|
-
if (c.name === "voltroDashboard" &&
|
|
869
|
-
let
|
|
870
|
-
if (!
|
|
873
|
+
if (c.name === "voltroDashboard" && a === "/api/dashboard/proxy") {
|
|
874
|
+
let r = new URL(n, "http://x").searchParams.get("target");
|
|
875
|
+
if (!r) {
|
|
871
876
|
t.writeHead(400, { "content-type": "text/plain" }), t.end("missing ?target=");
|
|
872
877
|
return;
|
|
873
878
|
}
|
|
874
|
-
if (!
|
|
879
|
+
if (!ce(r)) {
|
|
875
880
|
t.writeHead(400, { "content-type": "text/plain" }), t.end("target not allowed: must be loopback or an origin configured in VOLTRO_DASHBOARD_APPS");
|
|
876
881
|
return;
|
|
877
882
|
}
|
|
878
883
|
try {
|
|
879
|
-
let
|
|
880
|
-
|
|
884
|
+
let n = { accept: i.accept ?? "application/json" }, a = i.authorization;
|
|
885
|
+
a ? n.authorization = Array.isArray(a) ? a[0] : a : se(r) && process.env.VOLTRO_INSPECT_TOKEN && (n.authorization = `Bearer ${process.env.VOLTRO_INSPECT_TOKEN}`);
|
|
881
886
|
let o;
|
|
882
|
-
if (
|
|
887
|
+
if (l && l !== "GET" && l !== "HEAD") {
|
|
883
888
|
let t = [];
|
|
884
889
|
for await (let n of e) t.push(n);
|
|
885
890
|
o = Buffer.concat(t);
|
|
886
|
-
let
|
|
887
|
-
|
|
891
|
+
let r = i["content-type"];
|
|
892
|
+
r && (n["content-type"] = Array.isArray(r) ? r[0] : r);
|
|
888
893
|
}
|
|
889
|
-
let
|
|
894
|
+
let s = await fetch(r, {
|
|
890
895
|
redirect: "manual",
|
|
891
|
-
method:
|
|
892
|
-
headers:
|
|
896
|
+
method: l,
|
|
897
|
+
headers: n,
|
|
893
898
|
...o ? { body: new Uint8Array(o.buffer, o.byteOffset, o.byteLength) } : {}
|
|
894
|
-
}),
|
|
895
|
-
t.writeHead(
|
|
896
|
-
"content-type":
|
|
897
|
-
"content-length": String(
|
|
898
|
-
}), t.end(
|
|
899
|
+
}), c = Buffer.from(await s.arrayBuffer());
|
|
900
|
+
t.writeHead(s.status, {
|
|
901
|
+
"content-type": s.headers.get("content-type") ?? "application/octet-stream",
|
|
902
|
+
"content-length": String(c.length)
|
|
903
|
+
}), t.end(c);
|
|
899
904
|
} catch (e) {
|
|
900
905
|
t.writeHead(502, { "content-type": "text/plain" }), t.end(`proxy error: ${e.message}`);
|
|
901
906
|
}
|
|
902
907
|
return;
|
|
903
908
|
}
|
|
904
|
-
if (c.name === "voltroDashboard" &&
|
|
905
|
-
let
|
|
906
|
-
if (!
|
|
909
|
+
if (c.name === "voltroDashboard" && a === "/api/dashboard/proxy/stream") {
|
|
910
|
+
let r = new URL(n, "http://x").searchParams.get("target");
|
|
911
|
+
if (!r) {
|
|
907
912
|
t.writeHead(400, { "content-type": "text/plain" }), t.end("missing ?target=");
|
|
908
913
|
return;
|
|
909
914
|
}
|
|
910
|
-
if (!
|
|
915
|
+
if (!ce(r)) {
|
|
911
916
|
t.writeHead(400, { "content-type": "text/plain" }), t.end("target not allowed: must be loopback or an origin configured in VOLTRO_DASHBOARD_APPS");
|
|
912
917
|
return;
|
|
913
918
|
}
|
|
914
|
-
let
|
|
915
|
-
e.on("close", () =>
|
|
919
|
+
let a = new AbortController();
|
|
920
|
+
e.on("close", () => a.abort()), t.on("close", () => a.abort());
|
|
916
921
|
try {
|
|
917
|
-
let e =
|
|
922
|
+
let e = i.authorization ?? (se(r) && process.env.VOLTRO_INSPECT_TOKEN ? `Bearer ${process.env.VOLTRO_INSPECT_TOKEN}` : void 0), n = await fetch(r, {
|
|
918
923
|
redirect: "manual",
|
|
919
924
|
method: "GET",
|
|
920
925
|
headers: {
|
|
921
926
|
accept: "text/event-stream",
|
|
922
927
|
...e ? { authorization: Array.isArray(e) ? e[0] : e } : {}
|
|
923
928
|
},
|
|
924
|
-
signal:
|
|
929
|
+
signal: a.signal
|
|
925
930
|
});
|
|
926
|
-
if (!
|
|
927
|
-
t.writeHead(
|
|
931
|
+
if (!n.ok || !n.body) {
|
|
932
|
+
t.writeHead(n.status, { "content-type": "text/plain" }), t.end(`upstream ${n.status}`);
|
|
928
933
|
return;
|
|
929
934
|
}
|
|
930
935
|
t.writeHead(200, {
|
|
@@ -933,7 +938,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
933
938
|
connection: "keep-alive",
|
|
934
939
|
"x-accel-buffering": "no"
|
|
935
940
|
}), t.flushHeaders();
|
|
936
|
-
let o =
|
|
941
|
+
let o = n.body.getReader();
|
|
937
942
|
try {
|
|
938
943
|
for (;;) {
|
|
939
944
|
let { done: e, value: n } = await o.read();
|
|
@@ -948,23 +953,23 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
948
953
|
}
|
|
949
954
|
return;
|
|
950
955
|
}
|
|
951
|
-
if (
|
|
952
|
-
let
|
|
953
|
-
if (
|
|
956
|
+
if (a === "/_voltro/inspect/stream") {
|
|
957
|
+
let n = I(i.origin);
|
|
958
|
+
if (L()) {
|
|
954
959
|
t.writeHead(503, {
|
|
955
960
|
"content-type": "application/json",
|
|
956
|
-
...
|
|
961
|
+
...n
|
|
957
962
|
}), t.end(JSON.stringify({ error: "inspect disabled (VOLTRO_INSPECT=off)" }));
|
|
958
963
|
return;
|
|
959
964
|
}
|
|
960
|
-
let
|
|
961
|
-
if (!
|
|
965
|
+
let r = le(i, "GET");
|
|
966
|
+
if (!r.ok) {
|
|
962
967
|
t.writeHead(401, {
|
|
963
968
|
"content-type": "application/json",
|
|
964
|
-
...
|
|
969
|
+
...n
|
|
965
970
|
}), t.end(JSON.stringify({
|
|
966
971
|
error: "unauthorized",
|
|
967
|
-
reason:
|
|
972
|
+
reason: r.reason
|
|
968
973
|
}));
|
|
969
974
|
return;
|
|
970
975
|
}
|
|
@@ -973,32 +978,32 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
973
978
|
"cache-control": "no-cache, no-transform",
|
|
974
979
|
connection: "keep-alive",
|
|
975
980
|
"x-accel-buffering": "no",
|
|
976
|
-
...
|
|
981
|
+
...n
|
|
977
982
|
}), t.flushHeaders(), t.write("retry: 5000\n\n");
|
|
978
|
-
for (let e of
|
|
979
|
-
let
|
|
980
|
-
t.write(
|
|
981
|
-
}),
|
|
982
|
-
t.write(
|
|
983
|
-
}, 15e3),
|
|
984
|
-
clearInterval(
|
|
983
|
+
for (let e of h.buffered()) t.write(s(e));
|
|
984
|
+
let a = h.subscribe((e) => {
|
|
985
|
+
t.write(s(e));
|
|
986
|
+
}), c = setInterval(() => {
|
|
987
|
+
t.write(o());
|
|
988
|
+
}, 15e3), l = () => {
|
|
989
|
+
clearInterval(c), a();
|
|
985
990
|
};
|
|
986
|
-
e.on("close",
|
|
991
|
+
e.on("close", l), t.on("close", l);
|
|
987
992
|
return;
|
|
988
993
|
}
|
|
989
994
|
try {
|
|
990
|
-
let e = await Pe(
|
|
991
|
-
if (e.stream ? e.stream(t) : (t.writeHead(e.status, e.headers), t.end(e.body)), !
|
|
992
|
-
let t = Date.now() -
|
|
993
|
-
|
|
994
|
-
url:
|
|
995
|
+
let e = await Pe(n, i);
|
|
996
|
+
if (e.stream ? e.stream(t) : (t.writeHead(e.status, e.headers), t.end(e.body)), !a.startsWith("/_voltro/inspect")) {
|
|
997
|
+
let t = Date.now() - r;
|
|
998
|
+
h.emit("request", {
|
|
999
|
+
url: a,
|
|
995
1000
|
status: e.status,
|
|
996
1001
|
durationMs: t,
|
|
997
1002
|
renderedBy: e.headers["x-voltro-rendered-by"],
|
|
998
1003
|
cache: e.headers["x-voltro-cache"]
|
|
999
1004
|
});
|
|
1000
|
-
let n =
|
|
1001
|
-
|
|
1005
|
+
let n = Ee(a, W)?.route.pattern ?? (e.status === 404 ? "<unmatched>" : "<asset>");
|
|
1006
|
+
$.record({
|
|
1002
1007
|
kind: "request",
|
|
1003
1008
|
tag: n,
|
|
1004
1009
|
durationMs: t,
|
|
@@ -1009,34 +1014,34 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
1009
1014
|
t.writeHead(500, { "content-type": "text/plain" }), t.end(`internal error: ${e.message}`);
|
|
1010
1015
|
}
|
|
1011
1016
|
});
|
|
1012
|
-
await new Promise((e) => Ie.listen(
|
|
1013
|
-
port:
|
|
1014
|
-
distDir:
|
|
1017
|
+
await new Promise((e) => Ie.listen(_, "::", e)), Fe = !0, t.mark("ready"), J.info(`listening on http://localhost:${_}`, {
|
|
1018
|
+
port: _,
|
|
1019
|
+
distDir: y
|
|
1015
1020
|
}), J.debug("dynamic + ssr/isr routes resolve via SSR loader");
|
|
1016
1021
|
try {
|
|
1017
|
-
await
|
|
1022
|
+
await f({
|
|
1018
1023
|
id: T,
|
|
1019
|
-
name:
|
|
1024
|
+
name: w,
|
|
1020
1025
|
kind: "web",
|
|
1021
|
-
url: `http://localhost:${
|
|
1026
|
+
url: `http://localhost:${_}`,
|
|
1022
1027
|
pid: process.pid,
|
|
1023
1028
|
status: "live",
|
|
1024
|
-
logFile:
|
|
1029
|
+
logFile: D.path
|
|
1025
1030
|
});
|
|
1026
|
-
let
|
|
1027
|
-
if (
|
|
1028
|
-
let
|
|
1029
|
-
|
|
1031
|
+
let t = r(e);
|
|
1032
|
+
if (t) {
|
|
1033
|
+
let e = await i({ dashboardAppPath: t });
|
|
1034
|
+
e.status === "launched" ? J.info(`dashboard launched at http://localhost:${e.port}`, { port: e.port }) : e.status === "already-running" && J.debug(`dashboard already running on :${e.port}`, { port: e.port });
|
|
1030
1035
|
}
|
|
1031
1036
|
setInterval(() => {
|
|
1032
|
-
|
|
1037
|
+
f({
|
|
1033
1038
|
id: T,
|
|
1034
|
-
name:
|
|
1039
|
+
name: w,
|
|
1035
1040
|
kind: "web",
|
|
1036
|
-
url: `http://localhost:${
|
|
1041
|
+
url: `http://localhost:${_}`,
|
|
1037
1042
|
pid: process.pid,
|
|
1038
1043
|
status: "live",
|
|
1039
|
-
logFile:
|
|
1044
|
+
logFile: D.path
|
|
1040
1045
|
}).catch(() => {});
|
|
1041
1046
|
}, 1e4).unref();
|
|
1042
1047
|
} catch (e) {
|
|
@@ -1045,20 +1050,20 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
1045
1050
|
me({
|
|
1046
1051
|
app: c.name ?? "unnamed",
|
|
1047
1052
|
kind: "web",
|
|
1048
|
-
url: `http://localhost:${
|
|
1049
|
-
bootMs:
|
|
1053
|
+
url: `http://localhost:${_}`,
|
|
1054
|
+
bootMs: t.total()
|
|
1050
1055
|
});
|
|
1051
|
-
let Le =
|
|
1052
|
-
J.info(`start: ready in ${
|
|
1053
|
-
bootMs:
|
|
1056
|
+
let Le = t.phaseBreakdown();
|
|
1057
|
+
J.info(`start: ready in ${t.total()}ms`, {
|
|
1058
|
+
bootMs: t.total(),
|
|
1054
1059
|
...Le ? { phases: Le } : {}
|
|
1055
1060
|
});
|
|
1056
1061
|
let Re = !1, ze = (e) => async () => {
|
|
1057
1062
|
if (!Re) {
|
|
1058
|
-
if (Re = !0, J.info(`received ${e}, shutting down`, { signal: e }), Ie.close(), await
|
|
1063
|
+
if (Re = !0, J.info(`received ${e}, shutting down`, { signal: e }), Ie.close(), await Q.stop(), B) try {
|
|
1059
1064
|
await B.end();
|
|
1060
1065
|
} catch {}
|
|
1061
|
-
await
|
|
1066
|
+
await K.close(), await oe(T), await D.dispose(), process.exit(0);
|
|
1062
1067
|
}
|
|
1063
1068
|
};
|
|
1064
1069
|
process.on("SIGINT", ze("SIGINT")), process.on("SIGTERM", ze("SIGTERM"));
|
|
@@ -1070,10 +1075,10 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
1070
1075
|
e.unref();
|
|
1071
1076
|
}
|
|
1072
1077
|
return new Promise(() => {});
|
|
1073
|
-
},
|
|
1078
|
+
}, je = async (e) => {
|
|
1074
1079
|
process.env.NODE_ENV || (process.env.NODE_ENV = "production");
|
|
1075
|
-
let t = await
|
|
1080
|
+
let t = await Ae(z(e.find((e) => !e.startsWith("-")) ?? process.cwd()));
|
|
1076
1081
|
return t.ran ? t.exitCode : (J.error("no web app found at this path"), 1);
|
|
1077
1082
|
};
|
|
1078
1083
|
//#endregion
|
|
1079
|
-
export {
|
|
1084
|
+
export { je as t };
|