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