@voltro/cli 0.20.2 → 0.22.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 +398 -0
- package/THIRD-PARTY-NOTICES.md +61 -61
- package/dist/{apiBuild-qZBEu59d.js → apiBuild-2zRxj2hJ.js} +93 -80
- package/dist/apiBuild-sqNmWmY5.js +2 -0
- package/dist/bin.js +41 -20
- package/dist/{commands-kYbfVoPO.js → commands-DGaeTn2f.js} +3055 -2640
- package/dist/dbCommand-CO3eSAZR.js +2 -0
- package/dist/{dbCommand-BPp9R0Wc.js → dbCommand-DVASmZj2.js} +305 -249
- package/dist/dev-BEYBSGJ7.js +3 -0
- package/dist/{dev-OHLsAq4K.js → dev-DeHVUxQx.js} +1732 -1686
- package/dist/index.js +1 -1
- package/dist/inspect-BA67TF6v.js +2 -0
- package/dist/inspect-_ldwsAwH.js +945 -0
- package/dist/{inspectMetrics-DvPNXmGA.js → inspectMetrics-4AVPn6IS.js} +584 -571
- package/dist/{manifestBuild-P9yuCY2d.js → manifestBuild-Bs1Uw22_.js} +1 -1
- package/dist/manifestBuild-i-fRHg_H.js +2 -0
- package/dist/serveCommand-DEVTtnLy.js +1161 -0
- package/dist/serveEntry.js +2 -2
- package/dist/{start-CXQ7WL1W.js → start-BjGUIIvj.js} +389 -389
- package/dist/startEntry.js +2 -2
- package/package.json +27 -27
- package/templates/AGENTS.md +1 -1
- package/templates/agent-docs/_index.md +1 -1
- package/templates/agent-docs/cli.md +181 -5
- package/templates/agent-docs/data.md +58 -0
- package/templates/agent-docs/database/migrations.md +175 -31
- package/templates/agent-docs/database/schema.md +7 -0
- package/templates/agent-docs/database/seedsdialects.md +3 -3
- package/templates/agent-docs/plugins.md +1 -1
- package/templates/agent-docs/schema-driven-ui.md +2 -2
- package/templates/agent-docs/templates/apibackends.md +1 -1
- package/templates/agent-docs/whats-new.md +236 -9
- package/templates/apps/api-ai/package.json +12 -12
- package/templates/apps/api-auth/package.json +13 -13
- package/templates/apps/api-backend/package.json +12 -12
- package/templates/apps/api-backend-deactivation/package.json +12 -12
- package/templates/apps/api-backend-mail/package.json +11 -11
- package/templates/apps/api-backend-mariadb/package.json +14 -14
- package/templates/apps/api-backend-storage/package.json +11 -11
- package/templates/apps/api-data-advanced/package.json +13 -13
- package/templates/apps/api-durable/package.json +13 -13
- package/templates/apps/api-feature-flags/package.json +14 -14
- package/templates/apps/api-governance/package.json +13 -13
- package/templates/apps/api-kv/package.json +13 -13
- package/templates/apps/api-moderation/package.json +13 -13
- package/templates/apps/api-observability/package.json +13 -13
- package/templates/apps/api-ratelimit/package.json +13 -13
- package/templates/apps/api-rbac/package.json +13 -13
- package/templates/apps/api-rest/package.json +12 -12
- package/templates/apps/api-saas/package.json +16 -16
- package/templates/apps/api-search/package.json +13 -13
- package/templates/apps/api-versioning/package.json +13 -13
- package/templates/apps/api-webhooks/package.json +14 -14
- package/templates/apps/changelog/package.json +8 -8
- package/templates/apps/edge-functions/package.json +5 -5
- package/templates/apps/frontend-admin/package.json +10 -10
- package/templates/apps/frontend-app/package.json +10 -10
- package/templates/apps/frontend-blank/package.json +9 -9
- package/templates/apps/frontend-contact/package.json +11 -11
- package/templates/apps/frontend-dashboard/package.json +9 -9
- package/templates/apps/frontend-docs/package.json +9 -9
- package/templates/apps/frontend-i18n/package.json +8 -8
- package/templates/apps/frontend-landing/package.json +9 -9
- package/templates/apps/frontend-spa/package.json +9 -9
- package/templates/apps/frontend-ssr/package.json +9 -9
- package/templates/apps/frontend-ssr-api/package.json +10 -10
- package/templates/apps/frontend-static-blog/package.json +8 -8
- package/dist/apiBuild-C9aHz4Yh.js +0 -2
- package/dist/dbCommand-DtUe-0dM.js +0 -2
- package/dist/dev-2AvdzDg2.js +0 -3
- package/dist/inspect-DcZ04OME.js +0 -2
- package/dist/inspect-Dwx0_tUj.js +0 -921
- package/dist/manifestBuild-D1MzJAiQ.js +0 -2
- package/dist/serveCommand-BKqTKWTX.js +0 -1136
- /package/templates/patches/{@effect__cluster@0.59.0.patch → @effect__cluster@0.60.0.patch} +0 -0
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { D as
|
|
3
|
-
import { t as
|
|
4
|
-
import { dirname as
|
|
5
|
-
import { fileURLToPath as
|
|
6
|
-
import { createLogger as
|
|
7
|
-
import { promises as
|
|
8
|
-
import { snapshotMetricsSync as
|
|
9
|
-
import { createServer as
|
|
1
|
+
import { $ as e, C as t, E as n, G as r, H as i, J as a, P as o, Q as s, R as c, U as l, V as u, W as d, _ as f, a as p, at as m, b as ee, c as h, ct as g, dt as _, et as te, f as v, ft as y, g as ne, h as b, i as re, j as ie, m as x, nt as S, o as ae, p as C, pt as w, q as T, r as E, s as D, t as O, tt as k, ut as A, v as j, w as oe, y as M } from "./inspectMetrics-4AVPn6IS.js";
|
|
2
|
+
import { D as se, E as ce, T as le, a as N, p as ue, w as de } from "./inspect-_ldwsAwH.js";
|
|
3
|
+
import { t as fe } from "./bootTiming-BdyP9nYw.js";
|
|
4
|
+
import { dirname as pe, extname as P, join as F, resolve as I } from "node:path";
|
|
5
|
+
import { fileURLToPath as L, pathToFileURL as R } from "node:url";
|
|
6
|
+
import { createLogger as z, printReadyBlock as me } from "@voltro/logger";
|
|
7
|
+
import { promises as B } from "node:fs";
|
|
8
|
+
import { snapshotMetricsSync as he } from "@voltro/runtime";
|
|
9
|
+
import { createServer as ge } from "node:http";
|
|
10
10
|
//#region src/isrCdcInvalidator.ts
|
|
11
|
-
var
|
|
11
|
+
var V = z({ scope: "voltro:start:cdc" }), H = (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 H = B({ scope: "voltro:start:cdc" }), U = (e) => (t) => {
|
|
|
19
19
|
}));
|
|
20
20
|
}
|
|
21
21
|
return n;
|
|
22
|
-
},
|
|
22
|
+
}, U = () => !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
|
+
}, _e = (e) => {
|
|
29
|
+
let t = e.channel ?? "framework_changes", n = H(e), r = null, i = null;
|
|
30
30
|
return {
|
|
31
31
|
start: async () => {
|
|
32
|
-
let a =
|
|
32
|
+
let a = U();
|
|
33
33
|
if (!a) {
|
|
34
|
-
|
|
34
|
+
V.debug("skipped — no PG_* env vars set");
|
|
35
35
|
return;
|
|
36
36
|
}
|
|
37
37
|
if (e.tableSubscriptionsByPattern.size === 0) {
|
|
38
|
-
|
|
38
|
+
V.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 H = B({ scope: "voltro:start:cdc" }), U = (e) => (t) => {
|
|
|
44
44
|
try {
|
|
45
45
|
r = JSON.parse(e.payload);
|
|
46
46
|
} catch (e) {
|
|
47
|
-
|
|
47
|
+
V.warn("bad CDC payload", {}, e);
|
|
48
48
|
return;
|
|
49
49
|
}
|
|
50
50
|
let i = n(r.table);
|
|
51
|
-
i > 0 &&
|
|
51
|
+
i > 0 && V.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}`), V.info(`LISTEN ${t}`, {
|
|
57
57
|
channel: t,
|
|
58
58
|
host: a.host,
|
|
59
59
|
port: a.port,
|
|
@@ -69,7 +69,7 @@ var H = B({ scope: "voltro:start:cdc" }), U = (e) => (t) => {
|
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
71
|
};
|
|
72
|
-
},
|
|
72
|
+
}, W = z({ scope: "voltro:start:isr-cache" }), G = "voltro_isr_cache", ve = (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
|
+
`, ye = (e) => {
|
|
84
|
+
let t = e.tableName ?? G, { client: n } = e, r = /* @__PURE__ */ new Map(), i = !1, a = (async () => {
|
|
85
|
+
i || (i = !0, await n.query(ve(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, {
|
|
@@ -94,10 +94,10 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
94
94
|
staleWhileRevalidateMs: Number(t.stale_while_revalidate_ms)
|
|
95
95
|
});
|
|
96
96
|
}).catch((e) => {
|
|
97
|
-
|
|
97
|
+
W.warn("postgres bootstrap failed", {}, e);
|
|
98
98
|
}), o = (e, t) => {
|
|
99
99
|
a.then(() => n.query(e, t)).catch((e) => {
|
|
100
|
-
|
|
100
|
+
W.warn("postgres write failed", {}, e);
|
|
101
101
|
});
|
|
102
102
|
};
|
|
103
103
|
return {
|
|
@@ -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
|
-
},
|
|
145
|
+
}, K = z({ scope: "voltro:start" }), be = await (async () => {
|
|
146
146
|
try {
|
|
147
|
-
let e =
|
|
147
|
+
let e = F(pe(L(import.meta.url)), "..", "package.json"), t = await B.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
|
-
})(),
|
|
152
|
+
})(), q = (e) => e instanceof Error && e._voltroControl === "redirect" && typeof e.location == "string", xe = (e) => e instanceof Error && e._voltroControl === "not-found", J = {
|
|
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
|
+
}, Se = (e) => J[P(e).toLowerCase()] ?? "application/octet-stream", Y = (e) => e.replace(/<script\b(?=[^>]*\btype="module")(?:(?!<\/script>).)*<\/script>/gi, "").replace(/<script\b(?=[^>]*\bsrc=)(?:(?!<\/script>).)*<\/script>/gi, "").replace(/<link\b[^>]*\brel="modulepreload"[^>]*>/gi, ""), X = async (e) => {
|
|
171
171
|
try {
|
|
172
|
-
return await
|
|
172
|
+
return await B.stat(e), !0;
|
|
173
173
|
} catch {
|
|
174
174
|
return !1;
|
|
175
175
|
}
|
|
176
|
-
},
|
|
176
|
+
}, Z = (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
|
+
}, Ce = (e) => e.map((e) => {
|
|
186
|
+
let { regex: t, paramNames: n, priority: r } = Z(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), we = (e, t) => {
|
|
196
196
|
for (let n of t) {
|
|
197
197
|
let t = n.regex.exec(e);
|
|
198
198
|
if (!t) continue;
|
|
@@ -204,81 +204,81 @@ 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: t, route: n, params: r, pathname: i, dirs: a, shellTemplate:
|
|
209
|
-
if (
|
|
210
|
-
let
|
|
207
|
+
}, Te = async (e) => {
|
|
208
|
+
let { provider: t, route: n, params: r, pathname: i, dirs: a, shellTemplate: s, requestHeaders: c, requestUrl: l = "", apiOrigin: u, apiName: d } = e, m = re(u, c.cookie, { apiName: d }), h = await t.getPage(n.pattern, n.file), g = o(h, n.file), _ = g === "spa" && ae(a, n.dirChain).some((e) => e.hasLayout);
|
|
209
|
+
if (g !== "ssr" && g !== "isr" && !_) return null;
|
|
210
|
+
let te = ae(a, n.dirChain), v = {}, y = null, ne, ie = new AbortController();
|
|
211
211
|
try {
|
|
212
|
-
(await t.getHelpers()).beginStoreSeeds(), {chain:
|
|
213
|
-
entries:
|
|
212
|
+
(await t.getHelpers()).beginStoreSeeds(), {chain: ne, segmentLoaderData: v} = await p({
|
|
213
|
+
entries: te,
|
|
214
214
|
loadLayout: (e) => t.getLayout(e.dir),
|
|
215
215
|
loadError: (e) => t.getError(e.dir),
|
|
216
216
|
loadPending: (e) => t.getPending(e.dir),
|
|
217
217
|
ctx: {
|
|
218
218
|
params: r,
|
|
219
219
|
pathname: i,
|
|
220
|
-
signal:
|
|
221
|
-
headers:
|
|
222
|
-
query:
|
|
220
|
+
signal: ie.signal,
|
|
221
|
+
headers: c,
|
|
222
|
+
query: m
|
|
223
223
|
}
|
|
224
|
-
}), typeof
|
|
224
|
+
}), typeof h.loader == "function" && !_ && (y = await h.loader({
|
|
225
225
|
params: r,
|
|
226
226
|
pathname: i,
|
|
227
|
-
signal:
|
|
228
|
-
headers:
|
|
229
|
-
query:
|
|
227
|
+
signal: ie.signal,
|
|
228
|
+
headers: c,
|
|
229
|
+
query: m
|
|
230
230
|
}));
|
|
231
231
|
} catch (e) {
|
|
232
|
-
if (
|
|
232
|
+
if (q(e)) return {
|
|
233
233
|
control: "redirect",
|
|
234
234
|
status: e.status,
|
|
235
235
|
location: e.location
|
|
236
236
|
};
|
|
237
|
-
if (
|
|
237
|
+
if (xe(e)) return { control: "not-found" };
|
|
238
238
|
throw e;
|
|
239
239
|
}
|
|
240
|
-
let
|
|
240
|
+
let C = await t.getHelpers(), w = {
|
|
241
241
|
pattern: n.pattern,
|
|
242
|
-
Component:
|
|
243
|
-
meta:
|
|
244
|
-
loader:
|
|
245
|
-
ErrorBoundary:
|
|
246
|
-
Pending:
|
|
247
|
-
renderMode:
|
|
248
|
-
chain:
|
|
249
|
-
},
|
|
250
|
-
cookies:
|
|
251
|
-
headers:
|
|
252
|
-
url:
|
|
253
|
-
},
|
|
254
|
-
if (
|
|
255
|
-
let e =
|
|
256
|
-
helpers:
|
|
242
|
+
Component: h.default,
|
|
243
|
+
meta: h.meta,
|
|
244
|
+
loader: h.loader,
|
|
245
|
+
ErrorBoundary: h.ErrorBoundary,
|
|
246
|
+
Pending: h.Pending,
|
|
247
|
+
renderMode: g,
|
|
248
|
+
chain: ne
|
|
249
|
+
}, T = {
|
|
250
|
+
cookies: C.parseCookieHeader(c.cookie),
|
|
251
|
+
headers: c,
|
|
252
|
+
url: l
|
|
253
|
+
}, E = C.i18n?.resolve(c.cookie, c["accept-language"]), D = h.interactive ?? "full";
|
|
254
|
+
if (_) {
|
|
255
|
+
let e = j({
|
|
256
|
+
helpers: C,
|
|
257
257
|
page: n.pattern,
|
|
258
|
-
interactive:
|
|
258
|
+
interactive: D,
|
|
259
259
|
delivery: "stream",
|
|
260
260
|
renderInput: {
|
|
261
|
-
descriptor:
|
|
261
|
+
descriptor: w,
|
|
262
262
|
params: r,
|
|
263
263
|
pathname: i,
|
|
264
264
|
segmentLoaderData: v,
|
|
265
|
-
requestContext:
|
|
266
|
-
...
|
|
267
|
-
outerWrap:
|
|
268
|
-
locale:
|
|
265
|
+
requestContext: T,
|
|
266
|
+
...E ? {
|
|
267
|
+
outerWrap: E.outerWrap,
|
|
268
|
+
locale: E.locale
|
|
269
269
|
} : {}
|
|
270
270
|
}
|
|
271
|
-
}), t =
|
|
272
|
-
helpers:
|
|
271
|
+
}), t = E?.locale ?? T.cookies["voltro:lang"] ?? "en", a = (t) => ee({
|
|
272
|
+
helpers: C,
|
|
273
273
|
prepared: e,
|
|
274
274
|
meta: t,
|
|
275
|
-
interactive:
|
|
275
|
+
interactive: D
|
|
276
276
|
});
|
|
277
277
|
if (e.hasDeferred) {
|
|
278
|
-
let n =
|
|
278
|
+
let n = x({ shell: s });
|
|
279
279
|
return {
|
|
280
280
|
renderMode: "spa",
|
|
281
|
-
stream: (r) =>
|
|
281
|
+
stream: (r) => b({
|
|
282
282
|
res: r,
|
|
283
283
|
shell: n,
|
|
284
284
|
htmlLang: t,
|
|
@@ -287,57 +287,57 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
287
287
|
"x-voltro-rendered-by": "spa"
|
|
288
288
|
},
|
|
289
289
|
headInjection: a,
|
|
290
|
-
render: (t) =>
|
|
290
|
+
render: (t) => C.renderPageToStream({
|
|
291
291
|
...e.renderInput,
|
|
292
292
|
...t
|
|
293
293
|
}),
|
|
294
294
|
onShellError: (e) => {
|
|
295
|
-
|
|
295
|
+
K.error("spa layout shell render failed", { pathname: i }, e), r.writeHead(500, { "content-type": "text/plain; charset=utf-8" }), r.end("server error");
|
|
296
296
|
}
|
|
297
297
|
})
|
|
298
298
|
};
|
|
299
299
|
}
|
|
300
|
-
let
|
|
301
|
-
helpers:
|
|
300
|
+
let o = M({
|
|
301
|
+
helpers: C,
|
|
302
302
|
prepared: e
|
|
303
303
|
});
|
|
304
304
|
return {
|
|
305
|
-
html:
|
|
305
|
+
html: s.replace("<div id=\"root\"></div>", `<div id="root">${o.body}</div>`).replace("</head>", ` ${a(o.meta)}\n </head>`).replace(/<html(\s+lang="[^"]*")?/i, `<html lang="${t}"`),
|
|
306
306
|
renderMode: "spa",
|
|
307
307
|
revalidateMs: null
|
|
308
308
|
};
|
|
309
309
|
}
|
|
310
|
-
let
|
|
311
|
-
helpers:
|
|
310
|
+
let O = f({
|
|
311
|
+
helpers: C,
|
|
312
312
|
page: n.pattern,
|
|
313
313
|
pathname: i,
|
|
314
|
-
renderMode:
|
|
315
|
-
interactive:
|
|
316
|
-
loaderData:
|
|
314
|
+
renderMode: g,
|
|
315
|
+
interactive: D,
|
|
316
|
+
loaderData: y,
|
|
317
317
|
segmentLoaderData: v,
|
|
318
|
-
pageLoaderRan: typeof
|
|
319
|
-
}),
|
|
320
|
-
descriptor:
|
|
318
|
+
pageLoaderRan: typeof h.loader == "function"
|
|
319
|
+
}), k = {
|
|
320
|
+
descriptor: w,
|
|
321
321
|
params: r,
|
|
322
322
|
pathname: i,
|
|
323
|
-
loaderData:
|
|
324
|
-
segmentLoaderData:
|
|
325
|
-
requestContext:
|
|
326
|
-
...
|
|
327
|
-
outerWrap:
|
|
328
|
-
locale:
|
|
323
|
+
loaderData: O.loaderData,
|
|
324
|
+
segmentLoaderData: O.segmentLoaderData,
|
|
325
|
+
requestContext: T,
|
|
326
|
+
...E ? {
|
|
327
|
+
outerWrap: E.outerWrap,
|
|
328
|
+
locale: E.locale
|
|
329
329
|
} : {}
|
|
330
|
-
},
|
|
331
|
-
|
|
332
|
-
`<meta name="voltro-interactive" content="${
|
|
333
|
-
...
|
|
334
|
-
|
|
330
|
+
}, A = (e) => [
|
|
331
|
+
C.renderMetaToHtml(e),
|
|
332
|
+
`<meta name="voltro-interactive" content="${D}" />`,
|
|
333
|
+
...O.hasDeferred ? [C.renderDeferredRegistryScript()] : [],
|
|
334
|
+
C.renderRouterStateScript(O.stateInput)
|
|
335
335
|
].filter((e) => e.length > 0).join("\n ");
|
|
336
|
-
if (
|
|
337
|
-
let e =
|
|
336
|
+
if (g === "ssr" && D === "full" && e.buffered !== !0) {
|
|
337
|
+
let e = E?.locale ?? T.cookies["voltro:lang"] ?? "en", t = x({ shell: s });
|
|
338
338
|
return {
|
|
339
339
|
renderMode: "ssr",
|
|
340
|
-
stream: (n) =>
|
|
340
|
+
stream: (n) => b({
|
|
341
341
|
res: n,
|
|
342
342
|
shell: t,
|
|
343
343
|
htmlLang: e,
|
|
@@ -345,27 +345,27 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
345
345
|
"content-type": "text/html; charset=utf-8",
|
|
346
346
|
"x-voltro-rendered-by": "ssr"
|
|
347
347
|
},
|
|
348
|
-
headInjection:
|
|
349
|
-
render: (e) =>
|
|
350
|
-
...
|
|
348
|
+
headInjection: A,
|
|
349
|
+
render: (e) => C.renderPageToStream({
|
|
350
|
+
...k,
|
|
351
351
|
...e
|
|
352
352
|
}),
|
|
353
353
|
onShellError: (e) => {
|
|
354
|
-
|
|
354
|
+
K.error("ssr shell render failed", { pathname: i }, e), n.writeHead(500, { "content-type": "text/plain; charset=utf-8" }), n.end("server error");
|
|
355
355
|
}
|
|
356
356
|
})
|
|
357
357
|
};
|
|
358
358
|
}
|
|
359
|
-
let { html:
|
|
360
|
-
|
|
361
|
-
let
|
|
359
|
+
let { html: oe, meta: se } = C.renderPageToHtml(k), ce = A(se), le = E?.locale ?? T.cookies["voltro:lang"] ?? "en", N = s.replace("<div id=\"root\"></div>", `<div id="root">${oe}</div>`).replace("</head>", ` ${ce}\n </head>`).replace(/<html(\s+lang="[^"]*")?/i, `<html lang="${le}"`);
|
|
360
|
+
D === "none" && (N = Y(N));
|
|
361
|
+
let ue = g === "isr" ? S(h.revalidate) : null;
|
|
362
362
|
return {
|
|
363
|
-
html:
|
|
364
|
-
renderMode:
|
|
365
|
-
revalidateMs:
|
|
363
|
+
html: N,
|
|
364
|
+
renderMode: g,
|
|
365
|
+
revalidateMs: ue
|
|
366
366
|
};
|
|
367
|
-
},
|
|
368
|
-
let t = await import(
|
|
367
|
+
}, Q = (e) => e === "" ? "/" : e, Ee = async (e) => {
|
|
368
|
+
let t = await import(R(e).href);
|
|
369
369
|
return {
|
|
370
370
|
kind: "bundle",
|
|
371
371
|
getPageMeta: () => t.pageMeta,
|
|
@@ -375,18 +375,18 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
375
375
|
return typeof r == "function" ? await r() : r;
|
|
376
376
|
},
|
|
377
377
|
async getLayout(e) {
|
|
378
|
-
let n = t.layouts[
|
|
379
|
-
if (!n) throw Error(`[voltro start] ssr bundle missing layout for dir ${
|
|
378
|
+
let n = t.layouts[Q(e)];
|
|
379
|
+
if (!n) throw Error(`[voltro start] ssr bundle missing layout for dir ${Q(e)}`);
|
|
380
380
|
return typeof n == "function" ? await n() : n;
|
|
381
381
|
},
|
|
382
382
|
async getError(e) {
|
|
383
|
-
let n = t.errors[
|
|
384
|
-
if (!n) throw Error(`[voltro start] ssr bundle missing error for dir ${
|
|
383
|
+
let n = t.errors[Q(e)];
|
|
384
|
+
if (!n) throw Error(`[voltro start] ssr bundle missing error for dir ${Q(e)}`);
|
|
385
385
|
return typeof n == "function" ? await n() : n;
|
|
386
386
|
},
|
|
387
387
|
async getPending(e) {
|
|
388
|
-
let n = t.pendings[
|
|
389
|
-
if (!n) throw Error(`[voltro start] ssr bundle missing pending for dir ${
|
|
388
|
+
let n = t.pendings[Q(e)];
|
|
389
|
+
if (!n) throw Error(`[voltro start] ssr bundle missing pending for dir ${Q(e)}`);
|
|
390
390
|
return typeof n == "function" ? await n() : n;
|
|
391
391
|
},
|
|
392
392
|
async getHelpers() {
|
|
@@ -394,8 +394,8 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
394
394
|
},
|
|
395
395
|
async close() {}
|
|
396
396
|
};
|
|
397
|
-
},
|
|
398
|
-
let n = await
|
|
397
|
+
}, De = async (e, t) => {
|
|
398
|
+
let n = await g("vite", () => import("vite")), r = (await import("@vitejs/plugin-react")).default, i = (await import("@tailwindcss/vite")).default, o = await n.createServer({
|
|
399
399
|
root: t,
|
|
400
400
|
envPrefix: "__VOLTRO_VITE_ENV_DISABLED__",
|
|
401
401
|
plugins: [r(), i()],
|
|
@@ -407,129 +407,129 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
407
407
|
},
|
|
408
408
|
appType: "custom",
|
|
409
409
|
logLevel: "warn"
|
|
410
|
-
}),
|
|
411
|
-
limit:
|
|
412
|
-
onColdStart: (e) =>
|
|
413
|
-
onColdEnd: (e, { durationMs: t, failed: n }) =>
|
|
410
|
+
}), s = F(e, "src", "pages"), c = (e) => e === "" ? s : F(s, e), l = T({
|
|
411
|
+
limit: a(),
|
|
412
|
+
onColdStart: (e) => K.debug("ssr cold-compile start", { id: e }),
|
|
413
|
+
onColdEnd: (e, { durationMs: t, failed: n }) => K.debug(`ssr cold-compile ${n ? "FAILED" : "end"} ${t}ms`, {
|
|
414
414
|
id: e,
|
|
415
415
|
ms: t,
|
|
416
416
|
...n ? { failed: !0 } : {}
|
|
417
417
|
})
|
|
418
|
-
}), u = (e) =>
|
|
418
|
+
}), u = (e) => l.load(e, async () => await o.ssrLoadModule(e));
|
|
419
419
|
return {
|
|
420
420
|
kind: "middleware",
|
|
421
421
|
async getPage(e, t) {
|
|
422
|
-
return u(
|
|
422
|
+
return u(F(s, t));
|
|
423
423
|
},
|
|
424
424
|
async getLayout(e) {
|
|
425
|
-
return u(
|
|
425
|
+
return u(F(c(e), "layout.tsx"));
|
|
426
426
|
},
|
|
427
427
|
async getError(e) {
|
|
428
|
-
return u(
|
|
428
|
+
return u(F(c(e), "error.tsx"));
|
|
429
429
|
},
|
|
430
430
|
async getPending(e) {
|
|
431
|
-
return u(
|
|
431
|
+
return u(F(c(e), "loading.tsx"));
|
|
432
432
|
},
|
|
433
433
|
async getHelpers() {
|
|
434
434
|
return await u("@voltro/web/ssr");
|
|
435
435
|
},
|
|
436
436
|
async close() {
|
|
437
|
-
await
|
|
437
|
+
await o.close();
|
|
438
438
|
}
|
|
439
439
|
};
|
|
440
|
-
},
|
|
441
|
-
let
|
|
442
|
-
if (!
|
|
440
|
+
}, Oe = async (a) => {
|
|
441
|
+
let o = fe(), f = await D(a);
|
|
442
|
+
if (!f) return {
|
|
443
443
|
ran: !1,
|
|
444
444
|
exitCode: 0
|
|
445
445
|
};
|
|
446
|
-
if (
|
|
446
|
+
if (f.type !== "web") return K.error("only web apps are supported by `voltro start`"), {
|
|
447
447
|
ran: !0,
|
|
448
448
|
exitCode: 1
|
|
449
449
|
};
|
|
450
|
-
let { resolved:
|
|
451
|
-
rawEnv:
|
|
450
|
+
let { resolved: p } = await m({
|
|
451
|
+
rawEnv: f.env,
|
|
452
452
|
appType: "web",
|
|
453
|
-
root:
|
|
454
|
-
log:
|
|
453
|
+
root: a,
|
|
454
|
+
log: K,
|
|
455
455
|
generateTypes: !1
|
|
456
|
-
}),
|
|
457
|
-
|
|
458
|
-
let
|
|
459
|
-
|
|
460
|
-
let
|
|
456
|
+
}), ee = p.publicValues;
|
|
457
|
+
o.mark("config");
|
|
458
|
+
let g = d();
|
|
459
|
+
u(g), K.info("booting voltro start", { app: f.name ?? "(unnamed)" });
|
|
460
|
+
let b = (() => {
|
|
461
461
|
if (process.env.VOLTRO_IS_DASHBOARD === "1" && process.env.VOLTRO_DASHBOARD_PORT) return Number(process.env.VOLTRO_DASHBOARD_PORT);
|
|
462
462
|
if (process.env.PORT) {
|
|
463
463
|
let e = Number(process.env.PORT);
|
|
464
464
|
if (Number.isFinite(e) && e > 0) return e;
|
|
465
465
|
}
|
|
466
|
-
return
|
|
467
|
-
})(),
|
|
468
|
-
if (!await
|
|
466
|
+
return f.port ?? 5173;
|
|
467
|
+
})(), re = F(a, ".framework"), x = F(re, "dist"), S = F(x, "index.html");
|
|
468
|
+
if (!await X(S)) return K.error("no built dist found — run `voltro build` first", { distDir: x }), {
|
|
469
469
|
ran: !0,
|
|
470
470
|
exitCode: 1
|
|
471
471
|
};
|
|
472
|
-
let T =
|
|
473
|
-
await
|
|
474
|
-
id:
|
|
472
|
+
let T = f.name ?? "unnamed", j = A("web", T, b), M = n(T);
|
|
473
|
+
await w({
|
|
474
|
+
id: j,
|
|
475
475
|
name: T,
|
|
476
476
|
kind: "web",
|
|
477
|
-
url: `http://localhost:${
|
|
477
|
+
url: `http://localhost:${b}`,
|
|
478
478
|
pid: process.pid,
|
|
479
479
|
status: "booting",
|
|
480
|
-
logFile:
|
|
480
|
+
logFile: M.path
|
|
481
481
|
}).catch(() => {});
|
|
482
|
-
let
|
|
483
|
-
process.env.SSR_CACHE === "postgres" && process.env.PG_HOST ? (
|
|
482
|
+
let pe = F(x, "_voltro", "shell.html"), P = await X(pe) ? await B.readFile(pe, "utf8") : await B.readFile(S, "utf8"), I = await h(a, f), L = E(I[0]), R = I[0]?.name, z, V = null;
|
|
483
|
+
process.env.SSR_CACHE === "postgres" && process.env.PG_HOST ? (V = new (await (import("pg"))).default.Client({
|
|
484
484
|
host: process.env.PG_HOST,
|
|
485
485
|
port: Number(process.env.PG_PORT ?? 5432),
|
|
486
486
|
user: process.env.PG_USER ?? "app",
|
|
487
487
|
password: process.env.PG_PASSWORD ?? "app",
|
|
488
488
|
database: process.env.PG_DATABASE ?? "app"
|
|
489
|
-
}), await
|
|
490
|
-
let { pages:
|
|
491
|
-
|
|
492
|
-
let
|
|
493
|
-
if (!
|
|
494
|
-
let
|
|
495
|
-
|
|
496
|
-
kind:
|
|
497
|
-
...
|
|
498
|
-
}),
|
|
499
|
-
let
|
|
500
|
-
for (let e of
|
|
501
|
-
let t =
|
|
489
|
+
}), await V.connect(), z = ye({ client: V }), K.info("isr cache backend: postgres", { table: "voltro_isr_cache" })) : (z = k(), K.info("isr cache backend: memory (per-process)", { hint: "set SSR_CACHE=postgres for persistent storage" })), await C(a, f, I, ee);
|
|
490
|
+
let { pages: H, dirs: U } = await v(F(a, "src", "pages")), W = Ce(H);
|
|
491
|
+
o.mark("scan");
|
|
492
|
+
let G = F(x, "server", "ssrEntry.js"), ve = await X(G);
|
|
493
|
+
if (!ve && process.env.NODE_ENV === "production") throw K.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}`);
|
|
494
|
+
let q = ve ? await Ee(G) : await De(a, re);
|
|
495
|
+
K.info(`ssr loader: ${q.kind}`, {
|
|
496
|
+
kind: q.kind,
|
|
497
|
+
...q.kind === "middleware" ? { hint: "no pre-built SSR bundle found; run `voltro build` to enable bundle mode" } : {}
|
|
498
|
+
}), o.mark("provider");
|
|
499
|
+
let xe = q.getPageMeta?.(), J = /* @__PURE__ */ new Map(), Y = 0;
|
|
500
|
+
for (let e of H) {
|
|
501
|
+
let t = xe?.[e.pattern];
|
|
502
502
|
if (t) {
|
|
503
|
-
|
|
503
|
+
J.set(e.pattern, t);
|
|
504
504
|
continue;
|
|
505
505
|
}
|
|
506
506
|
try {
|
|
507
|
-
let t = await
|
|
508
|
-
|
|
507
|
+
let t = await q.getPage(e.pattern, e.file);
|
|
508
|
+
J.set(e.pattern, ie(t, e.file)), Y++;
|
|
509
509
|
} catch (t) {
|
|
510
|
-
|
|
510
|
+
K.warn("failed to load page metadata", { pattern: e.pattern }, t);
|
|
511
511
|
}
|
|
512
512
|
}
|
|
513
|
-
|
|
514
|
-
count:
|
|
515
|
-
fromManifest:
|
|
516
|
-
fromModules:
|
|
517
|
-
}),
|
|
518
|
-
let
|
|
519
|
-
for (let e of
|
|
520
|
-
|
|
521
|
-
let
|
|
522
|
-
for (let [e, t] of
|
|
523
|
-
let
|
|
524
|
-
for (let e of
|
|
525
|
-
let
|
|
526
|
-
cache:
|
|
527
|
-
tableSubscriptionsByPattern:
|
|
528
|
-
regexByPattern:
|
|
513
|
+
K.info(`registered ${J.size} route(s)`, {
|
|
514
|
+
count: J.size,
|
|
515
|
+
fromManifest: J.size - Y,
|
|
516
|
+
fromModules: Y
|
|
517
|
+
}), o.mark("routes");
|
|
518
|
+
let Z = /* @__PURE__ */ new Set();
|
|
519
|
+
for (let e of W) J.get(e.pattern)?.renderMode === "spa" && ae(U, e.dirChain).some((e) => e.hasLayout) && Z.add(e.pattern);
|
|
520
|
+
Z.size > 0 && K.info(`${Z.size} spa route(s) render an SSR layout shell`, { patterns: [...Z] });
|
|
521
|
+
let Q = /* @__PURE__ */ new Map();
|
|
522
|
+
for (let [e, t] of J) t.cacheInvalidatesOn.length > 0 && Q.set(e, t.cacheInvalidatesOn);
|
|
523
|
+
let Oe = /* @__PURE__ */ new Map();
|
|
524
|
+
for (let e of W) Oe.set(e.pattern, e.regex);
|
|
525
|
+
let ke = _e({
|
|
526
|
+
cache: z,
|
|
527
|
+
tableSubscriptionsByPattern: Q,
|
|
528
|
+
regexByPattern: Oe
|
|
529
529
|
});
|
|
530
|
-
await
|
|
531
|
-
let
|
|
532
|
-
let t =
|
|
530
|
+
await ke.start(), o.mark("cdc");
|
|
531
|
+
let Ae = O(), je = H.map((e) => {
|
|
532
|
+
let t = J.get(e.pattern);
|
|
533
533
|
return {
|
|
534
534
|
pattern: e.pattern,
|
|
535
535
|
file: e.file,
|
|
@@ -544,20 +544,20 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
544
544
|
hasMeta: t?.hasMeta ?? !1,
|
|
545
545
|
hasGetStaticPaths: t?.hasGetStaticPaths ?? !1
|
|
546
546
|
};
|
|
547
|
-
}),
|
|
547
|
+
}), Me = U.map((e) => ({
|
|
548
548
|
dir: e.dir,
|
|
549
549
|
hasLayout: e.hasLayout,
|
|
550
550
|
hasError: e.hasError,
|
|
551
551
|
hasPending: e.hasPending,
|
|
552
552
|
hasNotFound: e.hasNotFound
|
|
553
|
-
})),
|
|
553
|
+
})), Ne = V ? "postgres" : "memory", Pe = {
|
|
554
554
|
kind: "web",
|
|
555
555
|
meta: {
|
|
556
|
-
name:
|
|
557
|
-
voltroVersion:
|
|
558
|
-
port:
|
|
556
|
+
name: f.name ?? "(unnamed)",
|
|
557
|
+
voltroVersion: be,
|
|
558
|
+
port: b,
|
|
559
559
|
mode: "start",
|
|
560
|
-
apis: Object.entries(
|
|
560
|
+
apis: Object.entries(f.apis ?? {}).map(([e, t]) => {
|
|
561
561
|
let n = {
|
|
562
562
|
name: e,
|
|
563
563
|
package: t.package
|
|
@@ -565,10 +565,10 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
565
565
|
return t.url !== void 0 && (n.url = t.url), n;
|
|
566
566
|
})
|
|
567
567
|
},
|
|
568
|
-
routes:
|
|
569
|
-
dirs:
|
|
568
|
+
routes: je,
|
|
569
|
+
dirs: Me,
|
|
570
570
|
cache: () => {
|
|
571
|
-
let e = Date.now(), t =
|
|
571
|
+
let e = Date.now(), t = z.snapshot().map(([t, n]) => ({
|
|
572
572
|
key: t,
|
|
573
573
|
renderedAt: n.renderedAt,
|
|
574
574
|
expiresAt: n.expiresAt,
|
|
@@ -579,16 +579,16 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
579
579
|
staleWhileRevalidateMs: n.staleWhileRevalidateMs
|
|
580
580
|
}));
|
|
581
581
|
return {
|
|
582
|
-
backend:
|
|
583
|
-
size:
|
|
582
|
+
backend: Ne,
|
|
583
|
+
size: z.size(),
|
|
584
584
|
entries: t
|
|
585
585
|
};
|
|
586
586
|
},
|
|
587
|
-
metrics: () =>
|
|
588
|
-
},
|
|
589
|
-
let
|
|
590
|
-
if (
|
|
591
|
-
let e = await
|
|
587
|
+
metrics: () => he()
|
|
588
|
+
}, Fe = async (t, n) => {
|
|
589
|
+
let r = t.split("?")[0] ?? "/";
|
|
590
|
+
if (f.name === "voltroDashboard" && r === "/api/dashboard/registry") try {
|
|
591
|
+
let e = await _();
|
|
592
592
|
return {
|
|
593
593
|
status: 200,
|
|
594
594
|
headers: { "content-type": "application/json; charset=utf-8" },
|
|
@@ -601,7 +601,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
601
601
|
body: `registry read error: ${e.message}`
|
|
602
602
|
};
|
|
603
603
|
}
|
|
604
|
-
if (
|
|
604
|
+
if (f.name === "voltroDashboard" && r === "/api/dashboard/config") {
|
|
605
605
|
let e = process.env.VOLTRO_DASHBOARD_APPS, t = [];
|
|
606
606
|
if (e && e.trim().length > 0) {
|
|
607
607
|
let n;
|
|
@@ -630,103 +630,103 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
630
630
|
body: JSON.stringify({ apps: t })
|
|
631
631
|
};
|
|
632
632
|
}
|
|
633
|
-
if (
|
|
634
|
-
let
|
|
633
|
+
if (r === "/_voltro/inspect/logs") {
|
|
634
|
+
let e = c(t, i(), n);
|
|
635
635
|
return {
|
|
636
|
-
status:
|
|
636
|
+
status: e.status,
|
|
637
637
|
headers: {
|
|
638
|
-
"content-type":
|
|
639
|
-
...
|
|
638
|
+
"content-type": e.contentType,
|
|
639
|
+
...de(n.origin)
|
|
640
640
|
},
|
|
641
|
-
body:
|
|
641
|
+
body: e.body
|
|
642
642
|
};
|
|
643
643
|
}
|
|
644
|
-
if (
|
|
645
|
-
let
|
|
646
|
-
if (
|
|
647
|
-
status:
|
|
644
|
+
if (r !== "/_voltro/inspect/stream") {
|
|
645
|
+
let e = ue(t, Pe, n);
|
|
646
|
+
if (e !== null) return {
|
|
647
|
+
status: e.status,
|
|
648
648
|
headers: {
|
|
649
|
-
"content-type":
|
|
650
|
-
...
|
|
649
|
+
"content-type": e.contentType,
|
|
650
|
+
...e.headers ?? {}
|
|
651
651
|
},
|
|
652
|
-
body:
|
|
652
|
+
body: e.body
|
|
653
653
|
};
|
|
654
654
|
}
|
|
655
|
-
let
|
|
656
|
-
if (!
|
|
655
|
+
let o = we(r, W), l = o ? J.get(o.route.pattern)?.renderMode : void 0, u = l === "ssr" || l === "isr" || (o ? Z.has(o.route.pattern) : !1), d = r === "/" ? F(x, "index.html") : F(x, r.replace(/^\//, ""), "index.html");
|
|
656
|
+
if (!u && await X(d)) return {
|
|
657
657
|
status: 200,
|
|
658
658
|
headers: { "content-type": "text/html; charset=utf-8" },
|
|
659
|
-
body: await
|
|
659
|
+
body: await B.readFile(d)
|
|
660
660
|
};
|
|
661
|
-
if (/\.[a-z0-9]+$/i.test(
|
|
662
|
-
let e =
|
|
663
|
-
if (await
|
|
664
|
-
let t = await
|
|
661
|
+
if (/\.[a-z0-9]+$/i.test(r)) {
|
|
662
|
+
let e = F(x, r.replace(/^\//, ""));
|
|
663
|
+
if (await X(e)) {
|
|
664
|
+
let t = await B.readFile(e);
|
|
665
665
|
return {
|
|
666
666
|
status: 200,
|
|
667
|
-
headers: { "content-type":
|
|
667
|
+
headers: { "content-type": Se(e) },
|
|
668
668
|
body: t
|
|
669
669
|
};
|
|
670
670
|
}
|
|
671
671
|
}
|
|
672
|
-
let
|
|
673
|
-
if (!
|
|
672
|
+
let p = we(r, W);
|
|
673
|
+
if (!p) return {
|
|
674
674
|
status: 404,
|
|
675
675
|
headers: { "content-type": "text/plain" },
|
|
676
676
|
body: "not found"
|
|
677
677
|
};
|
|
678
|
-
let
|
|
679
|
-
...
|
|
680
|
-
...
|
|
681
|
-
}),
|
|
682
|
-
if (
|
|
678
|
+
let m = J.get(p.route.pattern), ee = n["x-tenant"] ?? "anonymous", h = (await q.getHelpers()).i18n?.resolve(n.cookie, n["accept-language"])?.locale, v = s(r, {
|
|
679
|
+
...m?.tenantAware ? { tenant: ee } : {},
|
|
680
|
+
...h ? { locale: h } : {}
|
|
681
|
+
}), y = z.get(v), b = Date.now();
|
|
682
|
+
if (y && e(y, b)) return g.emit("cache", {
|
|
683
683
|
kind: "HIT",
|
|
684
|
-
key:
|
|
685
|
-
ageMs:
|
|
684
|
+
key: v,
|
|
685
|
+
ageMs: b - y.renderedAt
|
|
686
686
|
}), {
|
|
687
687
|
status: 200,
|
|
688
688
|
headers: {
|
|
689
689
|
"content-type": "text/html; charset=utf-8",
|
|
690
690
|
"x-voltro-rendered-by": "isr",
|
|
691
691
|
"x-voltro-cache": "HIT",
|
|
692
|
-
"x-voltro-cache-key":
|
|
693
|
-
"x-voltro-cache-age-ms": String(
|
|
692
|
+
"x-voltro-cache-key": v,
|
|
693
|
+
"x-voltro-cache-age-ms": String(b - y.renderedAt)
|
|
694
694
|
},
|
|
695
|
-
body:
|
|
695
|
+
body: y.html
|
|
696
696
|
};
|
|
697
|
-
if (
|
|
697
|
+
if (y && te(y, b)) return g.emit("cache", {
|
|
698
698
|
kind: "STALE",
|
|
699
|
-
key:
|
|
700
|
-
ageMs:
|
|
699
|
+
key: v,
|
|
700
|
+
ageMs: b - y.renderedAt
|
|
701
701
|
}), (async () => {
|
|
702
702
|
try {
|
|
703
|
-
let
|
|
704
|
-
provider:
|
|
705
|
-
root:
|
|
706
|
-
route:
|
|
707
|
-
params:
|
|
708
|
-
pathname:
|
|
709
|
-
dirs:
|
|
710
|
-
shellTemplate:
|
|
711
|
-
requestHeaders:
|
|
712
|
-
apiOrigin:
|
|
713
|
-
apiName:
|
|
714
|
-
requestUrl:
|
|
703
|
+
let e = await Te({
|
|
704
|
+
provider: q,
|
|
705
|
+
root: a,
|
|
706
|
+
route: p.route,
|
|
707
|
+
params: p.params,
|
|
708
|
+
pathname: r,
|
|
709
|
+
dirs: U,
|
|
710
|
+
shellTemplate: P,
|
|
711
|
+
requestHeaders: n,
|
|
712
|
+
apiOrigin: L,
|
|
713
|
+
apiName: R,
|
|
714
|
+
requestUrl: t,
|
|
715
715
|
buffered: !0
|
|
716
716
|
});
|
|
717
|
-
if (
|
|
718
|
-
let
|
|
719
|
-
|
|
720
|
-
html:
|
|
721
|
-
renderedAt:
|
|
722
|
-
expiresAt:
|
|
723
|
-
servableUntil:
|
|
724
|
-
revalidateMs:
|
|
725
|
-
staleWhileRevalidateMs:
|
|
717
|
+
if (e && "html" in e && e.renderMode === "isr" && e.revalidateMs !== null) {
|
|
718
|
+
let t = J.get(p.route.pattern)?.staleWhileRevalidateMs ?? 0, n = Date.now();
|
|
719
|
+
z.set(v, {
|
|
720
|
+
html: e.html,
|
|
721
|
+
renderedAt: n,
|
|
722
|
+
expiresAt: n + e.revalidateMs,
|
|
723
|
+
servableUntil: n + e.revalidateMs + t,
|
|
724
|
+
revalidateMs: e.revalidateMs,
|
|
725
|
+
staleWhileRevalidateMs: t
|
|
726
726
|
});
|
|
727
727
|
}
|
|
728
728
|
} catch (e) {
|
|
729
|
-
|
|
729
|
+
K.warn("background SWR refresh failed", { url: r }, e);
|
|
730
730
|
}
|
|
731
731
|
})(), {
|
|
732
732
|
status: 200,
|
|
@@ -734,43 +734,43 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
734
734
|
"content-type": "text/html; charset=utf-8",
|
|
735
735
|
"x-voltro-rendered-by": "isr",
|
|
736
736
|
"x-voltro-cache": "STALE",
|
|
737
|
-
"x-voltro-cache-key":
|
|
738
|
-
"x-voltro-cache-age-ms": String(
|
|
737
|
+
"x-voltro-cache-key": v,
|
|
738
|
+
"x-voltro-cache-age-ms": String(b - y.renderedAt)
|
|
739
739
|
},
|
|
740
|
-
body:
|
|
740
|
+
body: y.html
|
|
741
741
|
};
|
|
742
742
|
try {
|
|
743
|
-
let
|
|
744
|
-
provider:
|
|
745
|
-
root:
|
|
746
|
-
route:
|
|
747
|
-
params:
|
|
748
|
-
pathname:
|
|
749
|
-
dirs:
|
|
750
|
-
shellTemplate:
|
|
751
|
-
requestHeaders:
|
|
752
|
-
apiOrigin:
|
|
753
|
-
apiName:
|
|
754
|
-
requestUrl:
|
|
743
|
+
let e = await Te({
|
|
744
|
+
provider: q,
|
|
745
|
+
root: a,
|
|
746
|
+
route: p.route,
|
|
747
|
+
params: p.params,
|
|
748
|
+
pathname: r,
|
|
749
|
+
dirs: U,
|
|
750
|
+
shellTemplate: P,
|
|
751
|
+
requestHeaders: n,
|
|
752
|
+
apiOrigin: L,
|
|
753
|
+
apiName: R,
|
|
754
|
+
requestUrl: t
|
|
755
755
|
});
|
|
756
|
-
if (!
|
|
756
|
+
if (!e) return {
|
|
757
757
|
status: 200,
|
|
758
758
|
headers: {
|
|
759
759
|
"content-type": "text/html; charset=utf-8",
|
|
760
760
|
"x-voltro-rendered-by": "spa-fallback"
|
|
761
761
|
},
|
|
762
|
-
body:
|
|
762
|
+
body: P
|
|
763
763
|
};
|
|
764
|
-
if ("stream" in
|
|
764
|
+
if ("stream" in e) return {
|
|
765
765
|
status: 200,
|
|
766
|
-
headers: { "x-voltro-rendered-by":
|
|
766
|
+
headers: { "x-voltro-rendered-by": e.renderMode },
|
|
767
767
|
body: "",
|
|
768
|
-
stream:
|
|
768
|
+
stream: e.stream
|
|
769
769
|
};
|
|
770
|
-
if ("control" in
|
|
771
|
-
status:
|
|
770
|
+
if ("control" in e) return e.control === "redirect" ? {
|
|
771
|
+
status: e.status,
|
|
772
772
|
headers: {
|
|
773
|
-
location:
|
|
773
|
+
location: e.location,
|
|
774
774
|
"x-voltro-rendered-by": "loader-redirect"
|
|
775
775
|
},
|
|
776
776
|
body: ""
|
|
@@ -784,34 +784,34 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
784
784
|
};
|
|
785
785
|
let i = {
|
|
786
786
|
"content-type": "text/html; charset=utf-8",
|
|
787
|
-
"x-voltro-rendered-by":
|
|
787
|
+
"x-voltro-rendered-by": e.renderMode
|
|
788
788
|
};
|
|
789
|
-
if (
|
|
790
|
-
let
|
|
791
|
-
|
|
792
|
-
html:
|
|
793
|
-
renderedAt:
|
|
794
|
-
expiresAt:
|
|
795
|
-
servableUntil:
|
|
796
|
-
revalidateMs:
|
|
797
|
-
staleWhileRevalidateMs:
|
|
798
|
-
}), i["x-voltro-cache"] = "MISS", i["x-voltro-cache-key"] =
|
|
789
|
+
if (e.renderMode === "isr" && e.revalidateMs !== null) {
|
|
790
|
+
let t = Date.now(), n = J.get(p.route.pattern)?.staleWhileRevalidateMs ?? 0;
|
|
791
|
+
z.set(v, {
|
|
792
|
+
html: e.html,
|
|
793
|
+
renderedAt: t,
|
|
794
|
+
expiresAt: t + e.revalidateMs,
|
|
795
|
+
servableUntil: t + e.revalidateMs + n,
|
|
796
|
+
revalidateMs: e.revalidateMs,
|
|
797
|
+
staleWhileRevalidateMs: n
|
|
798
|
+
}), i["x-voltro-cache"] = "MISS", i["x-voltro-cache-key"] = v, i["x-voltro-cache-revalidate-ms"] = String(e.revalidateMs), n > 0 && (i["x-voltro-cache-swr-ms"] = String(n)), g.emit("cache", {
|
|
799
799
|
kind: "MISS",
|
|
800
|
-
key:
|
|
801
|
-
revalidateMs:
|
|
802
|
-
swrMs:
|
|
800
|
+
key: v,
|
|
801
|
+
revalidateMs: e.revalidateMs,
|
|
802
|
+
swrMs: n
|
|
803
803
|
});
|
|
804
|
-
} else
|
|
804
|
+
} else e.renderMode === "isr" && (i["x-voltro-cache"] = "BYPASS", g.emit("cache", {
|
|
805
805
|
kind: "BYPASS",
|
|
806
|
-
key:
|
|
806
|
+
key: v
|
|
807
807
|
}));
|
|
808
808
|
return {
|
|
809
809
|
status: 200,
|
|
810
810
|
headers: i,
|
|
811
|
-
body:
|
|
811
|
+
body: e.html
|
|
812
812
|
};
|
|
813
813
|
} catch (e) {
|
|
814
|
-
return
|
|
814
|
+
return K.error("render error", { url: r }, e), ne(e) ? {
|
|
815
815
|
status: 500,
|
|
816
816
|
headers: {
|
|
817
817
|
"content-type": "text/plain; charset=utf-8",
|
|
@@ -824,56 +824,56 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
824
824
|
body: "server error"
|
|
825
825
|
};
|
|
826
826
|
}
|
|
827
|
-
},
|
|
828
|
-
let n = e.url ?? "/",
|
|
829
|
-
for (let [t, n] of Object.entries(e.headers)) n !== void 0 && (
|
|
830
|
-
let
|
|
831
|
-
if (
|
|
827
|
+
}, Ie = !1, Le = ge(async (e, t) => {
|
|
828
|
+
let n = e.url ?? "/", i = Date.now(), a = {};
|
|
829
|
+
for (let [t, n] of Object.entries(e.headers)) n !== void 0 && (a[t.toLowerCase()] = Array.isArray(n) ? n.join(", ") : n);
|
|
830
|
+
let o = n.split("?")[0] ?? "/", s = (e.method ?? "GET").toUpperCase();
|
|
831
|
+
if (o === "/internal/liveness") {
|
|
832
832
|
t.writeHead(200, {
|
|
833
833
|
"content-type": "text/plain",
|
|
834
834
|
"cache-control": "no-store"
|
|
835
835
|
}), t.end("ok");
|
|
836
836
|
return;
|
|
837
837
|
}
|
|
838
|
-
if (
|
|
839
|
-
let e =
|
|
838
|
+
if (o === "/internal/readiness") {
|
|
839
|
+
let e = Ie ? 200 : 503;
|
|
840
840
|
t.writeHead(e, {
|
|
841
841
|
"content-type": "text/plain",
|
|
842
842
|
"cache-control": "no-store"
|
|
843
|
-
}), t.end(
|
|
843
|
+
}), t.end(Ie ? "ready" : "not-ready");
|
|
844
844
|
return;
|
|
845
845
|
}
|
|
846
|
-
if (
|
|
847
|
-
let e =
|
|
846
|
+
if (s === "OPTIONS" && o.startsWith("/_voltro/inspect")) {
|
|
847
|
+
let e = de(a.origin);
|
|
848
848
|
t.writeHead(204, e), t.end();
|
|
849
849
|
return;
|
|
850
850
|
}
|
|
851
|
-
if (
|
|
851
|
+
if (f.name === "voltroDashboard" && o === "/api/dashboard/proxy") {
|
|
852
852
|
let r = new URL(n, "http://x").searchParams.get("target");
|
|
853
853
|
if (!r) {
|
|
854
854
|
t.writeHead(400, { "content-type": "text/plain" }), t.end("missing ?target=");
|
|
855
855
|
return;
|
|
856
856
|
}
|
|
857
|
-
if (!
|
|
857
|
+
if (!le(r)) {
|
|
858
858
|
t.writeHead(400, { "content-type": "text/plain" }), t.end("target not allowed: must be loopback or an origin configured in VOLTRO_DASHBOARD_APPS");
|
|
859
859
|
return;
|
|
860
860
|
}
|
|
861
861
|
try {
|
|
862
|
-
let n = { accept:
|
|
863
|
-
|
|
864
|
-
let
|
|
865
|
-
if (
|
|
862
|
+
let n = { accept: a.accept ?? "application/json" }, i = a.authorization;
|
|
863
|
+
i ? n.authorization = Array.isArray(i) ? i[0] : i : se(r) && process.env.VOLTRO_INSPECT_TOKEN && (n.authorization = `Bearer ${process.env.VOLTRO_INSPECT_TOKEN}`);
|
|
864
|
+
let o;
|
|
865
|
+
if (s && s !== "GET" && s !== "HEAD") {
|
|
866
866
|
let t = [];
|
|
867
867
|
for await (let n of e) t.push(n);
|
|
868
|
-
|
|
869
|
-
let r =
|
|
868
|
+
o = Buffer.concat(t);
|
|
869
|
+
let r = a["content-type"];
|
|
870
870
|
r && (n["content-type"] = Array.isArray(r) ? r[0] : r);
|
|
871
871
|
}
|
|
872
872
|
let c = await fetch(r, {
|
|
873
873
|
redirect: "manual",
|
|
874
|
-
method:
|
|
874
|
+
method: s,
|
|
875
875
|
headers: n,
|
|
876
|
-
...
|
|
876
|
+
...o ? { body: new Uint8Array(o.buffer, o.byteOffset, o.byteLength) } : {}
|
|
877
877
|
}), l = Buffer.from(await c.arrayBuffer());
|
|
878
878
|
t.writeHead(c.status, {
|
|
879
879
|
"content-type": c.headers.get("content-type") ?? "application/octet-stream",
|
|
@@ -884,27 +884,27 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
884
884
|
}
|
|
885
885
|
return;
|
|
886
886
|
}
|
|
887
|
-
if (
|
|
887
|
+
if (f.name === "voltroDashboard" && o === "/api/dashboard/proxy/stream") {
|
|
888
888
|
let r = new URL(n, "http://x").searchParams.get("target");
|
|
889
889
|
if (!r) {
|
|
890
890
|
t.writeHead(400, { "content-type": "text/plain" }), t.end("missing ?target=");
|
|
891
891
|
return;
|
|
892
892
|
}
|
|
893
|
-
if (!
|
|
893
|
+
if (!le(r)) {
|
|
894
894
|
t.writeHead(400, { "content-type": "text/plain" }), t.end("target not allowed: must be loopback or an origin configured in VOLTRO_DASHBOARD_APPS");
|
|
895
895
|
return;
|
|
896
896
|
}
|
|
897
|
-
let
|
|
898
|
-
e.on("close", () =>
|
|
897
|
+
let i = new AbortController();
|
|
898
|
+
e.on("close", () => i.abort()), t.on("close", () => i.abort());
|
|
899
899
|
try {
|
|
900
|
-
let e =
|
|
900
|
+
let e = a.authorization ?? (se(r) && process.env.VOLTRO_INSPECT_TOKEN ? `Bearer ${process.env.VOLTRO_INSPECT_TOKEN}` : void 0), n = await fetch(r, {
|
|
901
901
|
redirect: "manual",
|
|
902
902
|
method: "GET",
|
|
903
903
|
headers: {
|
|
904
904
|
accept: "text/event-stream",
|
|
905
905
|
...e ? { authorization: Array.isArray(e) ? e[0] : e } : {}
|
|
906
906
|
},
|
|
907
|
-
signal:
|
|
907
|
+
signal: i.signal
|
|
908
908
|
});
|
|
909
909
|
if (!n.ok || !n.body) {
|
|
910
910
|
t.writeHead(n.status, { "content-type": "text/plain" }), t.end(`upstream ${n.status}`);
|
|
@@ -931,23 +931,23 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
931
931
|
}
|
|
932
932
|
return;
|
|
933
933
|
}
|
|
934
|
-
if (
|
|
935
|
-
let n =
|
|
936
|
-
if (
|
|
934
|
+
if (o === "/_voltro/inspect/stream") {
|
|
935
|
+
let n = de(a.origin);
|
|
936
|
+
if (ce()) {
|
|
937
937
|
t.writeHead(503, {
|
|
938
938
|
"content-type": "application/json",
|
|
939
939
|
...n
|
|
940
940
|
}), t.end(JSON.stringify({ error: "inspect disabled (VOLTRO_INSPECT=off)" }));
|
|
941
941
|
return;
|
|
942
942
|
}
|
|
943
|
-
let
|
|
944
|
-
if (!
|
|
943
|
+
let i = N(a, "GET");
|
|
944
|
+
if (!i.ok) {
|
|
945
945
|
t.writeHead(401, {
|
|
946
946
|
"content-type": "application/json",
|
|
947
947
|
...n
|
|
948
948
|
}), t.end(JSON.stringify({
|
|
949
949
|
error: "unauthorized",
|
|
950
|
-
reason:
|
|
950
|
+
reason: i.reason
|
|
951
951
|
}));
|
|
952
952
|
return;
|
|
953
953
|
}
|
|
@@ -958,30 +958,30 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
958
958
|
"x-accel-buffering": "no",
|
|
959
959
|
...n
|
|
960
960
|
}), t.flushHeaders(), t.write("retry: 5000\n\n");
|
|
961
|
-
for (let e of
|
|
962
|
-
let
|
|
963
|
-
t.write(
|
|
964
|
-
}),
|
|
965
|
-
t.write(
|
|
966
|
-
}, 15e3),
|
|
967
|
-
clearInterval(
|
|
961
|
+
for (let e of g.buffered()) t.write(l(e));
|
|
962
|
+
let o = g.subscribe((e) => {
|
|
963
|
+
t.write(l(e));
|
|
964
|
+
}), s = setInterval(() => {
|
|
965
|
+
t.write(r());
|
|
966
|
+
}, 15e3), c = () => {
|
|
967
|
+
clearInterval(s), o();
|
|
968
968
|
};
|
|
969
|
-
e.on("close",
|
|
969
|
+
e.on("close", c), t.on("close", c);
|
|
970
970
|
return;
|
|
971
971
|
}
|
|
972
972
|
try {
|
|
973
|
-
let e = await
|
|
974
|
-
if (e.stream ? e.stream(t) : (t.writeHead(e.status, e.headers), t.end(e.body)), !
|
|
975
|
-
let t = Date.now() -
|
|
976
|
-
|
|
977
|
-
url:
|
|
973
|
+
let e = await Fe(n, a);
|
|
974
|
+
if (e.stream ? e.stream(t) : (t.writeHead(e.status, e.headers), t.end(e.body)), !o.startsWith("/_voltro/inspect")) {
|
|
975
|
+
let t = Date.now() - i;
|
|
976
|
+
g.emit("request", {
|
|
977
|
+
url: o,
|
|
978
978
|
status: e.status,
|
|
979
979
|
durationMs: t,
|
|
980
980
|
renderedBy: e.headers["x-voltro-rendered-by"],
|
|
981
981
|
cache: e.headers["x-voltro-cache"]
|
|
982
982
|
});
|
|
983
|
-
let n =
|
|
984
|
-
|
|
983
|
+
let n = we(o, W)?.route.pattern ?? (e.status === 404 ? "<unmatched>" : "<asset>");
|
|
984
|
+
Ae.record({
|
|
985
985
|
kind: "request",
|
|
986
986
|
tag: n,
|
|
987
987
|
durationMs: t,
|
|
@@ -992,71 +992,71 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
992
992
|
t.writeHead(500, { "content-type": "text/plain" }), t.end(`internal error: ${e.message}`);
|
|
993
993
|
}
|
|
994
994
|
});
|
|
995
|
-
await new Promise((e) =>
|
|
996
|
-
port:
|
|
997
|
-
distDir:
|
|
998
|
-
}),
|
|
995
|
+
await new Promise((e) => Le.listen(b, "::", e)), Ie = !0, o.mark("ready"), K.info(`listening on http://localhost:${b}`, {
|
|
996
|
+
port: b,
|
|
997
|
+
distDir: x
|
|
998
|
+
}), K.debug("dynamic + ssr/isr routes resolve via SSR loader");
|
|
999
999
|
try {
|
|
1000
|
-
await
|
|
1001
|
-
id:
|
|
1000
|
+
await w({
|
|
1001
|
+
id: j,
|
|
1002
1002
|
name: T,
|
|
1003
1003
|
kind: "web",
|
|
1004
|
-
url: `http://localhost:${
|
|
1004
|
+
url: `http://localhost:${b}`,
|
|
1005
1005
|
pid: process.pid,
|
|
1006
1006
|
status: "live",
|
|
1007
|
-
logFile:
|
|
1007
|
+
logFile: M.path
|
|
1008
1008
|
});
|
|
1009
|
-
let e =
|
|
1009
|
+
let e = oe(a);
|
|
1010
1010
|
if (e) {
|
|
1011
1011
|
let n = await t({ dashboardAppPath: e });
|
|
1012
|
-
n.status === "launched" ?
|
|
1012
|
+
n.status === "launched" ? K.info(`dashboard launched at http://localhost:${n.port}`, { port: n.port }) : n.status === "already-running" && K.debug(`dashboard already running on :${n.port}`, { port: n.port });
|
|
1013
1013
|
}
|
|
1014
1014
|
setInterval(() => {
|
|
1015
|
-
|
|
1016
|
-
id:
|
|
1015
|
+
w({
|
|
1016
|
+
id: j,
|
|
1017
1017
|
name: T,
|
|
1018
1018
|
kind: "web",
|
|
1019
|
-
url: `http://localhost:${
|
|
1019
|
+
url: `http://localhost:${b}`,
|
|
1020
1020
|
pid: process.pid,
|
|
1021
1021
|
status: "live",
|
|
1022
|
-
logFile:
|
|
1022
|
+
logFile: M.path
|
|
1023
1023
|
}).catch(() => {});
|
|
1024
1024
|
}, 1e4).unref();
|
|
1025
1025
|
} catch (e) {
|
|
1026
|
-
|
|
1026
|
+
K.warn("runtime-registry write failed", {}, e);
|
|
1027
1027
|
}
|
|
1028
|
-
|
|
1029
|
-
app:
|
|
1028
|
+
me({
|
|
1029
|
+
app: f.name ?? "unnamed",
|
|
1030
1030
|
kind: "web",
|
|
1031
|
-
url: `http://localhost:${
|
|
1032
|
-
bootMs:
|
|
1031
|
+
url: `http://localhost:${b}`,
|
|
1032
|
+
bootMs: o.total()
|
|
1033
1033
|
});
|
|
1034
|
-
let
|
|
1035
|
-
|
|
1036
|
-
bootMs:
|
|
1037
|
-
...
|
|
1034
|
+
let Re = o.phaseBreakdown();
|
|
1035
|
+
K.info(`start: ready in ${o.total()}ms`, {
|
|
1036
|
+
bootMs: o.total(),
|
|
1037
|
+
...Re ? { phases: Re } : {}
|
|
1038
1038
|
});
|
|
1039
|
-
let
|
|
1040
|
-
if (!
|
|
1041
|
-
if (
|
|
1042
|
-
await
|
|
1039
|
+
let ze = !1, $ = (e) => async () => {
|
|
1040
|
+
if (!ze) {
|
|
1041
|
+
if (ze = !0, K.info(`received ${e}, shutting down`, { signal: e }), Le.close(), await ke.stop(), V) try {
|
|
1042
|
+
await V.end();
|
|
1043
1043
|
} catch {}
|
|
1044
|
-
await
|
|
1044
|
+
await q.close(), await y(j), await M.dispose(), process.exit(0);
|
|
1045
1045
|
}
|
|
1046
1046
|
};
|
|
1047
|
-
process.on("SIGINT",
|
|
1047
|
+
process.on("SIGINT", $("SIGINT")), process.on("SIGTERM", $("SIGTERM"));
|
|
1048
1048
|
let Be = process.ppid;
|
|
1049
1049
|
if (Be > 1) {
|
|
1050
1050
|
let e = setInterval(() => {
|
|
1051
|
-
(process.ppid !== Be || process.ppid === 1) && (clearInterval(e),
|
|
1051
|
+
(process.ppid !== Be || process.ppid === 1) && (clearInterval(e), $("SIGTERM")());
|
|
1052
1052
|
}, 2e3);
|
|
1053
1053
|
e.unref();
|
|
1054
1054
|
}
|
|
1055
1055
|
return new Promise(() => {});
|
|
1056
|
-
},
|
|
1056
|
+
}, ke = async (e) => {
|
|
1057
1057
|
process.env.NODE_ENV || (process.env.NODE_ENV = "production");
|
|
1058
|
-
let t = await
|
|
1059
|
-
return t.ran ? t.exitCode : (
|
|
1058
|
+
let t = await Oe(I(e.find((e) => !e.startsWith("-")) ?? process.cwd()));
|
|
1059
|
+
return t.ran ? t.exitCode : (K.error("no web app found at this path"), 1);
|
|
1060
1060
|
};
|
|
1061
1061
|
//#endregion
|
|
1062
|
-
export {
|
|
1062
|
+
export { ke as t };
|