@voltro/cli 0.57.0 → 0.59.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +256 -0
- package/dist/apiBuild-B9OvhITV.js +2 -0
- package/dist/{apiBuild-DDr2aNFd.js → apiBuild-BU5cd-Fn.js} +52 -50
- package/dist/bin.js +1 -1
- package/dist/build-uRMZrT8z.js +1066 -0
- package/dist/{checkCommand-BISqx1OJ.js → checkCommand-C1CQc8lD.js} +1 -1
- package/dist/{checkCommand-DUtMWjcR.js → checkCommand-DC7k1_hP.js} +3 -3
- package/dist/{codegenCommand-DnVuDxwT.js → codegenCommand-kS3Twuc9.js} +7 -7
- package/dist/{codemodRunner-BlQPfjzA.js → codemodRunner-kNnh1I7_.js} +1227 -911
- package/dist/{commands-CRbxgxv0.js → commands-cu34ENUT.js} +21 -21
- package/dist/{dashboardCommand-Bf_-Ne3P.js → dashboardCommand-gG1y4PFG.js} +5 -5
- package/dist/{dataCommand-BoBJJ-Gb.js → dataCommand-hNOGKz4K.js} +6 -6
- package/dist/{dev-DOEJXicj.js → dev-Ce2gEziv.js} +2422 -2419
- package/dist/dev-Dff_pdik.js +3 -0
- package/dist/{doctorCommand-BrWu67JZ.js → doctorCommand-CGjefPmk.js} +505 -284
- package/dist/doctorCommand-DXnNpKQT.js +2 -0
- package/dist/{dormancyCommand-xn2y-pJm.js → dormancyCommand-DYgI0Kf-.js} +3 -3
- package/dist/{embeddingsCommand-Cn5MbRDM.js → embeddingsCommand-yJivQSrI.js} +2 -2
- package/dist/{envCommand-UJmJIbs9.js → envCommand-ORJUf8r_.js} +8 -8
- package/dist/{evolveCommand-Db30twUy.js → evolveCommand-8CuFBlbQ.js} +2 -2
- package/dist/index.js +1 -1
- package/dist/{infoCommand-BjVXpMlP.js → infoCommand-D02A4WI2.js} +1 -1
- package/dist/inspect-CZvsmp8t.js +2 -0
- package/dist/{inspect-DZnan87F.js → inspect-PcC5J-Dl.js} +6 -7
- package/dist/manifestBuild-AUh31bFU.js +2 -0
- package/dist/{manifestBuild-DnbFKF6w.js → manifestBuild-BwiS4iYm.js} +1 -1
- package/dist/{probeCommand-C5fuN6Z2.js → probeCommand-BUYzc0CT.js} +1 -1
- package/dist/{runtimeTrace-BQL_lfz6.js → runtimeTrace-DDuKJgVi.js} +1 -1
- package/dist/{sdkgen-CMUPrDjH.js → sdkgen-vq1fF9D_.js} +1 -1
- package/dist/serveCommand-1R52mo6F.js +2 -0
- package/dist/{serveCommand-B_w-Mpb_.js → serveCommand-Dr4KXmTS.js} +726 -725
- package/dist/serveEntry.js +1 -1
- package/dist/{start-s25GAIgn.js → start-C75w6ftA.js} +1 -1
- package/dist/{start-YaUehtDV.js → start-DNtIlBcn.js} +641 -609
- package/dist/startEntry.js +1 -1
- package/dist/{updateCommand-C9n_Z_oG.js → updateCommand-Bw3mCUDT.js} +1 -1
- package/dist/updateCommand-inInBIAh.js +2 -0
- package/dist/webDev-Bzb8ZFus.js +2 -0
- package/dist/{webDev-BgdkyjP6.js → webDev-CBN9KkyQ.js} +154 -146
- package/dist/{webhooksCommand-CYXTNvXq.js → webhooksCommand-BPJQOGTe.js} +1 -1
- package/package.json +73 -19
- package/templates/AGENTS.md +1 -1
- package/templates/agent-docs/_index.md +1 -1
- package/templates/agent-docs/_manifest.json +1 -1
- package/templates/agent-docs/ai.md +223 -0
- package/templates/agent-docs/authentication.md +34 -0
- package/templates/agent-docs/cli.md +7 -6
- package/templates/agent-docs/data.md +30 -0
- package/templates/agent-docs/database/transactions.md +48 -0
- package/templates/agent-docs/observability.md +13 -2
- package/templates/agent-docs/plugins/auth-supabase.md +21 -0
- package/templates/agent-docs/plugins/sentry.md +131 -9
- package/templates/agent-docs/schema-driven-ui.md +29 -0
- package/templates/agent-docs/whats-new.md +26 -165
- package/templates/apps/api-ai/package.json +6 -6
- 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 +9 -9
- 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-row-history/package.json +8 -8
- 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-webhooks/package.json +9 -9
- package/templates/apps/changelog/package.json +7 -7
- package/templates/apps/edge-functions/package.json +2 -2
- package/templates/apps/frontend-admin/package.json +7 -7
- package/templates/apps/frontend-app/package.json +8 -8
- package/templates/apps/frontend-auth/package.json +7 -7
- package/templates/apps/frontend-blank/package.json +6 -6
- package/templates/apps/frontend-cms/package.json +8 -8
- 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 +6 -6
- package/templates/apps/frontend-docs/package.json +8 -8
- 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 +7 -7
- package/templates/apps/frontend-saas/package.json +7 -7
- package/templates/apps/frontend-spa/package.json +6 -6
- package/templates/apps/frontend-ssr/package.json +6 -6
- package/templates/apps/frontend-ssr-api/package.json +7 -7
- package/templates/apps/frontend-static-blog/package.json +8 -8
- package/templates/apps/frontend-status/package.json +7 -7
- package/templates/apps/mobile-app/package.json +4 -4
- package/dist/apiBuild-B83Cb2Rv.js +0 -2
- package/dist/build-QKP6Bm0J.js +0 -872
- package/dist/dev-Bl9HqtV7.js +0 -3
- package/dist/doctorCommand-DrQv9SL3.js +0 -2
- package/dist/inspect-B0hL41s0.js +0 -2
- package/dist/manifestBuild-UXrnUcXP.js +0 -2
- package/dist/serveCommand-Dtb48ffg.js +0 -2
- package/dist/updateCommand-DsXEAHbd.js +0 -2
- package/dist/webDev-B6ZMX42w.js +0 -2
|
@@ -0,0 +1,1066 @@
|
|
|
1
|
+
import { An as e } from "./dev-Ce2gEziv.js";
|
|
2
|
+
import { At as t, Ct as n, D as r, Dt as i, Et as a, J as o, K as s, Mt as c, Nt as l, Ot as u, Qt as d, St as f, T as p, Tt as m, Yt as h, _t as g, c as _, et as v, gt as y, h as b, kt as x, m as S, nt as C, o as w, q as T, tt as E, u as D, vt as ee, w as te, wt as O, zt as k } from "./webDev-CBN9KkyQ.js";
|
|
3
|
+
import { d as A, i as j, o as M, s as N } from "./apiBuild-BU5cd-Fn.js";
|
|
4
|
+
import { t as P } from "./cliRuntime-Dh7UDinH.js";
|
|
5
|
+
import { a as F } from "./renderModeScan-43yQ2opo.js";
|
|
6
|
+
import { o as I } from "./imagePipeline-CBZmjT4i.js";
|
|
7
|
+
import { a as L } from "./fontPipeline-Tsh8kZfA.js";
|
|
8
|
+
import { n as ne } from "./renderProfile-DvrhVJHa.js";
|
|
9
|
+
import { dirname as R, join as z, resolve as B } from "node:path";
|
|
10
|
+
import { existsSync as V, promises as H } from "node:fs";
|
|
11
|
+
import { pathToFileURL as U } from "node:url";
|
|
12
|
+
import { createLogger as W } from "@voltro/logger";
|
|
13
|
+
import { setProcessBootPath as G } from "@voltro/protocol/identity";
|
|
14
|
+
import { Effect as K } from "effect";
|
|
15
|
+
import { createRequire as q } from "node:module";
|
|
16
|
+
import { readdir as J, rm as Y, stat as re } from "node:fs/promises";
|
|
17
|
+
//#region src/webStartBundle.ts
|
|
18
|
+
var X = W({ scope: "voltro:build" }), ie = async (e, t = {}) => {
|
|
19
|
+
let n = await d("esbuild", () => import("esbuild")), r = z(e, ".framework"), i = z(r, "dist-web", "startBundle");
|
|
20
|
+
await H.mkdir(r, { recursive: !0 });
|
|
21
|
+
let a = Date.now(), o = z(e, "tsconfig.json"), s = /* @__PURE__ */ new Set(), c = z(r, "startEntry.ts");
|
|
22
|
+
await H.writeFile(c, [
|
|
23
|
+
"// GENERATED BY `voltro build` — do not edit; overwritten on next build.",
|
|
24
|
+
"import { runStartCommand as __run, loadDotEnv } from '@voltro/cli/startEntry'",
|
|
25
|
+
"import { pathToFileURL, fileURLToPath } from 'node:url'",
|
|
26
|
+
"import { dirname, resolve } from 'node:path'",
|
|
27
|
+
"export const runStartCommand = (args = []) => { loadDotEnv([]); return __run(args) }",
|
|
28
|
+
"export { loadDotEnv }",
|
|
29
|
+
"",
|
|
30
|
+
"// DIRECT-INVOKE ENTRY. `node startEntry.js` is the PRODUCTION container command",
|
|
31
|
+
"// — no `pnpm voltro start` wrapper, so the container never resolves the @voltro/cli",
|
|
32
|
+
"// bin and `voltro prune-runtime` can drop the CLI (and the whole inlined",
|
|
33
|
+
"// effect/@voltro/react tree) from the runtime image: the trace roots at THIS",
|
|
34
|
+
"// self-contained bundle, which is now also the real entrypoint. When this module",
|
|
35
|
+
"// is IMPORTED instead (bin/voltro.mjs's dev fast path) the guard is inert.",
|
|
36
|
+
"if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {",
|
|
37
|
+
" // Relocation-safe: the app root is 3 dirs up from",
|
|
38
|
+
" // .framework/dist-web/startBundle/startEntry.js — chdir there so tryRunStart",
|
|
39
|
+
" // resolves the SSR bundle + appConfig from cwd regardless of the launch dir",
|
|
40
|
+
" // (WORKDIR already sets it in our image; this makes it robust anywhere).",
|
|
41
|
+
" process.chdir(resolve(dirname(fileURLToPath(import.meta.url)), '..', '..', '..'))",
|
|
42
|
+
" runStartCommand(process.argv.slice(2)).then((c) => process.exit(typeof c === 'number' ? c : 0))",
|
|
43
|
+
"}",
|
|
44
|
+
""
|
|
45
|
+
].join("\n"), "utf8"), await n.build({
|
|
46
|
+
entryPoints: [c],
|
|
47
|
+
bundle: !0,
|
|
48
|
+
format: "esm",
|
|
49
|
+
platform: "node",
|
|
50
|
+
target: "node22",
|
|
51
|
+
outdir: i,
|
|
52
|
+
splitting: !0,
|
|
53
|
+
write: !0,
|
|
54
|
+
minify: !0,
|
|
55
|
+
keepNames: !0,
|
|
56
|
+
sourcemap: t.sourcemaps === !0 && "external",
|
|
57
|
+
plugins: [M([], e, s)],
|
|
58
|
+
banner: { js: A() },
|
|
59
|
+
jsx: "automatic",
|
|
60
|
+
jsxImportSource: "react",
|
|
61
|
+
logLevel: "silent",
|
|
62
|
+
absWorkingDir: e,
|
|
63
|
+
alias: j("startEntry"),
|
|
64
|
+
...V(o) ? { tsconfig: o } : {}
|
|
65
|
+
});
|
|
66
|
+
let l = await N(i, a);
|
|
67
|
+
return X.info("web build: start bundle written", {
|
|
68
|
+
out: z(".framework", "dist-web", "startBundle", "startEntry.js"),
|
|
69
|
+
...s.size > 0 ? { externalizedOptionalPeers: [...s].join(", ") } : {},
|
|
70
|
+
...l > 0 ? { prunedStaleChunks: l } : {}
|
|
71
|
+
}), z(i, "startEntry.js");
|
|
72
|
+
}, ae = "~/assets", oe = (e, t) => {
|
|
73
|
+
if (e === void 0) return {
|
|
74
|
+
emit: !1,
|
|
75
|
+
keep: !1
|
|
76
|
+
};
|
|
77
|
+
if (e === "hidden") return {
|
|
78
|
+
emit: !0,
|
|
79
|
+
keep: !0
|
|
80
|
+
};
|
|
81
|
+
if (e.upload === void 0) return {
|
|
82
|
+
emit: !0,
|
|
83
|
+
keep: e.keep ?? !0
|
|
84
|
+
};
|
|
85
|
+
let { org: n, project: r, url: i, urlPrefix: a } = e.upload, o = e.upload.release ?? t.SENTRY_RELEASE;
|
|
86
|
+
if (o === void 0 || o === "") return { problem: "sourcemaps.upload is configured but no release is known. Sentry matches an uploaded artifact to an event by RELEASE, so an upload without one resolves no frame — and says nothing, because an upload that matched nothing looks exactly like one that worked.\n → set SENTRY_RELEASE for the build (the same value `sentryPlugin` reports events under), or pass `release` explicitly." };
|
|
87
|
+
let s = t.SENTRY_AUTH_TOKEN;
|
|
88
|
+
return s === void 0 || s === "" ? { problem: "sourcemaps.upload is configured but SENTRY_AUTH_TOKEN is not set.\n It is read from the environment and is deliberately NOT a config field: `app.config.ts` is committed, and a token with `project:releases` scope can write to every project in the org.\n → provide it to the BUILD (a CI secret / a Docker build secret), not to the deployment — the upload happens while the bundle is being built." } : {
|
|
89
|
+
emit: !0,
|
|
90
|
+
keep: e.keep ?? !1,
|
|
91
|
+
upload: {
|
|
92
|
+
org: n,
|
|
93
|
+
project: r,
|
|
94
|
+
release: o,
|
|
95
|
+
authToken: s,
|
|
96
|
+
...a === void 0 ? {} : { urlPrefix: a },
|
|
97
|
+
...i === void 0 ? {} : { url: i }
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
}, se = (e) => "problem" in e, Z = async (e) => {
|
|
101
|
+
let t = [], n = async (e) => {
|
|
102
|
+
let r;
|
|
103
|
+
try {
|
|
104
|
+
r = await J(e);
|
|
105
|
+
} catch {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
for (let i of r) {
|
|
109
|
+
let r = z(e, i), a = await re(r).catch(() => void 0);
|
|
110
|
+
a !== void 0 && (a.isDirectory() ? await n(r) : i.endsWith(".map") && t.push(r));
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
return await n(e), t.sort();
|
|
114
|
+
}, Q = (e, t) => {
|
|
115
|
+
let n = /* @__PURE__ */ new Map();
|
|
116
|
+
for (let r of e) {
|
|
117
|
+
let e = t ?? r.urlPrefix;
|
|
118
|
+
n.set(e, [...n.get(e) ?? [], r.dir]);
|
|
119
|
+
}
|
|
120
|
+
return [...n];
|
|
121
|
+
}, ce = (e) => async (t, n, r) => {
|
|
122
|
+
let i = new (await (ue(e)))(null, {
|
|
123
|
+
authToken: t.authToken,
|
|
124
|
+
org: t.org,
|
|
125
|
+
project: t.project,
|
|
126
|
+
...t.url === void 0 ? {} : { url: t.url },
|
|
127
|
+
silent: !1
|
|
128
|
+
});
|
|
129
|
+
await i.releases.new(t.release);
|
|
130
|
+
for (let [e, n] of Q(r, t.urlPrefix)) await i.releases.uploadSourceMaps(t.release, {
|
|
131
|
+
include: n,
|
|
132
|
+
urlPrefix: e,
|
|
133
|
+
rewrite: !0
|
|
134
|
+
});
|
|
135
|
+
await i.releases.finalize(t.release);
|
|
136
|
+
}, le = (e) => {
|
|
137
|
+
let t = e, n = [
|
|
138
|
+
t?.SentryCli,
|
|
139
|
+
t?.default?.SentryCli,
|
|
140
|
+
t?.default,
|
|
141
|
+
e
|
|
142
|
+
];
|
|
143
|
+
for (let e of n) if (typeof e == "function") return e;
|
|
144
|
+
}, ue = async (e) => {
|
|
145
|
+
let t = q(z(e, "package.json")), n = !1, r = [];
|
|
146
|
+
try {
|
|
147
|
+
let e = t.resolve("@sentry/cli");
|
|
148
|
+
n = !0;
|
|
149
|
+
let i = await import(U(e).href), a = le(i);
|
|
150
|
+
if (a !== void 0) return a;
|
|
151
|
+
r.push(`loaded ${e} but found no SentryCli constructor on it (keys: ${Object.keys(i).join(", ") || "none"})`);
|
|
152
|
+
} catch (e) {
|
|
153
|
+
r.push(e instanceof Error ? e.message : String(e));
|
|
154
|
+
}
|
|
155
|
+
throw Error((n ? "sourcemaps.upload is configured and `@sentry/cli` IS installed, but no constructor could be read from it.\n That is a module shape we do not recognise, not a missing install — the loader accepts both the 2.x (`module.exports =`) and 3.x (`exports.SentryCli =`) forms. Please report the version.\n" : "sourcemaps.upload is configured but `@sentry/cli` could not be resolved.\n The framework does not ship it: its licence (FSL-1.1-MIT) restricts commercial use, so it is yours to install rather than ours to depend on.\n → `pnpm add -D @sentry/cli` in the app being built.\n") + r.map((e) => ` · ${e}`).join("\n"));
|
|
156
|
+
}, de = async (e, t, n = {}) => {
|
|
157
|
+
if (!t.emit) return {
|
|
158
|
+
uploaded: 0,
|
|
159
|
+
deleted: 0
|
|
160
|
+
};
|
|
161
|
+
let r = (await Promise.all(e.map((e) => Z(e.dir)))).flat(), i = 0;
|
|
162
|
+
try {
|
|
163
|
+
t.upload !== void 0 && r.length > 0 && (await (n.upload ?? ce(n.appRoot ?? e[0]?.dir ?? "."))(t.upload, r, e), i = r.length, n.log?.info("source maps uploaded to Sentry", {
|
|
164
|
+
release: t.upload.release,
|
|
165
|
+
files: r.length,
|
|
166
|
+
dirs: e.length
|
|
167
|
+
}));
|
|
168
|
+
} finally {
|
|
169
|
+
if (!t.keep) {
|
|
170
|
+
for (let e of r) await Y(e, { force: !0 });
|
|
171
|
+
n.log?.info("source maps removed from the build output", { files: r.length });
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return {
|
|
175
|
+
uploaded: i,
|
|
176
|
+
deleted: t.keep ? 0 : r.length
|
|
177
|
+
};
|
|
178
|
+
}, fe = (e) => {
|
|
179
|
+
let t = e;
|
|
180
|
+
return t?.web?.sourcemaps === void 0 ? { option: t?.sourcemaps } : { problem: "`web.sourcemaps` moved to the top level of app.config.ts in 0.59.0.\n It now covers every bundle the build emits — the browser bundle AND the SSR, start and serve bundles, which were minified with no map and no way to ask for one.\n → move it out of `web:` (or run `voltro update`, which does it for you)." };
|
|
181
|
+
}, pe = (e) => "problem" in e, $ = W({ scope: "voltro:build" }), me = () => ({
|
|
182
|
+
name: "voltro:stub-engine-devtools",
|
|
183
|
+
resolveId: (e) => e === "@tanstack/devtools-event-client" ? "\0voltro-engine-devtools-stub" : void 0,
|
|
184
|
+
load: (e) => e === "\0voltro-engine-devtools-stub" ? "export class EventClient { constructor() {} on() { return () => {} } emit() {} }\n" : void 0
|
|
185
|
+
}), he = (e, t) => ({
|
|
186
|
+
name: "voltro:ssr-optional-peer-external",
|
|
187
|
+
enforce: "pre",
|
|
188
|
+
resolveId(n, r) {
|
|
189
|
+
if (n.startsWith(".") || n.startsWith("/") || n.startsWith("\0") || n.startsWith("node:") || n === "effect" || n.startsWith("@effect/") || n.startsWith("@voltro/")) return null;
|
|
190
|
+
for (let t of [r ? R(r) : void 0, e]) if (t !== void 0) try {
|
|
191
|
+
return q(z(t, "_.js")).resolve(n), null;
|
|
192
|
+
} catch {}
|
|
193
|
+
return t.add(n), {
|
|
194
|
+
id: n,
|
|
195
|
+
external: !0
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
}), ge = (e) => /\[/.test(e), _e = (e, t) => {
|
|
199
|
+
let n = e.split("/").filter(Boolean), r = [];
|
|
200
|
+
for (let i of n) if (i.startsWith("[[...") && i.endsWith("]]")) {
|
|
201
|
+
let e = t[i.slice(5, -2)];
|
|
202
|
+
e && e.length > 0 && r.push(e);
|
|
203
|
+
} else if (i.startsWith("[...") && i.endsWith("]")) {
|
|
204
|
+
let n = i.slice(4, -1), a = t[n];
|
|
205
|
+
if (!a) throw Error(`resolvePattern: missing required catch-all param "${n}" for pattern ${e}`);
|
|
206
|
+
r.push(a);
|
|
207
|
+
} else if (i.startsWith("[") && i.endsWith("]")) {
|
|
208
|
+
let n = i.slice(1, -1), a = t[n];
|
|
209
|
+
if (!a) throw Error(`resolvePattern: missing required param "${n}" for pattern ${e}`);
|
|
210
|
+
if (a.includes("/")) throw Error(`resolvePattern: param "${n}" contains "/" but pattern segment is single-component: ${e}`);
|
|
211
|
+
r.push(a);
|
|
212
|
+
} else r.push(i);
|
|
213
|
+
return r.length === 0 ? "/" : "/" + r.join("/");
|
|
214
|
+
}, ve = (e, t) => {
|
|
215
|
+
if (t === "/" || t === "") return z(e, "index.html");
|
|
216
|
+
let n = t.replace(/^\//, "").split("/");
|
|
217
|
+
return z(e, ...n, "index.html");
|
|
218
|
+
}, ye = (e) => e.replace(/<script\b(?=[^>]*\btype="module")(?:(?!<\/script>).)*<\/script>/gi, "").replace(/<script\b(?=[^>]*\bsrc=)(?:(?!<\/script>).)*<\/script>/gi, "").replace(/<link\b[^>]*\brel="modulepreload"[^>]*>/gi, ""), be = (e, t) => {
|
|
219
|
+
let n = e.replace("<div id=\"root\"></div>", `<div id="root">${t.body}</div>`), r = [
|
|
220
|
+
t.metaHtml,
|
|
221
|
+
`<meta name="voltro-interactive" content="${t.interactive}" />`,
|
|
222
|
+
t.stateScript
|
|
223
|
+
].filter((e) => e.length > 0).join("\n ");
|
|
224
|
+
return n = T(o(n, r), t.documentAttrs), t.interactive === "none" && (n = ye(n)), n;
|
|
225
|
+
}, xe = async (e) => {
|
|
226
|
+
let { page: t, chainEntries: n, pageMod: r, helpers: i } = e, a = n.filter((e) => e.hasLayout);
|
|
227
|
+
if (a.length === 0) return $.debug("skip page", {
|
|
228
|
+
pattern: t.pattern,
|
|
229
|
+
reason: "renderMode=spa with no layout — nothing to shell"
|
|
230
|
+
}), null;
|
|
231
|
+
if (ge(t.pattern)) return $.debug("skip page", {
|
|
232
|
+
pattern: t.pattern,
|
|
233
|
+
reason: "renderMode=spa with a dynamic pattern"
|
|
234
|
+
}), null;
|
|
235
|
+
let s = await Promise.all(a.map(e.loadLayout)), c = a.filter((e, t) => typeof s[t]?.loader == "function").map((e) => e.dir || "/");
|
|
236
|
+
if (c.length > 0) return $.info(`spa shell for ${t.pattern} left to on-demand rendering — its layout chain has a loader (${c.join(", ")}), whose output may be per-request`, {
|
|
237
|
+
pattern: t.pattern,
|
|
238
|
+
layouts: c
|
|
239
|
+
}), null;
|
|
240
|
+
let { chain: l, segmentLoaderData: u } = await _({
|
|
241
|
+
entries: n,
|
|
242
|
+
loadLayout: e.loadLayout,
|
|
243
|
+
loadError: e.loadError,
|
|
244
|
+
loadPending: e.loadPending,
|
|
245
|
+
ctx: e.ctx
|
|
246
|
+
}), d = {
|
|
247
|
+
pattern: t.pattern,
|
|
248
|
+
Component: r.default,
|
|
249
|
+
meta: r.meta,
|
|
250
|
+
ErrorBoundary: r.ErrorBoundary,
|
|
251
|
+
Pending: r.Pending,
|
|
252
|
+
renderMode: "spa",
|
|
253
|
+
chain: l
|
|
254
|
+
}, f = r.interactive ?? "full", p = v({
|
|
255
|
+
helpers: i,
|
|
256
|
+
page: t.pattern,
|
|
257
|
+
interactive: f,
|
|
258
|
+
delivery: "artefact",
|
|
259
|
+
renderInput: {
|
|
260
|
+
descriptor: d,
|
|
261
|
+
params: {},
|
|
262
|
+
pathname: t.pattern,
|
|
263
|
+
segmentLoaderData: u,
|
|
264
|
+
...e.outerWrap ? { outerWrap: e.outerWrap } : {},
|
|
265
|
+
...e.locale ? { locale: e.locale } : {}
|
|
266
|
+
}
|
|
267
|
+
}), m = E({
|
|
268
|
+
helpers: i,
|
|
269
|
+
prepared: p
|
|
270
|
+
}), h = C({
|
|
271
|
+
helpers: i,
|
|
272
|
+
prepared: p,
|
|
273
|
+
meta: m.meta,
|
|
274
|
+
interactive: f
|
|
275
|
+
}), g = o(e.shellTemplate.replace("<div id=\"root\"></div>", `<div id="root">${m.body}</div>`), h), y = ve(e.distDir, t.pattern);
|
|
276
|
+
return await H.mkdir(R(y), { recursive: !0 }), await H.writeFile(y, g, "utf8"), $.debug("prerendered spa layout shell", { pattern: t.pattern }), {
|
|
277
|
+
pattern: t.pattern,
|
|
278
|
+
outPath: y
|
|
279
|
+
};
|
|
280
|
+
}, Se = async (e) => {
|
|
281
|
+
let { root: t, distDir: r, pages: i, dirs: a, vite: o } = e, c = z(r, "index.html"), d = await H.readFile(c, "utf8"), p = z(r, "_voltro", "shell.html");
|
|
282
|
+
await H.mkdir(R(p), { recursive: !0 }), await H.writeFile(p, d, "utf8");
|
|
283
|
+
let m = /* @__PURE__ */ new Map();
|
|
284
|
+
for (let t of e.islandsPlans ?? []) {
|
|
285
|
+
let e = z(r, "island-shells", `${t.name}.html`);
|
|
286
|
+
try {
|
|
287
|
+
let n = l(await H.readFile(e, "utf8"), d);
|
|
288
|
+
await H.writeFile(e, n, "utf8"), m.set(t.pattern, n);
|
|
289
|
+
} catch {
|
|
290
|
+
$.warn("islands shell missing — page ships the full entry", {
|
|
291
|
+
pattern: t.pattern,
|
|
292
|
+
expected: e
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
let h = z(t, "node_modules", "@voltro", "ui-shadcn"), g = V(z(h, "package.json")) ? h : null, v = [...g ? [
|
|
297
|
+
{
|
|
298
|
+
find: "@voltro/ui-shadcn/tokens.css",
|
|
299
|
+
replacement: z(g, "src/tokens.css")
|
|
300
|
+
},
|
|
301
|
+
{
|
|
302
|
+
find: "@voltro/ui-shadcn/cn",
|
|
303
|
+
replacement: z(g, "src/cn.ts")
|
|
304
|
+
},
|
|
305
|
+
{
|
|
306
|
+
find: "@voltro/ui-shadcn/brand",
|
|
307
|
+
replacement: z(g, "src/brand/voltroLogo.tsx")
|
|
308
|
+
},
|
|
309
|
+
{
|
|
310
|
+
find: "@voltro/ui-shadcn",
|
|
311
|
+
replacement: z(g, "src/index.ts")
|
|
312
|
+
}
|
|
313
|
+
] : [], ...k(t)], y = await o.createServer({
|
|
314
|
+
root: z(t, ".framework"),
|
|
315
|
+
envPrefix: "__VOLTRO_VITE_ENV_DISABLED__",
|
|
316
|
+
plugins: [
|
|
317
|
+
(await import("@vitejs/plugin-react")).default(),
|
|
318
|
+
(await import("@tailwindcss/vite")).default(),
|
|
319
|
+
u({
|
|
320
|
+
root: t,
|
|
321
|
+
config: I(e.images),
|
|
322
|
+
urlMode: "build-urls"
|
|
323
|
+
}),
|
|
324
|
+
me()
|
|
325
|
+
],
|
|
326
|
+
resolve: {
|
|
327
|
+
alias: v,
|
|
328
|
+
dedupe: [
|
|
329
|
+
"react",
|
|
330
|
+
"react-dom",
|
|
331
|
+
"react-intl",
|
|
332
|
+
"@voltro/i18n"
|
|
333
|
+
]
|
|
334
|
+
},
|
|
335
|
+
ssr: { noExternal: ["react-intl", "@voltro/i18n"] },
|
|
336
|
+
optimizeDeps: { exclude: ["@voltro/devtools", "@voltro/devtools/styles.css"] },
|
|
337
|
+
server: {
|
|
338
|
+
middlewareMode: !0,
|
|
339
|
+
hmr: !1
|
|
340
|
+
},
|
|
341
|
+
appType: "custom",
|
|
342
|
+
logLevel: "warn"
|
|
343
|
+
}), b = await y.ssrLoadModule("@voltro/web/ssr"), { renderPageToHtml: x, renderMetaToHtml: S, renderRouterStateScript: C, isDeferredLoaderResult: w, assertDeferralSupported: T, beginStoreSeeds: E, seedPreloadedSubscription: ee, seedPreloadedSubscriptionFailure: te } = b, O, A = /* @__PURE__ */ new Map();
|
|
344
|
+
if (e.locales && e.locales.length > 0 && e.defaultLocale) try {
|
|
345
|
+
let n = await y.ssrLoadModule("@voltro/i18n");
|
|
346
|
+
try {
|
|
347
|
+
O = (await y.ssrLoadModule("@voltro/i18n/server")).resolveTimeZone?.({
|
|
348
|
+
configured: e.timeZone ?? null,
|
|
349
|
+
defaultTimeZone: e.defaultTimeZone ?? null
|
|
350
|
+
});
|
|
351
|
+
} catch {}
|
|
352
|
+
let r = n.makeSsgWrap;
|
|
353
|
+
if (typeof r != "function") throw Error("@voltro/i18n is installed but missing the `makeSsgWrap` export — upgrade @voltro/i18n to a version that ships SSG support.");
|
|
354
|
+
for (let n of e.locales) try {
|
|
355
|
+
let i = await y.ssrLoadModule(z(t, "src", "locales", `${n}.ts`)), a = i.default ?? i;
|
|
356
|
+
A.set(n, r(n, a, e.defaultLocale));
|
|
357
|
+
} catch (e) {
|
|
358
|
+
$.warn(`i18n catalog missing for locale '${n}' — pages rendered at /${n}/* will crash. Add src/locales/${n}.ts.`, {}, e);
|
|
359
|
+
}
|
|
360
|
+
} catch (e) {
|
|
361
|
+
$.warn("i18n wrapper unavailable for SSG — pages that call useT() will fail. Check that @voltro/i18n is installed.", {}, e);
|
|
362
|
+
}
|
|
363
|
+
let j = [], M = {}, N = (e) => e.dir === "" ? z(t, "src", "pages") : z(t, "src", "pages", e.dir), P = async (e) => await y.ssrLoadModule(z(N(e), "layout.tsx")), ne = async (e) => await y.ssrLoadModule(z(N(e), "error.tsx")), B = async (e) => await y.ssrLoadModule(z(N(e), "loading.tsx")), U = (e, t) => ({
|
|
364
|
+
params: e.params,
|
|
365
|
+
pathname: e.pathname,
|
|
366
|
+
search: "",
|
|
367
|
+
signal: t,
|
|
368
|
+
headers: {},
|
|
369
|
+
query: void 0,
|
|
370
|
+
isServer: !0
|
|
371
|
+
});
|
|
372
|
+
for (let o of i) {
|
|
373
|
+
let i = `${z(t, "src", "pages", o.file)}`, c = await y.ssrLoadModule(i), l = F(c, z("src", "pages", o.file));
|
|
374
|
+
M[o.pattern] = l;
|
|
375
|
+
let u = l.renderMode, p = D(a, o.dirChain);
|
|
376
|
+
if (u === "spa") {
|
|
377
|
+
let t = await xe({
|
|
378
|
+
page: o,
|
|
379
|
+
chainEntries: p,
|
|
380
|
+
pageMod: c,
|
|
381
|
+
shellTemplate: d,
|
|
382
|
+
distDir: r,
|
|
383
|
+
helpers: b,
|
|
384
|
+
loadLayout: P,
|
|
385
|
+
loadError: ne,
|
|
386
|
+
loadPending: B,
|
|
387
|
+
ctx: U({
|
|
388
|
+
params: {},
|
|
389
|
+
pathname: o.pattern
|
|
390
|
+
}, new AbortController().signal),
|
|
391
|
+
outerWrap: A.get(e.defaultLocale ?? ""),
|
|
392
|
+
locale: e.defaultLocale
|
|
393
|
+
});
|
|
394
|
+
t && j.push(t);
|
|
395
|
+
continue;
|
|
396
|
+
}
|
|
397
|
+
if (u !== "static") {
|
|
398
|
+
$.debug("skip page", {
|
|
399
|
+
pattern: o.pattern,
|
|
400
|
+
reason: `renderMode=${u}`
|
|
401
|
+
});
|
|
402
|
+
continue;
|
|
403
|
+
}
|
|
404
|
+
let h;
|
|
405
|
+
if (ge(o.pattern)) {
|
|
406
|
+
if (typeof c.getStaticPaths != "function") {
|
|
407
|
+
$.debug("skip page", {
|
|
408
|
+
pattern: o.pattern,
|
|
409
|
+
reason: "no getStaticPaths export"
|
|
410
|
+
});
|
|
411
|
+
continue;
|
|
412
|
+
}
|
|
413
|
+
try {
|
|
414
|
+
let e = await c.getStaticPaths();
|
|
415
|
+
if (!Array.isArray(e)) {
|
|
416
|
+
$.warn("skip page — getStaticPaths did not return an array", { pattern: o.pattern });
|
|
417
|
+
continue;
|
|
418
|
+
}
|
|
419
|
+
h = e.map((e) => ({
|
|
420
|
+
params: e.params,
|
|
421
|
+
pathname: _e(o.pattern, e.params)
|
|
422
|
+
}));
|
|
423
|
+
} catch (e) {
|
|
424
|
+
$.warn("skip page — getStaticPaths threw", { pattern: o.pattern }, e);
|
|
425
|
+
continue;
|
|
426
|
+
}
|
|
427
|
+
if (h.length === 0) {
|
|
428
|
+
$.debug("skip page", {
|
|
429
|
+
pattern: o.pattern,
|
|
430
|
+
reason: "getStaticPaths returned []"
|
|
431
|
+
});
|
|
432
|
+
continue;
|
|
433
|
+
}
|
|
434
|
+
} else h = [{
|
|
435
|
+
params: {},
|
|
436
|
+
pathname: o.pattern
|
|
437
|
+
}];
|
|
438
|
+
let g = c.interactive ?? "full";
|
|
439
|
+
for (let i of h) {
|
|
440
|
+
E();
|
|
441
|
+
let a, l, h = new AbortController();
|
|
442
|
+
try {
|
|
443
|
+
({chain: a, segmentLoaderData: l} = await _({
|
|
444
|
+
entries: p,
|
|
445
|
+
loadLayout: P,
|
|
446
|
+
loadError: ne,
|
|
447
|
+
loadPending: B,
|
|
448
|
+
ctx: U(i, h.signal)
|
|
449
|
+
}));
|
|
450
|
+
} catch (e) {
|
|
451
|
+
let t = e?._voltroControl;
|
|
452
|
+
if (e instanceof Error && t === "redirect") throw Error(`Static page "${i.pathname}" threw RedirectError from a LAYOUT loader at build time. Static pages can't redirect per-request — switch it to renderMode 'ssr'.`);
|
|
453
|
+
if (e instanceof Error && t === "not-found") {
|
|
454
|
+
$.warn("layout loader threw NotFoundError at build time — skipping artifact", { pathname: i.pathname });
|
|
455
|
+
continue;
|
|
456
|
+
}
|
|
457
|
+
throw Error(`Static page "${i.pathname}": a LAYOUT loader threw at build time — the page would prerender without its layout data. Fix the loader (cause below) or throw NotFoundError to skip this path.\ncause: ${e instanceof Error ? e.stack ?? e.message : String(e)}`);
|
|
458
|
+
}
|
|
459
|
+
let v = {
|
|
460
|
+
pattern: o.pattern,
|
|
461
|
+
Component: c.default,
|
|
462
|
+
meta: c.meta,
|
|
463
|
+
loader: c.loader,
|
|
464
|
+
ErrorBoundary: c.ErrorBoundary,
|
|
465
|
+
Pending: c.Pending,
|
|
466
|
+
renderMode: u,
|
|
467
|
+
chain: a
|
|
468
|
+
}, y = null;
|
|
469
|
+
if (typeof c.loader == "function") {
|
|
470
|
+
let e = new AbortController();
|
|
471
|
+
try {
|
|
472
|
+
y = await c.loader({
|
|
473
|
+
params: i.params,
|
|
474
|
+
pathname: i.pathname,
|
|
475
|
+
search: "",
|
|
476
|
+
headers: {},
|
|
477
|
+
query: void 0,
|
|
478
|
+
signal: e.signal,
|
|
479
|
+
isServer: !0
|
|
480
|
+
});
|
|
481
|
+
} catch (e) {
|
|
482
|
+
if (e instanceof Error && e._voltroControl === "redirect") throw Error(`Static page "${i.pathname}" threw RedirectError at build time. Static pages can't redirect per-request — switch it to renderMode 'ssr'.`);
|
|
483
|
+
if (e instanceof Error && e._voltroControl === "not-found") {
|
|
484
|
+
$.warn("loader threw NotFoundError at build time — skipping artifact", { pathname: i.pathname });
|
|
485
|
+
continue;
|
|
486
|
+
}
|
|
487
|
+
throw Error(`Static page "${i.pathname}": its loader threw at build time — the page would prerender EMPTY. Fix the loader (cause below) or throw NotFoundError to skip this path.\ncause: ${e instanceof Error ? e.stack ?? e.message : String(e)}`);
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
w(y) && T({
|
|
491
|
+
page: i.pathname,
|
|
492
|
+
renderMode: u,
|
|
493
|
+
interactive: g
|
|
494
|
+
});
|
|
495
|
+
for (let e of Object.values(l)) w(e) && T({
|
|
496
|
+
page: i.pathname,
|
|
497
|
+
renderMode: u,
|
|
498
|
+
interactive: g
|
|
499
|
+
});
|
|
500
|
+
await s({
|
|
501
|
+
pageMod: c,
|
|
502
|
+
params: i.params,
|
|
503
|
+
query: void 0,
|
|
504
|
+
apiName: void 0,
|
|
505
|
+
seed: ee,
|
|
506
|
+
seedFailure: te
|
|
507
|
+
});
|
|
508
|
+
let b = i.params.locale ?? e.defaultLocale ?? "en", D = A.get(b) ?? A.get(e.defaultLocale ?? ""), k = Date.now(), M = D ? (e) => D(e, {
|
|
509
|
+
timeZone: O,
|
|
510
|
+
renderedAt: k
|
|
511
|
+
}) : void 0, { html: N, meta: F } = x({
|
|
512
|
+
descriptor: v,
|
|
513
|
+
params: i.params,
|
|
514
|
+
pathname: i.pathname,
|
|
515
|
+
loaderData: y,
|
|
516
|
+
segmentLoaderData: l,
|
|
517
|
+
...M ? { outerWrap: M } : {},
|
|
518
|
+
locale: b
|
|
519
|
+
}), I = "";
|
|
520
|
+
if (typeof c.ogImage == "function") {
|
|
521
|
+
let a = await c.ogImage({
|
|
522
|
+
params: i.params,
|
|
523
|
+
loaderData: y,
|
|
524
|
+
locale: b
|
|
525
|
+
}), o = await f(t, e.fonts), { png: s } = await n({
|
|
526
|
+
element: a,
|
|
527
|
+
fonts: o
|
|
528
|
+
}), l = `assets/og/${L(s)}.png`;
|
|
529
|
+
await H.mkdir(z(r, "assets", "og"), { recursive: !0 }), await H.writeFile(z(r, l), Buffer.from(s));
|
|
530
|
+
let u = e.siteUrl === void 0 ? `/${l}` : `${e.siteUrl.replace(/\/$/, "")}/${l}`;
|
|
531
|
+
I = S(F).includes("og:image") ? "" : `<meta property="og:image" content="${u}" /><meta name="twitter:image" content="${u}" /><meta name="twitter:card" content="summary_large_image" />`;
|
|
532
|
+
}
|
|
533
|
+
let V = g === "islands" ? m.get(o.pattern) : void 0;
|
|
534
|
+
g === "islands" && V === void 0 && $.warn("islands page has no per-page entry (non-literal `interactive`?) — shipping the full app entry", { pattern: o.pattern });
|
|
535
|
+
let W = be(V ?? d, {
|
|
536
|
+
body: N,
|
|
537
|
+
metaHtml: S(F) + I,
|
|
538
|
+
stateScript: C({
|
|
539
|
+
path: i.pathname,
|
|
540
|
+
loaderData: y,
|
|
541
|
+
segmentLoaderData: l,
|
|
542
|
+
pageLoaderRan: typeof c.loader == "function"
|
|
543
|
+
}),
|
|
544
|
+
interactive: g,
|
|
545
|
+
documentAttrs: {
|
|
546
|
+
lang: b,
|
|
547
|
+
...O === void 0 ? {} : { timeZone: O },
|
|
548
|
+
renderedAt: k
|
|
549
|
+
}
|
|
550
|
+
}), G = ve(r, i.pathname);
|
|
551
|
+
await H.mkdir(R(G), { recursive: !0 }), await H.writeFile(G, W, "utf8"), j.push({
|
|
552
|
+
pattern: i.pathname,
|
|
553
|
+
outPath: G,
|
|
554
|
+
...F?.noIndex ? { noIndex: !0 } : {}
|
|
555
|
+
});
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
return await y.close(), {
|
|
559
|
+
rendered: j,
|
|
560
|
+
pageMeta: M
|
|
561
|
+
};
|
|
562
|
+
}, Ce = async (e, t, n, r, i, a, o, s) => {
|
|
563
|
+
let c = z(e, ".framework"), l = [];
|
|
564
|
+
for (let e of t) l.push(` ${JSON.stringify(e.pattern)}: () => import('../src/pages/${e.file}'),`);
|
|
565
|
+
let u = [], d = [], f = [];
|
|
566
|
+
for (let e of n) {
|
|
567
|
+
let t = e.dir === "" ? "../src/pages" : `../src/pages/${e.dir}`, n = e.dir === "" ? "/" : e.dir;
|
|
568
|
+
e.hasLayout && u.push(` ${JSON.stringify(n)}: () => import('${t}/layout.tsx'),`), e.hasError && d.push(` ${JSON.stringify(n)}: () => import('${t}/error.tsx'),`), e.hasPending && f.push(` ${JSON.stringify(n)}: () => import('${t}/loading.tsx'),`);
|
|
569
|
+
}
|
|
570
|
+
let p = [], m = [];
|
|
571
|
+
if (r && r.length > 0 && i) for (let t of r) {
|
|
572
|
+
if (!V(z(e, "src", "locales", `${t}.ts`))) continue;
|
|
573
|
+
let n = `__i18nCat_${t.replace(/[^a-zA-Z0-9]/g, "_")}`;
|
|
574
|
+
p.push(`import ${n} from '../src/locales/${t}'`), m.push(` ${JSON.stringify(t)}: makeSsgWrap(${JSON.stringify(t)}, ${n} as unknown as Record<string, string>, ${JSON.stringify(i)}),`);
|
|
575
|
+
}
|
|
576
|
+
let h = m.length > 0, g = !h && r !== void 0 && r.length > 0 && i !== void 0, _ = h ? [
|
|
577
|
+
"import { makeSsgWrap } from '@voltro/i18n'",
|
|
578
|
+
"import { makeSsrI18nResolver } from '@voltro/i18n/server'",
|
|
579
|
+
...p
|
|
580
|
+
] : g ? ["import { resolveLocale, resolveTimeZone } from '@voltro/i18n/server'"] : [], v = h ? [
|
|
581
|
+
"",
|
|
582
|
+
`const __I18N_SUPPORTED = ${JSON.stringify(r)} as ReadonlyArray<string>`,
|
|
583
|
+
`const __I18N_DEFAULT = ${JSON.stringify(i)}`,
|
|
584
|
+
"const __i18nWraps: Record<string, (children: unknown, request?: { timeZone?: string | undefined; renderedAt?: number | undefined }) => unknown> = {",
|
|
585
|
+
...m,
|
|
586
|
+
"}",
|
|
587
|
+
"// Cookie voltro:locale > Accept-Language > default → the matching wrapper.",
|
|
588
|
+
"// The SAME resolver `voltro dev` calls (webDev.ts) — this used to be a",
|
|
589
|
+
"// hand-written copy here and NOTHING at all in dev, which is why a",
|
|
590
|
+
"// localized page rendered under `voltro start` and threw under `voltro dev`.",
|
|
591
|
+
"const __resolveI18n = makeSsrI18nResolver({",
|
|
592
|
+
" wraps: __i18nWraps,",
|
|
593
|
+
" supported: __I18N_SUPPORTED,",
|
|
594
|
+
" defaultLocale: __I18N_DEFAULT,",
|
|
595
|
+
` timeZone: ${JSON.stringify(o?.timeZone ?? null)},`,
|
|
596
|
+
` defaultTimeZone: ${JSON.stringify(o?.defaultTimeZone ?? null)},`,
|
|
597
|
+
"})"
|
|
598
|
+
] : g ? [
|
|
599
|
+
"",
|
|
600
|
+
`const __I18N_SUPPORTED = ${JSON.stringify(r)} as ReadonlyArray<string>`,
|
|
601
|
+
`const __I18N_DEFAULT = ${JSON.stringify(i)}`,
|
|
602
|
+
"// `locales:` declared, no src/locales/* catalogs: resolve the language,",
|
|
603
|
+
"// wrap nothing. `outerWrap` is identity so every caller downstream is",
|
|
604
|
+
"// unchanged — the ONE difference from the wired path is that no provider",
|
|
605
|
+
"// is mounted, which is exactly what an app on its own i18n stack wants.",
|
|
606
|
+
"const __resolveI18n = (cookieHeader?: string | null, acceptLanguageHeader?: string | null) => ({",
|
|
607
|
+
" locale: resolveLocale({",
|
|
608
|
+
" cookieHeader: cookieHeader ?? null,",
|
|
609
|
+
" acceptLanguageHeader: acceptLanguageHeader ?? null,",
|
|
610
|
+
" supported: __I18N_SUPPORTED,",
|
|
611
|
+
" defaultLocale: __I18N_DEFAULT,",
|
|
612
|
+
" }),",
|
|
613
|
+
" timeZone: resolveTimeZone({",
|
|
614
|
+
" cookieHeader: cookieHeader ?? null,",
|
|
615
|
+
` configured: ${JSON.stringify(o?.timeZone ?? null)},`,
|
|
616
|
+
` defaultTimeZone: ${JSON.stringify(o?.defaultTimeZone ?? null)},`,
|
|
617
|
+
" }),",
|
|
618
|
+
" outerWrap: (children: unknown) => children,",
|
|
619
|
+
"})"
|
|
620
|
+
] : [], y = (s ?? []).map((e) => `${JSON.stringify(e.name)}: () => import('${e.pkg}/rpcGroup').then((m) => m.appDescriptors)`).join(", "), b = y === "" ? "" : `, apiDescriptors: { ${y} }`, x = "renderPageToHtml, renderPageToStream, renderMetaToHtml, renderRouterStateScript, renderDeferredRegistryScript, prepareDeferredLoaderData, deferredSettleScript, deferredId, assertDeferralSupported, parseCookieHeader, withStoreSeeds, beginStoreSeeds, registerSsrApiDescriptors", S = h || g ? `export const helpers = { ${x}, i18n: { resolve: __resolveI18n, locales: __I18N_SUPPORTED }${b} }` : `export const helpers = { ${x}${b} }`, C = [
|
|
621
|
+
"// GENERATED BY `voltro build` — do not edit; will be overwritten on next build.",
|
|
622
|
+
"// Entry for the pre-built SSR bundle. Imported by `voltro start`'s",
|
|
623
|
+
"// production runtime; bypasses Vite middleware-mode SSR loading.",
|
|
624
|
+
"",
|
|
625
|
+
"import { renderPageToHtml, renderPageToStream, renderMetaToHtml, renderRouterStateScript, renderDeferredRegistryScript, prepareDeferredLoaderData, deferredSettleScript, deferredId, assertDeferralSupported, parseCookieHeader, withStoreSeeds, beginStoreSeeds, registerSsrApiDescriptors } from '@voltro/web/ssr'",
|
|
626
|
+
..._,
|
|
627
|
+
"",
|
|
628
|
+
"// Lazy page loaders — a page's module (and content) loads only when its",
|
|
629
|
+
"// route is rendered, so importing this entry never pulls every page into memory.",
|
|
630
|
+
"export const pages: Record<string, () => Promise<unknown>> = {",
|
|
631
|
+
...l,
|
|
632
|
+
"}",
|
|
633
|
+
"// Build-time per-route metadata — `voltro start` reads this instead of",
|
|
634
|
+
"// importing every page module at boot just to inspect its render mode.",
|
|
635
|
+
`export const pageMeta: Record<string, unknown> = ${JSON.stringify(a ?? {}, null, 2)}`,
|
|
636
|
+
"export const layouts: Record<string, () => Promise<unknown>> = {",
|
|
637
|
+
...u,
|
|
638
|
+
"}",
|
|
639
|
+
"export const errors: Record<string, () => Promise<unknown>> = {",
|
|
640
|
+
...d,
|
|
641
|
+
"}",
|
|
642
|
+
"export const pendings: Record<string, () => Promise<unknown>> = {",
|
|
643
|
+
...f,
|
|
644
|
+
"}",
|
|
645
|
+
...v,
|
|
646
|
+
"",
|
|
647
|
+
S,
|
|
648
|
+
""
|
|
649
|
+
].join("\n"), w = z(c, "ssrEntry.ts");
|
|
650
|
+
return await H.writeFile(w, C, "utf8"), w;
|
|
651
|
+
}, we = async (e) => {
|
|
652
|
+
let { checkRpcGroupFreshness: t } = await import("./codegen-DbH7NbCR.js"), n = await t(e);
|
|
653
|
+
if (n.kind === "fresh") return;
|
|
654
|
+
n.kind === "stale" && $.info("rpcGroup.generated.ts is stale — regenerating", {
|
|
655
|
+
file: n.file,
|
|
656
|
+
reason: n.reason
|
|
657
|
+
});
|
|
658
|
+
let { regenerateRpcGroup: r } = await import("./codegenCommand-kS3Twuc9.js"), i = await r(e);
|
|
659
|
+
if (i.kind === "refused") {
|
|
660
|
+
$.warn("could not regenerate the rpc group — building against what is on disk", { reason: i.reason });
|
|
661
|
+
return;
|
|
662
|
+
}
|
|
663
|
+
i.kind === "wrote" && n.kind === "stale" && $.info("rpc group regenerated", {
|
|
664
|
+
plugins: i.plugins,
|
|
665
|
+
routes: i.routes
|
|
666
|
+
});
|
|
667
|
+
}, Te = async (e) => {
|
|
668
|
+
let n = await S(e, { preferSource: !0 });
|
|
669
|
+
if (!n) {
|
|
670
|
+
let { loadApiConfigDiagnosed: t } = await import("./dev-Dff_pdik.js"), n = await t(e), r = n.config;
|
|
671
|
+
if (!r && n.present) return $.error("app.config.ts is present but could not be loaded — this is NOT a statement about the app's type", { path: z(e, "app.config.ts") }, n.error), {
|
|
672
|
+
ran: !0,
|
|
673
|
+
exitCode: 1
|
|
674
|
+
};
|
|
675
|
+
if (r) {
|
|
676
|
+
$.info("building api app", { app: r.name ?? "(unnamed)" }), await we(e);
|
|
677
|
+
let t = fe(r);
|
|
678
|
+
if (pe(t)) return $.fatal(t.problem), {
|
|
679
|
+
ran: !0,
|
|
680
|
+
exitCode: 1
|
|
681
|
+
};
|
|
682
|
+
let n = oe(t.option, process.env);
|
|
683
|
+
if (se(n)) return $.fatal(n.problem), {
|
|
684
|
+
ran: !0,
|
|
685
|
+
exitCode: 1
|
|
686
|
+
};
|
|
687
|
+
let { runApiBuild: i, runServeBundleBuild: a } = await import("./apiBuild-B9OvhITV.js");
|
|
688
|
+
await i(e, { sourcemaps: n.emit });
|
|
689
|
+
try {
|
|
690
|
+
await a(e, { sourcemaps: n.emit });
|
|
691
|
+
} catch (e) {
|
|
692
|
+
return $.fatal("serve bundle build FAILED — refusing to ship a bundle-less image. Fix the error above (production serves from the bundle, never tsx).", {}, e), {
|
|
693
|
+
ran: !0,
|
|
694
|
+
exitCode: 1
|
|
695
|
+
};
|
|
696
|
+
}
|
|
697
|
+
if (n.emit) try {
|
|
698
|
+
let t = await de([{
|
|
699
|
+
dir: z(e, ".framework", "dist-api"),
|
|
700
|
+
urlPrefix: "~/"
|
|
701
|
+
}], n, {
|
|
702
|
+
appRoot: e,
|
|
703
|
+
log: $
|
|
704
|
+
});
|
|
705
|
+
(t.uploaded > 0 || t.deleted > 0) && $.debug("source maps handled", {
|
|
706
|
+
uploaded: t.uploaded,
|
|
707
|
+
deleted: t.deleted
|
|
708
|
+
});
|
|
709
|
+
} catch (e) {
|
|
710
|
+
return $.fatal(`source map upload failed:\n${e instanceof Error ? e.message : String(e)}`), {
|
|
711
|
+
ran: !0,
|
|
712
|
+
exitCode: 1
|
|
713
|
+
};
|
|
714
|
+
}
|
|
715
|
+
return {
|
|
716
|
+
ran: !0,
|
|
717
|
+
exitCode: 0
|
|
718
|
+
};
|
|
719
|
+
}
|
|
720
|
+
return {
|
|
721
|
+
ran: !1,
|
|
722
|
+
exitCode: 0
|
|
723
|
+
};
|
|
724
|
+
}
|
|
725
|
+
$.info("building web app", { app: n.name ?? "(unnamed)" });
|
|
726
|
+
let { resolved: o } = await h({
|
|
727
|
+
rawEnv: n.env,
|
|
728
|
+
appType: "web",
|
|
729
|
+
root: e,
|
|
730
|
+
log: $,
|
|
731
|
+
generateTypes: !0
|
|
732
|
+
}), s = await b(e, n);
|
|
733
|
+
await r(e, n, s, o.publicValues);
|
|
734
|
+
let { pages: l } = await p(z(e, "src", "pages")), f = [];
|
|
735
|
+
for (let t of l) {
|
|
736
|
+
let n = await H.readFile(z(e, "src", "pages", t.file), "utf8").catch(() => ""), r = c(n);
|
|
737
|
+
n.includes("<Script") && (r === "none" || r === "islands") && $.warn(r === "none" ? `page '${t.pattern}' uses <Script> but declares interactive: 'none' — zero-JS strips every script, so it will NEVER load. Remove the <Script>, or raise the page to islands/full.` : `page '${t.pattern}' uses <Script> in its STATIC part (the page file) while interactive: 'islands' — outside an island nothing mounts, so it will NEVER load. Move the <Script> into an *.island.tsx component (it fires when that island hydrates).`), r === "islands" && f.push({
|
|
738
|
+
pattern: t.pattern,
|
|
739
|
+
file: t.file
|
|
740
|
+
});
|
|
741
|
+
}
|
|
742
|
+
let _ = w(s, "../../app.config"), v = await x({
|
|
743
|
+
webRoot: e,
|
|
744
|
+
pages: f,
|
|
745
|
+
headSnippets: t(await H.readFile(z(e, ".framework", "index.html"), "utf8").catch(() => "")),
|
|
746
|
+
apiImports: _.imports,
|
|
747
|
+
apiEntriesLiteral: `[\n${_.providerEntryLines.join("\n")}\n ]`
|
|
748
|
+
});
|
|
749
|
+
v.length > 0 && $.info("per-page islands entries", { pages: v.map((e) => `${e.pattern}${e.usesClient ? " (client boot)" : ""}`) });
|
|
750
|
+
let { pages: C } = await p(z(e, "src", "pages"));
|
|
751
|
+
await ee({
|
|
752
|
+
appRoot: e,
|
|
753
|
+
pages: C,
|
|
754
|
+
mode: "prod"
|
|
755
|
+
});
|
|
756
|
+
let T = z(e, ".framework"), E = z(T, "dist"), D = z(e, "node_modules", "@voltro", "ui-shadcn"), j = V(z(D, "package.json")) ? D : null, N = [...j ? [
|
|
757
|
+
{
|
|
758
|
+
find: "@voltro/ui-shadcn/tokens.css",
|
|
759
|
+
replacement: z(j, "src/tokens.css")
|
|
760
|
+
},
|
|
761
|
+
{
|
|
762
|
+
find: "@voltro/ui-shadcn/cn",
|
|
763
|
+
replacement: z(j, "src/cn.ts")
|
|
764
|
+
},
|
|
765
|
+
{
|
|
766
|
+
find: "@voltro/ui-shadcn/brand",
|
|
767
|
+
replacement: z(j, "src/brand/voltroLogo.tsx")
|
|
768
|
+
},
|
|
769
|
+
{
|
|
770
|
+
find: "@voltro/ui-shadcn",
|
|
771
|
+
replacement: z(j, "src/index.ts")
|
|
772
|
+
}
|
|
773
|
+
] : [], ...k(e)];
|
|
774
|
+
$.info("running vite build");
|
|
775
|
+
let P = await d("vite", () => import("vite")), F = (await import("@vitejs/plugin-react")).default, L = (await import("@tailwindcss/vite")).default, B = fe(n);
|
|
776
|
+
if (pe(B)) return $.fatal(B.problem), {
|
|
777
|
+
ran: !0,
|
|
778
|
+
exitCode: 1
|
|
779
|
+
};
|
|
780
|
+
let U = oe(B.option, process.env);
|
|
781
|
+
if (se(U)) return $.fatal(U.problem), {
|
|
782
|
+
ran: !0,
|
|
783
|
+
exitCode: 1
|
|
784
|
+
};
|
|
785
|
+
let W = n.web?.assetPrefix;
|
|
786
|
+
if (W !== void 0 && !/^https?:\/\/|^\//.test(W)) return $.fatal(`web.assetPrefix must be an absolute URL or a root-relative path — got ${JSON.stringify(W)}. A bare host would be resolved against the page URL and 404 on every route but one.`), {
|
|
787
|
+
ran: !0,
|
|
788
|
+
exitCode: 1
|
|
789
|
+
};
|
|
790
|
+
await P.build({
|
|
791
|
+
root: T,
|
|
792
|
+
...W === void 0 ? {} : { base: W.endsWith("/") ? W : `${W}/` },
|
|
793
|
+
envPrefix: "__VOLTRO_VITE_ENV_DISABLED__",
|
|
794
|
+
plugins: [
|
|
795
|
+
F(),
|
|
796
|
+
L(),
|
|
797
|
+
u({
|
|
798
|
+
root: e,
|
|
799
|
+
config: I(n.images)
|
|
800
|
+
}),
|
|
801
|
+
me()
|
|
802
|
+
],
|
|
803
|
+
resolve: {
|
|
804
|
+
alias: N,
|
|
805
|
+
dedupe: [
|
|
806
|
+
"react",
|
|
807
|
+
"react-dom",
|
|
808
|
+
"react-intl",
|
|
809
|
+
"@voltro/i18n"
|
|
810
|
+
]
|
|
811
|
+
},
|
|
812
|
+
publicDir: z(e, "public"),
|
|
813
|
+
build: {
|
|
814
|
+
outDir: "dist",
|
|
815
|
+
emptyOutDir: !0,
|
|
816
|
+
...U.emit ? { sourcemap: "hidden" } : {},
|
|
817
|
+
rollupOptions: {
|
|
818
|
+
input: {
|
|
819
|
+
index: z(T, "index.html"),
|
|
820
|
+
...Object.fromEntries(v.map((e) => [`island_${e.name}`, z(T, e.htmlFile)]))
|
|
821
|
+
},
|
|
822
|
+
output: { manualChunks: te }
|
|
823
|
+
}
|
|
824
|
+
},
|
|
825
|
+
logLevel: "warn"
|
|
826
|
+
});
|
|
827
|
+
let G = async (t) => {
|
|
828
|
+
if (!U.emit) return null;
|
|
829
|
+
let n = z(T, "dist"), r = [{
|
|
830
|
+
dir: z(n, "assets"),
|
|
831
|
+
urlPrefix: ae
|
|
832
|
+
}, ...t.serverBundles ? [{
|
|
833
|
+
dir: z(n, "server"),
|
|
834
|
+
urlPrefix: "~/"
|
|
835
|
+
}, {
|
|
836
|
+
dir: z(T, "dist-web", "startBundle"),
|
|
837
|
+
urlPrefix: "~/"
|
|
838
|
+
}] : []], i = t.upload ? U : {
|
|
839
|
+
emit: U.emit,
|
|
840
|
+
keep: U.keep
|
|
841
|
+
};
|
|
842
|
+
try {
|
|
843
|
+
let t = await de(r, i, {
|
|
844
|
+
appRoot: e,
|
|
845
|
+
log: $
|
|
846
|
+
});
|
|
847
|
+
return (t.uploaded > 0 || t.deleted > 0) && $.debug("source maps handled", {
|
|
848
|
+
uploaded: t.uploaded,
|
|
849
|
+
deleted: t.deleted
|
|
850
|
+
}), null;
|
|
851
|
+
} catch (e) {
|
|
852
|
+
return $.fatal(`source map upload failed:\n${e instanceof Error ? e.message : String(e)}`), 1;
|
|
853
|
+
}
|
|
854
|
+
}, K = z(e, "src", "pages"), { pages: q, dirs: J } = await p(K);
|
|
855
|
+
if (q.length === 0) return $.info("no pages found — client-only bundle written", {
|
|
856
|
+
pagesDir: K,
|
|
857
|
+
distDir: E
|
|
858
|
+
}), {
|
|
859
|
+
ran: !0,
|
|
860
|
+
exitCode: await G({
|
|
861
|
+
serverBundles: !1,
|
|
862
|
+
upload: !0
|
|
863
|
+
}) ?? 0
|
|
864
|
+
};
|
|
865
|
+
{
|
|
866
|
+
let t = await i(e, n.fonts);
|
|
867
|
+
if (t !== null) {
|
|
868
|
+
for (let e of t.files) {
|
|
869
|
+
let t = z(E, e.fileName);
|
|
870
|
+
await H.mkdir(R(t), { recursive: !0 }), await H.writeFile(t, Buffer.from(e.bytes));
|
|
871
|
+
}
|
|
872
|
+
$.info(`fonts: ${t.files.length} hashed file(s) into dist/assets/fonts`);
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
a(e);
|
|
876
|
+
let { rendered: Y, pageMeta: re } = await Se({
|
|
877
|
+
root: e,
|
|
878
|
+
distDir: E,
|
|
879
|
+
pages: q,
|
|
880
|
+
dirs: J,
|
|
881
|
+
vite: P,
|
|
882
|
+
islandsPlans: v,
|
|
883
|
+
...n.locales ? { locales: n.locales } : {},
|
|
884
|
+
...n.defaultLocale ? { defaultLocale: n.defaultLocale } : {},
|
|
885
|
+
...n.timeZone ? { timeZone: n.timeZone } : {},
|
|
886
|
+
...n.defaultTimeZone ? { defaultTimeZone: n.defaultTimeZone } : {},
|
|
887
|
+
...n.images === void 0 ? {} : { images: n.images },
|
|
888
|
+
...n.fonts === void 0 ? {} : { fonts: n.fonts },
|
|
889
|
+
...n.seo?.siteUrl === void 0 ? {} : { siteUrl: n.seo.siteUrl }
|
|
890
|
+
});
|
|
891
|
+
await O(E), await m(E, n.feeds ?? [], n.seo?.siteUrl), $.info("generating .framework/ssrEntry.ts"), await Ce(e, q, J, n.locales, n.defaultLocale, re, {
|
|
892
|
+
...n.timeZone ? { timeZone: n.timeZone } : {},
|
|
893
|
+
...n.defaultTimeZone ? { defaultTimeZone: n.defaultTimeZone } : {}
|
|
894
|
+
}, s.map((e) => ({
|
|
895
|
+
name: e.name,
|
|
896
|
+
pkg: e.pkg
|
|
897
|
+
}))), $.info("vite build --ssr → dist/server/");
|
|
898
|
+
let X = /* @__PURE__ */ new Set();
|
|
899
|
+
try {
|
|
900
|
+
await P.build({
|
|
901
|
+
root: T,
|
|
902
|
+
envPrefix: "__VOLTRO_VITE_ENV_DISABLED__",
|
|
903
|
+
plugins: [
|
|
904
|
+
F(),
|
|
905
|
+
L(),
|
|
906
|
+
u({
|
|
907
|
+
root: e,
|
|
908
|
+
config: I(n.images)
|
|
909
|
+
}),
|
|
910
|
+
he(e, X),
|
|
911
|
+
me()
|
|
912
|
+
],
|
|
913
|
+
resolve: {
|
|
914
|
+
alias: N,
|
|
915
|
+
dedupe: [
|
|
916
|
+
"react",
|
|
917
|
+
"react-dom",
|
|
918
|
+
"react-intl",
|
|
919
|
+
"@voltro/i18n"
|
|
920
|
+
]
|
|
921
|
+
},
|
|
922
|
+
ssr: { noExternal: !0 },
|
|
923
|
+
esbuild: { keepNames: !0 },
|
|
924
|
+
build: {
|
|
925
|
+
outDir: "dist/server",
|
|
926
|
+
ssr: "ssrEntry.ts",
|
|
927
|
+
minify: "esbuild",
|
|
928
|
+
sourcemap: U.emit ? "hidden" : !1,
|
|
929
|
+
emptyOutDir: !0,
|
|
930
|
+
rollupOptions: { output: { format: "esm" } }
|
|
931
|
+
},
|
|
932
|
+
logLevel: "warn"
|
|
933
|
+
}), $.info("SSR bundle ready", {
|
|
934
|
+
path: "dist/server/ssrEntry.js",
|
|
935
|
+
...X.size > 0 ? { externalizedOptionalPeers: [...X].join(", ") } : {}
|
|
936
|
+
});
|
|
937
|
+
} catch (e) {
|
|
938
|
+
return $.fatal("SSR bundle build FAILED — refusing to ship a bundle-less image. Fix the error above (production renders from the SSR bundle, never by compiling on demand).", {}, e), await G({
|
|
939
|
+
serverBundles: !0,
|
|
940
|
+
upload: !1
|
|
941
|
+
}), {
|
|
942
|
+
ran: !0,
|
|
943
|
+
exitCode: 1
|
|
944
|
+
};
|
|
945
|
+
}
|
|
946
|
+
let Z = z(e, "app.config.ts");
|
|
947
|
+
if (V(Z)) {
|
|
948
|
+
$.info("precompiling app.config.ts → dist/server/appConfig.js");
|
|
949
|
+
try {
|
|
950
|
+
await (await d("esbuild", () => import("esbuild"))).build({
|
|
951
|
+
entryPoints: [Z],
|
|
952
|
+
outfile: z(E, "server", "appConfig.js"),
|
|
953
|
+
bundle: !0,
|
|
954
|
+
format: "esm",
|
|
955
|
+
platform: "node",
|
|
956
|
+
target: "node22",
|
|
957
|
+
plugins: [M([], e, /* @__PURE__ */ new Set())],
|
|
958
|
+
banner: { js: A() },
|
|
959
|
+
jsx: "automatic",
|
|
960
|
+
jsxImportSource: "react",
|
|
961
|
+
absWorkingDir: e,
|
|
962
|
+
logLevel: "silent",
|
|
963
|
+
...V(z(e, "tsconfig.json")) ? { tsconfig: z(e, "tsconfig.json") } : {}
|
|
964
|
+
});
|
|
965
|
+
} catch (e) {
|
|
966
|
+
return $.fatal("app.config precompile FAILED — production `voltro start` would need the tsx loader to read it.", {}, e), await G({
|
|
967
|
+
serverBundles: !0,
|
|
968
|
+
upload: !1
|
|
969
|
+
}), {
|
|
970
|
+
ran: !0,
|
|
971
|
+
exitCode: 1
|
|
972
|
+
};
|
|
973
|
+
}
|
|
974
|
+
}
|
|
975
|
+
try {
|
|
976
|
+
await ie(e, { sourcemaps: U.emit });
|
|
977
|
+
} catch (e) {
|
|
978
|
+
$.warn("start bundle build failed — `voltro start` will use the slower per-module boot", {}, e);
|
|
979
|
+
}
|
|
980
|
+
let Q = await G({
|
|
981
|
+
serverBundles: !0,
|
|
982
|
+
upload: !0
|
|
983
|
+
});
|
|
984
|
+
if (Q !== null) return {
|
|
985
|
+
ran: !0,
|
|
986
|
+
exitCode: Q
|
|
987
|
+
};
|
|
988
|
+
$.info(`pre-rendered ${Y.length} static route(s)`, {
|
|
989
|
+
count: Y.length,
|
|
990
|
+
routes: Y.map((e) => e.pattern)
|
|
991
|
+
});
|
|
992
|
+
try {
|
|
993
|
+
let e = process.env.VOLTRO_SEO_NOINDEX !== "1", t = n.seo?.siteUrl, r = n.locales ?? [], i = n.defaultLocale ?? r[0];
|
|
994
|
+
if (t && !V(z(E, "sitemap.xml"))) {
|
|
995
|
+
let n = new Set(r.filter((e) => e !== i)), a = Y.filter((e) => !e.noIndex).map((e) => e.pattern).filter((e) => {
|
|
996
|
+
let t = e.split("/").filter(Boolean)[0];
|
|
997
|
+
return t === void 0 || !n.has(t);
|
|
998
|
+
}).filter((e) => !e.includes("[")).map((e) => ({ path: e })), o = g({
|
|
999
|
+
siteUrl: t,
|
|
1000
|
+
entries: a,
|
|
1001
|
+
...r.length > 1 ? { locales: r } : {},
|
|
1002
|
+
...i ? { defaultLocale: i } : {}
|
|
1003
|
+
});
|
|
1004
|
+
await H.writeFile(z(E, "sitemap.xml"), o, "utf8"), $.info("wrote dist/sitemap.xml", {
|
|
1005
|
+
urls: a.length,
|
|
1006
|
+
indexable: e
|
|
1007
|
+
});
|
|
1008
|
+
}
|
|
1009
|
+
if (!V(z(E, "robots.txt"))) {
|
|
1010
|
+
let r = y({
|
|
1011
|
+
indexable: e,
|
|
1012
|
+
...e && t ? { sitemapUrl: `${t.replace(/\/$/, "")}/sitemap.xml` } : {},
|
|
1013
|
+
...n.seo?.disallow ? { disallow: n.seo.disallow } : {}
|
|
1014
|
+
});
|
|
1015
|
+
await H.writeFile(z(E, "robots.txt"), r, "utf8"), $.info("wrote dist/robots.txt", { indexable: e });
|
|
1016
|
+
}
|
|
1017
|
+
{
|
|
1018
|
+
let { precompressAssets: e } = await import("./precompressAssets-YhTi1aWp.js"), t = await e(E);
|
|
1019
|
+
t.files > 0 && $.info("pre-compressed assets", {
|
|
1020
|
+
files: t.files,
|
|
1021
|
+
raw: t.originalBytes,
|
|
1022
|
+
br: t.brotliBytes,
|
|
1023
|
+
gz: t.gzipBytes
|
|
1024
|
+
});
|
|
1025
|
+
}
|
|
1026
|
+
} catch (e) {
|
|
1027
|
+
$.warn("SEO artefact generation failed (non-fatal)", {}, e);
|
|
1028
|
+
}
|
|
1029
|
+
try {
|
|
1030
|
+
let t = await ne(e);
|
|
1031
|
+
await H.writeFile(z(E, ".voltro-build.json"), JSON.stringify({
|
|
1032
|
+
version: 1,
|
|
1033
|
+
profile: t
|
|
1034
|
+
}, null, 2), "utf8"), $.info("wrote deploy profile manifest", {
|
|
1035
|
+
staticSafe: t.staticSafe,
|
|
1036
|
+
ssr: t.counts.ssr,
|
|
1037
|
+
isr: t.counts.isr
|
|
1038
|
+
});
|
|
1039
|
+
} catch (e) {
|
|
1040
|
+
$.warn("could not write .voltro-build.json deploy manifest", {}, e);
|
|
1041
|
+
}
|
|
1042
|
+
return $.info("build complete", { distDir: E }), {
|
|
1043
|
+
ran: !0,
|
|
1044
|
+
exitCode: 0
|
|
1045
|
+
};
|
|
1046
|
+
}, Ee = (e) => K.gen(function* () {
|
|
1047
|
+
let t = yield* K.tryPromise({
|
|
1048
|
+
try: () => Te(B(e)),
|
|
1049
|
+
catch: (e) => e
|
|
1050
|
+
}).pipe(K.orDie);
|
|
1051
|
+
return t.ran ? t.exitCode : (yield* K.logError("no voltro app found at this path", { hint: "looked for an app.config.ts with `type: 'web'` or `type: 'api'` — a web app gets the vite build + prerender + start bundle, an api gets the precompiled serve bundle" }), 1);
|
|
1052
|
+
}), De = async (t) => {
|
|
1053
|
+
if (G("build"), t.includes("--target")) {
|
|
1054
|
+
let { runSdkBuildCommand: e } = await import("./sdkgen-vq1fF9D_.js");
|
|
1055
|
+
return e(t);
|
|
1056
|
+
}
|
|
1057
|
+
let n = t.find((e) => !e.startsWith("-")) ?? process.cwd(), r = await P(Ee(n), { scope: "voltro:build" });
|
|
1058
|
+
if (r === 0 && t.includes("--report")) {
|
|
1059
|
+
let { collectBuildReport: e, formatBuildReport: t } = await import("./buildReport-52gHKgfO.js");
|
|
1060
|
+
for (let r of t(e(n))) console.log(r);
|
|
1061
|
+
}
|
|
1062
|
+
let i = e(n);
|
|
1063
|
+
return i.warning !== void 0 && $.warn(i.warning), r;
|
|
1064
|
+
};
|
|
1065
|
+
//#endregion
|
|
1066
|
+
export { De as runBuildCommand };
|