@voltro/cli 0.11.3 → 0.11.4
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 +173 -0
- package/THIRD-PARTY-NOTICES.md +4 -4
- package/dist/apiBuild-D9MtlD02.js +2 -0
- package/dist/{apiBuild-zFDv0u8y.js → apiBuild-DHHuiwXF.js} +4 -4
- package/dist/bin.js +13 -6
- package/dist/{commands-BDGYrBhK.js → commands-BwbMqR-1.js} +1982 -1854
- package/dist/dev-BsBsIv93.js +2 -0
- package/dist/{dev-CGt0PP1f.js → dev-Cvojvb_J.js} +1696 -1654
- package/dist/{devActivity-1WtIVyHc.js → devActivity-BhIu6ncs.js} +7 -1
- package/dist/devActivity.js +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.js +1 -1
- package/dist/{inspectMetrics-SRtv8KDy.js → inspectMetrics-D4EJ8LTi.js} +331 -323
- package/dist/{serveCommand-p6e5Ahgx.js → serveCommand-ARqSs73o.js} +397 -350
- package/dist/serveEntry.js +3 -3
- package/dist/{start-Crl39M38.js → start-DyJE6w1R.js} +281 -273
- package/dist/startEntry.js +2 -2
- package/package.json +17 -17
- package/templates/agent-docs/_manifest.json +1 -1
- package/templates/agent-docs/cli.md +86 -2
- package/templates/agent-docs/data.md +104 -1
- package/templates/agent-docs/database/misc.md +32 -0
- package/templates/agent-docs/database/querying.md +14 -1
- package/templates/agent-docs/internationalization.md +3 -8
- package/templates/agent-docs/reference.md +35 -0
- package/templates/agent-docs/workflows.md +31 -0
- 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-storage/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-search/package.json +8 -8
- package/templates/apps/api-versioning/package.json +8 -8
- package/templates/apps/api-webhooks/README.md +3 -1
- package/templates/apps/api-webhooks/package.json +8 -8
- 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-blank/package.json +7 -7
- 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-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/dist/apiBuild-BmPdmhgi.js +0 -2
- package/dist/dev-D_PGP9Kx.js +0 -2
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { A as e,
|
|
2
|
-
import { t as
|
|
3
|
-
import { dirname as
|
|
4
|
-
import { fileURLToPath as
|
|
5
|
-
import { createLogger as z, printReadyBlock as
|
|
1
|
+
import { A as e, At as t, C as n, Ct as r, Dt as i, E as a, Et as o, G as s, H as c, I as l, J as u, N as d, Nt as f, O as p, R as m, Tt as h, U as g, V as _, W as v, Z as y, _ as ee, _t as te, a as b, at as ne, b as x, c as S, f as C, g as w, gt as T, h as E, i as D, j as O, k, m as A, o as re, p as ie, q as j, r as ae, s as oe, t as se, v as M, vt as N, w as P, wt as ce, y as F } from "./inspectMetrics-D4EJ8LTi.js";
|
|
2
|
+
import { t as le } from "./bootTiming-BdyP9nYw.js";
|
|
3
|
+
import { dirname as ue, extname as I, join as L, resolve as R } from "node:path";
|
|
4
|
+
import { fileURLToPath as de, pathToFileURL as fe } from "node:url";
|
|
5
|
+
import { createLogger as z, printReadyBlock as pe } from "@voltro/logger";
|
|
6
6
|
import { promises as B } from "node:fs";
|
|
7
|
-
import { snapshotMetricsSync as
|
|
8
|
-
import { createServer as
|
|
7
|
+
import { snapshotMetricsSync as me } from "@voltro/runtime";
|
|
8
|
+
import { createServer as he } from "node:http";
|
|
9
9
|
//#region src/isrCdcInvalidator.ts
|
|
10
10
|
var V = z({ scope: "voltro:start:cdc" }), H = (e) => (t) => {
|
|
11
11
|
let n = 0;
|
|
@@ -24,7 +24,7 @@ var V = z({ scope: "voltro:start:cdc" }), H = (e) => (t) => {
|
|
|
24
24
|
user: process.env.PG_USER ?? "app",
|
|
25
25
|
password: process.env.PG_PASSWORD ?? "app",
|
|
26
26
|
database: process.env.PG_DATABASE ?? "app"
|
|
27
|
-
},
|
|
27
|
+
}, ge = (e) => {
|
|
28
28
|
let t = e.channel ?? "framework_changes", n = H(e), r = null, i = null;
|
|
29
29
|
return {
|
|
30
30
|
start: async () => {
|
|
@@ -68,7 +68,7 @@ var V = z({ scope: "voltro:start:cdc" }), H = (e) => (t) => {
|
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
};
|
|
71
|
-
}, W = z({ scope: "voltro:start:isr-cache" }), G = "voltro_isr_cache",
|
|
71
|
+
}, W = z({ scope: "voltro:start:isr-cache" }), G = "voltro_isr_cache", _e = (e) => `
|
|
72
72
|
CREATE TABLE IF NOT EXISTS ${e} (
|
|
73
73
|
cache_key TEXT PRIMARY KEY,
|
|
74
74
|
html TEXT NOT NULL,
|
|
@@ -79,9 +79,9 @@ CREATE TABLE IF NOT EXISTS ${e} (
|
|
|
79
79
|
stale_while_revalidate_ms BIGINT NOT NULL DEFAULT 0
|
|
80
80
|
);
|
|
81
81
|
CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
82
|
-
`,
|
|
82
|
+
`, ve = (e) => {
|
|
83
83
|
let t = e.tableName ?? G, { client: n } = e, r = /* @__PURE__ */ new Map(), i = !1, a = (async () => {
|
|
84
|
-
i || (i = !0, await n.query(
|
|
84
|
+
i || (i = !0, await n.query(_e(t)));
|
|
85
85
|
})().then(async () => {
|
|
86
86
|
let e = await n.query(`SELECT * FROM ${t}`);
|
|
87
87
|
for (let t of e.rows) r.set(t.cache_key, {
|
|
@@ -141,14 +141,14 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
141
141
|
return Array.from(r.entries());
|
|
142
142
|
}
|
|
143
143
|
};
|
|
144
|
-
}, K = z({ scope: "voltro:start" }),
|
|
144
|
+
}, K = z({ scope: "voltro:start" }), ye = await (async () => {
|
|
145
145
|
try {
|
|
146
|
-
let e =
|
|
146
|
+
let e = L(ue(de(import.meta.url)), "..", "package.json"), t = await B.readFile(e, "utf8");
|
|
147
147
|
return JSON.parse(t).version ?? "0.0.0";
|
|
148
148
|
} catch {
|
|
149
149
|
return "0.0.0";
|
|
150
150
|
}
|
|
151
|
-
})(), q = (e) => e instanceof Error && e._voltroControl === "redirect" && typeof e.location == "string",
|
|
151
|
+
})(), q = (e) => e instanceof Error && e._voltroControl === "redirect" && typeof e.location == "string", be = (e) => e instanceof Error && e._voltroControl === "not-found", J = {
|
|
152
152
|
".html": "text/html; charset=utf-8",
|
|
153
153
|
".js": "application/javascript",
|
|
154
154
|
".mjs": "application/javascript",
|
|
@@ -166,7 +166,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
166
166
|
".woff": "font/woff",
|
|
167
167
|
".woff2": "font/woff2",
|
|
168
168
|
".txt": "text/plain; charset=utf-8"
|
|
169
|
-
},
|
|
169
|
+
}, xe = (e) => J[I(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) => {
|
|
170
170
|
try {
|
|
171
171
|
return await B.stat(e), !0;
|
|
172
172
|
} catch {
|
|
@@ -181,7 +181,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
181
181
|
paramNames: t,
|
|
182
182
|
priority: n
|
|
183
183
|
};
|
|
184
|
-
},
|
|
184
|
+
}, Se = (e) => e.map((e) => {
|
|
185
185
|
let { regex: t, paramNames: n, priority: r } = Z(e.pattern);
|
|
186
186
|
return {
|
|
187
187
|
pattern: e.pattern,
|
|
@@ -191,7 +191,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
191
191
|
paramNames: n,
|
|
192
192
|
priority: r
|
|
193
193
|
};
|
|
194
|
-
}).slice().sort((e, t) => e.priority - t.priority),
|
|
194
|
+
}).slice().sort((e, t) => e.priority - t.priority), Ce = (e, t) => {
|
|
195
195
|
for (let n of t) {
|
|
196
196
|
let t = n.regex.exec(e);
|
|
197
197
|
if (!t) continue;
|
|
@@ -203,13 +203,13 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
203
203
|
};
|
|
204
204
|
}
|
|
205
205
|
return null;
|
|
206
|
-
},
|
|
207
|
-
let { provider: t, route: n, params: r, pathname: a, dirs: o, shellTemplate:
|
|
208
|
-
if (
|
|
209
|
-
let
|
|
206
|
+
}, we = async (e) => {
|
|
207
|
+
let { provider: t, route: n, params: r, pathname: a, dirs: o, shellTemplate: s, requestHeaders: c, requestUrl: u = "", apiOrigin: d, apiName: f } = e, p = D(d, c.cookie, { apiName: f }), m = await t.getPage(n.pattern, n.file), h = l(m, n.file), g = h === "spa" && re(o, n.dirChain).some((e) => e.hasLayout);
|
|
208
|
+
if (h !== "ssr" && h !== "isr" && !g) return null;
|
|
209
|
+
let _ = re(o, n.dirChain), v = {}, y = null, te, ne = new AbortController();
|
|
210
210
|
try {
|
|
211
|
-
({chain:
|
|
212
|
-
entries:
|
|
211
|
+
({chain: te, segmentLoaderData: v} = await b({
|
|
212
|
+
entries: _,
|
|
213
213
|
loadLayout: (e) => t.getLayout(e.dir),
|
|
214
214
|
loadError: (e) => t.getError(e.dir),
|
|
215
215
|
loadPending: (e) => t.getPending(e.dir),
|
|
@@ -217,15 +217,15 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
217
217
|
params: r,
|
|
218
218
|
pathname: a,
|
|
219
219
|
signal: ne.signal,
|
|
220
|
-
headers:
|
|
221
|
-
query:
|
|
220
|
+
headers: c,
|
|
221
|
+
query: p
|
|
222
222
|
}
|
|
223
|
-
})), typeof
|
|
223
|
+
})), typeof m.loader == "function" && !g && (y = await m.loader({
|
|
224
224
|
params: r,
|
|
225
225
|
pathname: a,
|
|
226
226
|
signal: ne.signal,
|
|
227
|
-
headers:
|
|
228
|
-
query:
|
|
227
|
+
headers: c,
|
|
228
|
+
query: p
|
|
229
229
|
}));
|
|
230
230
|
} catch (e) {
|
|
231
231
|
if (q(e)) return {
|
|
@@ -233,51 +233,51 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
233
233
|
status: e.status,
|
|
234
234
|
location: e.location
|
|
235
235
|
};
|
|
236
|
-
if (
|
|
236
|
+
if (be(e)) return { control: "not-found" };
|
|
237
237
|
throw e;
|
|
238
238
|
}
|
|
239
|
-
let S = await t.getHelpers(),
|
|
239
|
+
let S = await t.getHelpers(), C = {
|
|
240
240
|
pattern: n.pattern,
|
|
241
|
-
Component:
|
|
242
|
-
meta:
|
|
243
|
-
loader:
|
|
244
|
-
ErrorBoundary:
|
|
245
|
-
Pending:
|
|
246
|
-
renderMode:
|
|
247
|
-
chain:
|
|
248
|
-
},
|
|
249
|
-
cookies: S.parseCookieHeader(
|
|
250
|
-
headers:
|
|
241
|
+
Component: m.default,
|
|
242
|
+
meta: m.meta,
|
|
243
|
+
loader: m.loader,
|
|
244
|
+
ErrorBoundary: m.ErrorBoundary,
|
|
245
|
+
Pending: m.Pending,
|
|
246
|
+
renderMode: h,
|
|
247
|
+
chain: te
|
|
248
|
+
}, w = {
|
|
249
|
+
cookies: S.parseCookieHeader(c.cookie),
|
|
250
|
+
headers: c,
|
|
251
251
|
url: u
|
|
252
|
-
},
|
|
253
|
-
if (
|
|
254
|
-
let e =
|
|
252
|
+
}, T = S.i18n?.resolve(c.cookie, c["accept-language"]), O = m.interactive ?? "full";
|
|
253
|
+
if (g) {
|
|
254
|
+
let e = M({
|
|
255
255
|
helpers: S,
|
|
256
256
|
page: n.pattern,
|
|
257
|
-
interactive:
|
|
257
|
+
interactive: O,
|
|
258
258
|
delivery: "stream",
|
|
259
259
|
renderInput: {
|
|
260
|
-
descriptor:
|
|
260
|
+
descriptor: C,
|
|
261
261
|
params: r,
|
|
262
262
|
pathname: a,
|
|
263
|
-
segmentLoaderData:
|
|
264
|
-
requestContext:
|
|
265
|
-
...
|
|
266
|
-
outerWrap:
|
|
267
|
-
locale:
|
|
263
|
+
segmentLoaderData: v,
|
|
264
|
+
requestContext: w,
|
|
265
|
+
...T ? {
|
|
266
|
+
outerWrap: T.outerWrap,
|
|
267
|
+
locale: T.locale
|
|
268
268
|
} : {}
|
|
269
269
|
}
|
|
270
|
-
}), t =
|
|
270
|
+
}), t = T?.locale ?? w.cookies["voltro:lang"] ?? "en", i = (t) => x({
|
|
271
271
|
helpers: S,
|
|
272
272
|
prepared: e,
|
|
273
273
|
meta: t,
|
|
274
|
-
interactive:
|
|
274
|
+
interactive: O
|
|
275
275
|
});
|
|
276
276
|
if (e.hasDeferred) {
|
|
277
|
-
let n =
|
|
277
|
+
let n = A({ shell: s });
|
|
278
278
|
return {
|
|
279
279
|
renderMode: "spa",
|
|
280
|
-
stream: (r) =>
|
|
280
|
+
stream: (r) => E({
|
|
281
281
|
res: r,
|
|
282
282
|
shell: n,
|
|
283
283
|
htmlLang: t,
|
|
@@ -296,47 +296,47 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
296
296
|
})
|
|
297
297
|
};
|
|
298
298
|
}
|
|
299
|
-
let o =
|
|
299
|
+
let o = F({
|
|
300
300
|
helpers: S,
|
|
301
301
|
prepared: e
|
|
302
302
|
});
|
|
303
303
|
return {
|
|
304
|
-
html:
|
|
304
|
+
html: s.replace("<div id=\"root\"></div>", `<div id="root">${o.body}</div>`).replace("</head>", ` ${i(o.meta)}\n </head>`).replace(/<html(\s+lang="[^"]*")?/i, `<html lang="${t}"`),
|
|
305
305
|
renderMode: "spa",
|
|
306
306
|
revalidateMs: null
|
|
307
307
|
};
|
|
308
308
|
}
|
|
309
|
-
let
|
|
309
|
+
let k = ee({
|
|
310
310
|
helpers: S,
|
|
311
311
|
page: n.pattern,
|
|
312
312
|
pathname: a,
|
|
313
|
-
renderMode:
|
|
314
|
-
interactive:
|
|
315
|
-
loaderData:
|
|
316
|
-
segmentLoaderData:
|
|
317
|
-
pageLoaderRan: typeof
|
|
318
|
-
}),
|
|
319
|
-
descriptor:
|
|
313
|
+
renderMode: h,
|
|
314
|
+
interactive: O,
|
|
315
|
+
loaderData: y,
|
|
316
|
+
segmentLoaderData: v,
|
|
317
|
+
pageLoaderRan: typeof m.loader == "function"
|
|
318
|
+
}), ie = {
|
|
319
|
+
descriptor: C,
|
|
320
320
|
params: r,
|
|
321
321
|
pathname: a,
|
|
322
|
-
loaderData:
|
|
323
|
-
segmentLoaderData:
|
|
324
|
-
requestContext:
|
|
325
|
-
...
|
|
326
|
-
outerWrap:
|
|
327
|
-
locale:
|
|
322
|
+
loaderData: k.loaderData,
|
|
323
|
+
segmentLoaderData: k.segmentLoaderData,
|
|
324
|
+
requestContext: w,
|
|
325
|
+
...T ? {
|
|
326
|
+
outerWrap: T.outerWrap,
|
|
327
|
+
locale: T.locale
|
|
328
328
|
} : {}
|
|
329
|
-
},
|
|
329
|
+
}, j = (e) => [
|
|
330
330
|
S.renderMetaToHtml(e),
|
|
331
|
-
`<meta name="voltro-interactive" content="${
|
|
332
|
-
...
|
|
333
|
-
S.renderRouterStateScript(
|
|
331
|
+
`<meta name="voltro-interactive" content="${O}" />`,
|
|
332
|
+
...k.hasDeferred ? [S.renderDeferredRegistryScript()] : [],
|
|
333
|
+
S.renderRouterStateScript(k.stateInput)
|
|
334
334
|
].filter((e) => e.length > 0).join("\n ");
|
|
335
|
-
if (
|
|
336
|
-
let e =
|
|
335
|
+
if (h === "ssr" && O === "full" && e.buffered !== !0) {
|
|
336
|
+
let e = T?.locale ?? w.cookies["voltro:lang"] ?? "en", t = A({ shell: s });
|
|
337
337
|
return {
|
|
338
338
|
renderMode: "ssr",
|
|
339
|
-
stream: (n) =>
|
|
339
|
+
stream: (n) => E({
|
|
340
340
|
res: n,
|
|
341
341
|
shell: t,
|
|
342
342
|
htmlLang: e,
|
|
@@ -344,9 +344,9 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
344
344
|
"content-type": "text/html; charset=utf-8",
|
|
345
345
|
"x-voltro-rendered-by": "ssr"
|
|
346
346
|
},
|
|
347
|
-
headInjection:
|
|
347
|
+
headInjection: j,
|
|
348
348
|
render: (e) => S.renderPageToStream({
|
|
349
|
-
...
|
|
349
|
+
...ie,
|
|
350
350
|
...e
|
|
351
351
|
}),
|
|
352
352
|
onShellError: (e) => {
|
|
@@ -355,16 +355,16 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
355
355
|
})
|
|
356
356
|
};
|
|
357
357
|
}
|
|
358
|
-
let { html:
|
|
359
|
-
|
|
360
|
-
let
|
|
358
|
+
let { html: ae, meta: oe } = S.renderPageToHtml(ie), se = j(oe), N = T?.locale ?? w.cookies["voltro:lang"] ?? "en", P = s.replace("<div id=\"root\"></div>", `<div id="root">${ae}</div>`).replace("</head>", ` ${se}\n </head>`).replace(/<html(\s+lang="[^"]*")?/i, `<html lang="${N}"`);
|
|
359
|
+
O === "none" && (P = Y(P));
|
|
360
|
+
let ce = h === "isr" ? i(m.revalidate) : null;
|
|
361
361
|
return {
|
|
362
|
-
html:
|
|
363
|
-
renderMode:
|
|
364
|
-
revalidateMs:
|
|
362
|
+
html: P,
|
|
363
|
+
renderMode: h,
|
|
364
|
+
revalidateMs: ce
|
|
365
365
|
};
|
|
366
|
-
}, Q = (e) => e === "" ? "/" : e,
|
|
367
|
-
let t = await import(
|
|
366
|
+
}, Q = (e) => e === "" ? "/" : e, Te = async (e) => {
|
|
367
|
+
let t = await import(fe(e).href);
|
|
368
368
|
return {
|
|
369
369
|
kind: "bundle",
|
|
370
370
|
getPageMeta: () => t.pageMeta,
|
|
@@ -393,8 +393,8 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
393
393
|
},
|
|
394
394
|
async close() {}
|
|
395
395
|
};
|
|
396
|
-
},
|
|
397
|
-
let n = await
|
|
396
|
+
}, Ee = async (e, t) => {
|
|
397
|
+
let n = await f("vite", () => import("vite")), r = (await import("@vitejs/plugin-react")).default, i = (await import("@tailwindcss/vite")).default, a = await n.createServer({
|
|
398
398
|
root: t,
|
|
399
399
|
envPrefix: "__VOLTRO_VITE_ENV_DISABLED__",
|
|
400
400
|
plugins: [r(), i()],
|
|
@@ -406,97 +406,97 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
406
406
|
},
|
|
407
407
|
appType: "custom",
|
|
408
408
|
logLevel: "warn"
|
|
409
|
-
}), o =
|
|
409
|
+
}), o = L(e, "src", "pages"), s = (e) => e === "" ? o : L(o, e), c = j({ limit: u() }), l = (e) => c.load(e, async () => await a.ssrLoadModule(e));
|
|
410
410
|
return {
|
|
411
411
|
kind: "middleware",
|
|
412
412
|
async getPage(e, t) {
|
|
413
|
-
return
|
|
413
|
+
return l(L(o, t));
|
|
414
414
|
},
|
|
415
415
|
async getLayout(e) {
|
|
416
|
-
return
|
|
416
|
+
return l(L(s(e), "layout.tsx"));
|
|
417
417
|
},
|
|
418
418
|
async getError(e) {
|
|
419
|
-
return
|
|
419
|
+
return l(L(s(e), "error.tsx"));
|
|
420
420
|
},
|
|
421
421
|
async getPending(e) {
|
|
422
|
-
return
|
|
422
|
+
return l(L(s(e), "loading.tsx"));
|
|
423
423
|
},
|
|
424
424
|
async getHelpers() {
|
|
425
|
-
return await
|
|
425
|
+
return await l("@voltro/web/ssr");
|
|
426
426
|
},
|
|
427
427
|
async close() {
|
|
428
428
|
await a.close();
|
|
429
429
|
}
|
|
430
430
|
};
|
|
431
|
-
},
|
|
432
|
-
let
|
|
433
|
-
if (!
|
|
431
|
+
}, De = async (i) => {
|
|
432
|
+
let l = le(), u = await oe(i);
|
|
433
|
+
if (!u) return {
|
|
434
434
|
ran: !1,
|
|
435
435
|
exitCode: 0
|
|
436
436
|
};
|
|
437
|
-
if (
|
|
437
|
+
if (u.type !== "web") return K.error("only web apps are supported by `voltro start`"), {
|
|
438
438
|
ran: !0,
|
|
439
439
|
exitCode: 1
|
|
440
440
|
};
|
|
441
|
-
let { resolved:
|
|
442
|
-
rawEnv:
|
|
441
|
+
let { resolved: f } = await t({
|
|
442
|
+
rawEnv: u.env,
|
|
443
443
|
appType: "web",
|
|
444
444
|
root: i,
|
|
445
445
|
log: K,
|
|
446
446
|
generateTypes: !1
|
|
447
|
-
}),
|
|
448
|
-
|
|
449
|
-
let
|
|
450
|
-
|
|
447
|
+
}), ee = f.publicValues;
|
|
448
|
+
l.mark("config");
|
|
449
|
+
let b = v();
|
|
450
|
+
_(b), K.info("booting voltro start", { app: u.name ?? "(unnamed)" });
|
|
451
451
|
let x = (() => {
|
|
452
452
|
if (process.env.VOLTRO_IS_DASHBOARD === "1" && process.env.VOLTRO_DASHBOARD_PORT) return Number(process.env.VOLTRO_DASHBOARD_PORT);
|
|
453
453
|
if (process.env.PORT) {
|
|
454
454
|
let e = Number(process.env.PORT);
|
|
455
455
|
if (Number.isFinite(e) && e > 0) return e;
|
|
456
456
|
}
|
|
457
|
-
return
|
|
458
|
-
})(),
|
|
459
|
-
if (!await X(
|
|
457
|
+
return u.port ?? 5173;
|
|
458
|
+
})(), E = L(i, ".framework"), D = L(E, "dist"), A = L(D, "index.html");
|
|
459
|
+
if (!await X(A)) return K.error("no built dist found — run `voltro build` first", { distDir: D }), {
|
|
460
460
|
ran: !0,
|
|
461
461
|
exitCode: 1
|
|
462
462
|
};
|
|
463
|
-
let
|
|
464
|
-
await
|
|
465
|
-
id:
|
|
466
|
-
name:
|
|
463
|
+
let j = u.name ?? "unnamed", M = p("web", j, x), F = a(j);
|
|
464
|
+
await O({
|
|
465
|
+
id: M,
|
|
466
|
+
name: j,
|
|
467
467
|
kind: "web",
|
|
468
468
|
url: `http://localhost:${x}`,
|
|
469
469
|
pid: process.pid,
|
|
470
470
|
status: "booting",
|
|
471
|
-
logFile:
|
|
471
|
+
logFile: F.path
|
|
472
472
|
}).catch(() => {});
|
|
473
|
-
let
|
|
473
|
+
let ue = L(D, "_voltro", "shell.html"), I = await X(ue) ? await B.readFile(ue, "utf8") : await B.readFile(A, "utf8"), R = await S(i, u), de = ae(R[0]), fe = R[0]?.name, z, V = null;
|
|
474
474
|
process.env.SSR_CACHE === "postgres" && process.env.PG_HOST ? (V = new (await (import("pg"))).default.Client({
|
|
475
475
|
host: process.env.PG_HOST,
|
|
476
476
|
port: Number(process.env.PG_PORT ?? 5432),
|
|
477
477
|
user: process.env.PG_USER ?? "app",
|
|
478
478
|
password: process.env.PG_PASSWORD ?? "app",
|
|
479
479
|
database: process.env.PG_DATABASE ?? "app"
|
|
480
|
-
}), await V.connect(), z =
|
|
481
|
-
let { pages: H, dirs: U } = await
|
|
482
|
-
|
|
483
|
-
let G =
|
|
484
|
-
if (!
|
|
485
|
-
let q =
|
|
480
|
+
}), await V.connect(), z = ve({ client: V }), K.info("isr cache backend: postgres", { table: "voltro_isr_cache" })) : (z = o(), K.info("isr cache backend: memory (per-process)", { hint: "set SSR_CACHE=postgres for persistent storage" })), await ie(i, u, R, ee);
|
|
481
|
+
let { pages: H, dirs: U } = await C(L(i, "src", "pages")), W = Se(H);
|
|
482
|
+
l.mark("scan");
|
|
483
|
+
let G = L(D, "server", "ssrEntry.js"), _e = await X(G);
|
|
484
|
+
if (!_e && 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}`);
|
|
485
|
+
let q = _e ? await Te(G) : await Ee(i, E);
|
|
486
486
|
K.info(`ssr loader: ${q.kind}`, {
|
|
487
487
|
kind: q.kind,
|
|
488
488
|
...q.kind === "middleware" ? { hint: "no pre-built SSR bundle found; run `voltro build` to enable bundle mode" } : {}
|
|
489
|
-
}),
|
|
490
|
-
let
|
|
489
|
+
}), l.mark("provider");
|
|
490
|
+
let be = q.getPageMeta?.(), J = /* @__PURE__ */ new Map(), Y = 0;
|
|
491
491
|
for (let e of H) {
|
|
492
|
-
let t =
|
|
492
|
+
let t = be?.[e.pattern];
|
|
493
493
|
if (t) {
|
|
494
494
|
J.set(e.pattern, t);
|
|
495
495
|
continue;
|
|
496
496
|
}
|
|
497
497
|
try {
|
|
498
498
|
let t = await q.getPage(e.pattern, e.file);
|
|
499
|
-
J.set(e.pattern,
|
|
499
|
+
J.set(e.pattern, d(t, e.file)), Y++;
|
|
500
500
|
} catch (t) {
|
|
501
501
|
K.warn("failed to load page metadata", { pattern: e.pattern }, t);
|
|
502
502
|
}
|
|
@@ -505,21 +505,21 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
505
505
|
count: J.size,
|
|
506
506
|
fromManifest: J.size - Y,
|
|
507
507
|
fromModules: Y
|
|
508
|
-
}),
|
|
508
|
+
}), l.mark("routes");
|
|
509
509
|
let Z = /* @__PURE__ */ new Set();
|
|
510
|
-
for (let e of W) J.get(e.pattern)?.renderMode === "spa" &&
|
|
510
|
+
for (let e of W) J.get(e.pattern)?.renderMode === "spa" && re(U, e.dirChain).some((e) => e.hasLayout) && Z.add(e.pattern);
|
|
511
511
|
Z.size > 0 && K.info(`${Z.size} spa route(s) render an SSR layout shell`, { patterns: [...Z] });
|
|
512
512
|
let Q = /* @__PURE__ */ new Map();
|
|
513
513
|
for (let [e, t] of J) t.cacheInvalidatesOn.length > 0 && Q.set(e, t.cacheInvalidatesOn);
|
|
514
|
-
let
|
|
515
|
-
for (let e of W)
|
|
516
|
-
let
|
|
514
|
+
let De = /* @__PURE__ */ new Map();
|
|
515
|
+
for (let e of W) De.set(e.pattern, e.regex);
|
|
516
|
+
let Oe = ge({
|
|
517
517
|
cache: z,
|
|
518
518
|
tableSubscriptionsByPattern: Q,
|
|
519
|
-
regexByPattern:
|
|
519
|
+
regexByPattern: De
|
|
520
520
|
});
|
|
521
|
-
await
|
|
522
|
-
let
|
|
521
|
+
await Oe.start(), l.mark("cdc");
|
|
522
|
+
let ke = se(), Ae = H.map((e) => {
|
|
523
523
|
let t = J.get(e.pattern);
|
|
524
524
|
return {
|
|
525
525
|
pattern: e.pattern,
|
|
@@ -535,20 +535,20 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
535
535
|
hasMeta: t?.hasMeta ?? !1,
|
|
536
536
|
hasGetStaticPaths: t?.hasGetStaticPaths ?? !1
|
|
537
537
|
};
|
|
538
|
-
}),
|
|
538
|
+
}), je = U.map((e) => ({
|
|
539
539
|
dir: e.dir,
|
|
540
540
|
hasLayout: e.hasLayout,
|
|
541
541
|
hasError: e.hasError,
|
|
542
542
|
hasPending: e.hasPending,
|
|
543
543
|
hasNotFound: e.hasNotFound
|
|
544
|
-
})),
|
|
544
|
+
})), Me = V ? "postgres" : "memory", Ne = {
|
|
545
545
|
kind: "web",
|
|
546
546
|
meta: {
|
|
547
|
-
name:
|
|
548
|
-
voltroVersion:
|
|
547
|
+
name: u.name ?? "(unnamed)",
|
|
548
|
+
voltroVersion: ye,
|
|
549
549
|
port: x,
|
|
550
550
|
mode: "start",
|
|
551
|
-
apis: Object.entries(
|
|
551
|
+
apis: Object.entries(u.apis ?? {}).map(([e, t]) => {
|
|
552
552
|
let n = {
|
|
553
553
|
name: e,
|
|
554
554
|
package: t.package
|
|
@@ -556,8 +556,8 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
556
556
|
return t.url !== void 0 && (n.url = t.url), n;
|
|
557
557
|
})
|
|
558
558
|
},
|
|
559
|
-
routes:
|
|
560
|
-
dirs:
|
|
559
|
+
routes: Ae,
|
|
560
|
+
dirs: je,
|
|
561
561
|
cache: () => {
|
|
562
562
|
let e = Date.now(), t = z.snapshot().map(([t, n]) => ({
|
|
563
563
|
key: t,
|
|
@@ -570,16 +570,16 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
570
570
|
staleWhileRevalidateMs: n.staleWhileRevalidateMs
|
|
571
571
|
}));
|
|
572
572
|
return {
|
|
573
|
-
backend:
|
|
573
|
+
backend: Me,
|
|
574
574
|
size: z.size(),
|
|
575
575
|
entries: t
|
|
576
576
|
};
|
|
577
577
|
},
|
|
578
|
-
metrics: () =>
|
|
579
|
-
},
|
|
580
|
-
let
|
|
581
|
-
if (
|
|
582
|
-
let e = await
|
|
578
|
+
metrics: () => me()
|
|
579
|
+
}, Pe = async (e, t) => {
|
|
580
|
+
let n = e.split("?")[0] ?? "/";
|
|
581
|
+
if (u.name === "voltroDashboard" && n === "/api/dashboard/registry") try {
|
|
582
|
+
let e = await k();
|
|
583
583
|
return {
|
|
584
584
|
status: 200,
|
|
585
585
|
headers: { "content-type": "application/json; charset=utf-8" },
|
|
@@ -592,7 +592,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
592
592
|
body: `registry read error: ${e.message}`
|
|
593
593
|
};
|
|
594
594
|
}
|
|
595
|
-
if (
|
|
595
|
+
if (u.name === "voltroDashboard" && n === "/api/dashboard/config") {
|
|
596
596
|
let e = process.env.VOLTRO_DASHBOARD_APPS, t = [];
|
|
597
597
|
if (e && e.trim().length > 0) {
|
|
598
598
|
let n;
|
|
@@ -621,19 +621,19 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
621
621
|
body: JSON.stringify({ apps: t })
|
|
622
622
|
};
|
|
623
623
|
}
|
|
624
|
-
if (
|
|
625
|
-
let n =
|
|
624
|
+
if (n === "/_voltro/inspect/logs") {
|
|
625
|
+
let n = m(e, c(), t);
|
|
626
626
|
return {
|
|
627
627
|
status: n.status,
|
|
628
628
|
headers: {
|
|
629
629
|
"content-type": n.contentType,
|
|
630
|
-
...
|
|
630
|
+
...T(t.origin)
|
|
631
631
|
},
|
|
632
632
|
body: n.body
|
|
633
633
|
};
|
|
634
634
|
}
|
|
635
|
-
if (
|
|
636
|
-
let n =
|
|
635
|
+
if (n !== "/_voltro/inspect/stream") {
|
|
636
|
+
let n = ne(e, Ne, t);
|
|
637
637
|
if (n !== null) return {
|
|
638
638
|
status: n.status,
|
|
639
639
|
headers: {
|
|
@@ -643,81 +643,81 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
643
643
|
body: n.body
|
|
644
644
|
};
|
|
645
645
|
}
|
|
646
|
-
let a =
|
|
647
|
-
if (!
|
|
646
|
+
let a = Ce(n, W), o = a ? J.get(a.route.pattern)?.renderMode : void 0, s = o === "ssr" || o === "isr" || (a ? Z.has(a.route.pattern) : !1), l = n === "/" ? L(D, "index.html") : L(D, n.replace(/^\//, ""), "index.html");
|
|
647
|
+
if (!s && await X(l)) return {
|
|
648
648
|
status: 200,
|
|
649
649
|
headers: { "content-type": "text/html; charset=utf-8" },
|
|
650
|
-
body: await B.readFile(
|
|
650
|
+
body: await B.readFile(l)
|
|
651
651
|
};
|
|
652
|
-
if (/\.[a-z0-9]+$/i.test(
|
|
653
|
-
let e =
|
|
652
|
+
if (/\.[a-z0-9]+$/i.test(n)) {
|
|
653
|
+
let e = L(D, n.replace(/^\//, ""));
|
|
654
654
|
if (await X(e)) {
|
|
655
655
|
let t = await B.readFile(e);
|
|
656
656
|
return {
|
|
657
657
|
status: 200,
|
|
658
|
-
headers: { "content-type":
|
|
658
|
+
headers: { "content-type": xe(e) },
|
|
659
659
|
body: t
|
|
660
660
|
};
|
|
661
661
|
}
|
|
662
662
|
}
|
|
663
|
-
let d =
|
|
663
|
+
let d = Ce(n, W);
|
|
664
664
|
if (!d) return {
|
|
665
665
|
status: 404,
|
|
666
666
|
headers: { "content-type": "text/plain" },
|
|
667
667
|
body: "not found"
|
|
668
668
|
};
|
|
669
|
-
let
|
|
670
|
-
...
|
|
671
|
-
...
|
|
672
|
-
}),
|
|
673
|
-
if (
|
|
669
|
+
let f = J.get(d.route.pattern), p = t["x-tenant"] ?? "anonymous", g = (await q.getHelpers()).i18n?.resolve(t.cookie, t["accept-language"])?.locale, _ = r(n, {
|
|
670
|
+
...f?.tenantAware ? { tenant: p } : {},
|
|
671
|
+
...g ? { locale: g } : {}
|
|
672
|
+
}), v = z.get(_), y = Date.now();
|
|
673
|
+
if (v && ce(v, y)) return b.emit("cache", {
|
|
674
674
|
kind: "HIT",
|
|
675
|
-
key:
|
|
676
|
-
ageMs:
|
|
675
|
+
key: _,
|
|
676
|
+
ageMs: y - v.renderedAt
|
|
677
677
|
}), {
|
|
678
678
|
status: 200,
|
|
679
679
|
headers: {
|
|
680
680
|
"content-type": "text/html; charset=utf-8",
|
|
681
681
|
"x-voltro-rendered-by": "isr",
|
|
682
682
|
"x-voltro-cache": "HIT",
|
|
683
|
-
"x-voltro-cache-key":
|
|
684
|
-
"x-voltro-cache-age-ms": String(
|
|
683
|
+
"x-voltro-cache-key": _,
|
|
684
|
+
"x-voltro-cache-age-ms": String(y - v.renderedAt)
|
|
685
685
|
},
|
|
686
|
-
body:
|
|
686
|
+
body: v.html
|
|
687
687
|
};
|
|
688
|
-
if (
|
|
688
|
+
if (v && h(v, y)) return b.emit("cache", {
|
|
689
689
|
kind: "STALE",
|
|
690
|
-
key:
|
|
691
|
-
ageMs:
|
|
690
|
+
key: _,
|
|
691
|
+
ageMs: y - v.renderedAt
|
|
692
692
|
}), (async () => {
|
|
693
693
|
try {
|
|
694
|
-
let
|
|
694
|
+
let r = await we({
|
|
695
695
|
provider: q,
|
|
696
696
|
root: i,
|
|
697
697
|
route: d.route,
|
|
698
698
|
params: d.params,
|
|
699
|
-
pathname:
|
|
699
|
+
pathname: n,
|
|
700
700
|
dirs: U,
|
|
701
|
-
shellTemplate:
|
|
701
|
+
shellTemplate: I,
|
|
702
702
|
requestHeaders: t,
|
|
703
|
-
apiOrigin:
|
|
704
|
-
apiName:
|
|
703
|
+
apiOrigin: de,
|
|
704
|
+
apiName: fe,
|
|
705
705
|
requestUrl: e,
|
|
706
706
|
buffered: !0
|
|
707
707
|
});
|
|
708
|
-
if (
|
|
708
|
+
if (r && "html" in r && r.renderMode === "isr" && r.revalidateMs !== null) {
|
|
709
709
|
let e = J.get(d.route.pattern)?.staleWhileRevalidateMs ?? 0, t = Date.now();
|
|
710
|
-
z.set(
|
|
711
|
-
html:
|
|
710
|
+
z.set(_, {
|
|
711
|
+
html: r.html,
|
|
712
712
|
renderedAt: t,
|
|
713
|
-
expiresAt: t +
|
|
714
|
-
servableUntil: t +
|
|
715
|
-
revalidateMs:
|
|
713
|
+
expiresAt: t + r.revalidateMs,
|
|
714
|
+
servableUntil: t + r.revalidateMs + e,
|
|
715
|
+
revalidateMs: r.revalidateMs,
|
|
716
716
|
staleWhileRevalidateMs: e
|
|
717
717
|
});
|
|
718
718
|
}
|
|
719
719
|
} catch (e) {
|
|
720
|
-
K.warn("background SWR refresh failed", { url:
|
|
720
|
+
K.warn("background SWR refresh failed", { url: n }, e);
|
|
721
721
|
}
|
|
722
722
|
})(), {
|
|
723
723
|
status: 200,
|
|
@@ -725,43 +725,43 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
725
725
|
"content-type": "text/html; charset=utf-8",
|
|
726
726
|
"x-voltro-rendered-by": "isr",
|
|
727
727
|
"x-voltro-cache": "STALE",
|
|
728
|
-
"x-voltro-cache-key":
|
|
729
|
-
"x-voltro-cache-age-ms": String(
|
|
728
|
+
"x-voltro-cache-key": _,
|
|
729
|
+
"x-voltro-cache-age-ms": String(y - v.renderedAt)
|
|
730
730
|
},
|
|
731
|
-
body:
|
|
731
|
+
body: v.html
|
|
732
732
|
};
|
|
733
733
|
try {
|
|
734
|
-
let
|
|
734
|
+
let r = await we({
|
|
735
735
|
provider: q,
|
|
736
736
|
root: i,
|
|
737
737
|
route: d.route,
|
|
738
738
|
params: d.params,
|
|
739
|
-
pathname:
|
|
739
|
+
pathname: n,
|
|
740
740
|
dirs: U,
|
|
741
|
-
shellTemplate:
|
|
741
|
+
shellTemplate: I,
|
|
742
742
|
requestHeaders: t,
|
|
743
|
-
apiOrigin:
|
|
744
|
-
apiName:
|
|
743
|
+
apiOrigin: de,
|
|
744
|
+
apiName: fe,
|
|
745
745
|
requestUrl: e
|
|
746
746
|
});
|
|
747
|
-
if (!
|
|
747
|
+
if (!r) return {
|
|
748
748
|
status: 200,
|
|
749
749
|
headers: {
|
|
750
750
|
"content-type": "text/html; charset=utf-8",
|
|
751
751
|
"x-voltro-rendered-by": "spa-fallback"
|
|
752
752
|
},
|
|
753
|
-
body:
|
|
753
|
+
body: I
|
|
754
754
|
};
|
|
755
|
-
if ("stream" in
|
|
755
|
+
if ("stream" in r) return {
|
|
756
756
|
status: 200,
|
|
757
|
-
headers: { "x-voltro-rendered-by":
|
|
757
|
+
headers: { "x-voltro-rendered-by": r.renderMode },
|
|
758
758
|
body: "",
|
|
759
|
-
stream:
|
|
759
|
+
stream: r.stream
|
|
760
760
|
};
|
|
761
|
-
if ("control" in
|
|
762
|
-
status:
|
|
761
|
+
if ("control" in r) return r.control === "redirect" ? {
|
|
762
|
+
status: r.status,
|
|
763
763
|
headers: {
|
|
764
|
-
location:
|
|
764
|
+
location: r.location,
|
|
765
765
|
"x-voltro-rendered-by": "loader-redirect"
|
|
766
766
|
},
|
|
767
767
|
body: ""
|
|
@@ -775,34 +775,34 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
775
775
|
};
|
|
776
776
|
let a = {
|
|
777
777
|
"content-type": "text/html; charset=utf-8",
|
|
778
|
-
"x-voltro-rendered-by":
|
|
778
|
+
"x-voltro-rendered-by": r.renderMode
|
|
779
779
|
};
|
|
780
|
-
if (
|
|
780
|
+
if (r.renderMode === "isr" && r.revalidateMs !== null) {
|
|
781
781
|
let e = Date.now(), t = J.get(d.route.pattern)?.staleWhileRevalidateMs ?? 0;
|
|
782
|
-
z.set(
|
|
783
|
-
html:
|
|
782
|
+
z.set(_, {
|
|
783
|
+
html: r.html,
|
|
784
784
|
renderedAt: e,
|
|
785
|
-
expiresAt: e +
|
|
786
|
-
servableUntil: e +
|
|
787
|
-
revalidateMs:
|
|
785
|
+
expiresAt: e + r.revalidateMs,
|
|
786
|
+
servableUntil: e + r.revalidateMs + t,
|
|
787
|
+
revalidateMs: r.revalidateMs,
|
|
788
788
|
staleWhileRevalidateMs: t
|
|
789
|
-
}), a["x-voltro-cache"] = "MISS", a["x-voltro-cache-key"] =
|
|
789
|
+
}), a["x-voltro-cache"] = "MISS", a["x-voltro-cache-key"] = _, a["x-voltro-cache-revalidate-ms"] = String(r.revalidateMs), t > 0 && (a["x-voltro-cache-swr-ms"] = String(t)), b.emit("cache", {
|
|
790
790
|
kind: "MISS",
|
|
791
|
-
key:
|
|
792
|
-
revalidateMs:
|
|
791
|
+
key: _,
|
|
792
|
+
revalidateMs: r.revalidateMs,
|
|
793
793
|
swrMs: t
|
|
794
794
|
});
|
|
795
|
-
} else
|
|
795
|
+
} else r.renderMode === "isr" && (a["x-voltro-cache"] = "BYPASS", b.emit("cache", {
|
|
796
796
|
kind: "BYPASS",
|
|
797
|
-
key:
|
|
797
|
+
key: _
|
|
798
798
|
}));
|
|
799
799
|
return {
|
|
800
800
|
status: 200,
|
|
801
801
|
headers: a,
|
|
802
|
-
body:
|
|
802
|
+
body: r.html
|
|
803
803
|
};
|
|
804
804
|
} catch (e) {
|
|
805
|
-
return K.error("render error", { url:
|
|
805
|
+
return K.error("render error", { url: n }, e), w(e) ? {
|
|
806
806
|
status: 500,
|
|
807
807
|
headers: {
|
|
808
808
|
"content-type": "text/plain; charset=utf-8",
|
|
@@ -815,51 +815,55 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
815
815
|
body: "server error"
|
|
816
816
|
};
|
|
817
817
|
}
|
|
818
|
-
},
|
|
818
|
+
}, Fe = !1, Ie = he(async (e, t) => {
|
|
819
819
|
let n = e.url ?? "/", r = Date.now(), i = {};
|
|
820
820
|
for (let [t, n] of Object.entries(e.headers)) n !== void 0 && (i[t.toLowerCase()] = Array.isArray(n) ? n.join(", ") : n);
|
|
821
|
-
let
|
|
822
|
-
if (
|
|
821
|
+
let a = n.split("?")[0] ?? "/", o = (e.method ?? "GET").toUpperCase();
|
|
822
|
+
if (a === "/internal/liveness") {
|
|
823
823
|
t.writeHead(200, {
|
|
824
824
|
"content-type": "text/plain",
|
|
825
825
|
"cache-control": "no-store"
|
|
826
826
|
}), t.end("ok");
|
|
827
827
|
return;
|
|
828
828
|
}
|
|
829
|
-
if (
|
|
830
|
-
let e =
|
|
829
|
+
if (a === "/internal/readiness") {
|
|
830
|
+
let e = Fe ? 200 : 503;
|
|
831
831
|
t.writeHead(e, {
|
|
832
832
|
"content-type": "text/plain",
|
|
833
833
|
"cache-control": "no-store"
|
|
834
|
-
}), t.end(
|
|
834
|
+
}), t.end(Fe ? "ready" : "not-ready");
|
|
835
835
|
return;
|
|
836
836
|
}
|
|
837
|
-
if (
|
|
838
|
-
let e =
|
|
837
|
+
if (o === "OPTIONS" && a.startsWith("/_voltro/inspect")) {
|
|
838
|
+
let e = T(i.origin);
|
|
839
839
|
t.writeHead(204, e), t.end();
|
|
840
840
|
return;
|
|
841
841
|
}
|
|
842
|
-
if (
|
|
842
|
+
if (u.name === "voltroDashboard" && a === "/api/dashboard/proxy") {
|
|
843
843
|
let r = new URL(n, "http://x").searchParams.get("target");
|
|
844
844
|
if (!r) {
|
|
845
845
|
t.writeHead(400, { "content-type": "text/plain" }), t.end("missing ?target=");
|
|
846
846
|
return;
|
|
847
847
|
}
|
|
848
|
+
if (!N(r)) {
|
|
849
|
+
t.writeHead(400, { "content-type": "text/plain" }), t.end("target must be a loopback address");
|
|
850
|
+
return;
|
|
851
|
+
}
|
|
848
852
|
try {
|
|
849
853
|
let n = { accept: i.accept ?? "application/json" }, a = i.authorization;
|
|
850
854
|
a && (n.authorization = Array.isArray(a) ? a[0] : a);
|
|
851
|
-
let
|
|
852
|
-
if (
|
|
855
|
+
let s;
|
|
856
|
+
if (o && o !== "GET" && o !== "HEAD") {
|
|
853
857
|
let t = [];
|
|
854
858
|
for await (let n of e) t.push(n);
|
|
855
|
-
|
|
859
|
+
s = Buffer.concat(t);
|
|
856
860
|
let r = i["content-type"];
|
|
857
861
|
r && (n["content-type"] = Array.isArray(r) ? r[0] : r);
|
|
858
862
|
}
|
|
859
863
|
let c = await fetch(r, {
|
|
860
|
-
method:
|
|
864
|
+
method: o,
|
|
861
865
|
headers: n,
|
|
862
|
-
...
|
|
866
|
+
...s ? { body: new Uint8Array(s.buffer, s.byteOffset, s.byteLength) } : {}
|
|
863
867
|
}), l = Buffer.from(await c.arrayBuffer());
|
|
864
868
|
t.writeHead(c.status, {
|
|
865
869
|
"content-type": c.headers.get("content-type") ?? "application/octet-stream",
|
|
@@ -870,12 +874,16 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
870
874
|
}
|
|
871
875
|
return;
|
|
872
876
|
}
|
|
873
|
-
if (
|
|
877
|
+
if (u.name === "voltroDashboard" && a === "/api/dashboard/proxy/stream") {
|
|
874
878
|
let r = new URL(n, "http://x").searchParams.get("target");
|
|
875
879
|
if (!r) {
|
|
876
880
|
t.writeHead(400, { "content-type": "text/plain" }), t.end("missing ?target=");
|
|
877
881
|
return;
|
|
878
882
|
}
|
|
883
|
+
if (!N(r)) {
|
|
884
|
+
t.writeHead(400, { "content-type": "text/plain" }), t.end("target must be a loopback address");
|
|
885
|
+
return;
|
|
886
|
+
}
|
|
879
887
|
let a = new AbortController();
|
|
880
888
|
e.on("close", () => a.abort()), t.on("close", () => a.abort());
|
|
881
889
|
try {
|
|
@@ -912,8 +920,8 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
912
920
|
}
|
|
913
921
|
return;
|
|
914
922
|
}
|
|
915
|
-
if (
|
|
916
|
-
let n =
|
|
923
|
+
if (a === "/_voltro/inspect/stream") {
|
|
924
|
+
let n = T(i.origin);
|
|
917
925
|
if (te()) {
|
|
918
926
|
t.writeHead(503, {
|
|
919
927
|
"content-type": "application/json",
|
|
@@ -921,7 +929,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
921
929
|
}), t.end(JSON.stringify({ error: "inspect disabled (VOLTRO_INSPECT=off)" }));
|
|
922
930
|
return;
|
|
923
931
|
}
|
|
924
|
-
let r =
|
|
932
|
+
let r = y(i);
|
|
925
933
|
if (!r.ok) {
|
|
926
934
|
t.writeHead(401, {
|
|
927
935
|
"content-type": "application/json",
|
|
@@ -939,30 +947,30 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
939
947
|
"x-accel-buffering": "no",
|
|
940
948
|
...n
|
|
941
949
|
}), t.flushHeaders(), t.write("retry: 5000\n\n");
|
|
942
|
-
for (let e of
|
|
943
|
-
let
|
|
944
|
-
t.write(
|
|
945
|
-
}),
|
|
946
|
-
t.write(
|
|
950
|
+
for (let e of b.buffered()) t.write(g(e));
|
|
951
|
+
let a = b.subscribe((e) => {
|
|
952
|
+
t.write(g(e));
|
|
953
|
+
}), o = setInterval(() => {
|
|
954
|
+
t.write(s());
|
|
947
955
|
}, 15e3), c = () => {
|
|
948
|
-
clearInterval(
|
|
956
|
+
clearInterval(o), a();
|
|
949
957
|
};
|
|
950
958
|
e.on("close", c), t.on("close", c);
|
|
951
959
|
return;
|
|
952
960
|
}
|
|
953
961
|
try {
|
|
954
|
-
let e = await
|
|
955
|
-
if (e.stream ? e.stream(t) : (t.writeHead(e.status, e.headers), t.end(e.body)), !
|
|
962
|
+
let e = await Pe(n, i);
|
|
963
|
+
if (e.stream ? e.stream(t) : (t.writeHead(e.status, e.headers), t.end(e.body)), !a.startsWith("/_voltro/inspect")) {
|
|
956
964
|
let t = Date.now() - r;
|
|
957
|
-
|
|
958
|
-
url:
|
|
965
|
+
b.emit("request", {
|
|
966
|
+
url: a,
|
|
959
967
|
status: e.status,
|
|
960
968
|
durationMs: t,
|
|
961
969
|
renderedBy: e.headers["x-voltro-rendered-by"],
|
|
962
970
|
cache: e.headers["x-voltro-cache"]
|
|
963
971
|
});
|
|
964
|
-
let n =
|
|
965
|
-
|
|
972
|
+
let n = Ce(a, W)?.route.pattern ?? (e.status === 404 ? "<unmatched>" : "<asset>");
|
|
973
|
+
ke.record({
|
|
966
974
|
kind: "request",
|
|
967
975
|
tag: n,
|
|
968
976
|
durationMs: t,
|
|
@@ -973,71 +981,71 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
973
981
|
t.writeHead(500, { "content-type": "text/plain" }), t.end(`internal error: ${e.message}`);
|
|
974
982
|
}
|
|
975
983
|
});
|
|
976
|
-
await new Promise((e) =>
|
|
984
|
+
await new Promise((e) => Ie.listen(x, "::", e)), Fe = !0, l.mark("ready"), K.info(`listening on http://localhost:${x}`, {
|
|
977
985
|
port: x,
|
|
978
|
-
distDir:
|
|
986
|
+
distDir: D
|
|
979
987
|
}), K.debug("dynamic + ssr/isr routes resolve via SSR loader");
|
|
980
988
|
try {
|
|
981
|
-
await
|
|
982
|
-
id:
|
|
983
|
-
name:
|
|
989
|
+
await O({
|
|
990
|
+
id: M,
|
|
991
|
+
name: j,
|
|
984
992
|
kind: "web",
|
|
985
993
|
url: `http://localhost:${x}`,
|
|
986
994
|
pid: process.pid,
|
|
987
995
|
status: "live",
|
|
988
|
-
logFile:
|
|
996
|
+
logFile: F.path
|
|
989
997
|
});
|
|
990
|
-
let e =
|
|
998
|
+
let e = P(i);
|
|
991
999
|
if (e) {
|
|
992
|
-
let
|
|
993
|
-
|
|
1000
|
+
let t = await n({ dashboardAppPath: e });
|
|
1001
|
+
t.status === "launched" ? K.info(`dashboard launched at http://localhost:${t.port}`, { port: t.port }) : t.status === "already-running" && K.debug(`dashboard already running on :${t.port}`, { port: t.port });
|
|
994
1002
|
}
|
|
995
1003
|
setInterval(() => {
|
|
996
|
-
|
|
997
|
-
id:
|
|
998
|
-
name:
|
|
1004
|
+
O({
|
|
1005
|
+
id: M,
|
|
1006
|
+
name: j,
|
|
999
1007
|
kind: "web",
|
|
1000
1008
|
url: `http://localhost:${x}`,
|
|
1001
1009
|
pid: process.pid,
|
|
1002
1010
|
status: "live",
|
|
1003
|
-
logFile:
|
|
1011
|
+
logFile: F.path
|
|
1004
1012
|
}).catch(() => {});
|
|
1005
1013
|
}, 1e4).unref();
|
|
1006
1014
|
} catch (e) {
|
|
1007
1015
|
K.warn("runtime-registry write failed", {}, e);
|
|
1008
1016
|
}
|
|
1009
|
-
|
|
1010
|
-
app:
|
|
1017
|
+
pe({
|
|
1018
|
+
app: u.name ?? "unnamed",
|
|
1011
1019
|
kind: "web",
|
|
1012
1020
|
url: `http://localhost:${x}`,
|
|
1013
|
-
bootMs:
|
|
1021
|
+
bootMs: l.total()
|
|
1014
1022
|
});
|
|
1015
|
-
let
|
|
1016
|
-
K.info(`start: ready in ${
|
|
1017
|
-
bootMs:
|
|
1018
|
-
...
|
|
1023
|
+
let Le = l.phaseBreakdown();
|
|
1024
|
+
K.info(`start: ready in ${l.total()}ms`, {
|
|
1025
|
+
bootMs: l.total(),
|
|
1026
|
+
...Le ? { phases: Le } : {}
|
|
1019
1027
|
});
|
|
1020
|
-
let
|
|
1021
|
-
if (!
|
|
1022
|
-
if (
|
|
1028
|
+
let Re = !1, $ = (t) => async () => {
|
|
1029
|
+
if (!Re) {
|
|
1030
|
+
if (Re = !0, K.info(`received ${t}, shutting down`, { signal: t }), Ie.close(), await Oe.stop(), V) try {
|
|
1023
1031
|
await V.end();
|
|
1024
1032
|
} catch {}
|
|
1025
|
-
await q.close(), await e(
|
|
1033
|
+
await q.close(), await e(M), await F.dispose(), process.exit(0);
|
|
1026
1034
|
}
|
|
1027
1035
|
};
|
|
1028
1036
|
process.on("SIGINT", $("SIGINT")), process.on("SIGTERM", $("SIGTERM"));
|
|
1029
|
-
let
|
|
1030
|
-
if (
|
|
1037
|
+
let ze = process.ppid;
|
|
1038
|
+
if (ze > 1) {
|
|
1031
1039
|
let e = setInterval(() => {
|
|
1032
|
-
(process.ppid !==
|
|
1040
|
+
(process.ppid !== ze || process.ppid === 1) && (clearInterval(e), $("SIGTERM")());
|
|
1033
1041
|
}, 2e3);
|
|
1034
1042
|
e.unref();
|
|
1035
1043
|
}
|
|
1036
1044
|
return new Promise(() => {});
|
|
1037
|
-
},
|
|
1045
|
+
}, Oe = async (e) => {
|
|
1038
1046
|
process.env.NODE_ENV || (process.env.NODE_ENV = "production");
|
|
1039
|
-
let t = await
|
|
1047
|
+
let t = await De(R(e.find((e) => !e.startsWith("-")) ?? process.cwd()));
|
|
1040
1048
|
return t.ran ? t.exitCode : (K.error("no web app found at this path"), 1);
|
|
1041
1049
|
};
|
|
1042
1050
|
//#endregion
|
|
1043
|
-
export {
|
|
1051
|
+
export { Oe as t };
|