@voltro/cli 0.58.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.
Files changed (79) hide show
  1. package/CHANGELOG.md +55 -0
  2. package/dist/apiBuild-B9OvhITV.js +2 -0
  3. package/dist/{apiBuild-CkpsCqIu.js → apiBuild-BU5cd-Fn.js} +50 -48
  4. package/dist/bin.js +1 -1
  5. package/dist/{build-51qBWfYY.js → build-uRMZrT8z.js} +338 -253
  6. package/dist/{checkCommand-C1EbNmwl.js → checkCommand-C1CQc8lD.js} +1 -1
  7. package/dist/{checkCommand-C30J2F18.js → checkCommand-DC7k1_hP.js} +1 -1
  8. package/dist/{codemodRunner-BKjCwGiN.js → codemodRunner-kNnh1I7_.js} +474 -390
  9. package/dist/{commands-DowWkYtd.js → commands-cu34ENUT.js} +10 -10
  10. package/dist/{doctorCommand-5ULMpL10.js → doctorCommand-CGjefPmk.js} +2 -2
  11. package/dist/doctorCommand-DXnNpKQT.js +2 -0
  12. package/dist/{evolveCommand-DTawtTxf.js → evolveCommand-8CuFBlbQ.js} +2 -2
  13. package/dist/index.js +1 -1
  14. package/dist/{infoCommand-BFksHunl.js → infoCommand-D02A4WI2.js} +1 -1
  15. package/dist/{runtimeTrace-BUk5zMXY.js → runtimeTrace-DDuKJgVi.js} +1 -1
  16. package/dist/{sdkgen-CAhmmbjx.js → sdkgen-vq1fF9D_.js} +1 -1
  17. package/dist/serveCommand-1R52mo6F.js +2 -0
  18. package/dist/{serveCommand-DhtC7WBq.js → serveCommand-Dr4KXmTS.js} +1 -1
  19. package/dist/serveEntry.js +1 -1
  20. package/dist/{updateCommand-CtuD5r1t.js → updateCommand-Bw3mCUDT.js} +1 -1
  21. package/dist/updateCommand-inInBIAh.js +2 -0
  22. package/package.json +31 -19
  23. package/templates/AGENTS.md +1 -1
  24. package/templates/agent-docs/_index.md +1 -1
  25. package/templates/agent-docs/ai.md +50 -1
  26. package/templates/agent-docs/cli.md +7 -6
  27. package/templates/agent-docs/plugins/sentry.md +54 -15
  28. package/templates/agent-docs/whats-new.md +24 -170
  29. package/templates/apps/api-ai/package.json +6 -6
  30. package/templates/apps/api-auth/package.json +8 -8
  31. package/templates/apps/api-backend/package.json +7 -7
  32. package/templates/apps/api-backend-deactivation/package.json +7 -7
  33. package/templates/apps/api-backend-mail/package.json +8 -8
  34. package/templates/apps/api-backend-mariadb/package.json +9 -9
  35. package/templates/apps/api-backend-sqlite/package.json +8 -8
  36. package/templates/apps/api-backend-storage/package.json +8 -8
  37. package/templates/apps/api-cms/package.json +9 -9
  38. package/templates/apps/api-collab/package.json +8 -8
  39. package/templates/apps/api-data-advanced/package.json +8 -8
  40. package/templates/apps/api-durable/package.json +8 -8
  41. package/templates/apps/api-feature-flags/package.json +9 -9
  42. package/templates/apps/api-governance/package.json +8 -8
  43. package/templates/apps/api-kv/package.json +8 -8
  44. package/templates/apps/api-moderation/package.json +8 -8
  45. package/templates/apps/api-observability/package.json +8 -8
  46. package/templates/apps/api-ratelimit/package.json +8 -8
  47. package/templates/apps/api-rbac/package.json +8 -8
  48. package/templates/apps/api-rest/package.json +7 -7
  49. package/templates/apps/api-row-history/package.json +8 -8
  50. package/templates/apps/api-saas/package.json +11 -11
  51. package/templates/apps/api-saas-starter/package.json +10 -10
  52. package/templates/apps/api-search/package.json +8 -8
  53. package/templates/apps/api-status/package.json +8 -8
  54. package/templates/apps/api-webhooks/package.json +9 -9
  55. package/templates/apps/changelog/package.json +7 -7
  56. package/templates/apps/edge-functions/package.json +2 -2
  57. package/templates/apps/frontend-admin/package.json +7 -7
  58. package/templates/apps/frontend-app/package.json +8 -8
  59. package/templates/apps/frontend-auth/package.json +7 -7
  60. package/templates/apps/frontend-blank/package.json +6 -6
  61. package/templates/apps/frontend-cms/package.json +8 -8
  62. package/templates/apps/frontend-collab/package.json +9 -9
  63. package/templates/apps/frontend-contact/package.json +7 -7
  64. package/templates/apps/frontend-dashboard/package.json +6 -6
  65. package/templates/apps/frontend-docs/package.json +8 -8
  66. package/templates/apps/frontend-i18n/package.json +6 -6
  67. package/templates/apps/frontend-landing/package.json +7 -7
  68. package/templates/apps/frontend-portal/package.json +7 -7
  69. package/templates/apps/frontend-saas/package.json +7 -7
  70. package/templates/apps/frontend-spa/package.json +6 -6
  71. package/templates/apps/frontend-ssr/package.json +6 -6
  72. package/templates/apps/frontend-ssr-api/package.json +7 -7
  73. package/templates/apps/frontend-static-blog/package.json +8 -8
  74. package/templates/apps/frontend-status/package.json +7 -7
  75. package/templates/apps/mobile-app/package.json +4 -4
  76. package/dist/apiBuild-CDE4NXNi.js +0 -2
  77. package/dist/doctorCommand-B8H2MYCE.js +0 -2
  78. package/dist/serveCommand-BUXUtSF5.js +0 -2
  79. package/dist/updateCommand-eVKVHj3N.js +0 -2
@@ -1,25 +1,25 @@
1
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 O, wt as k, zt as A } from "./webDev-CBN9KkyQ.js";
3
- import { d as j, i as M, o as N, s as P } from "./apiBuild-CkpsCqIu.js";
4
- import { t as F } from "./cliRuntime-Dh7UDinH.js";
5
- import { a as I } from "./renderModeScan-43yQ2opo.js";
6
- import { o as L } from "./imagePipeline-CBZmjT4i.js";
7
- import { a as R } from "./fontPipeline-Tsh8kZfA.js";
8
- import { n as z } from "./renderProfile-DvrhVJHa.js";
9
- import { dirname as B, join as V, resolve as H } from "node:path";
10
- import { existsSync as U, promises as W } from "node:fs";
11
- import { pathToFileURL as G } from "node:url";
12
- import { createLogger as K } from "@voltro/logger";
13
- import { setProcessBootPath as q } from "@voltro/protocol/identity";
14
- import { Effect as J } from "effect";
15
- import { createRequire as Y } from "node:module";
16
- import { readdir as te, rm as X, stat as Z } from "node:fs/promises";
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
17
  //#region src/webStartBundle.ts
