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