18
- var ne = K({ scope: "voltro:build" }), re = async (e) => {
19
- let t = await d("esbuild", () => import("esbuild")), n = V(e, ".framework"), r = V(n, "dist-web", "startBundle");
20
- await W.mkdir(n, { recursive: !0 });
21
- let i = Date.now(), a = V(e, "tsconfig.json"), o = /* @__PURE__ */ new Set(), s = V(n, "startEntry.ts");
22
- await W.writeFile(s, [
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
23
  "// GENERATED BY `voltro build` — do not edit; overwritten on next build.",
24
24
  "import { runStartCommand as __run, loadDotEnv } from '@voltro/cli/startEntry'",
25
25
  "import { pathToFileURL, fileURLToPath } from 'node:url'",
@@ -42,33 +42,34 @@ var ne = K({ scope: "voltro:build" }), re = async (e) => {
42
42
  " runStartCommand(process.argv.slice(2)).then((c) => process.exit(typeof c === 'number' ? c : 0))",
43
43
  "}",
44
44
  ""
45
- ].join("\n"), "utf8"), await t.build({
46
- entryPoints: [s],
45
+ ].join("\n"), "utf8"), await n.build({
46
+ entryPoints: [c],
47
47
  bundle: !0,
48
48
  format: "esm",
49
49
  platform: "node",
50
50
  target: "node22",
51
- outdir: r,
51
+ outdir: i,
52
52
  splitting: !0,
53
53
  write: !0,
54
54
  minify: !0,
55
55
  keepNames: !0,
56
- plugins: [N([], e, o)],
57
- banner: { js: j() },
56
+ sourcemap: t.sourcemaps === !0 && "external",
57
+ plugins: [M([], e, s)],
58
+ banner: { js: A() },
58
59
  jsx: "automatic",
59
60
  jsxImportSource: "react",
60
61
  logLevel: "silent",
61
62
  absWorkingDir: e,
62
- alias: M("startEntry"),
63
- ...U(a) ? { tsconfig: a } : {}
63
+ alias: j("startEntry"),
64
+ ...V(o) ? { tsconfig: o } : {}
64
65
  });
65
- let c = await P(r, i);
66
- return ne.info("web build: start bundle written", {
67
- out: V(".framework", "dist-web", "startBundle", "startEntry.js"),
68
- ...o.size > 0 ? { externalizedOptionalPeers: [...o].join(", ") } : {},
69
- ...c > 0 ? { prunedStaleChunks: c } : {}
70
- }), V(r, "startEntry.js");
71
- }, ie = "~/assets", ae = (e, t) => {
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) => {
72
73
  if (e === void 0) return {
73
74
  emit: !1,
74
75
  keep: !1
@@ -82,9 +83,9 @@ var ne = K({ scope: "voltro:build" }), re = async (e) => {
82
83
  keep: e.keep ?? !0
83
84
  };
84
85
  let { org: n, project: r, url: i, urlPrefix: a } = e.upload, o = e.upload.release ?? t.SENTRY_RELEASE;
85
- if (o === void 0 || o === "") return { problem: "web.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." };
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." };
86
87
  let s = t.SENTRY_AUTH_TOKEN;
87
- return s === void 0 || s === "" ? { problem: "web.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." } : {
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." } : {
88
89
  emit: !0,
89
90
  keep: e.keep ?? !1,
90
91
  upload: {
@@ -92,61 +93,81 @@ var ne = K({ scope: "voltro:build" }), re = async (e) => {
92
93
  project: r,
93
94
  release: o,
94
95
  authToken: s,
95
- urlPrefix: a ?? ie,
96
+ ...a === void 0 ? {} : { urlPrefix: a },
96
97
  ...i === void 0 ? {} : { url: i }
97
98
  }
98
99
  };
99
- }, oe = (e) => "problem" in e, se = async (e) => {
100
+ }, se = (e) => "problem" in e, Z = async (e) => {
100
101
  let t = [], n = async (e) => {
101
102
  let r;
102
103
  try {
103
- r = await te(e);
104
+ r = await J(e);
104
105
  } catch {
105
106
  return;
106
107
  }
107
108
  for (let i of r) {
108
- let r = V(e, i), a = await Z(r).catch(() => void 0);
109
+ let r = z(e, i), a = await re(r).catch(() => void 0);
109
110
  a !== void 0 && (a.isDirectory() ? await n(r) : i.endsWith(".map") && t.push(r));
110
111
  }
111
112
  };
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];
113
121
  }, ce = (e) => async (t, n, r) => {
114
- let i = new (await (le(e)))(null, {
122
+ let i = new (await (ue(e)))(null, {
115
123
  authToken: t.authToken,
116
124
  org: t.org,
117
125
  project: t.project,
118
126
  ...t.url === void 0 ? {} : { url: t.url },
119
127
  silent: !1
120
128
  });
121
- await i.releases.new(t.release), await i.releases.uploadSourceMaps(t.release, {
122
- include: [r],
123
- urlPrefix: t.urlPrefix,
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,
124
133
  rewrite: !0
125
- }), await i.releases.finalize(t.release);
126
- }, le = async (e) => {
127
- let t = Y(V(e, "package.json")), n = [];
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 = [];
128
146
  try {
129
- let e = await import(G(t.resolve("@sentry/cli")).href), r = e.default ?? e;
130
- if (typeof r == "function") return r;
131
- n.push("resolved a module that is not the SentryCli constructor");
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"})`);
132
152
  } catch (e) {
133
- n.push(e instanceof Error ? e.message : String(e));
153
+ r.push(e instanceof Error ? e.message : String(e));
134
154
  }
135
- throw Error("web.sourcemaps.upload is configured but `@sentry/cli` could not be loaded.\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 web app.\n" + n.map((e) => ` · ${e}`).join("\n"));
136
- }, ue = async (e, t, n = {}) => {
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 = {}) => {
137
157
  if (!t.emit) return {
138
158
  uploaded: 0,
139
159
  deleted: 0
140
160
  };
141
- let r = await se(e), i = 0;
161
+ let r = (await Promise.all(e.map((e) => Z(e.dir)))).flat(), i = 0;
142
162
  try {
143
- t.upload !== void 0 && r.length > 0 && (await (n.upload ?? ce(n.appRoot ?? e))(t.upload, r, e), i = r.length, n.log?.info("source maps uploaded to Sentry", {
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", {
144
164
  release: t.upload.release,
145
- files: r.length
165
+ files: r.length,
166
+ dirs: e.length
146
167
  }));
147
168
  } finally {
148
169
  if (!t.keep) {
149
- for (let e of r) await X(e, { force: !0 });
170
+ for (let e of r) await Y(e, { force: !0 });
150
171
  n.log?.info("source maps removed from the build output", { files: r.length });
151
172
  }
152
173
  }
@@ -154,24 +175,27 @@ var ne = K({ scope: "voltro:build" }), re = async (e) => {
154
175
  uploaded: i,
155
176
  deleted: t.keep ? 0 : r.length
156
177
  };
157
- }, Q = K({ scope: "voltro:build" }), $ = () => ({
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 = () => ({
158
182
  name: "voltro:stub-engine-devtools",
159
183
  resolveId: (e) => e === "@tanstack/devtools-event-client" ? "\0voltro-engine-devtools-stub" : void 0,
160
184
  load: (e) => e === "\0voltro-engine-devtools-stub" ? "export class EventClient { constructor() {} on() { return () => {} } emit() {} }\n" : void 0
161
- }), de = (e, t) => ({
185
+ }), he = (e, t) => ({
162
186
  name: "voltro:ssr-optional-peer-external",
163
187
  enforce: "pre",
164
188
  resolveId(n, r) {
165
189
  if (n.startsWith(".") || n.startsWith("/") || n.startsWith("\0") || n.startsWith("node:") || n === "effect" || n.startsWith("@effect/") || n.startsWith("@voltro/")) return null;
166
- for (let t of [r ? B(r) : void 0, e]) if (t !== void 0) try {
167
- return Y(V(t, "_.js")).resolve(n), 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;
168
192
  } catch {}
169
193
  return t.add(n), {
170
194
  id: n,
171
195
  external: !0
172
196
  };
173
197
  }
174
- }), fe = (e) => /\[/.test(e), pe = (e, t) => {
198
+ }), ge = (e) => /\[/.test(e), _e = (e, t) => {
175
199
  let n = e.split("/").filter(Boolean), r = [];
176
200
  for (let i of n) if (i.startsWith("[[...") && i.endsWith("]]")) {
177
201
  let e = t[i.slice(5, -2)];
@@ -187,29 +211,29 @@ var ne = K({ scope: "voltro:build" }), re = async (e) => {
187
211
  r.push(a);
188
212
  } else r.push(i);
189
213
  return r.length === 0 ? "/" : "/" + r.join("/");
190
- }, me = (e, t) => {
191
- if (t === "/" || t === "") return V(e, "index.html");
214
+ }, ve = (e, t) => {
215
+ if (t === "/" || t === "") return z(e, "index.html");
192
216
  let n = t.replace(/^\//, "").split("/");
193
- return V(e, ...n, "index.html");
194
- }, he = (e) => e.replace(/<script\b(?=[^>]*\btype="module")(?:(?!<\/script>).)*<\/script>/gi, "").replace(/<script\b(?=[^>]*\bsrc=)(?:(?!<\/script>).)*<\/script>/gi, "").replace(/<link\b[^>]*\brel="modulepreload"[^>]*>/gi, ""), ge = (e, t) => {
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) => {
195
219
  let n = e.replace("<div id=\"root\"></div>", `<div id="root">${t.body}</div>`), r = [
196
220
  t.metaHtml,
197
221
  `<meta name="voltro-interactive" content="${t.interactive}" />`,
198
222
  t.stateScript
199
223
  ].filter((e) => e.length > 0).join("\n ");
200
- return n = T(o(n, r), t.documentAttrs), t.interactive === "none" && (n = he(n)), n;
201
- }, _e = async (e) => {
224
+ return n = T(o(n, r), t.documentAttrs), t.interactive === "none" && (n = ye(n)), n;
225
+ }, xe = async (e) => {
202
226
  let { page: t, chainEntries: n, pageMod: r, helpers: i } = e, a = n.filter((e) => e.hasLayout);
203
- if (a.length === 0) return Q.debug("skip page", {
227
+ if (a.length === 0) return $.debug("skip page", {
204
228
  pattern: t.pattern,
205
229
  reason: "renderMode=spa with no layout — nothing to shell"
206
230
  }), null;
207
- if (fe(t.pattern)) return Q.debug("skip page", {
231
+ if (ge(t.pattern)) return $.debug("skip page", {
208
232
  pattern: t.pattern,
209
233
  reason: "renderMode=spa with a dynamic pattern"
210
234
  }), null;
211
235
  let s = await Promise.all(a.map(e.loadLayout)), c = a.filter((e, t) => typeof s[t]?.loader == "function").map((e) => e.dir || "/");
212
- if (c.length > 0) return Q.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`, {
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`, {
213
237
  pattern: t.pattern,
214
238
  layouts: c
215
239
  }), null;
@@ -248,56 +272,56 @@ var ne = K({ scope: "voltro:build" }), re = async (e) => {
248
272
  prepared: p,
249
273
  meta: m.meta,
250
274
  interactive: f
251
- }), g = o(e.shellTemplate.replace("<div id=\"root\"></div>", `<div id="root">${m.body}</div>`), h), y = me(e.distDir, t.pattern);
252
- return await W.mkdir(B(y), { recursive: !0 }), await W.writeFile(y, g, "utf8"), Q.debug("prerendered spa layout shell", { pattern: t.pattern }), {
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 }), {
253
277
  pattern: t.pattern,
254
278
  outPath: y
255
279
  };
256
- }, ve = async (e) => {
257
- let { root: t, distDir: r, pages: i, dirs: a, vite: o } = e, c = V(r, "index.html"), d = await W.readFile(c, "utf8"), p = V(r, "_voltro", "shell.html");
258
- await W.mkdir(B(p), { recursive: !0 }), await W.writeFile(p, d, "utf8");
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");
259
283
  let m = /* @__PURE__ */ new Map();
260
284
  for (let t of e.islandsPlans ?? []) {
261
- let e = V(r, "island-shells", `${t.name}.html`);
285
+ let e = z(r, "island-shells", `${t.name}.html`);
262
286
  try {
263
- let n = l(await W.readFile(e, "utf8"), d);
264
- await W.writeFile(e, n, "utf8"), m.set(t.pattern, n);
287
+ let n = l(await H.readFile(e, "utf8"), d);
288
+ await H.writeFile(e, n, "utf8"), m.set(t.pattern, n);
265
289
  } catch {
266
- Q.warn("islands shell missing — page ships the full entry", {
290
+ $.warn("islands shell missing — page ships the full entry", {
267
291
  pattern: t.pattern,
268
292
  expected: e
269
293
  });
270
294
  }
271
295
  }
272
- let h = V(t, "node_modules", "@voltro", "ui-shadcn"), g = U(V(h, "package.json")) ? h : null, v = [...g ? [
296
+ let h = z(t, "node_modules", "@voltro", "ui-shadcn"), g = V(z(h, "package.json")) ? h : null, v = [...g ? [
273
297
  {
274
298
  find: "@voltro/ui-shadcn/tokens.css",
275
- replacement: V(g, "src/tokens.css")
299
+ replacement: z(g, "src/tokens.css")
276
300
  },
277
301
  {
278
302
  find: "@voltro/ui-shadcn/cn",
279
- replacement: V(g, "src/cn.ts")
303
+ replacement: z(g, "src/cn.ts")
280
304
  },
281
305
  {
282
306
  find: "@voltro/ui-shadcn/brand",
283
- replacement: V(g, "src/brand/voltroLogo.tsx")
307
+ replacement: z(g, "src/brand/voltroLogo.tsx")
284
308
  },
285
309
  {
286
310
  find: "@voltro/ui-shadcn",
287
- replacement: V(g, "src/index.ts")
311
+ replacement: z(g, "src/index.ts")
288
312
  }
289
- ] : [], ...A(t)], y = await o.createServer({
290
- root: V(t, ".framework"),
313
+ ] : [], ...k(t)], y = await o.createServer({
314
+ root: z(t, ".framework"),
291
315
  envPrefix: "__VOLTRO_VITE_ENV_DISABLED__",
292
316
  plugins: [
293
317
  (await import("@vitejs/plugin-react")).default(),
294
318
  (await import("@tailwindcss/vite")).default(),
295
319
  u({
296
320
  root: t,
297
- config: L(e.images),
321
+ config: I(e.images),
298
322
  urlMode: "build-urls"
299
323
  }),
300
- $()
324
+ me()
301
325
  ],
302
326
  resolve: {
303
327
  alias: v,
@@ -316,11 +340,11 @@ var ne = K({ scope: "voltro:build" }), re = async (e) => {
316
340
  },
317
341
  appType: "custom",
318
342
  logLevel: "warn"
319
- }), b = await y.ssrLoadModule("@voltro/web/ssr"), { renderPageToHtml: x, renderMetaToHtml: S, renderRouterStateScript: C, isDeferredLoaderResult: w, assertDeferralSupported: T, beginStoreSeeds: E, seedPreloadedSubscription: ee, seedPreloadedSubscriptionFailure: O } = b, k, j = /* @__PURE__ */ new Map();
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();
320
344
  if (e.locales && e.locales.length > 0 && e.defaultLocale) try {
321
345
  let n = await y.ssrLoadModule("@voltro/i18n");
322
346
  try {
323
- k = (await y.ssrLoadModule("@voltro/i18n/server")).resolveTimeZone?.({
347
+ O = (await y.ssrLoadModule("@voltro/i18n/server")).resolveTimeZone?.({
324
348
  configured: e.timeZone ?? null,
325
349
  defaultTimeZone: e.defaultTimeZone ?? null
326
350
  });
@@ -328,15 +352,15 @@ var ne = K({ scope: "voltro:build" }), re = async (e) => {
328
352
  let r = n.makeSsgWrap;
329
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.");
330
354
  for (let n of e.locales) try {
331
- let i = await y.ssrLoadModule(V(t, "src", "locales", `${n}.ts`)), a = i.default ?? i;
332
- j.set(n, r(n, a, e.defaultLocale));
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));
333
357
  } catch (e) {
334
- Q.warn(`i18n catalog missing for locale '${n}' — pages rendered at /${n}/* will crash. Add src/locales/${n}.ts.`, {}, e);
358
+ $.warn(`i18n catalog missing for locale '${n}' — pages rendered at /${n}/* will crash. Add src/locales/${n}.ts.`, {}, e);
335
359
  }
336
360
  } catch (e) {
337
- Q.warn("i18n wrapper unavailable for SSG — pages that call useT() will fail. Check that @voltro/i18n is installed.", {}, e);
361
+ $.warn("i18n wrapper unavailable for SSG — pages that call useT() will fail. Check that @voltro/i18n is installed.", {}, e);
338
362
  }
339
- let M = [], N = {}, P = (e) => e.dir === "" ? V(t, "src", "pages") : V(t, "src", "pages", e.dir), F = async (e) => await y.ssrLoadModule(V(P(e), "layout.tsx")), z = async (e) => await y.ssrLoadModule(V(P(e), "error.tsx")), H = async (e) => await y.ssrLoadModule(V(P(e), "loading.tsx")), G = (e, t) => ({
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) => ({
340
364
  params: e.params,
341
365
  pathname: e.pathname,
342
366
  search: "",
@@ -346,41 +370,41 @@ var ne = K({ scope: "voltro:build" }), re = async (e) => {
346
370
  isServer: !0
347
371
  });
348
372
  for (let o of i) {
349
- let i = `${V(t, "src", "pages", o.file)}`, c = await y.ssrLoadModule(i), l = I(c, V("src", "pages", o.file));
350
- N[o.pattern] = l;
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;
351
375
  let u = l.renderMode, p = D(a, o.dirChain);
352
376
  if (u === "spa") {
353
- let t = await _e({
377
+ let t = await xe({
354
378
  page: o,
355
379
  chainEntries: p,
356
380
  pageMod: c,
357
381
  shellTemplate: d,
358
382
  distDir: r,
359
383
  helpers: b,
360
- loadLayout: F,
361
- loadError: z,
362
- loadPending: H,
363
- ctx: G({
384
+ loadLayout: P,
385
+ loadError: ne,
386
+ loadPending: B,
387
+ ctx: U({
364
388
  params: {},
365
389
  pathname: o.pattern
366
390
  }, new AbortController().signal),
367
- outerWrap: j.get(e.defaultLocale ?? ""),
391
+ outerWrap: A.get(e.defaultLocale ?? ""),
368
392
  locale: e.defaultLocale
369
393
  });
370
- t && M.push(t);
394
+ t && j.push(t);
371
395
  continue;
372
396
  }
373
397
  if (u !== "static") {
374
- Q.debug("skip page", {
398
+ $.debug("skip page", {
375
399
  pattern: o.pattern,
376
400
  reason: `renderMode=${u}`
377
401
  });
378
402
  continue;
379
403
  }
380
404
  let h;
381
- if (fe(o.pattern)) {
405
+ if (ge(o.pattern)) {
382
406
  if (typeof c.getStaticPaths != "function") {
383
- Q.debug("skip page", {
407
+ $.debug("skip page", {
384
408
  pattern: o.pattern,
385
409
  reason: "no getStaticPaths export"
386
410
  });
@@ -389,19 +413,19 @@ var ne = K({ scope: "voltro:build" }), re = async (e) => {
389
413
  try {
390
414
  let e = await c.getStaticPaths();
391
415
  if (!Array.isArray(e)) {
392
- Q.warn("skip page — getStaticPaths did not return an array", { pattern: o.pattern });
416
+ $.warn("skip page — getStaticPaths did not return an array", { pattern: o.pattern });
393
417
  continue;
394
418
  }
395
419
  h = e.map((e) => ({
396
420
  params: e.params,
397
- pathname: pe(o.pattern, e.params)
421
+ pathname: _e(o.pattern, e.params)
398
422
  }));
399
423
  } catch (e) {
400
- Q.warn("skip page — getStaticPaths threw", { pattern: o.pattern }, e);
424
+ $.warn("skip page — getStaticPaths threw", { pattern: o.pattern }, e);
401
425
  continue;
402
426
  }
403
427
  if (h.length === 0) {
404
- Q.debug("skip page", {
428
+ $.debug("skip page", {
405
429
  pattern: o.pattern,
406
430
  reason: "getStaticPaths returned []"
407
431
  });
@@ -418,16 +442,16 @@ var ne = K({ scope: "voltro:build" }), re = async (e) => {
418
442
  try {
419
443
  ({chain: a, segmentLoaderData: l} = await _({
420
444
  entries: p,
421
- loadLayout: F,
422
- loadError: z,
423
- loadPending: H,
424
- ctx: G(i, h.signal)
445
+ loadLayout: P,
446
+ loadError: ne,
447
+ loadPending: B,
448
+ ctx: U(i, h.signal)
425
449
  }));
426
450
  } catch (e) {
427
451
  let t = e?._voltroControl;
428
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'.`);
429
453
  if (e instanceof Error && t === "not-found") {
430
- Q.warn("layout loader threw NotFoundError at build time — skipping artifact", { pathname: i.pathname });
454
+ $.warn("layout loader threw NotFoundError at build time — skipping artifact", { pathname: i.pathname });
431
455
  continue;
432
456
  }
433
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)}`);
@@ -457,7 +481,7 @@ var ne = K({ scope: "voltro:build" }), re = async (e) => {
457
481
  } catch (e) {
458
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'.`);
459
483
  if (e instanceof Error && e._voltroControl === "not-found") {
460
- Q.warn("loader threw NotFoundError at build time — skipping artifact", { pathname: i.pathname });
484
+ $.warn("loader threw NotFoundError at build time — skipping artifact", { pathname: i.pathname });
461
485
  continue;
462
486
  }
463
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)}`);
@@ -479,20 +503,20 @@ var ne = K({ scope: "voltro:build" }), re = async (e) => {
479
503
  query: void 0,
480
504
  apiName: void 0,
481
505
  seed: ee,
482
- seedFailure: O
506
+ seedFailure: te
483
507
  });
484
- let b = i.params.locale ?? e.defaultLocale ?? "en", D = j.get(b) ?? j.get(e.defaultLocale ?? ""), A = Date.now(), N = D ? (e) => D(e, {
485
- timeZone: k,
486
- renderedAt: A
487
- }) : void 0, { html: P, meta: I } = x({
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({
488
512
  descriptor: v,
489
513
  params: i.params,
490
514
  pathname: i.pathname,
491
515
  loaderData: y,
492
516
  segmentLoaderData: l,
493
- ...N ? { outerWrap: N } : {},
517
+ ...M ? { outerWrap: M } : {},
494
518
  locale: b
495
- }), L = "";
519
+ }), I = "";
496
520
  if (typeof c.ogImage == "function") {
497
521
  let a = await c.ogImage({
498
522
  params: i.params,
@@ -501,16 +525,16 @@ var ne = K({ scope: "voltro:build" }), re = async (e) => {
501
525
  }), o = await f(t, e.fonts), { png: s } = await n({
502
526
  element: a,
503
527
  fonts: o
504
- }), l = `assets/og/${R(s)}.png`;
505
- await W.mkdir(V(r, "assets", "og"), { recursive: !0 }), await W.writeFile(V(r, l), Buffer.from(s));
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));
506
530
  let u = e.siteUrl === void 0 ? `/${l}` : `${e.siteUrl.replace(/\/$/, "")}/${l}`;
507
- L = S(I).includes("og:image") ? "" : `<meta property="og:image" content="${u}" /><meta name="twitter:image" content="${u}" /><meta name="twitter:card" content="summary_large_image" />`;
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" />`;
508
532
  }
509
- let U = g === "islands" ? m.get(o.pattern) : void 0;
510
- g === "islands" && U === void 0 && Q.warn("islands page has no per-page entry (non-literal `interactive`?) — shipping the full app entry", { pattern: o.pattern });
511
- let K = ge(U ?? d, {
512
- body: P,
513
- metaHtml: S(I) + L,
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,
514
538
  stateScript: C({
515
539
  path: i.pathname,
516
540
  loaderData: y,
@@ -520,23 +544,23 @@ var ne = K({ scope: "voltro:build" }), re = async (e) => {
520
544
  interactive: g,
521
545
  documentAttrs: {
522
546
  lang: b,
523
- ...k === void 0 ? {} : { timeZone: k },
524
- renderedAt: A
547
+ ...O === void 0 ? {} : { timeZone: O },
548
+ renderedAt: k
525
549
  }
526
- }), q = me(r, i.pathname);
527
- await W.mkdir(B(q), { recursive: !0 }), await W.writeFile(q, K, "utf8"), M.push({
550
+ }), G = ve(r, i.pathname);
551
+ await H.mkdir(R(G), { recursive: !0 }), await H.writeFile(G, W, "utf8"), j.push({
528
552
  pattern: i.pathname,
529
- outPath: q,
530
- ...I?.noIndex ? { noIndex: !0 } : {}
553
+ outPath: G,
554
+ ...F?.noIndex ? { noIndex: !0 } : {}
531
555
  });
532
556
  }
533
557
  }
534
558
  return await y.close(), {
535
- rendered: M,
536
- pageMeta: N
559
+ rendered: j,
560
+ pageMeta: M
537
561
  };
538
- }, ye = async (e, t, n, r, i, a, o, s) => {
539
- let c = V(e, ".framework"), l = [];
562
+ }, Ce = async (e, t, n, r, i, a, o, s) => {
563
+ let c = z(e, ".framework"), l = [];
540
564
  for (let e of t) l.push(` ${JSON.stringify(e.pattern)}: () => import('../src/pages/${e.file}'),`);
541
565
  let u = [], d = [], f = [];
542
566
  for (let e of n) {
@@ -545,7 +569,7 @@ var ne = K({ scope: "voltro:build" }), re = async (e) => {
545
569
  }
546
570
  let p = [], m = [];
547
571
  if (r && r.length > 0 && i) for (let t of r) {
548
- if (!U(V(e, "src", "locales", `${t}.ts`))) continue;
572
+ if (!V(z(e, "src", "locales", `${t}.ts`))) continue;
549
573
  let n = `__i18nCat_${t.replace(/[^a-zA-Z0-9]/g, "_")}`;
550
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)}),`);
551
575
  }
@@ -622,40 +646,68 @@ var ne = K({ scope: "voltro:build" }), re = async (e) => {
622
646
  "",
623
647
  S,
624
648
  ""
625
- ].join("\n"), w = V(c, "ssrEntry.ts");
626
- return await W.writeFile(w, C, "utf8"), w;
627
- }, be = async (e) => {
649
+ ].join("\n"), w = z(c, "ssrEntry.ts");
650
+ return await H.writeFile(w, C, "utf8"), w;
651
+ }, we = async (e) => {
628
652
  let { checkRpcGroupFreshness: t } = await import("./codegen-DbH7NbCR.js"), n = await t(e);
629
653
  if (n.kind === "fresh") return;
630
- n.kind === "stale" && Q.info("rpcGroup.generated.ts is stale — regenerating", {
654
+ n.kind === "stale" && $.info("rpcGroup.generated.ts is stale — regenerating", {
631
655
  file: n.file,
632
656
  reason: n.reason
633
657
  });
634
658
  let { regenerateRpcGroup: r } = await import("./codegenCommand-kS3Twuc9.js"), i = await r(e);
635
659
  if (i.kind === "refused") {
636
- Q.warn("could not regenerate the rpc group — building against what is on disk", { reason: i.reason });
660
+ $.warn("could not regenerate the rpc group — building against what is on disk", { reason: i.reason });
637
661
  return;
638
662
  }
639
- i.kind === "wrote" && n.kind === "stale" && Q.info("rpc group regenerated", {
663
+ i.kind === "wrote" && n.kind === "stale" && $.info("rpc group regenerated", {
640
664
  plugins: i.plugins,
641
665
  routes: i.routes
642
666
  });
643
- }, xe = async (e) => {
667
+ }, Te = async (e) => {
644
668
  let n = await S(e, { preferSource: !0 });
645
669
  if (!n) {
646
670
  let { loadApiConfigDiagnosed: t } = await import("./dev-Dff_pdik.js"), n = await t(e), r = n.config;
647
- if (!r && n.present) return Q.error("app.config.ts is present but could not be loaded — this is NOT a statement about the app's type", { path: V(e, "app.config.ts") }, n.error), {
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), {
648
672
  ran: !0,
649
673
  exitCode: 1
650
674
  };
651
675
  if (r) {
652
- Q.info("building api app", { app: r.name ?? "(unnamed)" }), await be(e);
653
- let { runApiBuild: t, runServeBundleBuild: n } = await import("./apiBuild-CDE4NXNi.js");
654
- await t(e);
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 });
655
689
  try {
656
- await n(e);
690
+ await a(e, { sourcemaps: n.emit });
657
691
  } catch (e) {
658
- return Q.fatal("serve bundle build FAILED — refusing to ship a bundle-less image. Fix the error above (production serves from the bundle, never tsx).", {}, 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)}`), {
659
711
  ran: !0,
660
712
  exitCode: 1
661
713
  };
@@ -670,19 +722,19 @@ var ne = K({ scope: "voltro:build" }), re = async (e) => {
670
722
  exitCode: 0
671
723
  };
672
724
  }
673
- Q.info("building web app", { app: n.name ?? "(unnamed)" });
725
+ $.info("building web app", { app: n.name ?? "(unnamed)" });
674
726
  let { resolved: o } = await h({
675
727
  rawEnv: n.env,
676
728
  appType: "web",
677
729
  root: e,
678
- log: Q,
730
+ log: $,
679
731
  generateTypes: !0
680
732
  }), s = await b(e, n);
681
733
  await r(e, n, s, o.publicValues);
682
- let { pages: l } = await p(V(e, "src", "pages")), f = [];
734
+ let { pages: l } = await p(z(e, "src", "pages")), f = [];
683
735
  for (let t of l) {
684
- let n = await W.readFile(V(e, "src", "pages", t.file), "utf8").catch(() => ""), r = c(n);
685
- n.includes("<Script") && (r === "none" || r === "islands") && Q.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({
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({
686
738
  pattern: t.pattern,
687
739
  file: t.file
688
740
  });
@@ -690,61 +742,66 @@ var ne = K({ scope: "voltro:build" }), re = async (e) => {
690
742
  let _ = w(s, "../../app.config"), v = await x({
691
743
  webRoot: e,
692
744
  pages: f,
693
- headSnippets: t(await W.readFile(V(e, ".framework", "index.html"), "utf8").catch(() => "")),
745
+ headSnippets: t(await H.readFile(z(e, ".framework", "index.html"), "utf8").catch(() => "")),
694
746
  apiImports: _.imports,
695
747
  apiEntriesLiteral: `[\n${_.providerEntryLines.join("\n")}\n ]`
696
748
  });
697
- v.length > 0 && Q.info("per-page islands entries", { pages: v.map((e) => `${e.pattern}${e.usesClient ? " (client boot)" : ""}`) });
698
- let { pages: C } = await p(V(e, "src", "pages"));
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"));
699
751
  await ee({
700
752
  appRoot: e,
701
753
  pages: C,
702
754
  mode: "prod"
703
755
  });
704
- let T = V(e, ".framework"), E = V(T, "dist"), D = V(e, "node_modules", "@voltro", "ui-shadcn"), M = U(V(D, "package.json")) ? D : null, P = [...M ? [
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 ? [
705
757
  {
706
758
  find: "@voltro/ui-shadcn/tokens.css",
707
- replacement: V(M, "src/tokens.css")
759
+ replacement: z(j, "src/tokens.css")
708
760
  },
709
761
  {
710
762
  find: "@voltro/ui-shadcn/cn",
711
- replacement: V(M, "src/cn.ts")
763
+ replacement: z(j, "src/cn.ts")
712
764
  },
713
765
  {
714
766
  find: "@voltro/ui-shadcn/brand",
715
- replacement: V(M, "src/brand/voltroLogo.tsx")
767
+ replacement: z(j, "src/brand/voltroLogo.tsx")
716
768
  },
717
769
  {
718
770
  find: "@voltro/ui-shadcn",
719
- replacement: V(M, "src/index.ts")
771
+ replacement: z(j, "src/index.ts")
720
772
  }
721
- ] : [], ...A(e)];
722
- Q.info("running vite build");
723
- let F = await d("vite", () => import("vite")), I = (await import("@vitejs/plugin-react")).default, R = (await import("@tailwindcss/vite")).default, H = ae(n.web?.sourcemaps, process.env);
724
- if (oe(H)) return Q.fatal(H.problem), {
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), {
725
782
  ran: !0,
726
783
  exitCode: 1
727
784
  };
728
- let G = n.web?.assetPrefix;
729
- if (G !== void 0 && !/^https?:\/\/|^\//.test(G)) return Q.fatal(`web.assetPrefix must be an absolute URL or a root-relative path — got ${JSON.stringify(G)}. A bare host would be resolved against the page URL and 404 on every route but one.`), {
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.`), {
730
787
  ran: !0,
731
788
  exitCode: 1
732
789
  };
733
- if (await F.build({
790
+ await P.build({
734
791
  root: T,
735
- ...G === void 0 ? {} : { base: G.endsWith("/") ? G : `${G}/` },
792
+ ...W === void 0 ? {} : { base: W.endsWith("/") ? W : `${W}/` },
736
793
  envPrefix: "__VOLTRO_VITE_ENV_DISABLED__",
737
794
  plugins: [
738
- I(),
739
- R(),
795
+ F(),
796
+ L(),
740
797
  u({
741
798
  root: e,
742
- config: L(n.images)
799
+ config: I(n.images)
743
800
  }),
744
- $()
801
+ me()
745
802
  ],
746
803
  resolve: {
747
- alias: P,
804
+ alias: N,
748
805
  dedupe: [
749
806
  "react",
750
807
  "react-dom",
@@ -752,63 +809,76 @@ var ne = K({ scope: "voltro:build" }), re = async (e) => {
752
809
  "@voltro/i18n"
753
810
  ]
754
811
  },
755
- publicDir: V(e, "public"),
812
+ publicDir: z(e, "public"),
756
813
  build: {
757
814
  outDir: "dist",
758
815
  emptyOutDir: !0,
759
- ...H.emit ? { sourcemap: "hidden" } : {},
816
+ ...U.emit ? { sourcemap: "hidden" } : {},
760
817
  rollupOptions: {
761
818
  input: {
762
- index: V(T, "index.html"),
763
- ...Object.fromEntries(v.map((e) => [`island_${e.name}`, V(T, e.htmlFile)]))
819
+ index: z(T, "index.html"),
820
+ ...Object.fromEntries(v.map((e) => [`island_${e.name}`, z(T, e.htmlFile)]))
764
821
  },
765
- output: { manualChunks: O }
822
+ output: { manualChunks: te }
766
823
  }
767
824
  },
768
825
  logLevel: "warn"
769
- }), H.emit) {
770
- let t = V(T, "dist");
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
+ };
771
842
  try {
772
- let n = await ue(t, H, {
843
+ let t = await de(r, i, {
773
844
  appRoot: e,
774
- log: Q
775
- });
776
- (n.uploaded > 0 || n.deleted > 0) && Q.debug("source maps handled", {
777
- uploaded: n.uploaded,
778
- deleted: n.deleted
845
+ log: $
779
846
  });
847
+ return (t.uploaded > 0 || t.deleted > 0) && $.debug("source maps handled", {
848
+ uploaded: t.uploaded,
849
+ deleted: t.deleted
850
+ }), null;
780
851
  } catch (e) {
781
- return Q.fatal(`source map upload failed:\n${e instanceof Error ? e.message : String(e)}`), {
782
- ran: !0,
783
- exitCode: 1
784
- };
852
+ return $.fatal(`source map upload failed:\n${e instanceof Error ? e.message : String(e)}`), 1;
785
853
  }
786
- }
787
- let K = V(e, "src", "pages"), { pages: q, dirs: J } = await p(K);
788
- if (q.length === 0) return Q.info("no pages found — client-only bundle written", {
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", {
789
856
  pagesDir: K,
790
857
  distDir: E
791
858
  }), {
792
859
  ran: !0,
793
- exitCode: 0
860
+ exitCode: await G({
861
+ serverBundles: !1,
862
+ upload: !0
863
+ }) ?? 0
794
864
  };
795
865
  {
796
866
  let t = await i(e, n.fonts);
797
867
  if (t !== null) {
798
868
  for (let e of t.files) {
799
- let t = V(E, e.fileName);
800
- await W.mkdir(B(t), { recursive: !0 }), await W.writeFile(t, Buffer.from(e.bytes));
869
+ let t = z(E, e.fileName);
870
+ await H.mkdir(R(t), { recursive: !0 }), await H.writeFile(t, Buffer.from(e.bytes));
801
871
  }
802
- Q.info(`fonts: ${t.files.length} hashed file(s) into dist/assets/fonts`);
872
+ $.info(`fonts: ${t.files.length} hashed file(s) into dist/assets/fonts`);
803
873
  }
804
874
  }
805
875
  a(e);
806
- let { rendered: Y, pageMeta: te } = await ve({
876
+ let { rendered: Y, pageMeta: re } = await Se({
807
877
  root: e,
808
878
  distDir: E,
809
879
  pages: q,
810
880
  dirs: J,
811
- vite: F,
881
+ vite: P,
812
882
  islandsPlans: v,
813
883
  ...n.locales ? { locales: n.locales } : {},
814
884
  ...n.defaultLocale ? { defaultLocale: n.defaultLocale } : {},
@@ -818,30 +888,30 @@ var ne = K({ scope: "voltro:build" }), re = async (e) => {
818
888
  ...n.fonts === void 0 ? {} : { fonts: n.fonts },
819
889
  ...n.seo?.siteUrl === void 0 ? {} : { siteUrl: n.seo.siteUrl }
820
890
  });
821
- await k(E), await m(E, n.feeds ?? [], n.seo?.siteUrl), Q.info("generating .framework/ssrEntry.ts"), await ye(e, q, J, n.locales, n.defaultLocale, te, {
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, {
822
892
  ...n.timeZone ? { timeZone: n.timeZone } : {},
823
893
  ...n.defaultTimeZone ? { defaultTimeZone: n.defaultTimeZone } : {}
824
894
  }, s.map((e) => ({
825
895
  name: e.name,
826
896
  pkg: e.pkg
827
- }))), Q.info("vite build --ssr → dist/server/");
897
+ }))), $.info("vite build --ssr → dist/server/");
828
898
  let X = /* @__PURE__ */ new Set();
829
899
  try {
830
- await F.build({
900
+ await P.build({
831
901
  root: T,
832
902
  envPrefix: "__VOLTRO_VITE_ENV_DISABLED__",
833
903
  plugins: [
834
- I(),
835
- R(),
904
+ F(),
905
+ L(),
836
906
  u({
837
907
  root: e,
838
- config: L(n.images)
908
+ config: I(n.images)
839
909
  }),
840
- de(e, X),
841
- $()
910
+ he(e, X),
911
+ me()
842
912
  ],
843
913
  resolve: {
844
- alias: P,
914
+ alias: N,
845
915
  dedupe: [
846
916
  "react",
847
917
  "react-dom",
@@ -855,58 +925,73 @@ var ne = K({ scope: "voltro:build" }), re = async (e) => {
855
925
  outDir: "dist/server",
856
926
  ssr: "ssrEntry.ts",
857
927
  minify: "esbuild",
928
+ sourcemap: U.emit ? "hidden" : !1,
858
929
  emptyOutDir: !0,
859
930
  rollupOptions: { output: { format: "esm" } }
860
931
  },
861
932
  logLevel: "warn"
862
- }), Q.info("SSR bundle ready", {
933
+ }), $.info("SSR bundle ready", {
863
934
  path: "dist/server/ssrEntry.js",
864
935
  ...X.size > 0 ? { externalizedOptionalPeers: [...X].join(", ") } : {}
865
936
  });
866
937
  } catch (e) {
867
- return Q.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), {
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
+ }), {
868
942
  ran: !0,
869
943
  exitCode: 1
870
944
  };
871
945
  }
872
- let Z = V(e, "app.config.ts");
873
- if (U(Z)) {
874
- Q.info("precompiling app.config.ts → dist/server/appConfig.js");
946
+ let Z = z(e, "app.config.ts");
947
+ if (V(Z)) {
948
+ $.info("precompiling app.config.ts → dist/server/appConfig.js");
875
949
  try {
876
950
  await (await d("esbuild", () => import("esbuild"))).build({
877
951
  entryPoints: [Z],
878
- outfile: V(E, "server", "appConfig.js"),
952
+ outfile: z(E, "server", "appConfig.js"),
879
953
  bundle: !0,
880
954
  format: "esm",
881
955
  platform: "node",
882
956
  target: "node22",
883
- plugins: [N([], e, /* @__PURE__ */ new Set())],
884
- banner: { js: j() },
957
+ plugins: [M([], e, /* @__PURE__ */ new Set())],
958
+ banner: { js: A() },
885
959
  jsx: "automatic",
886
960
  jsxImportSource: "react",
887
961
  absWorkingDir: e,
888
962
  logLevel: "silent",
889
- ...U(V(e, "tsconfig.json")) ? { tsconfig: V(e, "tsconfig.json") } : {}
963
+ ...V(z(e, "tsconfig.json")) ? { tsconfig: z(e, "tsconfig.json") } : {}
890
964
  });
891
965
  } catch (e) {
892
- return Q.fatal("app.config precompile FAILED — production `voltro start` would need the tsx loader to read it.", {}, 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
+ }), {
893
970
  ran: !0,
894
971
  exitCode: 1
895
972
  };
896
973
  }
897
974
  }
898
975
  try {
899
- await re(e);
976
+ await ie(e, { sourcemaps: U.emit });
900
977
  } catch (e) {
901
- Q.warn("start bundle build failed — `voltro start` will use the slower per-module boot", {}, e);
978
+ $.warn("start bundle build failed — `voltro start` will use the slower per-module boot", {}, e);
902
979
  }
903
- Q.info(`pre-rendered ${Y.length} static route(s)`, {
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)`, {
904
989
  count: Y.length,
905
990
  routes: Y.map((e) => e.pattern)
906
991
  });
907
992
  try {
908
993
  let e = process.env.VOLTRO_SEO_NOINDEX !== "1", t = n.seo?.siteUrl, r = n.locales ?? [], i = n.defaultLocale ?? r[0];
909
- if (t && !U(V(E, "sitemap.xml"))) {
994
+ if (t && !V(z(E, "sitemap.xml"))) {
910
995
  let n = new Set(r.filter((e) => e !== i)), a = Y.filter((e) => !e.noIndex).map((e) => e.pattern).filter((e) => {
911
996
  let t = e.split("/").filter(Boolean)[0];
912
997
  return t === void 0 || !n.has(t);
@@ -916,22 +1001,22 @@ var ne = K({ scope: "voltro:build" }), re = async (e) => {
916
1001
  ...r.length > 1 ? { locales: r } : {},
917
1002
  ...i ? { defaultLocale: i } : {}
918
1003
  });
919
- await W.writeFile(V(E, "sitemap.xml"), o, "utf8"), Q.info("wrote dist/sitemap.xml", {
1004
+ await H.writeFile(z(E, "sitemap.xml"), o, "utf8"), $.info("wrote dist/sitemap.xml", {
920
1005
  urls: a.length,
921
1006
  indexable: e
922
1007
  });
923
1008
  }
924
- if (!U(V(E, "robots.txt"))) {
1009
+ if (!V(z(E, "robots.txt"))) {
925
1010
  let r = y({
926
1011
  indexable: e,
927
1012
  ...e && t ? { sitemapUrl: `${t.replace(/\/$/, "")}/sitemap.xml` } : {},
928
1013
  ...n.seo?.disallow ? { disallow: n.seo.disallow } : {}
929
1014
  });
930
- await W.writeFile(V(E, "robots.txt"), r, "utf8"), Q.info("wrote dist/robots.txt", { indexable: e });
1015
+ await H.writeFile(z(E, "robots.txt"), r, "utf8"), $.info("wrote dist/robots.txt", { indexable: e });
931
1016
  }
932
1017
  {
933
1018
  let { precompressAssets: e } = await import("./precompressAssets-YhTi1aWp.js"), t = await e(E);
934
- t.files > 0 && Q.info("pre-compressed assets", {
1019
+ t.files > 0 && $.info("pre-compressed assets", {
935
1020
  files: t.files,
936
1021
  raw: t.originalBytes,
937
1022
  br: t.brotliBytes,
@@ -939,43 +1024,43 @@ var ne = K({ scope: "voltro:build" }), re = async (e) => {
939
1024
  });
940
1025
  }
941
1026
  } catch (e) {
942
- Q.warn("SEO artefact generation failed (non-fatal)", {}, e);
1027
+ $.warn("SEO artefact generation failed (non-fatal)", {}, e);
943
1028
  }
944
1029
  try {
945
- let t = await z(e);
946
- await W.writeFile(V(E, ".voltro-build.json"), JSON.stringify({
1030
+ let t = await ne(e);
1031
+ await H.writeFile(z(E, ".voltro-build.json"), JSON.stringify({
947
1032
  version: 1,
948
1033
  profile: t
949
- }, null, 2), "utf8"), Q.info("wrote deploy profile manifest", {
1034
+ }, null, 2), "utf8"), $.info("wrote deploy profile manifest", {
950
1035
  staticSafe: t.staticSafe,
951
1036
  ssr: t.counts.ssr,
952
1037
  isr: t.counts.isr
953
1038
  });
954
1039
  } catch (e) {
955
- Q.warn("could not write .voltro-build.json deploy manifest", {}, e);
1040
+ $.warn("could not write .voltro-build.json deploy manifest", {}, e);
956
1041
  }
957
- return Q.info("build complete", { distDir: E }), {
1042
+ return $.info("build complete", { distDir: E }), {
958
1043
  ran: !0,
959
1044
  exitCode: 0
960
1045
  };
961
- }, Se = (e) => J.gen(function* () {
962
- let t = yield* J.tryPromise({
963
- try: () => xe(H(e)),
1046
+ }, Ee = (e) => K.gen(function* () {
1047
+ let t = yield* K.tryPromise({
1048
+ try: () => Te(B(e)),
964
1049
  catch: (e) => e
965
- }).pipe(J.orDie);
966
- return t.ran ? t.exitCode : (yield* J.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);
967
- }), Ce = async (t) => {
968
- if (q("build"), t.includes("--target")) {
969
- let { runSdkBuildCommand: e } = await import("./sdkgen-CAhmmbjx.js");
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");
970
1055
  return e(t);
971
1056
  }
972
- let n = t.find((e) => !e.startsWith("-")) ?? process.cwd(), r = await F(Se(n), { scope: "voltro:build" });
1057
+ let n = t.find((e) => !e.startsWith("-")) ?? process.cwd(), r = await P(Ee(n), { scope: "voltro:build" });
973
1058
  if (r === 0 && t.includes("--report")) {
974
1059
  let { collectBuildReport: e, formatBuildReport: t } = await import("./buildReport-52gHKgfO.js");
975
1060
  for (let r of t(e(n))) console.log(r);
976
1061
  }
977
1062
  let i = e(n);
978
- return i.warning !== void 0 && Q.warn(i.warning), r;
1063
+ return i.warning !== void 0 && $.warn(i.warning), r;
979
1064
  };
980
1065
  //#endregion
981
- export { Ce as runBuildCommand };
1066
+ export { De as runBuildCommand };