@voltro/cli 0.11.4 → 0.12.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 (73) hide show
  1. package/CHANGELOG.md +263 -0
  2. package/dist/{apiBuild-DHHuiwXF.js → apiBuild-GefjNI5d.js} +9 -8
  3. package/dist/apiBuild-s7swuEU5.js +2 -0
  4. package/dist/appModuleLoader-C9r9mxZt.js +19 -0
  5. package/dist/bin.js +21 -10
  6. package/dist/cliArgs-qdZSElM3.js +28 -0
  7. package/dist/{commands-BwbMqR-1.js → commands-BmNi1RgZ.js} +2502 -2543
  8. package/dist/dbCommand-Bt6BCG7g.js +2 -0
  9. package/dist/dbCommand-DNrkb58g.js +862 -0
  10. package/dist/dev-YHbHmeXt.js +3 -0
  11. package/dist/{dev-Cvojvb_J.js → dev-d0LjACxE.js} +1574 -2357
  12. package/dist/index.d.ts +19 -0
  13. package/dist/index.js +3 -3
  14. package/dist/inspect-DcZ04OME.js +2 -0
  15. package/dist/inspect-Dwx0_tUj.js +921 -0
  16. package/dist/inspectMetrics-uEfIS1vp.js +3399 -0
  17. package/dist/manifestBuild-D1MzJAiQ.js +2 -0
  18. package/dist/manifestBuild-P9yuCY2d.js +39 -0
  19. package/dist/seedRunner-DZmhoqNt.js +821 -0
  20. package/dist/serveCommand-B2-YV9TU.js +1112 -0
  21. package/dist/serveEntry.js +4 -4
  22. package/dist/{start-DyJE6w1R.js → start-DKcQd52a.js} +346 -343
  23. package/dist/startEntry.js +2 -2
  24. package/dist/startup.js +1 -1
  25. package/dist/{startupRunner-DhlX9nqd.js → startupRunner-DPGFchOa.js} +19 -33
  26. package/package.json +17 -17
  27. package/templates/AGENTS.md +1 -0
  28. package/templates/agent-docs/_index.md +1 -0
  29. package/templates/agent-docs/cli.md +180 -14
  30. package/templates/agent-docs/data.md +39 -0
  31. package/templates/agent-docs/scheduling.md +35 -1
  32. package/templates/agent-docs/security.md +48 -0
  33. package/templates/agent-docs/templates/apibackends.md +90 -17
  34. package/templates/agent-docs/whats-new.md +177 -0
  35. package/templates/apps/api-ai/package.json +7 -7
  36. package/templates/apps/api-auth/package.json +8 -8
  37. package/templates/apps/api-backend/package.json +7 -7
  38. package/templates/apps/api-backend-deactivation/package.json +7 -7
  39. package/templates/apps/api-backend-mail/package.json +8 -8
  40. package/templates/apps/api-backend-mariadb/package.json +9 -9
  41. package/templates/apps/api-backend-storage/package.json +8 -8
  42. package/templates/apps/api-data-advanced/package.json +8 -8
  43. package/templates/apps/api-durable/package.json +8 -8
  44. package/templates/apps/api-feature-flags/package.json +9 -9
  45. package/templates/apps/api-governance/package.json +8 -8
  46. package/templates/apps/api-kv/package.json +8 -8
  47. package/templates/apps/api-moderation/package.json +8 -8
  48. package/templates/apps/api-observability/package.json +8 -8
  49. package/templates/apps/api-ratelimit/package.json +8 -8
  50. package/templates/apps/api-rbac/package.json +8 -8
  51. package/templates/apps/api-rest/package.json +7 -7
  52. package/templates/apps/api-saas/package.json +11 -11
  53. package/templates/apps/api-search/package.json +8 -8
  54. package/templates/apps/api-versioning/package.json +8 -8
  55. package/templates/apps/api-webhooks/package.json +8 -8
  56. package/templates/apps/changelog/package.json +6 -6
  57. package/templates/apps/edge-functions/package.json +2 -2
  58. package/templates/apps/frontend-admin/package.json +8 -8
  59. package/templates/apps/frontend-app/package.json +8 -8
  60. package/templates/apps/frontend-blank/package.json +7 -7
  61. package/templates/apps/frontend-contact/package.json +7 -7
  62. package/templates/apps/frontend-dashboard/package.json +7 -7
  63. package/templates/apps/frontend-docs/package.json +7 -7
  64. package/templates/apps/frontend-i18n/package.json +6 -6
  65. package/templates/apps/frontend-landing/package.json +7 -7
  66. package/templates/apps/frontend-spa/package.json +7 -7
  67. package/templates/apps/frontend-ssr/package.json +7 -7
  68. package/templates/apps/frontend-ssr-api/package.json +8 -8
  69. package/templates/apps/frontend-static-blog/package.json +6 -6
  70. package/dist/apiBuild-D9MtlD02.js +0 -2
  71. package/dist/dev-BsBsIv93.js +0 -2
  72. package/dist/inspectMetrics-D4EJ8LTi.js +0 -4255
  73. package/dist/serveCommand-ARqSs73o.js +0 -1117
@@ -0,0 +1,3399 @@
1
+ import { D as e, E as t, T as n, a as r, p as i, w as a } from "./inspect-Dwx0_tUj.js";
2
+ import { basename as o, dirname as s, isAbsolute as c, join as l, relative as u, resolve as d } from "node:path";
3
+ import { fileURLToPath as f, pathToFileURL as p } from "node:url";
4
+ import { FileSystem as m } from "@effect/platform";
5
+ import { NodeContext as h, NodeRuntime as g } from "@effect/platform-node";
6
+ import { Cause as _, Effect as v, Layer as y } from "effect";
7
+ import { LoggerLayer as b, addSink as x, createLogger as S, printReadyBlock as C } from "@voltro/logger";
8
+ import { closeSync as w, existsSync as T, mkdirSync as E, openSync as D, promises as O, readFileSync as k, readdirSync as A, statSync as j, unlinkSync as M, unwatchFile as N, watchFile as P, writeSync as ee } from "node:fs";
9
+ import { currentTraceContext as F, recordSample as te, resolveSecret as I } from "@voltro/runtime";
10
+ import { createRequire as L } from "node:module";
11
+ import { homedir as R } from "node:os";
12
+ import { FRAMEWORK_ENV_CATALOG as ne, appEnvEntries as re, checkEnvNaming as ie, formatEnvErrors as ae, installEnvSnapshot as oe, isEnvContract as se, pluginEnvEntries as ce, renderDotEnvExample as le, resolveEnv as z } from "@voltro/env";
13
+ import { __installPublicEnv as ue } from "@voltro/env/public";
14
+ import { mkdir as de, readFile as fe, writeFile as B } from "node:fs/promises";
15
+ import { createHash as pe } from "node:crypto";
16
+ import { spawn as me } from "node:child_process";
17
+ import { createConnection as he } from "node:net";
18
+ import { PassThrough as ge } from "node:stream";
19
+ //#region src/cliRuntime.ts
20
+ var _e = [
21
+ "severity",
22
+ "code",
23
+ "detail",
24
+ "hint",
25
+ "position",
26
+ "internalPosition",
27
+ "internalQuery",
28
+ "where",
29
+ "schema",
30
+ "table",
31
+ "column",
32
+ "dataType",
33
+ "constraint",
34
+ "file",
35
+ "line",
36
+ "routine"
37
+ ], ve = (e, t = 0, n = /* @__PURE__ */ new WeakSet()) => {
38
+ if (t > 10 || typeof e != "object" || !e || n.has(e)) return null;
39
+ n.add(e);
40
+ let r = e, i = r.message;
41
+ if (typeof i == "string" && i.length > 0 && i !== "Failed to execute statement") {
42
+ let e = { message: i };
43
+ typeof r.stack == "string" && (e.stack = r.stack);
44
+ for (let t of _e) r[t] !== void 0 && (e[t] = r[t]);
45
+ return e;
46
+ }
47
+ for (let e of [
48
+ "cause",
49
+ "defect",
50
+ "left",
51
+ "right",
52
+ "failure",
53
+ "failures"
54
+ ]) {
55
+ let i = r[e];
56
+ if (i !== void 0) {
57
+ let e = ve(i, t + 1, n);
58
+ if (e) return e;
59
+ }
60
+ }
61
+ if (Array.isArray(r.failures)) for (let e of r.failures) {
62
+ let r = ve(e, t + 1, n);
63
+ if (r) return r;
64
+ }
65
+ return null;
66
+ }, ye = (e = {}) => y.merge(h.layer, b({
67
+ ...e.scope ? { defaultScope: e.scope } : {},
68
+ ...e.logger
69
+ })), V = async (e, t = {}) => {
70
+ let n = e.pipe(v.provide(ye(t)));
71
+ return await v.runPromise(v.matchCauseEffect(n, {
72
+ onSuccess: (e) => v.succeed(e),
73
+ onFailure: (e) => {
74
+ let t = [..._.defects(e)];
75
+ if (process.env.VOLTRO_CAUSE_DEBUG === "1") for (let [e, n] of t.entries()) {
76
+ let t = Object.getOwnPropertyNames(n);
77
+ process.stderr.write(`[VOLTRO_CAUSE_DEBUG] defect[${e}] ctor=${n?.constructor?.name} props=${JSON.stringify(t)}\n`);
78
+ let r = n;
79
+ if (r.message && process.stderr.write(` message: ${String(r.message)}\n`), r.cause) {
80
+ let e = r.cause;
81
+ process.stderr.write(` cause.ctor=${e.constructor?.name} cause.message=${String(e.message)} cause.code=${String(e.code)}\n`);
82
+ }
83
+ }
84
+ let n = null;
85
+ for (let e of t) {
86
+ let t = ve(e);
87
+ if (t) {
88
+ n = t;
89
+ break;
90
+ }
91
+ }
92
+ let r = n ? {
93
+ pgMessage: n.message,
94
+ ...n.code ? { pgCode: n.code } : {},
95
+ ...n.detail ? { pgDetail: n.detail } : {},
96
+ ...n.hint ? { pgHint: n.hint } : {},
97
+ ...n.table ? { pgTable: n.table } : {},
98
+ ...n.column ? { pgColumn: n.column } : {},
99
+ ...n.constraint ? { pgConstraint: n.constraint } : {},
100
+ ...n.routine ? { pgRoutine: n.routine } : {},
101
+ causePretty: _.pretty(e)
102
+ } : { causePretty: _.pretty(e) };
103
+ return v.zipRight(v.logError("cli command failed", r), v.succeed(1));
104
+ }
105
+ }).pipe(v.provide(b(t.logger ?? {}))));
106
+ }, be = (e, t = {}) => {
107
+ let n = e.pipe(v.provide(ye(t)));
108
+ g.runMain(n, { disableErrorReporting: !1 });
109
+ }, xe = s(f(import.meta.url)), H = [d(xe, "..", "templates"), d(xe, "..", "..", "templates")], U = (e) => ({
110
+ _tag: "TemplateNotFoundError",
111
+ searched: e
112
+ }), Se = ["AGENTS.md", "CLAUDE.md"], Ce = "voltro:agents-md:keep", we = 2048, Te = "<!-- VOLTRO:INDEX -->", W = (e, t) => e.exists(t).pipe(v.orElseSucceed(() => !1)), G = (e, t) => e.readFileString(t).pipe(v.orElseSucceed(() => "")), Ee = (e, t) => e.readFileString(t).pipe(v.map((e) => {
113
+ try {
114
+ return JSON.parse(e).workspaces !== void 0;
115
+ } catch {
116
+ return !1;
117
+ }
118
+ }), v.orElseSucceed(() => !1)), De = (e) => v.gen(function* () {
119
+ let t = yield* m.FileSystem, n = d(e);
120
+ for (;;) {
121
+ if ((yield* W(t, l(n, ".git"))) || (yield* W(t, l(n, "pnpm-workspace.yaml"))) || (yield* Ee(t, l(n, "package.json")))) return n;
122
+ let r = s(n);
123
+ if (r === n) return d(e);
124
+ n = r;
125
+ }
126
+ }), Oe = (e, t, n) => v.gen(function* () {
127
+ yield* e.makeDirectory(n, { recursive: !0 }).pipe(v.orElseSucceed(() => void 0));
128
+ let r = yield* e.readDirectory(t).pipe(v.orElseSucceed(() => []));
129
+ for (let i of r) {
130
+ let r = l(t, i), a = l(n, i);
131
+ (yield* e.stat(r).pipe(v.orElseSucceed(() => null)))?.type === "Directory" ? yield* Oe(e, r, a) : yield* e.copyFile(r, a).pipe(v.orElseSucceed(() => void 0));
132
+ }
133
+ }), ke = (e) => typeof e?.name == "string" && e.name.length > 0 ? e.name.split("#")[0] : null, Ae = (e, t) => v.gen(function* () {
134
+ let n = l(t, "app.config.ts");
135
+ if (!(yield* W(e, n))) return null;
136
+ let r = (yield* v.tryPromise(() => import(p(n).href)).pipe(v.orElseSucceed(() => null)))?.default;
137
+ return !r || r.type && r.type !== "api" ? r?.type === "web" ? [] : null : (r.plugins ?? []).map(ke).filter((e) => e !== null);
138
+ }), je = (e, t) => v.gen(function* () {
139
+ let n = [], r = [], i = l(t, "apps");
140
+ if (!(yield* W(e, i))) return {
141
+ apis: n,
142
+ webs: r
143
+ };
144
+ for (let t of yield* e.readDirectory(i).pipe(v.orElseSucceed(() => []))) {
145
+ let a = l(i, t);
146
+ if ((yield* e.stat(a).pipe(v.orElseSucceed(() => null)))?.type === "Directory") for (let t of yield* e.readDirectory(a).pipe(v.orElseSucceed(() => []))) {
147
+ let i = l(a, t), o = l(i, "app.config.ts");
148
+ if (!(yield* W(e, o))) continue;
149
+ let s = yield* G(e, o);
150
+ /type:\s*['"]web['"]/.test(s) ? r.push(i) : n.push(i);
151
+ }
152
+ }
153
+ return {
154
+ apis: n,
155
+ webs: r
156
+ };
157
+ }), Me = (e) => e.replace(/\|/g, "\\|").replace(/\n/g, " ").trim(), Ne = (e, t, n) => {
158
+ let r = [
159
+ "<!-- voltro agent-docs index — regenerated at seed time -->",
160
+ "## Deep reference (read on demand)",
161
+ "",
162
+ "Each row is a file to OPEN when you work on that topic — not loaded into",
163
+ "context by default. Paths are from the repo root.",
164
+ "",
165
+ "### Topics",
166
+ "",
167
+ "| Topic | Open | Summary |",
168
+ "|---|---|---|",
169
+ ...e.modules.map((e) => `| ${e.title} | \`${n}${e.path}\` | ${Me(e.description)} |`),
170
+ ""
171
+ ], i = new Map(e.plugins.map((e) => [e.pkg, e])), a = t === null ? e.plugins.map((e) => `| ${e.slug} | \`node_modules/${e.pkg}/README.md\` | ${Me(e.description)} |`) : t.map((e) => {
172
+ let t = i.get(e);
173
+ return t ? `| ${t.slug} | \`node_modules/${e}/README.md\` | ${Me(t.description)} |` : `| ${e.replace(/^@[^/]+\//, "")} | \`node_modules/${e}/README.md\` | (see plugin README) |`;
174
+ });
175
+ return r.push(`### Plugins${t === null ? "" : " (installed)"}`, "", "| Plugin | Open | Summary |", "|---|---|---|"), r.push(a.length ? a.join("\n") : "| _(none installed)_ | | |", ""), r.join("\n");
176
+ }, Pe = (e, t, n) => {
177
+ let r = t.templates?.[e] ?? t.templates?.[e.replace(/^frontend-/, "")];
178
+ return `\nScaffolded from the \`${e}\` template — see \`${r ? `${n}${r}` : `${n}agent-docs/templates/overview.md`}\`.\n`;
179
+ }, Fe = {
180
+ api: (e, t, n = "") => `# api — agent notes
181
+
182
+ You are in a Voltro **api** app. Server primitives live here: \`queries/\`,
183
+ \`mutations/\`, \`actions/\`, \`workflows/\`, \`database/\`, \`schedules/\`.
184
+
185
+ - Every RPC primitive is a descriptor + \`*.server.ts\` executor pair. Descriptors
186
+ are **browser-loaded** — keep them free of \`node:*\` / \`@voltro/database\` /
187
+ server-only imports (transitively too).
188
+ - Pick the primitive with the rubric in the repo-root \`AGENTS.md\`.
189
+
190
+ Deep reference (paths from the repo root):
191
+ - Data primitives → \`${e}agent-docs/data.md\`
192
+ - Schema / queries → \`${e}agent-docs/database/schema.md\`, \`${e}agent-docs/database/querying.md\`
193
+ - Workflows → \`${e}agent-docs/workflows.md\`
194
+ ${t && t.length ? `\nThis api's plugins: ${t.join(", ")} (API in each \`node_modules/<pkg>/README.md\`).` : ""}
195
+ ${n}`,
196
+ database: (e) => `# database — agent notes
197
+
198
+ Schema lives here: one table per \`*.entity.ts\`; \`index.ts\` builds the handle.
199
+
200
+ - Mixins compose via \`.with(...)\` and auto-stamp columns; declare \`.index([...])\`
201
+ AFTER \`.with(...)\`. Indexes are table-level (no column-level \`.index()\`).
202
+ - Don't add tenant filters on \`tenant()\` tables — the runtime does it.
203
+
204
+ Deep reference (paths from the repo root): \`${e}agent-docs/database/schema.md\`,
205
+ \`${e}agent-docs/database/columntypes.md\`, \`${e}agent-docs/database/querying.md\`,
206
+ \`${e}agent-docs/database/migrations.md\`.
207
+ `,
208
+ web: (e, t = "") => `# web — agent notes
209
+
210
+ You are in a Voltro **web** app. File-based routing under \`src/pages/**\`.
211
+
212
+ - Use \`useSubscription\` / \`useMutation\` / \`useAction\` from \`@voltro/client\`.
213
+ - Never read \`window.location\` (use \`useLocation()\`); never toggle \`dark\` from
214
+ \`useEffect\` (set \`theme\` in \`app.config.ts\`).
215
+
216
+ Deep reference (paths from the repo root): \`${e}agent-docs/routing.md\`,
217
+ \`${e}agent-docs/schema-driven-ui.md\`, \`${e}agent-docs/internationalization.md\`.
218
+ ${t}`
219
+ }, Ie = [
220
+ {
221
+ name: "voltro-schema",
222
+ description: "Define or change a Voltro database table/schema (columns, mixins, indexes, relations).",
223
+ module: "database/schema.md"
224
+ },
225
+ {
226
+ name: "voltro-data",
227
+ description: "Write a Voltro query, mutation, action, or stream (the descriptor + server executor pair).",
228
+ module: "data.md"
229
+ },
230
+ {
231
+ name: "voltro-workflows",
232
+ description: "Write or debug a durable Voltro workflow (steps, signals, retries).",
233
+ module: "workflows.md"
234
+ },
235
+ {
236
+ name: "voltro-routing",
237
+ description: "Add or change a Voltro web page, layout, loader, or render mode.",
238
+ module: "routing.md"
239
+ },
240
+ {
241
+ name: "voltro-plugins",
242
+ description: "Wire a Voltro plugin (storage, mail, billing, auth, rbac, …) into an app.",
243
+ module: "plugins.md"
244
+ },
245
+ {
246
+ name: "voltro-data-transfer",
247
+ description: "Export/import + backup/restore Voltro data & assets, and copy prod→dev/stage SAFELY with fail-closed masking/anonymization (.sensitive()/.safe()) + referential subsetting. Use for data takeout, seeding lower envs, backups, or cross-dialect moves.",
248
+ module: "cli.md"
249
+ }
250
+ ], Le = (e, t) => `---
251
+ name: ${e.name}
252
+ description: ${e.description}
253
+ ---
254
+
255
+ Open the full reference and follow the patterns there:
256
+
257
+ \`${t}agent-docs/${e.module}\`
258
+
259
+ Also read the repo-root \`AGENTS.md\` for the always-true rules (browser/server
260
+ boundary, naming, anti-patterns) before editing.
261
+ `, Re = (e, t, n, r) => v.gen(function* () {
262
+ let i = yield* W(e, t);
263
+ if (i) {
264
+ if ((yield* G(e, t)).slice(0, we).includes("voltro:agents-md:keep")) return {
265
+ path: t,
266
+ action: "protected"
267
+ };
268
+ if (!r) return {
269
+ path: t,
270
+ action: "present"
271
+ };
272
+ }
273
+ return yield* e.makeDirectory(s(t), { recursive: !0 }).pipe(v.orElseSucceed(() => void 0)), yield* e.writeFileString(t, n).pipe(v.orDie), {
274
+ path: t,
275
+ action: i ? "overwritten" : "created"
276
+ };
277
+ }), ze = (e, t = {}) => v.gen(function* () {
278
+ let n = yield* m.FileSystem, r = yield* De(e), i = null;
279
+ for (let e of H) if (yield* W(n, l(e, "AGENTS.core.md"))) {
280
+ i = e;
281
+ break;
282
+ }
283
+ if (i === null) {
284
+ for (let e of H) if (yield* W(n, l(e, "AGENTS.md"))) {
285
+ let i = yield* G(n, l(e, "AGENTS.md")), a = [];
286
+ for (let e of Se) a.push(yield* Re(n, l(r, e), i, t.force ?? !1));
287
+ return { files: a };
288
+ }
289
+ return yield* v.fail(U(H.map((e) => l(e, "AGENTS.core.md"))));
290
+ }
291
+ let a = yield* G(n, l(i, "AGENTS.core.md")), o = yield* G(n, l(i, "agent-docs", "_manifest.json")), s = o ? JSON.parse(o) : {
292
+ modules: [],
293
+ plugins: []
294
+ }, c = (t.preferPointer ?? !1) || (yield* W(n, l(r, "node_modules/@voltro/cli/templates/agent-docs", "_manifest.json"))), u = c ? "node_modules/@voltro/cli/templates/" : "", f = t.force ?? !1, p = Se.map((e) => l(r, e));
295
+ if ((yield* v.forEach(p, (e) => G(n, e).pipe(v.map((e) => e.slice(0, we))))).every((e) => e.includes("voltro:agents-md:keep"))) return { files: p.map((e) => ({
296
+ path: e,
297
+ action: "protected"
298
+ })) };
299
+ let { apis: h, webs: g } = yield* je(n, r), _ = /* @__PURE__ */ new Map(), y = /* @__PURE__ */ new Set(), b = !1;
300
+ for (let e of h) {
301
+ let t = yield* Ae(n, e);
302
+ if (_.set(e, t), t !== null) {
303
+ b = !0;
304
+ for (let e of t) y.add(e);
305
+ }
306
+ }
307
+ let x = t.plugins ? t.plugins.map(ke).filter((e) => e !== null) : b ? [...y] : null, S = a.includes(Te) ? a.replace(Te, Ne(s, x, u)) : a, C = [];
308
+ for (let e of p) C.push(yield* Re(n, e, S, f));
309
+ c || (yield* Oe(n, l(i, "agent-docs"), l(r, "agent-docs")));
310
+ let w = new Map((t.appTemplates ?? []).map((e) => [d(e.dir), e.template])), T = (e) => {
311
+ let t = w.get(d(e));
312
+ return t ? Pe(t, s, u) : "";
313
+ }, E = (e, t) => v.forEach(Se, (r) => Re(n, l(e, r), t, f));
314
+ for (let e of h) C.push(...yield* E(e, Fe.api(u, _.get(e) ?? null, T(e)))), (yield* W(n, l(e, "database"))) && C.push(...yield* E(l(e, "database"), Fe.database(u)));
315
+ for (let e of g) C.push(...yield* E(e, Fe.web(u, T(e))));
316
+ for (let e of Ie) C.push(yield* Re(n, l(r, ".claude", "skills", e.name, "SKILL.md"), Le(e, u), f));
317
+ return { files: C };
318
+ }), Be = (e, t = {}) => v.runPromise(ze(e, t).pipe(v.provide(h.layer))), Ve = async (e) => {
319
+ let t = e.includes("--force"), n = e.find((e) => !e.startsWith("-")) ?? process.cwd();
320
+ return V(v.gen(function* () {
321
+ let e = yield* ze(n, { force: t });
322
+ for (let t of e.files) {
323
+ let e = t.action === "created" ? "wrote" : t.action === "overwritten" ? "overwrote" : t.action === "protected" ? `protected (hand-maintained — has "${Ce}")` : "present (use --force to overwrite)";
324
+ yield* v.logInfo(`${t.path.split("/").slice(-2).join("/")} ${e}`, { action: t.action });
325
+ }
326
+ return 0;
327
+ }).pipe(v.catchTag("TemplateNotFoundError", (e) => v.gen(function* () {
328
+ return yield* v.logError("AGENTS.md template not found", { searched: e.searched }), 1;
329
+ }))), { scope: "voltro:agents-md" });
330
+ }, He = (e) => e.replace(/\\"|"(?:[^"\\]|\\.)*"|(\/\/[^\n]*|\/\*[\s\S]*?\*\/)/g, (e, t) => t ? "" : e), Ue = (e) => {
331
+ try {
332
+ let t = l(e, "tsconfig.json");
333
+ if (!T(t)) return [];
334
+ let n = JSON.parse(He(k(t, "utf8"))).compilerOptions ?? {}, r = n.paths ?? {}, i = d(e, n.baseUrl ?? "."), a = [];
335
+ for (let [e, t] of Object.entries(r)) {
336
+ let n = t[0];
337
+ if (!n) continue;
338
+ let r = n.replace(/\\/g, "/");
339
+ if (!(r.includes("/@types/") || r.endsWith(".d.ts"))) if (e.endsWith("/*") && n.endsWith("/*")) {
340
+ let t = e.slice(0, -2).replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
341
+ a.push({
342
+ find: RegExp(`^${t}/(.*)$`),
343
+ replacement: `${l(i, n.slice(0, -2))}/$1`
344
+ });
345
+ } else a.push({
346
+ find: e,
347
+ replacement: l(i, n)
348
+ });
349
+ }
350
+ return a;
351
+ } catch {
352
+ return [];
353
+ }
354
+ }, We = (e) => {
355
+ let t = e;
356
+ return t?.code === "ERR_MODULE_NOT_FOUND" || /Cannot find (package|module)/.test(String(t?.message ?? ""));
357
+ }, Ge = async (e, t) => {
358
+ try {
359
+ return await t();
360
+ } catch (t) {
361
+ throw We(t) ? Error(`voltro: the build tool '${e}' is not installed.\n\nIt's an OPTIONAL dependency of @voltro/cli — needed by 'voltro dev' and 'voltro build', but excluded from a serve-only production install (that's how prod images stay lean). If you are building, reinstall WITHOUT '--no-optional' (e.g. 'pnpm install'). A production SERVE container does not need '${e}' — it boots from the precompiled bundle.`) : t;
362
+ }
363
+ }, Ke = "// AUTO-GENERATED by Voltro — DO NOT EDIT.\n// Source: app.config.ts `env` (defineEnv). Regenerated on every `voltro dev` boot.\n", qe = (e, t) => t ? `${e} | undefined` : e, Je = (e, t) => Object.entries(e.vars).filter(([, e]) => t(e.access)).map(([e, t]) => `${t.description ? ` /** ${t.description} */\n` : ""} readonly ${e}: ${qe(t.tsType, t.optional)}`).join("\n"), Ye = async (e, t) => {
364
+ let n = Je(t, () => !0), r = `${Ke}
365
+ import '@voltro/env/server'
366
+
367
+ declare module '@voltro/env/server' {
368
+ interface ServerEnv {
369
+ ${n.length > 0 ? n : " // (no variables declared)"}
370
+ }
371
+ }
372
+ `;
373
+ await B(l(e, "env.generated.d.ts"), r, "utf8");
374
+ }, Xe = async (e, t) => {
375
+ let n = Je(t, (e) => e === "public"), r = `${Ke}
376
+ import '@voltro/env/public'
377
+
378
+ declare module '@voltro/env/public' {
379
+ interface PublicEnv {
380
+ ${n.length > 0 ? n : " // (no public variables declared)"}
381
+ }
382
+ }
383
+ `, i = l(e, "src");
384
+ await de(i, { recursive: !0 }), await B(l(i, "voltro-env.d.ts"), r, "utf8");
385
+ }, Ze = async (e, t) => {
386
+ let n = `${Ke}
387
+ import { __installPublicEnv } from '@voltro/env/public'
388
+
389
+ export const publicEnvValues = ${JSON.stringify(t, null, 2)} as const
390
+
391
+ // Set the browser/SSR-shared global the \`publicEnv\` accessor reads.
392
+ __installPublicEnv(publicEnvValues)
393
+ `;
394
+ await de(e, { recursive: !0 }), await B(l(e, "env.public.ts"), n, "utf8");
395
+ }, Qe = async (e) => {
396
+ let t = se(e.rawEnv) ? e.rawEnv : void 0, n = await z({
397
+ contract: t,
398
+ resolveSecret: I
399
+ }), r = [...n.errors, ...ie(t, e.appType)];
400
+ if (r.length > 0) throw Error(ae(r));
401
+ oe(n.values), e.appType === "web" && ue(n.publicValues);
402
+ let i = t ? Object.keys(t.vars).length : 0;
403
+ if (i > 0) {
404
+ let r = Object.keys(n.publicValues).length;
405
+ if (e.log.info(`env: ${i} declared var(s) validated`, {
406
+ public: r,
407
+ secret: i - r
408
+ }), e.appType === "web" && t) {
409
+ let n = Object.entries(t.vars).filter(([, e]) => e.access === "secret").map(([e]) => e);
410
+ n.length > 0 && e.log.warn(`env: ${n.length} secret var(s) declared on a web app — secrets are reachable only from server-side render code and are NEVER bundled. Prefer declaring secrets on the api.`, { keys: n });
411
+ }
412
+ }
413
+ return e.generateTypes && t && (e.appType === "api" ? await Ye(e.root, t) : await Xe(e.root, t)), {
414
+ resolved: n,
415
+ contract: t
416
+ };
417
+ }, $e = (e) => {
418
+ let t = re(e.contract), n = (e.plugins ?? []).flatMap((e) => ce(e.name, e.declaredEnv)), r = e.includeFramework === !1 ? [] : ne, i = /* @__PURE__ */ new Set(), a = [];
419
+ for (let e of [
420
+ ...t,
421
+ ...n,
422
+ ...r
423
+ ]) i.has(e.key) || (i.add(e.key), a.push(e));
424
+ return a;
425
+ }, et = (e, t, n = (e) => process.env[e]) => {
426
+ let r = $e(t).map((e) => {
427
+ let t = n(e.key) !== void 0;
428
+ return {
429
+ ...e,
430
+ isSet: t,
431
+ satisfied: t || e.default !== void 0 || !e.required
432
+ };
433
+ });
434
+ return {
435
+ app: e,
436
+ entries: r,
437
+ summary: {
438
+ total: r.length,
439
+ set: r.filter((e) => e.isSet).length,
440
+ missingRequired: r.filter((e) => e.required && !e.isSet && e.default === void 0).length
441
+ }
442
+ };
443
+ }, tt = (e, t) => le($e({
444
+ ...e,
445
+ includeFramework: !1
446
+ }), {
447
+ includeFramework: e.includeFramework !== !1,
448
+ ...t ? { header: t } : {}
449
+ }), nt = () => {
450
+ let e = /* @__PURE__ */ new Map();
451
+ return {
452
+ get(t) {
453
+ return e.get(t);
454
+ },
455
+ set(t, n) {
456
+ e.set(t, n);
457
+ },
458
+ invalidate(t) {
459
+ e.delete(t);
460
+ },
461
+ invalidateBy(t) {
462
+ let n = 0;
463
+ for (let r of e.keys()) t(r) && (e.delete(r), n++);
464
+ return n;
465
+ },
466
+ clear() {
467
+ e.clear();
468
+ },
469
+ size() {
470
+ return e.size;
471
+ },
472
+ snapshot() {
473
+ return Array.from(e.entries());
474
+ }
475
+ };
476
+ }, K = (e) => {
477
+ if (typeof e == "number" && Number.isFinite(e) && e > 0) return e * 1e3;
478
+ if (typeof e != "string") return null;
479
+ let t = /^\s*(\d+)\s*(s|seconds?|m|minutes?|h|hours?|d|days?)\s*$/i.exec(e);
480
+ if (!t) return null;
481
+ let n = parseInt(t[1], 10);
482
+ if (!Number.isFinite(n) || n <= 0) return null;
483
+ let r = t[2].toLowerCase();
484
+ return r === "s" || r.startsWith("second") ? n * 1e3 : r === "m" || r.startsWith("minute") ? n * 6e4 : r === "h" || r.startsWith("hour") ? n * 36e5 : r === "d" || r.startsWith("day") ? n * 864e5 : null;
485
+ }, rt = (e, t = {}) => {
486
+ let n = [e];
487
+ return t.tenant !== void 0 && t.tenant !== "" && n.push(`tenant=${t.tenant}`), t.locale !== void 0 && t.locale !== "" && n.push(`lang=${t.locale}`), n.join("|");
488
+ }, it = (e, t) => e.expiresAt > t, at = (e, t) => e.expiresAt <= t && e.servableUntil > t, ot = S({ scope: "voltro:cli" }), st = [], ct = (e) => {
489
+ st.length = 0;
490
+ let t = e[1] && !e[1].startsWith("-") ? e[1] : void 0, n = t ? c(t) ? t : d(process.cwd(), t) : process.cwd(), r = [], i = n;
491
+ for (;;) {
492
+ r.push(i);
493
+ let e = s(i);
494
+ if (e === i) break;
495
+ i = e;
496
+ }
497
+ for (let e of r) for (let t of [".env.local", ".env"]) {
498
+ let n = d(e, t);
499
+ if (T(n)) {
500
+ st.push(n);
501
+ try {
502
+ let e = k(n, "utf8");
503
+ for (let t of e.split(/\r?\n/)) {
504
+ let e = t.trim();
505
+ if (e === "" || e.startsWith("#")) continue;
506
+ let n = e.indexOf("=");
507
+ if (n < 1) continue;
508
+ let r = e.slice(0, n).trim(), i = e.slice(n + 1).trim();
509
+ (i.startsWith("\"") && i.endsWith("\"") || i.startsWith("'") && i.endsWith("'")) && (i = i.slice(1, -1)), process.env[r] === void 0 && (process.env[r] = i);
510
+ }
511
+ } catch (e) {
512
+ ot.warn("failed to load env file (continuing)", { path: n }, e);
513
+ }
514
+ }
515
+ }
516
+ }, lt = 500, ut = (e, t, n = {}) => {
517
+ if (e.length === 0) return () => {};
518
+ let r = (e) => n.root ? u(n.root, e) : e, i = !1, a = (e) => {
519
+ i || (i = !0, t.warn(`.env changed (${r(e)}) — hard-restarting: process.env is read once at boot, a reload would keep stale values`, { file: r(e) }), Promise.resolve().then(() => n.onBeforeRestart?.()).catch((e) => t.warn(".env restart: onBeforeRestart failed (continuing)", {}, e)).finally(() => {
520
+ let e = me(process.execPath, [...process.execArgv, ...process.argv.slice(1)], {
521
+ stdio: "inherit",
522
+ env: process.env,
523
+ cwd: n.cwd ?? process.cwd()
524
+ }), r = (t) => {
525
+ e.kill(t);
526
+ }, i = () => r("SIGINT"), a = () => r("SIGTERM");
527
+ process.on("SIGINT", i), process.on("SIGTERM", a), e.on("exit", (e, t) => {
528
+ process.off("SIGINT", i), process.off("SIGTERM", a), t ? process.kill(process.pid, t) : process.exit(e ?? 0);
529
+ }), e.on("error", (e) => {
530
+ t.error(".env restart: spawn failed", {}, e), process.exit(1);
531
+ });
532
+ }));
533
+ };
534
+ for (let t of e) P(t, { interval: lt }, (e, n) => {
535
+ e.mtimeMs !== n.mtimeMs && a(t);
536
+ });
537
+ return t.info("watching .env files for changes", {
538
+ files: e.map(r),
539
+ intervalMs: lt
540
+ }), () => {
541
+ for (let t of e) N(t);
542
+ };
543
+ }, q = S({ scope: "vite" }), dt = /\x1b\[[0-9;]*m/g, ft = /^\s*\[?vite\]?\s*(\([a-z-]+\)\s*)?/, pt = (e) => e.replace(dt, "").replace(ft, "").trim(), mt = /proxy error/i, ht = [
544
+ "ECONNREFUSED",
545
+ "ECONNRESET",
546
+ "ECONNABORTED",
547
+ "EPIPE",
548
+ "ETIMEDOUT"
549
+ ], gt = (e, t = 0) => {
550
+ if (e == null || t > 5) return !1;
551
+ let n = e;
552
+ return typeof n.code == "string" && ht.includes(n.code) || typeof n.message == "string" && ht.some((e) => n.message.includes(e)) || Array.isArray(n.errors) && n.errors.some((e) => gt(e, t + 1)) ? !0 : gt(n.cause, t + 1);
553
+ }, _t = 4e3, vt = () => {
554
+ let e = /* @__PURE__ */ new Set(), t = 0, n = {
555
+ hasWarned: !1,
556
+ info: (e) => {
557
+ let t = pt(e);
558
+ t.length !== 0 && q.info(t);
559
+ },
560
+ warn: (e) => {
561
+ n.hasWarned = !0;
562
+ let t = pt(e);
563
+ t.length !== 0 && q.warn(t);
564
+ },
565
+ warnOnce: (t) => {
566
+ let r = pt(t);
567
+ e.has(r) || (e.add(r), n.hasWarned = !0, r.length !== 0 && q.warn(r));
568
+ },
569
+ error: (e, n) => {
570
+ let r = pt(e), i = n?.error;
571
+ if (r.length !== 0) {
572
+ if (mt.test(r) && gt(i)) {
573
+ let e = Date.now();
574
+ e - t > _t && (t = e, q.info("waiting for api — proxy upstream not accepting connections yet (still starting?)"));
575
+ return;
576
+ }
577
+ q.error(r, {}, i);
578
+ }
579
+ },
580
+ clearScreen: () => {},
581
+ hasErrorLogged: (e) => !1
582
+ };
583
+ return n;
584
+ }, yt = (e = process.env) => {
585
+ let t = e.VOLTRO_DEV_SSR_COMPILE_CONCURRENCY;
586
+ if (t === void 0 || t.trim() === "") return 4;
587
+ let n = Number(t);
588
+ return Number.isFinite(n) && n >= 1 ? Math.floor(n) : 4;
589
+ }, bt = (e) => {
590
+ let t = Math.max(1, Math.floor(e)), n = 0, r = [], i = () => n < t ? (n++, Promise.resolve()) : new Promise((e) => r.push(e)), a = () => {
591
+ let e = r.shift();
592
+ e ? e() : n--;
593
+ };
594
+ return {
595
+ withPermit: async (e) => {
596
+ await i();
597
+ try {
598
+ return await e();
599
+ } finally {
600
+ a();
601
+ }
602
+ },
603
+ get active() {
604
+ return n;
605
+ }
606
+ };
607
+ }, xt = (e) => {
608
+ let t = bt(e.limit), n = /* @__PURE__ */ new Map(), r = /* @__PURE__ */ new Set();
609
+ return {
610
+ load: (i, a) => {
611
+ if (r.has(i)) return a();
612
+ let o = n.get(i);
613
+ if (o) return o;
614
+ let s = t.withPermit(async () => {
615
+ e.onColdStart?.(i);
616
+ try {
617
+ return await a();
618
+ } finally {
619
+ e.onColdEnd?.(i);
620
+ }
621
+ }).then((e) => (r.add(i), e)).finally(() => {
622
+ n.delete(i);
623
+ });
624
+ return n.set(i, s), s;
625
+ },
626
+ get inFlightCount() {
627
+ return n.size;
628
+ },
629
+ get warmCount() {
630
+ return r.size;
631
+ }
632
+ };
633
+ }, St = (e) => {
634
+ let t = [];
635
+ for (let n of e.split("/").filter(Boolean)) n.startsWith("[[...") && n.endsWith("]]") ? t.push({
636
+ name: n.slice(5, -2),
637
+ catchAll: !0,
638
+ optional: !0
639
+ }) : n.startsWith("[...") && n.endsWith("]") ? t.push({
640
+ name: n.slice(4, -1),
641
+ catchAll: !0,
642
+ optional: !1
643
+ }) : n.startsWith("[") && n.endsWith("]") && t.push({
644
+ name: n.slice(1, -1),
645
+ catchAll: !1,
646
+ optional: !1
647
+ });
648
+ return t;
649
+ }, Ct = (e) => e.replace(/-([a-z0-9])/g, (e, t) => t.toUpperCase()), wt = async (e) => {
650
+ let t = d(e);
651
+ for (let e = 0; e < 4; e++) {
652
+ let e = l(t, "project.json");
653
+ if (T(e)) try {
654
+ let n = await O.readFile(e, "utf8");
655
+ return {
656
+ projectDir: t,
657
+ manifest: JSON.parse(n)
658
+ };
659
+ } catch {
660
+ return null;
661
+ }
662
+ let n = s(t);
663
+ if (n === t) break;
664
+ t = n;
665
+ }
666
+ return null;
667
+ }, Tt = async (e) => {
668
+ let t = await wt(e);
669
+ if (!t) return [];
670
+ let { projectDir: n, manifest: r } = t, i = o(e), a = r.apps ?? {}, s = [];
671
+ for (let [e, t] of Object.entries(a)) {
672
+ if (e === i || t.kind !== "web" || typeof t.port != "number") continue;
673
+ let r = l(l(n, t.path ?? e), "src", "pages");
674
+ if (!T(r)) continue;
675
+ let a;
676
+ try {
677
+ let { pages: e } = await $(r);
678
+ a = e.map((e) => ({
679
+ pattern: e.pattern,
680
+ params: St(e.pattern)
681
+ }));
682
+ } catch {
683
+ continue;
684
+ }
685
+ s.push({
686
+ key: Ct(e),
687
+ origin: `http://localhost:${t.port}`,
688
+ ...typeof t.origin == "string" && t.origin.length > 0 ? { prodOrigin: t.origin } : {},
689
+ routes: a
690
+ });
691
+ }
692
+ return s;
693
+ }, Et = (e) => {
694
+ if (e.params.length === 0) return `'${e.pattern}'`;
695
+ let t = e.pattern;
696
+ for (let n of e.params) {
697
+ let e = n.optional ? `[[...${n.name}]]` : n.catchAll ? `[...${n.name}]` : `[${n.name}]`, r = n.optional ? "${" + n.name + " === undefined ? \"\" : encodeURI(" + n.name + ")}" : n.catchAll ? "${encodeURI(" + n.name + ")}" : "${encodeURIComponent(" + n.name + ")}";
698
+ t = t.replace(e, r);
699
+ }
700
+ return "`" + t + "`";
701
+ }, Dt = (e) => e.params.length === 0 ? "EmptyParams" : `{ ${e.params.map((e) => {
702
+ let t = "string";
703
+ return e.optional ? `readonly ${e.name}?: ${t}` : `readonly ${e.name}: ${t}`;
704
+ }).join("; ")} }`, Ot = (e, t, n) => {
705
+ let r = Dt(e), i = Et(e), a = t ? "VoltroExternalUrl" : "VoltroRouteUrl", o = t && n ? `${n} + ` : "";
706
+ return e.params.length === 0 ? `() => (${o}${i}) as ${a}` : `({ ${e.params.map((e) => e.name).join(", ")} }: ${r}) => (${o}${i}) as ${a}`;
707
+ }, kt = (e) => `{\n${[...e].sort((e, t) => e.pattern.localeCompare(t.pattern)).map((e) => ` ${JSON.stringify(e.pattern)}: ${Ot(e, !1)},`).join("\n")}\n}`, At = (e, t) => {
708
+ if (e.routes.length === 0) return ` ${e.key}: {} as Record<string, never>,`;
709
+ let n = [...e.routes].sort((e, t) => e.pattern.localeCompare(t.pattern)), r = t === "prod" && e.prodOrigin ? e.prodOrigin : e.origin, i = JSON.stringify(r), a = n.map((e) => ` ${JSON.stringify(e.pattern)}: ${Ot(e, !0, i)},`);
710
+ return ` ${e.key}: {\n${a.join("\n")}\n },`;
711
+ }, jt = async (e) => {
712
+ let t = e.pages.map((e) => ({
713
+ pattern: e.pattern,
714
+ params: St(e.pattern)
715
+ })), n = await Tt(e.appRoot), r = [
716
+ "// THIS FILE IS GENERATED — DO NOT EDIT BY HAND.",
717
+ "// Re-emitted by `voltro dev` whenever `src/pages/**` changes.",
718
+ "// Type-safe route builders consumed by <Link to={...}>.",
719
+ "",
720
+ "import type { VoltroRouteUrl, VoltroExternalUrl } from '@voltro/web'",
721
+ "",
722
+ "type EmptyParams = Record<string, never>",
723
+ ""
724
+ ].join("\n"), i = e.mode ?? "dev", a = `${r}\n${`export const routes = ${kt(t)} as const\n`}\n${n.length === 0 ? "export const siblingApps = {} as Record<string, never>\n" : `export const siblingApps = {\n${n.map((e) => At(e, i)).join("\n")}\n} as const\n`}`, o = l(e.appRoot, ".framework", "routes.generated.ts");
725
+ await O.mkdir(s(o), { recursive: !0 });
726
+ let c = null;
727
+ try {
728
+ c = await O.readFile(o, "utf8");
729
+ } catch {}
730
+ return c === a ? {
731
+ path: o,
732
+ wrote: !1
733
+ } : (await O.writeFile(o, a, "utf8"), {
734
+ path: o,
735
+ wrote: !0
736
+ });
737
+ }, Mt = 256, Nt = (e = Mt) => {
738
+ let t = [], n = /* @__PURE__ */ new Set();
739
+ return {
740
+ emit(r, i) {
741
+ let a = {
742
+ ts: Date.now(),
743
+ channel: r,
744
+ payload: i
745
+ };
746
+ t.push(a), t.length > e && t.shift();
747
+ for (let e of n) try {
748
+ e(a);
749
+ } catch {}
750
+ },
751
+ subscribe(e) {
752
+ return n.add(e), () => {
753
+ n.delete(e);
754
+ };
755
+ },
756
+ buffered() {
757
+ return t.slice();
758
+ }
759
+ };
760
+ }, Pt = (e) => `event: ${e.channel}\ndata: ${JSON.stringify(e)}\n\n`, Ft = () => `: keep-alive ${Date.now()}\n\n`, It = {
761
+ trace: 0,
762
+ debug: 1,
763
+ info: 2,
764
+ warn: 3,
765
+ error: 4,
766
+ fatal: 5
767
+ }, Lt = 2e3, Rt = 200, zt = class {
768
+ capacity;
769
+ buffer = [];
770
+ constructor(e = Lt) {
771
+ this.capacity = e;
772
+ }
773
+ append(e) {
774
+ this.buffer.push(e), this.buffer.length > this.capacity && this.buffer.shift();
775
+ }
776
+ query(e = {}) {
777
+ let t = e.since ?? 0, n = e.until ?? Date.now(), r = Math.min(e.max ?? Rt, this.capacity), i = e.minLevel === void 0 ? It.trace : It[e.minLevel], a = e.scope?.toLowerCase(), o = e.source, s = e.filter?.toLowerCase(), c = e.traceId, l = [];
778
+ for (let e = this.buffer.length - 1; e >= 0 && l.length < r; e--) {
779
+ let r = this.buffer[e];
780
+ r.ts < t || r.ts > n || It[r.level] < i || o !== void 0 && r.source !== o || a !== void 0 && (r.scope === void 0 || !r.scope.toLowerCase().includes(a)) || s !== void 0 && !r.message.toLowerCase().includes(s) || c !== void 0 && r.fields.traceId !== c || l.push(r);
781
+ }
782
+ return l.reverse();
783
+ }
784
+ size() {
785
+ return this.buffer.length;
786
+ }
787
+ capacityHint() {
788
+ return this.capacity;
789
+ }
790
+ clear() {
791
+ this.buffer = [];
792
+ }
793
+ }, Bt = null, Vt = () => (Bt === null && (Bt = new zt()), Bt), Ht = (e) => {
794
+ if (typeof e == "string") return e;
795
+ if (e instanceof Error) return e.message;
796
+ try {
797
+ return JSON.stringify(e);
798
+ } catch {
799
+ return String(e);
800
+ }
801
+ }, Ut = (e) => {
802
+ let t = {
803
+ log: console.log.bind(console),
804
+ info: console.info.bind(console),
805
+ warn: console.warn.bind(console),
806
+ error: console.error.bind(console),
807
+ debug: console.debug.bind(console)
808
+ }, n = Vt(), r = !1, i = (i) => (...a) => {
809
+ if (t[i](...a), !r) {
810
+ r = !0;
811
+ try {
812
+ let t = a.length > 0 ? Ht(a[0]) : "", r = t.length > 500 ? t.slice(0, 500) + "…" : t, o = F();
813
+ e.emit("log", {
814
+ level: i,
815
+ message: r,
816
+ argsCount: a.length,
817
+ ...o ? { traceId: o.traceId } : {}
818
+ });
819
+ let s = i === "log" ? "info" : i;
820
+ n.append({
821
+ ts: Date.now(),
822
+ level: s,
823
+ source: "server",
824
+ message: r,
825
+ fields: {
826
+ ...a.length > 1 ? { argsCount: a.length } : {},
827
+ ...o ? {
828
+ traceId: o.traceId,
829
+ ...o.spanId === void 0 ? {} : { spanId: o.spanId }
830
+ } : {}
831
+ }
832
+ });
833
+ } finally {
834
+ r = !1;
835
+ }
836
+ }
837
+ };
838
+ console.log = i("log"), console.info = i("info"), console.warn = i("warn"), console.error = i("error"), console.debug = i("debug");
839
+ let a = x((t) => {
840
+ if (!r) {
841
+ r = !0;
842
+ try {
843
+ let r = t.level === "trace" || t.level === "debug" ? "debug" : t.level === "info" ? "info" : t.level === "warn" ? "warn" : "error", i = `${t.scope ? `[${t.scope}] ` : ""}${t.message}`;
844
+ e.emit("log", {
845
+ level: r,
846
+ message: i.length > 500 ? i.slice(0, 500) + "…" : i,
847
+ argsCount: 1,
848
+ ...t.scope === void 0 ? {} : { scope: t.scope }
849
+ });
850
+ let a = F(), o = a !== void 0 && t.fields.traceId === void 0 ? {
851
+ ...t.fields,
852
+ traceId: a.traceId
853
+ } : t.fields;
854
+ n.append({
855
+ ts: t.ts.getTime(),
856
+ level: t.level,
857
+ source: t.scope === "client" ? "client" : "server",
858
+ ...t.scope === void 0 ? {} : { scope: t.scope },
859
+ message: t.message,
860
+ fields: o
861
+ });
862
+ } finally {
863
+ r = !1;
864
+ }
865
+ }
866
+ });
867
+ return () => {
868
+ console.log = t.log, console.info = t.info, console.warn = t.warn, console.error = t.error, console.debug = t.debug, a();
869
+ };
870
+ }, Wt = 2e3, Gt = 8, Kt = 1e3, qt = 200, J = (e, t) => e.length > t ? `${e.slice(0, t)}…` : e, Jt = (e) => {
871
+ switch (e) {
872
+ case "error": return "error";
873
+ case "warn": return "warn";
874
+ case "debug": return "debug";
875
+ default: return "info";
876
+ }
877
+ }, Yt = S({ scope: "client" }), Xt = (e, t) => {
878
+ let n;
879
+ try {
880
+ n = JSON.parse(e);
881
+ } catch {
882
+ return Zt(400, { error: "invalid JSON body" });
883
+ }
884
+ if (typeof n != "object" || !n) return Zt(400, { error: "body must be a JSON object" });
885
+ let r = n;
886
+ if (!Array.isArray(r.entries)) return Zt(400, { error: "entries must be an array" });
887
+ let i = typeof r.app == "string" ? J(r.app, 120) : void 0, a = typeof r.page == "string" ? J(r.page, 200) : void 0, o = typeof r.ua == "string" ? J(r.ua, 200) : void 0, s = r.entries.slice(0, qt), c = 0;
888
+ for (let e of s) {
889
+ if (typeof e != "object" || !e) continue;
890
+ let n = e;
891
+ if (typeof n.message != "string") continue;
892
+ let r = typeof n.level == "string" && [
893
+ "log",
894
+ "info",
895
+ "warn",
896
+ "error",
897
+ "debug"
898
+ ].includes(n.level) ? n.level : "log", s = typeof n.ts == "number" && Number.isFinite(n.ts) ? n.ts : Date.now(), l = J(n.message, Wt), u = Array.isArray(n.args) ? n.args.slice(0, Gt).filter((e) => typeof e == "string").map((e) => J(e, Kt)) : void 0, d = typeof n.stack == "string" ? J(n.stack, Wt) : void 0;
899
+ t.emit("clientLog", {
900
+ ts: s,
901
+ level: r,
902
+ message: l,
903
+ ...u === void 0 ? {} : { args: u },
904
+ ...d === void 0 ? {} : { stack: d },
905
+ ...i === void 0 ? {} : { app: i },
906
+ ...a === void 0 ? {} : { page: a },
907
+ ...o === void 0 ? {} : { ua: o }
908
+ });
909
+ let f = {
910
+ ...i === void 0 ? {} : { app: i },
911
+ ...a === void 0 ? {} : { page: a },
912
+ ...u !== void 0 && u.length > 0 ? { args: u } : {}
913
+ }, p = Jt(r);
914
+ (p === "error" || p === "warn") && d !== void 0 ? Yt[p](l, f, { stack: d }) : Yt[p](l, {
915
+ ...f,
916
+ ...d === void 0 ? {} : { stack: d }
917
+ }), c++;
918
+ }
919
+ return Zt(202, {
920
+ accepted: c,
921
+ dropped: r.entries.length - c
922
+ });
923
+ }, Zt = (e, t) => ({
924
+ status: e,
925
+ contentType: "application/json; charset=utf-8",
926
+ body: JSON.stringify(t)
927
+ }), Qt = "/_voltro/inspect/clientLog", $t = [
928
+ "trace",
929
+ "debug",
930
+ "info",
931
+ "warn",
932
+ "error",
933
+ "fatal"
934
+ ], en = {
935
+ trace: "TRACE",
936
+ debug: "DEBUG",
937
+ info: "INFO ",
938
+ warn: "WARN ",
939
+ error: "ERROR",
940
+ fatal: "FATAL"
941
+ }, tn = (e) => $t.includes(e), nn = (e, n, i = {}) => {
942
+ if (t()) return {
943
+ status: 503,
944
+ contentType: "application/json",
945
+ body: JSON.stringify({ error: "inspect disabled (VOLTRO_INSPECT=off)" })
946
+ };
947
+ let a = r(i);
948
+ if (!a.ok) return {
949
+ status: 401,
950
+ contentType: "application/json",
951
+ body: JSON.stringify({
952
+ error: "unauthorized",
953
+ reason: a.reason
954
+ })
955
+ };
956
+ let o = e.indexOf("?"), s = o === -1 ? new URLSearchParams() : new URLSearchParams(e.slice(o + 1)), c = {}, l = s.get("since");
957
+ if (l !== null) {
958
+ let e = Number(l);
959
+ Number.isFinite(e) && (c.since = e);
960
+ }
961
+ let u = s.get("until");
962
+ if (u !== null) {
963
+ let e = Number(u);
964
+ Number.isFinite(e) && (c.until = e);
965
+ }
966
+ let d = s.get("max");
967
+ if (d !== null) {
968
+ let e = Number(d);
969
+ Number.isFinite(e) && e > 0 && (c.max = Math.floor(e));
970
+ }
971
+ let f = s.get("level");
972
+ f !== null && tn(f) && (c.minLevel = f);
973
+ let p = s.get("source");
974
+ (p === "server" || p === "client") && (c.source = p);
975
+ let m = s.get("scope");
976
+ m !== null && m.length > 0 && (c.scope = m);
977
+ let h = s.get("filter");
978
+ h !== null && h.length > 0 && (c.filter = h);
979
+ let g = s.get("trace");
980
+ g !== null && g.length > 0 && (c.traceId = g);
981
+ let _ = n.query(c);
982
+ if ((s.get("format") ?? "json") === "text") return {
983
+ status: 200,
984
+ contentType: "text/plain; charset=utf-8",
985
+ body: _.map(rn).join("\n") + (_.length > 0 ? "\n" : "")
986
+ };
987
+ let v = {
988
+ capturedAt: Date.now(),
989
+ bufferCapacity: n.capacityHint(),
990
+ bufferSize: n.size(),
991
+ returned: _.length,
992
+ records: _
993
+ };
994
+ return {
995
+ status: 200,
996
+ contentType: "application/json; charset=utf-8",
997
+ body: JSON.stringify(v)
998
+ };
999
+ }, rn = (e) => {
1000
+ let t = new Date(e.ts), n = String(t.getHours()).padStart(2, "0"), r = String(t.getMinutes()).padStart(2, "0"), i = String(t.getSeconds()).padStart(2, "0"), a = String(t.getMilliseconds()).padStart(3, "0"), o = `[${e.scope ?? "?"}/${e.source}]`, s = on(e.fields);
1001
+ return `${n}:${r}:${i}.${a} ${en[e.level]} ${o} ${e.message}${s}`;
1002
+ }, an = 80, on = (e) => {
1003
+ let t = Object.entries(e);
1004
+ if (t.length === 0) return "";
1005
+ let n = [];
1006
+ for (let [e, r] of t) {
1007
+ if (r === void 0) continue;
1008
+ let t = sn(r);
1009
+ n.push(`${e}=${t}`);
1010
+ }
1011
+ return n.length > 0 ? " " + n.join(" ") : "";
1012
+ }, sn = (e) => {
1013
+ if (typeof e == "string") {
1014
+ let t = e.length > an ? e.slice(0, an) + "…" : e;
1015
+ return /[\s=]/.test(t) ? `"${t.replace(/"/g, "\\\"")}"` : t;
1016
+ }
1017
+ if (e === null) return "null";
1018
+ if (typeof e == "number" || typeof e == "boolean") return String(e);
1019
+ try {
1020
+ let t = JSON.stringify(e);
1021
+ return t.length > an ? t.slice(0, an) + "…" : t;
1022
+ } catch {
1023
+ return "[unserialisable]";
1024
+ }
1025
+ }, cn = "/_voltro/inspect/logs", ln = [{
1026
+ match: (e) => typeof e == "string" && e.startsWith("[BABEL] Note: The code generator has deoptimised"),
1027
+ handle: (e, t) => {
1028
+ let n = e[0], r = n.match(/deoptimised the styling of (.+?) as it exceeds the max of (\d+\w*B)\.?/);
1029
+ if (r) {
1030
+ let [, e, n] = r;
1031
+ t.info(`code generator deoptimised (${n}+)`, {
1032
+ path: e,
1033
+ threshold: n
1034
+ });
1035
+ } else t.info(n);
1036
+ }
1037
+ }], un = () => {
1038
+ let e = {
1039
+ warn: console.warn.bind(console),
1040
+ error: console.error.bind(console)
1041
+ }, t = S({ scope: "babel" }), n = !1, r = (r) => (...i) => {
1042
+ if (!n) {
1043
+ for (let e of ln) if (e.match(i[0])) {
1044
+ n = !0;
1045
+ try {
1046
+ e.handle(i, t);
1047
+ } finally {
1048
+ n = !1;
1049
+ }
1050
+ return;
1051
+ }
1052
+ }
1053
+ e[r](...i);
1054
+ };
1055
+ return console.warn = r("warn"), console.error = r("error"), () => {
1056
+ console.warn = e.warn, console.error = e.error;
1057
+ };
1058
+ }, dn = {
1059
+ loader: "it runs on the server, and the router caches its result per route + params",
1060
+ renderMode: "it picks the server render strategy",
1061
+ dynamic: "it picks the server render strategy",
1062
+ meta: "the server rendered it into <head>",
1063
+ getStaticPaths: "it enumerates which paths get prerendered",
1064
+ revalidate: "it sets the ISR cache window",
1065
+ staleWhileRevalidate: "it sets the ISR stale-while-revalidate window",
1066
+ cacheInvalidatesOn: "it wires this page into the ISR cache invalidator",
1067
+ interactive: "it decides how much client JS the server ships",
1068
+ tenantAware: "it is part of the server-side cache key"
1069
+ }, fn = Object.keys(dn), pn = "virtual:voltro-route-refresh", mn = `\0${pn}`, hn = /(?:^|&)(raw|url|inline|worker|sharedworker|direct)(?:&|=|$)/, gn = () => `
1070
+ // GENERATED by @voltro/cli — the \`voltro dev\` route Fast Refresh runtime.
1071
+
1072
+ /** Mirrors react-refresh's own \`isLikelyComponentType\` closely enough for the
1073
+ * decision we make with it: an uppercase-named function, or a React element
1074
+ * type object (memo / forwardRef / lazy carry \`$$typeof\`). */
1075
+ const isComponentLike = (value) => {
1076
+ if (typeof value === 'function') {
1077
+ const name = value.displayName ?? value.name
1078
+ return typeof name === 'string' && /^[A-Z]/.test(name)
1079
+ }
1080
+ return typeof value === 'object' && value !== null && '$$typeof' in value
1081
+ }
1082
+
1083
+ /** Value identity that survives module re-evaluation. A function is compared by
1084
+ * SOURCE TEXT — a re-evaluated but unedited \`loader\` is a brand-new object
1085
+ * with identical text — and everything else by its JSON form, so a \`meta\`
1086
+ * object literal does not read as changed on every edit. */
1087
+ const stableForm = (value) => {
1088
+ if (typeof value === 'function') return 'fn:' + String(value)
1089
+ try { return 'js:' + JSON.stringify(value) } catch { return 'st:' + String(value) }
1090
+ }
1091
+
1092
+ /** The route-module exports the SERVER reads to produce the HTML — injected
1093
+ * from \`SERVER_RELEVANT_ROUTE_EXPORTS\`, which is derived from
1094
+ * \`computeRouteMetadata\`'s own parameter type so it cannot drift from the
1095
+ * readers (\`build.ts\` prerender, \`webDev.ts\` dev SSR, \`start.ts\`). A change to
1096
+ * one of THESE cannot be hot-applied: the server already ran with the old
1097
+ * value. Everything else a page exports is plain client-side data. */
1098
+ const serverRelevantExports = ${JSON.stringify(fn)}
1099
+
1100
+ /** Name → the server step that already consumed it, so the reload message can
1101
+ * say WHY rather than just WHAT. Injected from the same single source. */
1102
+ const serverExportEffect = ${JSON.stringify(dn)}
1103
+
1104
+ /** The reason \`name\` forces a reload, for the console line. */
1105
+ export const serverEffectOf = (name) =>
1106
+ serverExportEffect[name] ?? 'the server reads it off the route module'
1107
+
1108
+ /** id (absolute file path, as react-refresh spells it) → export names that
1109
+ * react-refresh must NOT judge. */
1110
+ const ignoredExports = new Map()
1111
+
1112
+ export const registerRouteModule = (id, moduleExports) => {
1113
+ const names = []
1114
+ for (const key of Object.keys(moduleExports)) {
1115
+ if (key === 'default') continue
1116
+ if (isComponentLike(moduleExports[key])) continue
1117
+ names.push(key)
1118
+ }
1119
+ ignoredExports.set(id, names)
1120
+ }
1121
+
1122
+ /** The name of the first SERVER-RELEVANT export whose VALUE changed, or null
1123
+ * when this update is one Fast Refresh can apply in place — a component edit,
1124
+ * or a change to a page-local value the server never read.
1125
+ *
1126
+ * Only the server-relevant names are inspected. A plain value export
1127
+ * (\`const COLUMNS = [...]\`) changing is NOT a reason to throw the page away:
1128
+ * the module re-evaluates, the component renders with the new value, and any
1129
+ * other importer is Vite's own graph propagation to resolve. */
1130
+ export const routeUpdateNeedsReload = (prevExports, nextExports) => {
1131
+ for (const key of serverRelevantExports) {
1132
+ if (stableForm(prevExports[key]) !== stableForm(nextExports[key])) return key
1133
+ }
1134
+ return null
1135
+ }
1136
+
1137
+ // \`globalThis\`, not \`window\`: identical in the browser (which is the only place
1138
+ // this module is ever loaded) and it keeps the runtime evaluatable by the unit
1139
+ // test, which is what lets the test read the REAL source instead of a copy.
1140
+ // Chained rather than overwritten — another plugin may own the hook for its own
1141
+ // modules, and ours only answers for ids it registered.
1142
+ const previousHook = globalThis.__getReactRefreshIgnoredExports
1143
+ globalThis.__getReactRefreshIgnoredExports = (args) =>
1144
+ ignoredExports.get(args.id) ?? previousHook?.(args) ?? []
1145
+ `, _n = (e) => `
1146
+ if (import.meta.hot) {
1147
+ // Self-import to read our OWN exports, the same technique the react plugin
1148
+ // uses; the namespace is only complete after evaluation, hence the promise.
1149
+ import(/* @vite-ignore */ import.meta.url).then((__voltro_exports) => {
1150
+ __voltro_registerRouteModule(${JSON.stringify(e)}, __voltro_exports)
1151
+ import.meta.hot.accept((__voltro_next) => {
1152
+ if (!__voltro_next) return
1153
+ const changed = __voltro_routeUpdateNeedsReload(__voltro_exports, __voltro_next)
1154
+ if (changed === null) {
1155
+ __voltro_registerRouteModule(${JSON.stringify(e)}, __voltro_next)
1156
+ return
1157
+ }
1158
+ console.info(
1159
+ '[voltro] full reload: \`' + changed + '\` changed in ' + ${JSON.stringify(e)} +
1160
+ ' — the server READS that export (' + __voltro_serverEffect(changed) +
1161
+ '), and the page in front of you was produced from the old value, so it ' +
1162
+ 'must be re-rendered. Other exports of this module hot-update in place.',
1163
+ )
1164
+ window.location.reload()
1165
+ })
1166
+ })
1167
+ }
1168
+ import {
1169
+ registerRouteModule as __voltro_registerRouteModule,
1170
+ routeUpdateNeedsReload as __voltro_routeUpdateNeedsReload,
1171
+ serverEffectOf as __voltro_serverEffect,
1172
+ } from '${pn}'
1173
+ `, vn = (e) => e.replace(/\\/g, "/"), yn = (e, t) => {
1174
+ let [n = "", r] = vn(e).split("?");
1175
+ if (!n.endsWith(".tsx") || r !== void 0 && hn.test(r)) return !1;
1176
+ let i = vn(t).replace(/\/$/, "");
1177
+ return n.startsWith(`${i}/`);
1178
+ }, bn = (e, t, n) => yn(t, n) ? `${e}${_n(vn(t).split("?")[0] ?? t)}` : null, xn = (e) => ({
1179
+ name: "voltro:route-fast-refresh",
1180
+ enforce: "pre",
1181
+ resolveId: (e) => e === "virtual:voltro-route-refresh" ? mn : void 0,
1182
+ load: (e) => e === mn ? gn() : void 0,
1183
+ transform: (t, n, r) => {
1184
+ if (r?.ssr === !0) return null;
1185
+ let i = bn(t, n, e);
1186
+ return i === null ? null : {
1187
+ code: i,
1188
+ map: null
1189
+ };
1190
+ }
1191
+ }), Sn = [
1192
+ "static",
1193
+ "spa",
1194
+ "ssr",
1195
+ "isr"
1196
+ ], Cn = (e) => typeof e == "string" && Sn.includes(e), wn = Sn.map((e) => `'${e}'`).join(" | "), Tn = (e, t) => `[voltro] ${e}: unknown renderMode '${t}'.\n Valid values: ${wn}.${t === "client" || t === "csr" || t === "browser" ? "\n A page that renders only in the browser is 'spa': it is skipped by the prerender and mounts on the client. If its route has a layout, that layout still renders server-side as an SSR shell." : t === "server" || t === "dynamic" ? "\n A page rendered per request is 'ssr'." : t === "ssg" || t === "prerender" ? "\n A page rendered once at build time is 'static' (the default)." : ""}`, En = class extends Error {
1197
+ page;
1198
+ value;
1199
+ name = "InvalidRenderModeError";
1200
+ constructor(e, t) {
1201
+ super(Tn(e, t)), this.page = e, this.value = t;
1202
+ }
1203
+ }, Dn = (e, t = "<page>") => {
1204
+ if (e.renderMode !== void 0 && e.renderMode !== null) {
1205
+ if (!Cn(e.renderMode)) throw new En(t, String(e.renderMode));
1206
+ return e.renderMode;
1207
+ }
1208
+ return e.dynamic === "force-dynamic" ? "ssr" : (e.dynamic, "static");
1209
+ }, On = (e, t = "<page>") => ({
1210
+ renderMode: Dn(e, t),
1211
+ tenantAware: e.tenantAware === !0,
1212
+ revalidateMs: K(e.revalidate),
1213
+ staleWhileRevalidateMs: K(e.staleWhileRevalidate) ?? 0,
1214
+ cacheInvalidatesOn: Array.isArray(e.cacheInvalidatesOn) ? e.cacheInvalidatesOn : [],
1215
+ interactive: e.interactive ?? "full",
1216
+ hasLoader: typeof e.loader == "function",
1217
+ hasMeta: e.meta != null,
1218
+ hasGetStaticPaths: typeof e.getStaticPaths == "function"
1219
+ }), kn = /export\s+const\s+renderMode\s*(?::[^=]+)?=\s*['"]([^'"]*)['"]/, An = (e) => kn.exec(e)?.[1] ?? null, jn = async (e, t) => {
1220
+ let n = (await Promise.all(t.map(async (t) => {
1221
+ let n;
1222
+ try {
1223
+ n = await fe(l(e, t.file), "utf8");
1224
+ } catch {
1225
+ return null;
1226
+ }
1227
+ let r = An(n);
1228
+ return r === null || Cn(r) ? null : {
1229
+ file: t.file,
1230
+ value: r
1231
+ };
1232
+ }))).filter((e) => e !== null);
1233
+ if (n.length !== 0) throw Error(n.map((e) => Tn(l("src", "pages", e.file), e.value)).join("\n\n"));
1234
+ }, Mn = l(R(), ".voltro"), Nn = l(Mn, "runtime-registry.json"), Pn = 3e4, Fn = () => {
1235
+ let e = Math.random().toString(36).slice(2, 10);
1236
+ return `${Nn}.${process.pid}.${Date.now()}.${e}.tmp`;
1237
+ }, In = async () => {
1238
+ await O.mkdir(Mn, { recursive: !0 });
1239
+ }, Ln = async () => {
1240
+ try {
1241
+ let e = await O.readFile(Nn, "utf8"), t = JSON.parse(e);
1242
+ return t.version !== 1 || !Array.isArray(t.apps) ? {
1243
+ version: 1,
1244
+ apps: []
1245
+ } : t;
1246
+ } catch {
1247
+ return {
1248
+ version: 1,
1249
+ apps: []
1250
+ };
1251
+ }
1252
+ }, Rn = async (e) => {
1253
+ await In();
1254
+ let t = Fn();
1255
+ try {
1256
+ await O.writeFile(t, JSON.stringify(e, null, 2), {
1257
+ encoding: "utf8",
1258
+ mode: 384
1259
+ }), await O.rename(t, Nn), await O.chmod(Nn, 384).catch(() => {});
1260
+ } catch (e) {
1261
+ try {
1262
+ await O.unlink(t);
1263
+ } catch {}
1264
+ throw e;
1265
+ }
1266
+ }, zn = (e) => {
1267
+ try {
1268
+ return process.kill(e, 0), !0;
1269
+ } catch {
1270
+ return !1;
1271
+ }
1272
+ }, Bn = (e) => {
1273
+ let t = Date.now();
1274
+ return e.filter((e) => zn(e.pid) ? t - new Date(e.heartbeatAt).getTime() < Pn : !1);
1275
+ }, Vn = async () => {
1276
+ let e = await Ln(), t = Bn(e.apps);
1277
+ if (t.length === e.apps.length) return e;
1278
+ try {
1279
+ await Rn({
1280
+ version: 1,
1281
+ apps: t
1282
+ });
1283
+ } catch {}
1284
+ return {
1285
+ version: 1,
1286
+ apps: t
1287
+ };
1288
+ }, Hn = async (e) => {
1289
+ let t = await Ln(), n = (/* @__PURE__ */ new Date()).toISOString(), r = t.apps.findIndex((t) => t.id === e.id), i = e.inspectToken ?? process.env.VOLTRO_INSPECT_TOKEN, a = {
1290
+ ...e,
1291
+ ...i !== void 0 && i !== "" ? { inspectToken: i } : {},
1292
+ registeredAt: r >= 0 ? t.apps[r].registeredAt : n,
1293
+ heartbeatAt: n
1294
+ };
1295
+ await Rn({
1296
+ version: 1,
1297
+ apps: r >= 0 ? t.apps.map((e, t) => t === r ? a : e) : [...t.apps, a]
1298
+ });
1299
+ }, Un = async (e) => {
1300
+ try {
1301
+ let t = await Ln(), n = t.apps.filter((t) => t.id !== e);
1302
+ if (n.length === t.apps.length) return;
1303
+ await Rn({
1304
+ version: 1,
1305
+ apps: n
1306
+ });
1307
+ } catch {}
1308
+ }, Wn = (e, t, n) => `${e}:${t}:${n}`, Y = l(R(), ".voltro", "logs"), Gn = () => {
1309
+ let e = Number(process.env.VOLTRO_LOG_FILE_TTL_MS);
1310
+ return Number.isFinite(e) && e > 0 ? e : 3600 * 1e3;
1311
+ }, Kn = !1, qn = () => {
1312
+ if (Kn) return;
1313
+ Kn = !0;
1314
+ let e = Date.now() - Gn(), t = [];
1315
+ try {
1316
+ t = A(Y);
1317
+ } catch {
1318
+ return;
1319
+ }
1320
+ for (let n of t) {
1321
+ if (!n.endsWith(".log")) continue;
1322
+ let t = l(Y, n);
1323
+ try {
1324
+ j(t).mtimeMs < e && M(t);
1325
+ } catch {}
1326
+ }
1327
+ }, Jn = (e) => e.replace(/[^a-zA-Z0-9._-]/g, "_").slice(0, 80), Yn = (e, t) => l(Y, `${Jn(e)}-${t}.log`), Xn = (e) => {
1328
+ let t = Jn(e), n = [];
1329
+ try {
1330
+ n = A(Y);
1331
+ } catch {
1332
+ return;
1333
+ }
1334
+ let r = n.filter((e) => e.startsWith(`${t}-`) && e.endsWith(".log"));
1335
+ if (r.length === 0) return;
1336
+ let i, a = -1;
1337
+ for (let e of r) {
1338
+ let t = l(Y, e);
1339
+ try {
1340
+ let e = j(t);
1341
+ e.mtimeMs > a && (a = e.mtimeMs, i = t);
1342
+ } catch {}
1343
+ }
1344
+ return i;
1345
+ }, Zn = (e) => {
1346
+ try {
1347
+ E(Y, { recursive: !0 });
1348
+ } catch {}
1349
+ qn();
1350
+ let t = Yn(e, process.pid), n = D(t, "w"), r = (e) => {
1351
+ let t = {
1352
+ ts: e.ts.getTime(),
1353
+ level: e.level,
1354
+ source: e.scope === "client" ? "client" : "server",
1355
+ message: e.message,
1356
+ fields: e.fields
1357
+ };
1358
+ e.scope !== void 0 && (t.scope = e.scope);
1359
+ try {
1360
+ return JSON.stringify(t) + "\n";
1361
+ } catch {
1362
+ return JSON.stringify({
1363
+ ts: e.ts.getTime(),
1364
+ level: e.level,
1365
+ source: t.source,
1366
+ message: e.message,
1367
+ fields: {},
1368
+ ...e.scope === void 0 ? {} : { scope: e.scope }
1369
+ }) + "\n";
1370
+ }
1371
+ }, i = !1, a = x((e) => {
1372
+ if (!i) try {
1373
+ ee(n, r(e));
1374
+ } catch {}
1375
+ }), o = () => {
1376
+ if (!i) {
1377
+ i = !0;
1378
+ try {
1379
+ w(n);
1380
+ } catch {}
1381
+ }
1382
+ };
1383
+ process.once("exit", o);
1384
+ let s = () => o();
1385
+ return process.on("uncaughtException", s), process.on("unhandledRejection", s), {
1386
+ path: t,
1387
+ dispose: async () => {
1388
+ a(), o(), process.off("exit", o), process.off("uncaughtException", s), process.off("unhandledRejection", s);
1389
+ }
1390
+ };
1391
+ }, Qn = async (e, t) => {
1392
+ let n;
1393
+ try {
1394
+ n = await O.readFile(e, "utf8");
1395
+ } catch {
1396
+ return [];
1397
+ }
1398
+ let r = n.split("\n"), i = [], a = t?.since ?? 0;
1399
+ for (let e of r) if (e.length !== 0) try {
1400
+ let t = JSON.parse(e);
1401
+ if (typeof t.ts != "number" || t.ts < a) continue;
1402
+ i.push(t);
1403
+ } catch {}
1404
+ return t?.max !== void 0 && i.length > t.max ? i.slice(i.length - t.max) : i;
1405
+ }, $n = S({ scope: "voltro:dashboard" }), er = L(import.meta.url), tr = 5179, nr = (e) => {
1406
+ let t = process.env.VOLTRO_DASHBOARD_PATH;
1407
+ if (t && T(l(d(t), "app.config.ts"))) return d(t);
1408
+ try {
1409
+ let e = s(er.resolve("@voltro/dashboard/package.json"));
1410
+ if (T(l(e, "app.config.ts"))) return e;
1411
+ } catch {}
1412
+ let n = l("voltro-devtools", "apps", "dashboard"), r = d(e);
1413
+ for (let e = 0; e < 10; e++) {
1414
+ let e = l(r, n);
1415
+ if (T(l(e, "app.config.ts"))) return e;
1416
+ let t = s(r);
1417
+ if (t === r) break;
1418
+ r = t;
1419
+ }
1420
+ return null;
1421
+ }, rr = "VOLTRO_IS_DASHBOARD", ir = (e, t = "127.0.0.1", n = 250) => new Promise((r) => {
1422
+ let i = he({
1423
+ port: e,
1424
+ host: t
1425
+ }), a = !1, o = (e) => {
1426
+ a || (a = !0, i.destroy(), r(e));
1427
+ };
1428
+ i.once("connect", () => o(!0)), i.once("error", () => o(!1)), setTimeout(() => o(!1), n);
1429
+ }), ar = () => !!(process.env.VOLTRO_DASHBOARD === "off" || process.argv.includes("--disable-dashboard")), or = () => process.env[rr] === "1", sr = () => process.stdout.isTTY === !0, X = l(R(), ".voltro", "dashboard-launch.lock"), cr = 1e4, lr = async () => {
1430
+ try {
1431
+ await O.mkdir(s(X), { recursive: !0 });
1432
+ let e = await O.open(X, "wx");
1433
+ return await e.write(`${process.pid}\n${Date.now()}\n`), await e.close(), !0;
1434
+ } catch {
1435
+ try {
1436
+ let e = await O.stat(X);
1437
+ if (Date.now() - e.mtimeMs > cr) return await O.unlink(X).catch(() => void 0), lr();
1438
+ } catch {}
1439
+ return !1;
1440
+ }
1441
+ }, ur = async () => {
1442
+ try {
1443
+ await O.unlink(X);
1444
+ } catch {}
1445
+ }, dr = async (e) => {
1446
+ let t = e.port ?? 5179;
1447
+ if (ar()) return {
1448
+ status: "skipped",
1449
+ reason: "disabled by flag/env",
1450
+ port: t
1451
+ };
1452
+ if (or()) return {
1453
+ status: "skipped",
1454
+ reason: "this process IS the dashboard",
1455
+ port: t
1456
+ };
1457
+ if (!sr()) return {
1458
+ status: "skipped",
1459
+ reason: "stdout is not a TTY (CI/smoke)",
1460
+ port: t
1461
+ };
1462
+ if (!await lr()) return {
1463
+ status: "skipped",
1464
+ reason: "another voltro process is currently launching the dashboard",
1465
+ port: t
1466
+ };
1467
+ if (await ir(t)) return await ur(), {
1468
+ status: "already-running",
1469
+ port: t
1470
+ };
1471
+ let n = e.voltroBin;
1472
+ if (!n) {
1473
+ let e = process.argv[1];
1474
+ n = e && e.endsWith("/src/bin.ts") ? l(s(e), "..", "bin", "voltro.mjs") : e ?? "voltro";
1475
+ }
1476
+ let r = T(l(e.dashboardAppPath, ".framework", "dist", "index.html")), i = r ? "start" : "dev", a = me(process.execPath, [
1477
+ n,
1478
+ i,
1479
+ e.dashboardAppPath
1480
+ ], {
1481
+ stdio: "ignore",
1482
+ env: {
1483
+ ...process.env,
1484
+ [rr]: "1",
1485
+ VOLTRO_DASHBOARD_PORT: String(t)
1486
+ }
1487
+ });
1488
+ return process.on("exit", () => {
1489
+ if (a.exitCode === null && a.signalCode === null) try {
1490
+ a.kill("SIGTERM");
1491
+ } catch {}
1492
+ }), $n.info(`auto-launching dashboard at http://localhost:${t}`, {
1493
+ port: t,
1494
+ mode: i,
1495
+ prebuilt: r
1496
+ }), r || $n.debug("no pre-built dashboard — running `voltro dev`. Build with `cd voltro-devtools && pnpm build` for a fast prod boot."), $n.debug("disable via --disable-dashboard or VOLTRO_DASHBOARD=off"), setTimeout(() => {
1497
+ ur();
1498
+ }, 4e3).unref(), {
1499
+ status: "launched",
1500
+ port: t
1501
+ };
1502
+ }, fr = class extends Error {
1503
+ _voltroDeferral = !0;
1504
+ constructor(e) {
1505
+ super(e), this.name = "DeferralNotSupportedError";
1506
+ }
1507
+ }, pr = (e) => typeof e == "object" && !!e && e._voltroDeferral === !0, mr = (e) => {
1508
+ let { helpers: t } = e, n = t.prepareDeferredLoaderData(e.loaderData, "page"), r = {}, i = {}, a = {};
1509
+ for (let [n, o] of Object.entries(e.segmentLoaderData)) {
1510
+ let e = Number(n), s = t.prepareDeferredLoaderData(o, e);
1511
+ r[e] = s.renderData, i[e] = s.stateData, s.deferredIds && (a[e] = s.deferredIds);
1512
+ }
1513
+ let o = n.deferredIds !== void 0 || Object.keys(a).length > 0;
1514
+ if (o) try {
1515
+ t.assertDeferralSupported({
1516
+ page: e.page,
1517
+ renderMode: e.renderMode,
1518
+ interactive: e.interactive,
1519
+ ...e.layoutShell ? { layoutShell: e.layoutShell } : {}
1520
+ });
1521
+ } catch (e) {
1522
+ throw new fr(e instanceof Error ? e.message : String(e));
1523
+ }
1524
+ return {
1525
+ loaderData: n.renderData,
1526
+ segmentLoaderData: r,
1527
+ hasDeferred: o,
1528
+ stateInput: {
1529
+ path: e.pathname,
1530
+ loaderData: n.stateData,
1531
+ segmentLoaderData: i,
1532
+ pageLoaderRan: e.pageLoaderRan,
1533
+ ...e.layoutShell ? { pageClientOnly: !0 } : {},
1534
+ ...n.deferredIds ? { deferredPageIds: n.deferredIds } : {},
1535
+ ...Object.keys(a).length > 0 ? { deferredSegmentIds: a } : {}
1536
+ }
1537
+ };
1538
+ }, hr = (e) => {
1539
+ let { helpers: t, renderInput: n } = e, r = mr({
1540
+ helpers: t,
1541
+ page: e.page,
1542
+ pathname: n.pathname,
1543
+ renderMode: "spa",
1544
+ interactive: e.interactive,
1545
+ loaderData: null,
1546
+ segmentLoaderData: n.segmentLoaderData ?? {},
1547
+ pageLoaderRan: !1,
1548
+ layoutShell: e.delivery
1549
+ });
1550
+ return {
1551
+ renderInput: {
1552
+ ...n,
1553
+ pageSlot: !0,
1554
+ loaderData: null,
1555
+ segmentLoaderData: r.segmentLoaderData
1556
+ },
1557
+ stateScript: t.renderRouterStateScript(r.stateInput),
1558
+ hasDeferred: r.hasDeferred
1559
+ };
1560
+ }, gr = (e) => {
1561
+ let { html: t, meta: n } = e.helpers.renderPageToHtml(e.prepared.renderInput);
1562
+ return {
1563
+ body: t,
1564
+ meta: n
1565
+ };
1566
+ }, _r = (e) => [
1567
+ ...e.extra ?? [],
1568
+ e.helpers.renderMetaToHtml(e.meta),
1569
+ `<meta name="voltro-interactive" content="${e.interactive}" />`,
1570
+ ...e.prepared.hasDeferred ? [e.helpers.renderDeferredRegistryScript()] : [],
1571
+ e.prepared.stateScript
1572
+ ].filter((e) => e.length > 0).join("\n "), vr = "<div id=\"root\"></div>", yr = "<div id=\"root\">", br = "</div>", xr = /<script\b[^>]*\btype=["']module["'][^>]*><\/script>[ \t]*\n?/gi, Sr = /\bsrc=["']([^"']+)["']/i, Cr = /<script(?![^>]*\basync\b)([^>]*\btype=["']module["'][^>]*)>/gi, wr = (e) => {
1573
+ let t = e.keepScriptInHead ?? ((e) => e.startsWith("/@")), n = [], r = e.shell.replace(xr, (e) => {
1574
+ let r = Sr.exec(e)?.[1];
1575
+ return r === void 0 || t(r) ? e : (n.push(r), "");
1576
+ });
1577
+ e.inlineModuleScriptsAsync && (r = r.replace(Cr, "<script async$1>"));
1578
+ let i = r.indexOf(vr);
1579
+ if (i === -1) throw Error(`[voltro] the generated shell has no \`${vr}\` element, so a streamed response cannot be split around the page body. This is a framework bug unless the app overrode \`.framework/index.html\` by hand.`);
1580
+ return {
1581
+ head: `${r.slice(0, i)}${yr}`,
1582
+ tail: `${br}${r.slice(i + 21)}`,
1583
+ bootstrapModules: n
1584
+ };
1585
+ }, Tr = (e) => e.head.replace("</head>", ` ${e.headInjection}\n </head>`).replace(/<html(\s+lang="[^"]*")?/i, `<html lang="${e.htmlLang}"`), Er = (e) => {
1586
+ let { res: t, shell: n, htmlLang: r, headInjection: i } = e, a = null, o = !1, s = !1, c = () => {
1587
+ if (s || !o || a === null) return;
1588
+ s = !0, t.statusCode = e.statusCode ?? 200;
1589
+ for (let [n, r] of Object.entries(e.headers ?? {})) t.setHeader(n, r);
1590
+ t.flushHeaders?.(), t.write(Tr({
1591
+ head: n.head,
1592
+ headInjection: i(a.meta),
1593
+ htmlLang: r
1594
+ }));
1595
+ let c = new ge();
1596
+ c.pipe(t, { end: !1 }), c.on("end", () => {
1597
+ t.end(n.tail);
1598
+ }), a.stream.pipe(c);
1599
+ }, l = () => {
1600
+ a?.stream.abort();
1601
+ };
1602
+ t.once("close", l), t.once("finish", () => {
1603
+ t.off("close", l);
1604
+ });
1605
+ try {
1606
+ a = e.render({
1607
+ bootstrapModules: n.bootstrapModules,
1608
+ onShellReady: () => {
1609
+ o = !0, c();
1610
+ },
1611
+ onShellError: (t) => {
1612
+ s || e.onShellError(t);
1613
+ }
1614
+ });
1615
+ } catch (t) {
1616
+ e.onShellError(t);
1617
+ return;
1618
+ }
1619
+ c();
1620
+ }, Z = S({ scope: "voltro:dev:web" }), Dr = S({ scope: "vite" }), Or = await (async () => {
1621
+ try {
1622
+ let e = l(s(f(import.meta.url)), "..", "package.json"), t = await O.readFile(e, "utf8");
1623
+ return JSON.parse(t).version ?? "0.0.0";
1624
+ } catch {
1625
+ return "0.0.0";
1626
+ }
1627
+ })(), kr = async () => {
1628
+ try {
1629
+ let e = s(f(import.meta.url)), t = d(e, "..", "..", "devtools");
1630
+ if (T(l(t, "package.json"))) return t;
1631
+ let n = d(e, "..", "..", "..", "devtools");
1632
+ return T(l(n, "package.json")) ? n : null;
1633
+ } catch {
1634
+ return null;
1635
+ }
1636
+ }, Ar = (e, t) => e.disableDevtools || !t ? [] : [
1637
+ "",
1638
+ "// Dev-only in-page devtools overlay. The `import.meta.env.DEV` guard is a",
1639
+ "// compile-time constant, so prod builds strip this whole `if` block — the",
1640
+ "// dynamic `@voltro/devtools` import (+ its CSS) never reaches Rollup.",
1641
+ "let Devtools",
1642
+ "if (import.meta.env.DEV) {",
1643
+ " await import('@voltro/devtools/styles.css')",
1644
+ " Devtools = (await import('@voltro/devtools')).VoltroDevtools",
1645
+ "}"
1646
+ ], jr = (e, t) => e.disableDevtools || !t ? [] : [" ...(Devtools ? { Devtools } : {}),"], Mr = (e) => e.sentry ? ["import { initSentryBrowser } from '@voltro/plugin-sentry/web'"] : [], Nr = (e) => e.sentry ? [
1647
+ "",
1648
+ "// Browser-side Sentry (frontend half of the deep integration). Errors +",
1649
+ "// browser rpc spans flow to Sentry, sharing the server transactions' trace.",
1650
+ `await initSentryBrowser(${JSON.stringify(e.sentry)})`
1651
+ ] : [], Pr = (e) => e.env ? ["import './env.public'"] : [], Fr = (e) => {
1652
+ let t = [], n = d(e);
1653
+ for (;;) {
1654
+ T(l(n, "pnpm-workspace.yaml")) && t.push(n);
1655
+ let e = s(n);
1656
+ if (e === n) break;
1657
+ n = e;
1658
+ }
1659
+ return t;
1660
+ }, Ir = /* @__PURE__ */ new Set([
1661
+ "layout.tsx",
1662
+ "error.tsx",
1663
+ "loading.tsx",
1664
+ "not-found.tsx"
1665
+ ]), Lr = (e) => /\.(test|spec)\.tsx$/.test(e), Rr = (e) => {
1666
+ if (/\/node_modules\/(?:\.pnpm\/[^/]+\/node_modules\/)?(?:react|react-dom|scheduler)\//.test(e)) return "react";
1667
+ let t = /\/([^/]+)\.island\.tsx?$/.exec(e);
1668
+ if (t) return `island-${t[1]}`;
1669
+ }, zr = /export\s+(?:async\s+)?(?:const|function|let|var)\s+loader\b/, Br = (e) => e.startsWith("(") && e.endsWith(")"), Vr = (e) => e.filter((e) => !Br(e)), Hr = (e) => {
1670
+ let t = e.replace(/\.tsx$/, "").split("/").filter(Boolean).filter((e) => !Br(e)), n = t.length > 0 && t[t.length - 1] === "index" ? t.slice(0, -1) : t;
1671
+ return n.length === 0 ? "/" : "/" + n.join("/");
1672
+ }, Ur = (e) => `${e.replace(/\.tsx$/, "").split("/").filter(Boolean).map((e) => e.replace(/[()]/g, "").replace(/\[\.\.\./g, "_rest_").replace(/[[\]]/g, "_")).map((e) => e.charAt(0).toUpperCase() + e.slice(1)).join("").replace(/[^A-Za-z0-9_]/g, "_") || "Index"}Page`, Q = (e, t) => e === "" ? `Root${t}` : `${e.split("/").filter(Boolean).map((e) => e.replace(/[()]/g, "").replace(/\[\.\.\./g, "_rest_").replace(/[[\]]/g, "_")).map((e) => e.charAt(0).toUpperCase() + e.slice(1)).join("").replace(/[^A-Za-z0-9_]/g, "_") || "Root"}${t}`, $ = async (e) => {
1673
+ let t = [], n = [], r = async (e, i) => {
1674
+ let a = [];
1675
+ try {
1676
+ a = await O.readdir(e, { withFileTypes: !0 });
1677
+ } catch {
1678
+ return;
1679
+ }
1680
+ let o = a.filter((e) => e.isDirectory()).map((e) => e.name).sort(), s = a.filter((e) => e.isFile() && e.name.endsWith(".tsx") && !Lr(e.name)).map((e) => e.name).sort(), c = new Set(s), u = i.join("/");
1681
+ if (s.some((e) => Ir.has(e))) {
1682
+ let t = c.has("layout.tsx"), r = !1;
1683
+ if (t) try {
1684
+ let t = await O.readFile(l(e, "layout.tsx"), "utf8");
1685
+ r = zr.test(t);
1686
+ } catch {}
1687
+ n.push({
1688
+ dir: u,
1689
+ chain: i,
1690
+ contributesToUrl: i.length === 0 || !Br(i[i.length - 1]),
1691
+ hasLayout: t,
1692
+ hasLayoutLoader: r,
1693
+ hasError: c.has("error.tsx"),
1694
+ hasPending: c.has("loading.tsx"),
1695
+ hasNotFound: c.has("not-found.tsx")
1696
+ });
1697
+ }
1698
+ for (let e of s) {
1699
+ if (Ir.has(e)) continue;
1700
+ let n = u ? `${u}/${e}` : e;
1701
+ t.push({
1702
+ file: n,
1703
+ pattern: Hr(n),
1704
+ ident: Ur(n),
1705
+ dirChain: i
1706
+ });
1707
+ }
1708
+ for (let t of o) await r(l(e, t), [...i, t]);
1709
+ };
1710
+ return await r(e, []), t.sort((e, t) => e.file < t.file ? -1 : 1), {
1711
+ pages: t,
1712
+ dirs: n
1713
+ };
1714
+ }, Wr = (e, t) => {
1715
+ let n = [];
1716
+ for (let r = 0; r <= t.length; r++) {
1717
+ let i = t.slice(0, r).join("/"), a = e.find((e) => e.dir === i);
1718
+ a && n.push(a);
1719
+ }
1720
+ return n;
1721
+ }, Gr = async (e) => {
1722
+ let { entries: t, loadLayout: n, loadError: r, loadPending: i, ctx: a } = e, o = {};
1723
+ return {
1724
+ chain: await Promise.all(t.map(async (e, t) => {
1725
+ let s = {};
1726
+ if (e.hasLayout) {
1727
+ let r = await n(e);
1728
+ s.Layout = r.default, typeof r.loader == "function" && (s.loader = r.loader, o[t] = await r.loader({
1729
+ params: a.params,
1730
+ pathname: a.pathname,
1731
+ signal: a.signal,
1732
+ headers: a.headers,
1733
+ query: a.query
1734
+ }));
1735
+ }
1736
+ return e.hasError && (s.Error = (await r(e)).default), e.hasPending && (s.Pending = (await i(e)).default), {
1737
+ id: e.dir || "/",
1738
+ ...s
1739
+ };
1740
+ })),
1741
+ segmentLoaderData: o
1742
+ };
1743
+ }, Kr = (e) => {
1744
+ let t = Vr(e);
1745
+ return t.length === 0 ? "" : "/" + t.join("/");
1746
+ }, qr = [
1747
+ "// Hot-reload bridge: keep SSR-injected <link rel=\"stylesheet\"> tags",
1748
+ "// in sync with Vite's CSS HMR. Without this, edits to .css files",
1749
+ "// only update the JS-injected <style> overlay; the underlying <link>",
1750
+ "// stays pinned to the old CSS until a full page reload.",
1751
+ "//",
1752
+ "// Also publishes a \"Compiling…\" status to @voltro/web's statusBus so",
1753
+ "// the devtools floating button morphs into a Next.js-style pill while",
1754
+ "// vite is rebuilding. The dispose handle returned by pushStatus()",
1755
+ "// pops the status on vite:afterUpdate. Plain JS, no React in this",
1756
+ "// file — the bus is React-free.",
1757
+ "if (import.meta.hot) {",
1758
+ " let _vdtCompilingDispose = null",
1759
+ " let _vdtCompilingTimer = null",
1760
+ " const _vdtCompilingStart = (label) => {",
1761
+ " if (_vdtCompilingDispose) return // dedupe overlapping events",
1762
+ " import('@voltro/web').then((m) => {",
1763
+ " if (_vdtCompilingDispose) return",
1764
+ " _vdtCompilingDispose = m.pushStatus({",
1765
+ " id: 'voltro:hmr:compiling',",
1766
+ " kind: 'compiling',",
1767
+ " label,",
1768
+ " })",
1769
+ " }).catch(() => {})",
1770
+ " }",
1771
+ " const _vdtCompilingStop = () => {",
1772
+ " if (_vdtCompilingTimer) { clearTimeout(_vdtCompilingTimer); _vdtCompilingTimer = null }",
1773
+ " if (_vdtCompilingDispose) {",
1774
+ " // Hold the indicator briefly so single-frame compiles are still",
1775
+ " // visible — otherwise the morph happens too fast to register.",
1776
+ " _vdtCompilingTimer = setTimeout(() => {",
1777
+ " const dispose = _vdtCompilingDispose",
1778
+ " _vdtCompilingDispose = null",
1779
+ " _vdtCompilingTimer = null",
1780
+ " if (dispose) dispose()",
1781
+ " }, 220)",
1782
+ " }",
1783
+ " }",
1784
+ " import.meta.hot.on('vite:beforeUpdate', (payload) => {",
1785
+ " _vdtCompilingStart('Compiling…')",
1786
+ " for (const u of payload.updates ?? []) {",
1787
+ " if (u.type !== 'css-update' || !u.path) continue",
1788
+ " const targetPath = u.path.split('?')[0]",
1789
+ " const links = document.querySelectorAll('link[rel=\"stylesheet\"]')",
1790
+ " for (const link of links) {",
1791
+ " const href = link.getAttribute('href') ?? ''",
1792
+ " const linkPath = href.split('?')[0]",
1793
+ " if (linkPath === targetPath || linkPath.endsWith(targetPath)) {",
1794
+ " const url = new URL(href, window.location.origin)",
1795
+ " url.searchParams.set('t', String(Date.now()))",
1796
+ " link.setAttribute('href', url.toString())",
1797
+ " }",
1798
+ " }",
1799
+ " }",
1800
+ " })",
1801
+ " // Sticky \"Build error\" status on vite:error — held until the",
1802
+ " // next successful update clears it (vite:afterUpdate). Different",
1803
+ " // kind from compiling so the devtools FAB can re-colour to",
1804
+ " // danger red. The compile status (if any) is also cleared so we",
1805
+ " // don't show two pills at once.",
1806
+ " let _vdtErrorDispose = null",
1807
+ " const _vdtErrorStart = (label) => {",
1808
+ " if (_vdtErrorDispose) return",
1809
+ " import('@voltro/web').then((m) => {",
1810
+ " if (_vdtErrorDispose) return",
1811
+ " _vdtErrorDispose = m.pushStatus({",
1812
+ " id: 'voltro:hmr:error',",
1813
+ " kind: 'error',",
1814
+ " label,",
1815
+ " })",
1816
+ " }).catch(() => {})",
1817
+ " }",
1818
+ " const _vdtErrorStop = () => {",
1819
+ " if (_vdtErrorDispose) { _vdtErrorDispose(); _vdtErrorDispose = null }",
1820
+ " }",
1821
+ " import.meta.hot.on('vite:afterUpdate', () => {",
1822
+ " _vdtCompilingStop()",
1823
+ " _vdtErrorStop() // successful update clears any sticky build-error",
1824
+ " })",
1825
+ " import.meta.hot.on('vite:beforeFullReload', () => _vdtCompilingStart('Reloading…'))",
1826
+ " import.meta.hot.on('vite:error', (payload) => {",
1827
+ " _vdtCompilingStop()",
1828
+ " // Pill label stays short (\"Build error\") — the actual message",
1829
+ " // is way too long for a ~180px pill (e.g. \"Failed to resolve",
1830
+ " // import '../foo' from 'bar.tsx'\"). Detail goes to the console",
1831
+ " // (vite already logs it) and to the devtools error panel later.",
1832
+ " const err = payload?.err",
1833
+ " if (err && typeof err.message === 'string') {",
1834
+ " console.error('[voltro:hmr] build error:', err.message)",
1835
+ " }",
1836
+ " _vdtErrorStart('Build error')",
1837
+ " })",
1838
+ "}"
1839
+ ].join("\n"), Jr = (e) => {
1840
+ let t = [], n = 0, r = e.split("/").filter(Boolean), i = [];
1841
+ for (let e of r) e.startsWith("[[...") && e.endsWith("]]") ? (i.push("(.*)"), t.push(e.slice(5, -2)), n += 2) : e.startsWith("[...") && e.endsWith("]") ? (i.push("(.+)"), t.push(e.slice(4, -1)), n += 3) : e.startsWith("[") && e.endsWith("]") ? (i.push("([^/]+)"), t.push(e.slice(1, -1)), n += 1) : i.push(e.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"));
1842
+ let a = i.join("/");
1843
+ return {
1844
+ regex: a.length === 0 ? /^\/?$/ : RegExp(`^/${a}/?$`),
1845
+ paramNames: t,
1846
+ priority: n
1847
+ };
1848
+ }, Yr = (e) => e.map((e) => {
1849
+ let { regex: t, paramNames: n, priority: r } = Jr(e.pattern);
1850
+ return {
1851
+ pattern: e.pattern,
1852
+ file: e.file,
1853
+ dirChain: e.dirChain,
1854
+ regex: t,
1855
+ paramNames: n,
1856
+ priority: r
1857
+ };
1858
+ }).slice().sort((e, t) => e.priority - t.priority), Xr = (e, t) => {
1859
+ for (let n of t) {
1860
+ let t = n.regex.exec(e);
1861
+ if (!t) continue;
1862
+ let r = {};
1863
+ for (let e = 0; e < n.paramNames.length; e++) r[n.paramNames[e]] = t[e + 1] ?? "";
1864
+ return {
1865
+ route: n,
1866
+ params: r
1867
+ };
1868
+ }
1869
+ return null;
1870
+ }, Zr = async (e, t) => {
1871
+ let n = e;
1872
+ for (;;) {
1873
+ let e = l(n, "node_modules", t);
1874
+ try {
1875
+ if ((await O.stat(e)).isDirectory()) {
1876
+ let t = await O.realpath(e);
1877
+ return t.includes("/node_modules/") ? null : t;
1878
+ }
1879
+ } catch {}
1880
+ let r = s(n);
1881
+ if (r === n) return null;
1882
+ n = r;
1883
+ }
1884
+ }, Qr = async (e) => {
1885
+ try {
1886
+ let t = await import(p(l(e, "app.config.ts")).href), n = t.default?.port, r = typeof n == "number" ? n : 4e3, i = t.default?.transport?.wsPath, a = typeof i == "string" && i.startsWith("/") ? i : void 0;
1887
+ return a ? {
1888
+ port: r,
1889
+ wsPath: a
1890
+ } : { port: r };
1891
+ } catch {}
1892
+ return { port: 4e3 };
1893
+ }, $r = (e, t) => ({
1894
+ name: e,
1895
+ pkg: t.package,
1896
+ browserWsUrl: t.url,
1897
+ proxyTarget: void 0,
1898
+ ...t.serverUrl ? { serverOrigin: t.serverUrl } : {},
1899
+ ...t.headers ? { headers: t.headers } : {},
1900
+ ...t.authHeaders ? { hasAuthHeaders: !0 } : {}
1901
+ }), ei = (e, t, n) => {
1902
+ let r = t.transport?.wsPath ?? n.wsPath;
1903
+ return {
1904
+ name: e,
1905
+ pkg: t.package,
1906
+ browserWsUrl: r ?? `/ws/${e}`,
1907
+ proxyTarget: `ws://localhost:${n.port}`,
1908
+ ...r ? { wsPath: r } : {},
1909
+ ...t.serverUrl ? { serverOrigin: t.serverUrl } : {},
1910
+ ...t.headers ? { headers: t.headers } : {},
1911
+ ...t.authHeaders ? { hasAuthHeaders: !0 } : {}
1912
+ };
1913
+ }, ti = (e) => {
1914
+ let t = /* @__PURE__ */ new Map();
1915
+ for (let n of e) {
1916
+ if (n.proxyTarget === void 0) continue;
1917
+ let e = t.get(n.browserWsUrl);
1918
+ if (e) throw Error(`[voltro] api ${JSON.stringify(n.name)} and ${JSON.stringify(e)} both resolve the same-origin WS path ${JSON.stringify(n.browserWsUrl)}. A custom transport.wsPath must be unique per origin (one api per origin may use a fixed path). Give each a distinct wsPath, or drop the override to use the default /ws/<name>.`);
1919
+ t.set(n.browserWsUrl, n.name);
1920
+ }
1921
+ }, ni = async (e, t) => {
1922
+ let n = Object.entries(t.apis ?? {}), r = [];
1923
+ for (let [t, i] of n) {
1924
+ if (i.url) {
1925
+ r.push($r(t, i));
1926
+ continue;
1927
+ }
1928
+ let n = await Zr(e, i.package);
1929
+ if (!n) throw Error(`[voltro dev] api ${JSON.stringify(t)} (package ${JSON.stringify(i.package)}) is not a workspace dep and has no \`url\` set in app.config.ts. External apis need an explicit \`url\` because the framework can't discover their dev port.`);
1930
+ r.push(ei(t, i, await Qr(n)));
1931
+ }
1932
+ return ti(r), r;
1933
+ }, ri = (e) => {
1934
+ if (!(!/^wss?:\/\//.test(e) && !/^https?:\/\//.test(e))) try {
1935
+ let t = new URL(e);
1936
+ return t.protocol = t.protocol === "wss:" || t.protocol === "https:" ? "https:" : "http:", `${t.protocol}//${t.host}`;
1937
+ } catch {
1938
+ return;
1939
+ }
1940
+ }, ii = (e) => `VOLTRO_API_ORIGIN_${e.toUpperCase().replace(/[^A-Z0-9]/g, "_")}`, ai = (e) => process.env[ii(e)] ?? process.env.VOLTRO_API_ORIGIN, oi = (e, t) => {
1941
+ if (!e) return;
1942
+ let n = ai(e.name) ?? e.serverOrigin;
1943
+ if (n) {
1944
+ let e = ri(n);
1945
+ if (e) return e;
1946
+ }
1947
+ if (t?.allowDevProxy && e.proxyTarget) {
1948
+ let t = ri(e.proxyTarget);
1949
+ if (t) return t;
1950
+ }
1951
+ if (!e.proxyTarget && /^wss?:\/\//.test(e.browserWsUrl)) return ri(e.browserWsUrl);
1952
+ }, si = (e, t, n) => {
1953
+ if (!e) {
1954
+ if (n?.apiName === void 0) return;
1955
+ let e = n.apiName;
1956
+ return async () => {
1957
+ throw Error(`[loader.query] api '${e}' has no server-side origin for SSR. In a split web/api deployment the web pod reaches the api by internal DNS, not the browser's relative wsPath — set ${ii(e)} (or VOLTRO_API_ORIGIN, or apis.${e}.serverUrl in app.config.ts) to the api's internal origin, e.g. http://api.<namespace>.svc.cluster.local. The browser transport is unaffected.`);
1958
+ };
1959
+ }
1960
+ return async (r, i) => {
1961
+ let a = {
1962
+ _tag: "Request",
1963
+ id: "0",
1964
+ tag: r,
1965
+ payload: i ?? {},
1966
+ headers: []
1967
+ }, o;
1968
+ try {
1969
+ o = await fetch(`${e}/rpc`, {
1970
+ method: "POST",
1971
+ headers: {
1972
+ "content-type": "application/json",
1973
+ ...t ? { cookie: t } : {}
1974
+ },
1975
+ body: JSON.stringify(a)
1976
+ });
1977
+ } catch (t) {
1978
+ let i = t?.cause?.code ?? String(t?.message ?? t);
1979
+ throw Error(`[loader.query] ${r}: could not reach the api at ${e}/rpc (${i}). ${n?.apiName ? `Set ${ii(n.apiName)} / VOLTRO_API_ORIGIN` : "Set the api server origin"} to the api's SSR-reachable origin (internal cluster DNS in a split deployment).`, { cause: t });
1980
+ }
1981
+ if (!o.ok) throw Error(`[loader.query] ${r}: HTTP ${o.status} ${await o.text()}`);
1982
+ let s = await o.json();
1983
+ if (!Array.isArray(s)) throw Error(`[loader.query] ${r}: unexpected non-array rpc response`);
1984
+ let c = (e) => e && typeof e == "object" && "_tag" in e && "data" in e && e._tag === "snapshot" ? e.data : e, l, u = !1;
1985
+ for (let e of s) {
1986
+ if (e._tag === "ClientProtocolError") throw Error(`[loader.query] ${r}: protocol error ${JSON.stringify(e.error)}`);
1987
+ if (!(e.requestId !== void 0 && String(e.requestId) !== "0")) {
1988
+ if (e._tag === "Chunk" && e.values && e.values.length > 0 && !u && (l = c(e.values[0]), u = !0), e._tag === "Defect") throw Error(`[loader.query] ${r}: defect ${JSON.stringify(e)}`);
1989
+ if (e._tag === "Exit" && e.exit) {
1990
+ if (e.exit._tag === "Failure") throw Error(`[loader.query] ${r}: rpc failed ${JSON.stringify(e.exit.cause ?? e.exit)}`);
1991
+ !u && e.exit._tag === "Success" && e.exit.value !== void 0 && (l = c(e.exit.value), u = !0);
1992
+ }
1993
+ }
1994
+ }
1995
+ if (u) return l;
1996
+ };
1997
+ }, ci = async (e, t, n, r = {}) => {
1998
+ let i = t.title ?? t.name ?? "app", a = t.theme === "dark" ? " class=\"dark\"" : t.theme === "light" ? " class=\"light\"" : "", o = T(l(e, "node_modules", "@voltro", "devtools", "package.json")) || await kr() !== null, s = t.theme === "system" ? [
1999
+ " <script>",
2000
+ " (function () {",
2001
+ " var root = document.documentElement",
2002
+ " var readCookie = function () {",
2003
+ " try {",
2004
+ " var m = document.cookie.match(/(?:^|;\\s*)voltro:theme=([^;]*)/)",
2005
+ " return m ? decodeURIComponent(m[1]) : ''",
2006
+ " } catch (e) { return '' }",
2007
+ " }",
2008
+ " var apply = function () {",
2009
+ " var stored = readCookie()",
2010
+ " var dark = stored === 'dark' || (stored !== 'light' && window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches)",
2011
+ " root.classList.toggle('dark', dark)",
2012
+ " }",
2013
+ " apply()",
2014
+ " if (window.matchMedia) {",
2015
+ " try { window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', apply) } catch (e) {}",
2016
+ " }",
2017
+ " })()",
2018
+ " <\/script>"
2019
+ ].join("\n") : "", c = [
2020
+ "<!doctype html>",
2021
+ "<!-- GENERATED BY `voltro dev` — do not edit; will be overwritten on next boot. -->",
2022
+ `<html lang="en"${a}>`,
2023
+ " <head>",
2024
+ " <meta charset=\"UTF-8\" />",
2025
+ " <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />",
2026
+ ` <title>${i}</title>`,
2027
+ " <link rel=\"icon\" type=\"image/svg+xml\" href=\"/favicon.svg\" />",
2028
+ ...s ? [s] : [],
2029
+ " </head>",
2030
+ " <body>",
2031
+ " <div id=\"root\"></div>",
2032
+ " <script type=\"module\" src=\"/main.tsx\"><\/script>",
2033
+ " </body>",
2034
+ "</html>",
2035
+ ""
2036
+ ].join("\n"), u = l(e, "src", "pages"), { pages: d, dirs: f } = await $(u);
2037
+ await jn(u, d);
2038
+ let p = (e) => `${e.replace(/[^a-zA-Z0-9]/g, "_")}AppGroup`, m = (e) => `${e.replace(/[^a-zA-Z0-9]/g, "_")}AppDescriptors`, h = n.map((e) => `import { appGroup as ${p(e.name)}, appDescriptors as ${m(e.name)} } from '${e.pkg}/rpcGroup'`);
2039
+ n.some((e) => e.hasAuthHeaders) && (h.push("import __voltroAppConfig from '../app.config'"), h.push("const __voltroAuthHeaders = (__voltroAppConfig as { readonly apis?: Record<string, { readonly authHeaders?: () => Record<string, string> | Promise<Record<string, string>> }> }).apis"));
2040
+ let g = n.map((e) => {
2041
+ let t = [`group: ${p(e.name)}`];
2042
+ return t.push(`descriptors: ${m(e.name)}`), t.push(`wsUrl: ${JSON.stringify(e.browserWsUrl)}`), e.hasAuthHeaders ? t.push(`headers: __voltroAuthHeaders?.[${JSON.stringify(e.name)}]?.authHeaders`) : e.headers && t.push(`headers: ${JSON.stringify(e.headers)}`), ` ${JSON.stringify(e.name)}: { ${t.join(", ")} },`;
2043
+ }), _, v, y;
2044
+ if (d.length > 0) {
2045
+ let e = d.map((e) => ` ${JSON.stringify(e.pattern)}: () => import('../src/pages/${e.file}'),`), n = [];
2046
+ for (let e of f) {
2047
+ let t = e.dir === "" ? "../src/pages" : `../src/pages/${e.dir}`;
2048
+ e.hasLayout && e.hasLayoutLoader ? n.push(`import * as ${Q(e.dir, "Layout")}Mod from '${t}/layout.tsx'`) : e.hasLayout && n.push(`import ${Q(e.dir, "Layout")} from '${t}/layout.tsx'`), e.hasError && n.push(`import ${Q(e.dir, "Error")} from '${t}/error.tsx'`), e.hasPending && n.push(`import ${Q(e.dir, "Pending")} from '${t}/loading.tsx'`), e.hasNotFound && n.push(`import ${Q(e.dir, "NotFound")} from '${t}/not-found.tsx'`);
2049
+ }
2050
+ let r = d.map((e) => {
2051
+ let t = Wr(f, e.dirChain).map((e) => {
2052
+ let t = [`id: ${JSON.stringify(e.dir || "/")}`], n = JSON.stringify(e.dir);
2053
+ return e.hasLayout && t.push(`Layout: refs.layouts[${n}]`), e.hasLayoutLoader && t.push(`loader: refs.layoutLoaders[${n}]`), e.hasError && t.push(`Error: refs.errors[${n}]`), e.hasPending && t.push(`Pending: refs.pendings[${n}]`), ` { ${t.join(", ")} }`;
2054
+ }).join(",\n");
2055
+ return ` makePageRoute(${JSON.stringify(e.pattern)}, ${t.length > 0 ? `[\n${t},\n ]` : "undefined"}),`;
2056
+ }), i = f.filter((e) => e.hasNotFound).map((e) => {
2057
+ let t = Kr(e.chain), n = Wr(f, e.chain).map((e) => {
2058
+ let t = [`id: ${JSON.stringify(e.dir || "/")}`], n = JSON.stringify(e.dir);
2059
+ return e.hasLayout && t.push(`Layout: refs.layouts[${n}]`), e.hasError && t.push(`Error: refs.errors[${n}]`), ` { ${t.join(", ")} }`;
2060
+ }).join(",\n"), r = n.length > 0 ? `\n chain: [\n${n},\n ],` : "";
2061
+ return ` {\n prefix: ${JSON.stringify(t)},\n Component: refs.notFounds[${JSON.stringify(e.dir)}],${r}\n },`;
2062
+ }), a = [], s = [], c = [], l = [], u = [], p = [];
2063
+ for (let e of f) {
2064
+ let t = e.dir === "" ? "../src/pages/layout.tsx" : `../src/pages/${e.dir}/layout.tsx`, n = e.dir === "" ? "../src/pages/error.tsx" : `../src/pages/${e.dir}/error.tsx`, r = e.dir === "" ? "../src/pages/loading.tsx" : `../src/pages/${e.dir}/loading.tsx`, i = e.dir === "" ? "../src/pages/not-found.tsx" : `../src/pages/${e.dir}/not-found.tsx`, o = JSON.stringify(e.dir);
2065
+ e.hasLayout && e.hasLayoutLoader ? (s.push(` ${o}: ${Q(e.dir, "Layout")}Mod.default,`), c.push(` ${o}: ${Q(e.dir, "Layout")}Mod.loader,`), a.push({
2066
+ relPath: t,
2067
+ kind: "layout",
2068
+ slotKey: e.dir
2069
+ })) : e.hasLayout && (s.push(` ${o}: ${Q(e.dir, "Layout")},`), a.push({
2070
+ relPath: t,
2071
+ kind: "layout",
2072
+ slotKey: e.dir
2073
+ })), e.hasError && (l.push(` ${o}: ${Q(e.dir, "Error")},`), a.push({
2074
+ relPath: n,
2075
+ kind: "error",
2076
+ slotKey: e.dir
2077
+ })), e.hasPending && (u.push(` ${o}: ${Q(e.dir, "Pending")},`), a.push({
2078
+ relPath: r,
2079
+ kind: "pending",
2080
+ slotKey: e.dir
2081
+ })), e.hasNotFound && (p.push(` ${o}: ${Q(e.dir, "NotFound")},`), a.push({
2082
+ relPath: i,
2083
+ kind: "notFound",
2084
+ slotKey: e.dir
2085
+ }));
2086
+ }
2087
+ for (let e of d) a.push({
2088
+ relPath: `../src/pages/${e.file}`,
2089
+ kind: "page",
2090
+ slotKey: e.pattern
2091
+ });
2092
+ let m = a.map((e) => ` ${JSON.stringify(e.relPath)},`), b = a.map((e, t) => {
2093
+ let n = JSON.stringify(e.slotKey);
2094
+ return e.kind === "page" ? ` if (newMods[${t}] && refs.pages[${n}] !== undefined) { refs.pages[${n}] = newMods[${t}]; changed = true }` : ` if (newMods[${t}]?.default) { refs.${e.kind === "layout" ? "layouts" : e.kind === "error" ? "errors" : e.kind === "pending" ? "pendings" : "notFounds"}[${n}] = newMods[${t}].default;${e.kind === "layout" ? ` refs.layoutLoaders[${n}] = newMods[${t}].loader;` : ""} changed = true }`;
2095
+ }), x = t.locales ?? [], S = x.length > 0, C = t.defaultLocale ?? x[0] ?? "en";
2096
+ if (S && !x.includes(C)) throw Error(`[voltro dev] app.config.ts: defaultLocale '${C}' must be one of locales [${x.join(", ")}]`);
2097
+ let w = S ? [
2098
+ "import { I18nProvider } from '@voltro/i18n'",
2099
+ "import { resolveLocale } from '@voltro/i18n/server'",
2100
+ "import { useServerRequest } from '@voltro/web'",
2101
+ ...x.map((e) => `import i18nCatalog_${e} from '../src/locales/${e}'`)
2102
+ ] : [];
2103
+ v = [
2104
+ "// GENERATED BY `voltro dev` — do not edit; will be overwritten on next boot.",
2105
+ "// Routes + per-page chain + not-found scopes assembled from src/pages/.",
2106
+ "//",
2107
+ "// This is a plain `.ts` module on purpose: it declares NO component, so",
2108
+ "// react-refresh never treats it as a boundary and never re-executes it on a",
2109
+ "// component edit. The mutable `refs` registry therefore OUTLIVES a refresh",
2110
+ "// of `app.tsx` — a refreshed `App` keeps every already-loaded page module.",
2111
+ "//",
2112
+ "// HMR architecture (server-pushed re-render with a living React tree):",
2113
+ "// page + layout module references live in the `refs` registry below, and",
2114
+ "// the generated route array reads from `refs` on every `buildRoutes()`",
2115
+ "// call — never from the static imports directly. When a route module is",
2116
+ "// NOT a valid react-refresh boundary Vite delivers the new module to the",
2117
+ "// multi-dep `accept` callback below, which patches the matching slot in",
2118
+ "// `refs` and bumps the version counter; `App`'s `useSyncExternalStore`",
2119
+ "// subscription picks up the bump → `useMemo` rebuilds the routes array →",
2120
+ "// the Router rebuilds its compiled match → React renders the new module",
2121
+ "// without unmounting the surrounding tree.",
2122
+ "",
2123
+ "import { pageRoute, lazyPageRoute, preloadRouteModule, type PageDescriptor, type NotFoundDescriptor } from '@voltro/web'",
2124
+ ...n,
2125
+ "",
2126
+ "// Mutable module registry. Initial values come from the static",
2127
+ "// imports above; HMR patches the slot, never the import.",
2128
+ "const refs: {",
2129
+ " layouts: Record<string, unknown>",
2130
+ " layoutLoaders: Record<string, unknown>",
2131
+ " errors: Record<string, unknown>",
2132
+ " pendings: Record<string, unknown>",
2133
+ " notFounds: Record<string, unknown>",
2134
+ " pages: Record<string, unknown>",
2135
+ "} = {",
2136
+ " layouts: {",
2137
+ ...s,
2138
+ " },",
2139
+ " layoutLoaders: {",
2140
+ ...c,
2141
+ " },",
2142
+ " errors: {",
2143
+ ...l,
2144
+ " },",
2145
+ " pendings: {",
2146
+ ...u,
2147
+ " },",
2148
+ " notFounds: {",
2149
+ ...p,
2150
+ " },",
2151
+ " pages: {},",
2152
+ "}",
2153
+ "",
2154
+ "// Per-pattern dynamic-import thunks. Each is a literal `import()` so vite",
2155
+ "// code-splits the page into its own chunk and only fetches it on match.",
2156
+ "const pageLoaders: Record<string, () => Promise<Record<string, unknown>>> = {",
2157
+ ...e,
2158
+ "}",
2159
+ "",
2160
+ "let version = 0",
2161
+ "const listeners = new Set<() => void>()",
2162
+ "export const subscribe = (cb: () => void): (() => void) => {",
2163
+ " listeners.add(cb)",
2164
+ " return () => { listeners.delete(cb) }",
2165
+ "}",
2166
+ "export const getVersion = (): number => version",
2167
+ "const bump = (): void => {",
2168
+ " version++",
2169
+ " for (const cb of listeners) cb()",
2170
+ "}",
2171
+ "",
2172
+ "// Returns an EAGER route once the page module is in `refs.pages` (already",
2173
+ "// loaded, or just HMR-patched), otherwise a LAZY route whose load thunk",
2174
+ "// fetches the chunk, stores it in `refs.pages`, and bumps the version so",
2175
+ "// the next buildRoutes() upgrades it to eager. `buildRoutes` re-runs on",
2176
+ "// every bump, so layout HMR (the rebuilt `chain`) stays live too.",
2177
+ "const makePageRoute = (",
2178
+ " pattern: string,",
2179
+ " chain?: PageDescriptor['chain'],",
2180
+ "): PageDescriptor =>",
2181
+ " refs.pages[pattern] !== undefined",
2182
+ " ? pageRoute(pattern, refs.pages[pattern] as Record<string, unknown>, { chain })",
2183
+ " : lazyPageRoute(pattern, async () => {",
2184
+ " const mod = await pageLoaders[pattern]()",
2185
+ " refs.pages[pattern] = mod",
2186
+ " bump()",
2187
+ " return mod",
2188
+ " }, { chain })",
2189
+ "",
2190
+ "export const buildRoutes = (): PageDescriptor[] => [",
2191
+ ...r,
2192
+ "]",
2193
+ "",
2194
+ "// Preload the CURRENT url's page chunk before hydration. main.tsx awaits",
2195
+ "// this pre-mount so the lazy page module is in `refs.pages` (→ an EAGER",
2196
+ "// route) for the first client render — matching the SSG/SSR-prerendered",
2197
+ "// HTML instead of a null leaf that would trip a hydration mismatch.",
2198
+ "//",
2199
+ "// Lives HERE and not in app.tsx: app.tsx must export the `App` component",
2200
+ "// and nothing else, or react-refresh rejects it as a boundary and every",
2201
+ "// edit in the app ends in a full page reload.",
2202
+ "export const preloadCurrentRoute = async (): Promise<void> => {",
2203
+ " if (typeof window === 'undefined') return",
2204
+ " await preloadRouteModule(buildRoutes(), window.location.pathname)",
2205
+ "}",
2206
+ "",
2207
+ "export const buildNotFounds = (): NotFoundDescriptor[] => [",
2208
+ ...i,
2209
+ "]",
2210
+ "",
2211
+ "if (import.meta.hot) {",
2212
+ " import.meta.hot.accept(",
2213
+ " [",
2214
+ ...m,
2215
+ " ],",
2216
+ " (newMods: Array<Record<string, unknown> | undefined>) => {",
2217
+ " let changed = false",
2218
+ ...b,
2219
+ " if (changed) bump()",
2220
+ " },",
2221
+ " )",
2222
+ "}",
2223
+ ""
2224
+ ].join("\n"), _ = [
2225
+ "// GENERATED BY `voltro dev` — do not edit; will be overwritten on next boot.",
2226
+ "// The app's root component. It exports `App` and NOTHING ELSE: react-refresh",
2227
+ "// only accepts a module whose every export is a component, and a module it",
2228
+ "// rejects invalidates upward until something accepts — which for this graph",
2229
+ "// means main.tsx, which accepts nothing, i.e. a FULL PAGE RELOAD.",
2230
+ "// The route table (and the mutable module registry HMR patches) lives in",
2231
+ "// ./routeTable so that a refresh of THIS file cannot reset it.",
2232
+ "",
2233
+ "import { useMemo, useSyncExternalStore } from 'react'",
2234
+ "import { Router } from '@voltro/web'",
2235
+ ...w,
2236
+ "import { subscribe, getVersion, buildRoutes, buildNotFounds } from './routeTable'",
2237
+ "",
2238
+ ...S ? [
2239
+ `// i18n auto-wiring (config.locales = [${x.map((e) => JSON.stringify(e)).join(", ")}]).`,
2240
+ "const I18N_CATALOGS: Record<string, import('@voltro/i18n').MessageCatalog> = {",
2241
+ ...x.map((e) => ` ${JSON.stringify(e)}: i18nCatalog_${e},`),
2242
+ "}",
2243
+ `const I18N_SUPPORTED: ReadonlyArray<string> = [${x.map((e) => JSON.stringify(e)).join(", ")}]`,
2244
+ `const I18N_DEFAULT = ${JSON.stringify(C)}`,
2245
+ "",
2246
+ "const pickI18nLocale = (ssr: ReturnType<typeof useServerRequest>): string => {",
2247
+ " if (ssr) {",
2248
+ " return resolveLocale({",
2249
+ " cookieHeader: ssr.headers['cookie'] ?? null,",
2250
+ " acceptLanguageHeader: ssr.headers['accept-language'] ?? null,",
2251
+ " supported: I18N_SUPPORTED,",
2252
+ " defaultLocale: I18N_DEFAULT,",
2253
+ " })",
2254
+ " }",
2255
+ " // Client-side: cookie only. Accept-Language sniffing is",
2256
+ " // server-exclusive — navigator.languages can diverge from",
2257
+ " // what the server saw and would produce a hydration",
2258
+ " // mismatch on first paint.",
2259
+ " if (typeof document === 'undefined') return I18N_DEFAULT",
2260
+ " return resolveLocale({",
2261
+ " cookieHeader: document.cookie,",
2262
+ " acceptLanguageHeader: null,",
2263
+ " supported: I18N_SUPPORTED,",
2264
+ " defaultLocale: I18N_DEFAULT,",
2265
+ " })",
2266
+ "}",
2267
+ ""
2268
+ ] : [],
2269
+ "export const App = (): React.ReactNode => {",
2270
+ " // `useSyncExternalStore` keeps the React tree alive across HMR-driven",
2271
+ " // module swaps. When version bumps, the snapshot changes, the component",
2272
+ " // re-renders, `buildRoutes()` reads the freshest refs slot, and React",
2273
+ " // sees a new Component identity → renders the patched module's output",
2274
+ " // without unmounting the Router or any ancestors.",
2275
+ " const v = useSyncExternalStore(subscribe, getVersion, getVersion)",
2276
+ " const routes = useMemo(() => buildRoutes(), [v])",
2277
+ " const notFounds = useMemo(() => buildNotFounds(), [v])",
2278
+ ...S ? [
2279
+ " const ssr = useServerRequest()",
2280
+ " const locale = pickI18nLocale(ssr)",
2281
+ " const messages = I18N_CATALOGS[locale] ?? I18N_CATALOGS[I18N_DEFAULT]!",
2282
+ " return (",
2283
+ " <I18nProvider locale={locale} messages={messages} defaultLocale={I18N_DEFAULT}>",
2284
+ " <Router routes={routes} notFounds={notFounds} />",
2285
+ " </I18nProvider>",
2286
+ " )"
2287
+ ] : [" return <Router routes={routes} notFounds={notFounds} />"],
2288
+ "}",
2289
+ ""
2290
+ ].join("\n"), y = [
2291
+ "// GENERATED BY `voltro dev` — do not edit; will be overwritten on next boot.",
2292
+ "// Entry: imports the generated App component and calls mount() with the",
2293
+ "// resolved apis map. Side-effect only — no local component definitions —",
2294
+ "// so downstream invalidations (user page edits) terminate at app.tsx.",
2295
+ "",
2296
+ ...Pr(t),
2297
+ "import { mount } from '@voltro/web'",
2298
+ ...h,
2299
+ "import { App } from './app'",
2300
+ "import { preloadCurrentRoute } from './routeTable'",
2301
+ ...Mr(t),
2302
+ ...Ar(t, o),
2303
+ ...Nr(t),
2304
+ "",
2305
+ "// Preload the current route's page chunk BEFORE hydration so the first",
2306
+ "// client render matches the SSG/SSR-prerendered HTML. Without it, a lazy",
2307
+ "// page resolves to a null leaf on the first render (its chunk hasn't",
2308
+ "// loaded), diverging from the server's full <main> → React #418. Only",
2309
+ "// when hydrating pre-rendered markup (a fresh SPA mount has nothing to",
2310
+ "// match); the load-error path is swallowed inside preloadRouteModule.",
2311
+ "const __voltroRoot = document.getElementById('root')",
2312
+ "if (document.getElementById('__voltro_state__') && __voltroRoot && __voltroRoot.children.length > 0) {",
2313
+ " await preloadCurrentRoute()",
2314
+ "}",
2315
+ "",
2316
+ "mount(App, {",
2317
+ " apis: {",
2318
+ ...g,
2319
+ " },",
2320
+ ...jr(t, o),
2321
+ "})",
2322
+ "",
2323
+ qr
2324
+ ].join("\n");
2325
+ } else _ = "", v = "", y = [
2326
+ "// GENERATED BY `voltro dev` — do not edit; will be overwritten on next boot.",
2327
+ "// The user's root component lives at ../src/App.tsx; this file imports it",
2328
+ "// and calls mount(). Side-effect only, no component definitions, so the",
2329
+ "// user's component file remains the Fast Refresh boundary.",
2330
+ "",
2331
+ ...Pr(t),
2332
+ "import { mount } from '@voltro/web'",
2333
+ ...h,
2334
+ "import App from '../src/App'",
2335
+ ...Mr(t),
2336
+ ...Ar(t, o),
2337
+ ...Nr(t),
2338
+ "",
2339
+ "mount(App, {",
2340
+ " apis: {",
2341
+ ...g,
2342
+ " },",
2343
+ ...jr(t, o),
2344
+ "})",
2345
+ "",
2346
+ qr
2347
+ ].join("\n");
2348
+ let b = l(e, ".framework");
2349
+ await O.mkdir(b, { recursive: !0 }), t.env ? await Ze(b, r) : await O.rm(l(b, "env.public.ts"), { force: !0 }), await O.writeFile(l(b, "index.html"), c, "utf8"), await O.writeFile(l(b, "main.tsx"), y, "utf8"), _ ? (await O.writeFile(l(b, "app.tsx"), _, "utf8"), await O.writeFile(l(b, "routeTable.ts"), v, "utf8")) : (await O.rm(l(b, "app.tsx"), { force: !0 }), await O.rm(l(b, "routeTable.ts"), { force: !0 }));
2350
+ let x = l(e, ".gitignore"), S = "";
2351
+ try {
2352
+ S = await O.readFile(x, "utf8");
2353
+ } catch {}
2354
+ let C = ["/.framework/"], w = S.split("\n").filter((e) => e.trim() !== "");
2355
+ for (let e of C) w.includes(e) || w.push(e);
2356
+ await O.writeFile(x, w.join("\n") + "\n", "utf8");
2357
+ }, li = async (e, t) => {
2358
+ try {
2359
+ let n = l(s(e), "project.json");
2360
+ if (!T(n)) return;
2361
+ let r = await O.readFile(n, "utf8"), i = JSON.parse(r).apps ?? {}, a = e.split("/").filter(Boolean).pop() ?? "", o = [];
2362
+ for (let [e, n] of Object.entries(i)) e !== a && n.port === t && o.push(e);
2363
+ if (o.length === 0) return;
2364
+ Z.warn("sibling app(s) claim the same port — only one boots", {
2365
+ port: t,
2366
+ conflicts: o,
2367
+ projectJson: n
2368
+ });
2369
+ } catch {}
2370
+ }, ui = (e) => l(e, ".framework", "dist", "server", "appConfig.js"), di = async (e) => {
2371
+ let t = ui(e), n = T(t) ? t : l(e, "app.config.ts");
2372
+ try {
2373
+ let e = (await import(p(n).href)).default;
2374
+ return typeof e == "object" && e && "type" in e && e.type === "web" ? e : null;
2375
+ } catch {
2376
+ return null;
2377
+ }
2378
+ }, fi = async (s) => {
2379
+ let c = await di(s);
2380
+ if (!c) return {
2381
+ ran: !1,
2382
+ exitCode: 0
2383
+ };
2384
+ un();
2385
+ let f = Nt();
2386
+ Ut(f), Z.info("booting voltro dev (web)", { app: c.name ?? "(unnamed)" });
2387
+ let p = await ni(s, c);
2388
+ for (let e of p) Z.info("api wired", {
2389
+ name: e.name,
2390
+ pkg: e.pkg,
2391
+ ...e.proxyTarget ? { proxyTo: e.proxyTarget } : { directWs: e.browserWsUrl }
2392
+ });
2393
+ Be(s).then((e) => {
2394
+ for (let t of e.files) if (t.action === "created") {
2395
+ let e = t.path.split("/").pop() ?? t.path;
2396
+ Z.info(`${e} seeded`, { path: t.path });
2397
+ }
2398
+ }).catch(() => {});
2399
+ let { resolved: m } = await Qe({
2400
+ rawEnv: c.env,
2401
+ appType: "web",
2402
+ root: s,
2403
+ log: Z,
2404
+ generateTypes: !0
2405
+ }), h = m.publicValues;
2406
+ await ci(s, c, p, h), Z.debug("generated framework entry files", { files: [
2407
+ "index.html",
2408
+ ".framework/main.tsx",
2409
+ ...c.env ? [".framework/env.public.ts"] : []
2410
+ ] });
2411
+ let g = process.env.VOLTRO_IS_DASHBOARD === "1" && process.env.VOLTRO_DASHBOARD_PORT ? Number(process.env.VOLTRO_DASHBOARD_PORT) : c.port ?? 5173, _ = c.name ?? "unnamed", v = Wn("web", _, g), y = Zn(_);
2412
+ await Hn({
2413
+ id: v,
2414
+ name: _,
2415
+ kind: "web",
2416
+ url: `http://localhost:${g}`,
2417
+ pid: process.pid,
2418
+ status: "booting",
2419
+ logFile: y.path
2420
+ }).catch(() => {}), await li(s, g);
2421
+ let { pages: b, dirs: x } = await $(l(s, "src", "pages")), S = x.map((e) => ({
2422
+ dir: e.dir,
2423
+ hasLayout: e.hasLayout,
2424
+ hasError: e.hasError,
2425
+ hasPending: e.hasPending,
2426
+ hasNotFound: e.hasNotFound
2427
+ })), w = await jt({
2428
+ appRoot: s,
2429
+ pages: b
2430
+ });
2431
+ w.wrote && Z.debug("routes codegen wrote", { path: u(s, w.path) });
2432
+ let E = await Ge("vite", () => import("vite")), D = (await import("@vitejs/plugin-react")).default, k = (await import("@tailwindcss/vite")).default, A = l(s, ".framework"), j = l(s, "src"), M = /* @__PURE__ */ new Set([
2433
+ ".framework",
2434
+ "node_modules",
2435
+ "dist",
2436
+ ".git",
2437
+ ".vite",
2438
+ ".turbo",
2439
+ ".cache"
2440
+ ]), N = {
2441
+ name: "framework:watch-app-sources",
2442
+ async configureServer(e) {
2443
+ try {
2444
+ let t = (await O.readdir(s, { withFileTypes: !0 })).filter((e) => e.isDirectory() && !M.has(e.name));
2445
+ for (let n of t) e.watcher.add(l(s, n.name));
2446
+ t.length === 0 && e.watcher.add(j);
2447
+ } catch {
2448
+ e.watcher.add(j);
2449
+ }
2450
+ try {
2451
+ let t = await O.readFile(l(s, "package.json"), "utf8"), n = JSON.parse(t), r = Object.keys({
2452
+ ...n.dependencies,
2453
+ ...n.devDependencies
2454
+ });
2455
+ await Promise.all(r.map(async (t) => {
2456
+ let n = await Zr(s, t);
2457
+ if (!n) return;
2458
+ let r = l(n, "src");
2459
+ try {
2460
+ (await O.stat(r)).isDirectory() && e.watcher.add(r);
2461
+ } catch {}
2462
+ }));
2463
+ } catch {}
2464
+ }
2465
+ }, P = l(s, "src", "pages"), ee = (e) => e.endsWith(".tsx") && (e === P || e.startsWith(P + "/")), F = (e) => e === P || e.startsWith(P + "/"), te = async (e) => {
2466
+ try {
2467
+ let t = Date.now();
2468
+ await ci(s, c, p, h);
2469
+ let { pages: n } = await $(P);
2470
+ await jt({
2471
+ appRoot: s,
2472
+ pages: n
2473
+ }), Z.info("page tree regenerated", {
2474
+ reason: e,
2475
+ ms: Date.now() - t
2476
+ });
2477
+ } catch (t) {
2478
+ Z.error("page tree regen failed", { reason: e }, t);
2479
+ }
2480
+ }, I = {
2481
+ name: "framework:regenerate-on-page-tree-change",
2482
+ configureServer(e) {
2483
+ let t = null, n = [], r = (e) => {
2484
+ n.push(e), t && clearTimeout(t), t = setTimeout(() => {
2485
+ t = null;
2486
+ let e = n.length === 1 ? n[0] : `${n.length} events (${n[0]}, …)`;
2487
+ n.length = 0, te(e);
2488
+ }, 50);
2489
+ };
2490
+ e.watcher.on("add", (e) => {
2491
+ ee(e) && r(`add ${u(s, e)}`);
2492
+ }), e.watcher.on("unlink", (e) => {
2493
+ ee(e) && r(`unlink ${u(s, e)}`);
2494
+ }), e.watcher.on("addDir", (e) => {
2495
+ F(e) && r(`addDir ${u(s, e)}`);
2496
+ }), e.watcher.on("unlinkDir", (e) => {
2497
+ F(e) && r(`unlinkDir ${u(s, e)}`);
2498
+ });
2499
+ }
2500
+ }, L = l(s, "app.config.ts"), R = (e) => {
2501
+ if (!se(e.env)) return "";
2502
+ let t = Object.entries(e.env.vars).map(([e, t]) => `${e}:${t.access}`).sort();
2503
+ return `${String(e.env.publicPrefix)}|${t.join(",")}`;
2504
+ }, ne = (e, t) => {
2505
+ let n = [];
2506
+ return e.port !== t.port && n.push(`port ${e.port ?? "(default)"} → ${t.port ?? "(default)"}`), JSON.stringify(e.proxies) !== JSON.stringify(t.proxies) && n.push("proxies"), JSON.stringify(e.allowedHosts) !== JSON.stringify(t.allowedHosts) && n.push("allowedHosts"), JSON.stringify(e.apis) !== JSON.stringify(t.apis) && n.push("apis"), R(e) !== R(t) && n.push("env"), n;
2507
+ }, re = c, ie = d(L), ae = {
2508
+ name: "framework:watch-app-config",
2509
+ async configureServer(e) {
2510
+ e.watcher.add(L), Z.info("watching app.config.ts for changes", { path: u(s, L) });
2511
+ let t = async () => {
2512
+ try {
2513
+ try {
2514
+ let t = e.moduleGraph.getModuleById(L);
2515
+ t && e.moduleGraph.invalidateModule(t);
2516
+ } catch {}
2517
+ let t = (await e.ssrLoadModule(L, { fixStacktrace: !0 })).default;
2518
+ return typeof t == "object" && t && "type" in t && t.type === "web" ? t : (Z.warn("app.config.ts re-load returned wrong shape", { hasDefault: t !== void 0 }), null);
2519
+ } catch (e) {
2520
+ return Z.warn("app.config.ts re-load failed — ignoring this change", {}, e), null;
2521
+ }
2522
+ }, n = null, r = () => {
2523
+ n && clearTimeout(n), n = setTimeout(() => {
2524
+ n = null, i();
2525
+ }, 100);
2526
+ }, i = async () => {
2527
+ let n = await t();
2528
+ if (!n) {
2529
+ Z.info("app.config.ts onConfigChange: load returned null — skipping");
2530
+ return;
2531
+ }
2532
+ if (Z.info("app.config.ts onConfigChange: loaded", {
2533
+ theme: n.theme,
2534
+ port: n.port,
2535
+ name: n.name
2536
+ }), JSON.stringify(n) === JSON.stringify(re)) {
2537
+ Z.info("app.config.ts onConfigChange: parsed config unchanged — skipping (no-op edit?)");
2538
+ return;
2539
+ }
2540
+ let r = ne(re, n);
2541
+ if (r.length > 0) {
2542
+ Z.warn("app.config.ts changed — hard restart required", { fields: r });
2543
+ try {
2544
+ await e.close();
2545
+ } catch {}
2546
+ let t = me(process.execPath, [...process.execArgv, ...process.argv.slice(1)], {
2547
+ stdio: "inherit",
2548
+ env: process.env,
2549
+ cwd: process.cwd()
2550
+ }), n = (e) => {
2551
+ t.kill(e);
2552
+ }, i = () => n("SIGINT"), a = () => n("SIGTERM");
2553
+ process.on("SIGINT", i), process.on("SIGTERM", a), t.on("exit", (e, t) => {
2554
+ process.off("SIGINT", i), process.off("SIGTERM", a), t ? process.kill(process.pid, t) : process.exit(e ?? 0);
2555
+ }), t.on("error", (e) => {
2556
+ Z.error("restart spawn failed", {}, e), process.exit(1);
2557
+ });
2558
+ return;
2559
+ }
2560
+ try {
2561
+ let t = Date.now();
2562
+ await ci(s, n, await ni(s, n)), re = n, e.ws && e.ws.send({
2563
+ type: "full-reload",
2564
+ path: "*"
2565
+ }), Z.info("app.config.ts soft-regen", {
2566
+ ms: Date.now() - t,
2567
+ reload: "full"
2568
+ });
2569
+ } catch (e) {
2570
+ Z.error("app.config.ts soft-regen failed", {}, e);
2571
+ }
2572
+ }, a = (e) => o(e) === "app.config.ts" ? e === L || d(e) === ie : !1;
2573
+ e.watcher.on("change", (e) => {
2574
+ a(e) && (Z.info("app.config.ts change event (chokidar)", { file: e }), r());
2575
+ }), e.watcher.on("add", (e) => {
2576
+ a(e) && (Z.info("app.config.ts add event (chokidar)", { file: e }), r());
2577
+ });
2578
+ try {
2579
+ let { watchFile: e } = await import("node:fs");
2580
+ e(L, { interval: 500 }, (e, t) => {
2581
+ e.mtimeMs !== t.mtimeMs && (Z.info("app.config.ts change event (poll)", { mtime: e.mtimeMs }), r());
2582
+ }), Z.info("app.config.ts polling watcher attached", { intervalMs: 500 });
2583
+ } catch (e) {
2584
+ Z.warn("app.config.ts polling watcher could not attach", {}, e);
2585
+ }
2586
+ ut(st, Z, {
2587
+ root: s,
2588
+ onBeforeRestart: () => e.close()
2589
+ });
2590
+ }
2591
+ }, oe = /\/apps\/[^/]+\/.*\.(route|mutation|workflow|schema)\.tsx?$/, ce = {
2592
+ name: "framework:suppress-api-hmr",
2593
+ handleHotUpdate(e) {
2594
+ if (oe.test(e.file)) return [];
2595
+ }
2596
+ }, le = {
2597
+ name: "framework:reoptimize-on-rpcgroup-change",
2598
+ async configureServer(e) {
2599
+ let t = /* @__PURE__ */ new Map();
2600
+ for (let n of p) {
2601
+ if (!n.proxyTarget) continue;
2602
+ let r = await Zr(s, n.pkg);
2603
+ if (!r) continue;
2604
+ let i = l(r, "rpcGroup.generated.ts");
2605
+ try {
2606
+ t.set(i, await O.readFile(i, "utf8"));
2607
+ } catch {
2608
+ t.set(i, "");
2609
+ }
2610
+ try {
2611
+ e.watcher.add(i);
2612
+ } catch {}
2613
+ }
2614
+ if (t.size === 0) return;
2615
+ let n = null, r = !1, i = async () => {
2616
+ if (r) return;
2617
+ let n = null;
2618
+ for (let [e, r] of t) {
2619
+ let i;
2620
+ try {
2621
+ i = await O.readFile(e, "utf8");
2622
+ } catch {
2623
+ continue;
2624
+ }
2625
+ i !== r && (t.set(e, i), n = e);
2626
+ }
2627
+ if (n !== null) {
2628
+ r = !0, Z.info(`rpcGroup changed (${u(s, n)}) — re-bundling the api client + reloading (descriptor edits propagate automatically; no manual restart needed)`);
2629
+ try {
2630
+ await O.rm(l(A, ".vite", "deps"), {
2631
+ recursive: !0,
2632
+ force: !0
2633
+ }), await e.restart(!0);
2634
+ } catch (e) {
2635
+ r = !1, Z.error("rpcGroup re-optimize failed", {}, e);
2636
+ }
2637
+ }
2638
+ }, a = (e) => {
2639
+ t.has(d(e)) && (n && clearTimeout(n), n = setTimeout(() => {
2640
+ i();
2641
+ }, 120));
2642
+ };
2643
+ e.watcher.on("change", a), e.watcher.on("add", a);
2644
+ }
2645
+ }, z = {};
2646
+ for (let e of p) {
2647
+ if (!e.proxyTarget) continue;
2648
+ z[e.browserWsUrl] = {
2649
+ target: e.proxyTarget,
2650
+ ws: !0,
2651
+ changeOrigin: !0,
2652
+ ...e.wsPath ? {} : { rewrite: () => "/ws" }
2653
+ };
2654
+ let t = e.proxyTarget.replace(/^ws/, "http");
2655
+ z[`/_voltro/api/${e.name}`] = {
2656
+ target: t,
2657
+ changeOrigin: !0,
2658
+ rewrite: (t) => t.replace(RegExp(`^/_voltro/api/${e.name}`), "")
2659
+ };
2660
+ }
2661
+ for (let [e, t] of Object.entries(c.proxies ?? {})) {
2662
+ if (z[e]) {
2663
+ Z.warn("user proxy ignored — prefix already claimed by an api ws proxy", { prefix: e });
2664
+ continue;
2665
+ }
2666
+ z[e] = {
2667
+ target: t.target,
2668
+ changeOrigin: t.changeOrigin ?? !0,
2669
+ ...t.rewrite === void 0 ? {} : { rewrite: (n) => n.replace(RegExp(`^${e}`), t.rewrite) }
2670
+ }, Z.info(`proxy ${e} → ${t.target}`, {
2671
+ prefix: e,
2672
+ target: t.target,
2673
+ ...t.rewrite === void 0 ? {} : { rewrite: t.rewrite }
2674
+ });
2675
+ }
2676
+ let ue = {
2677
+ name: "framework:inspect",
2678
+ configureServer(o) {
2679
+ let u = null, d = async () => {
2680
+ if (u !== null) return u;
2681
+ let e = [];
2682
+ for (let t of b) try {
2683
+ let n = await o.ssrLoadModule(l(s, "src", "pages", t.file));
2684
+ e.push({
2685
+ pattern: t.pattern,
2686
+ file: t.file,
2687
+ dirChain: t.dirChain,
2688
+ renderMode: Dn(n, l("src", "pages", t.file)),
2689
+ interactive: n.interactive ?? "full",
2690
+ tenantAware: n.tenantAware === !0,
2691
+ revalidateMs: K(n.revalidate),
2692
+ staleWhileRevalidateMs: K(n.staleWhileRevalidate) ?? 0,
2693
+ cacheInvalidatesOn: Array.isArray(n.cacheInvalidatesOn) ? n.cacheInvalidatesOn : [],
2694
+ hasLoader: typeof n.loader == "function",
2695
+ hasMeta: n.meta != null,
2696
+ hasGetStaticPaths: typeof n.getStaticPaths == "function"
2697
+ });
2698
+ } catch (e) {
2699
+ Z.warn("inspect: failed to load page metadata", { pattern: t.pattern }, e);
2700
+ }
2701
+ return u = e, e;
2702
+ };
2703
+ o.middlewares.use((e, t, n) => {
2704
+ let r = e.url ?? "/";
2705
+ if (r.startsWith("/_voltro/inspect") || r.startsWith("/api/dashboard/proxy")) return n();
2706
+ let i = Date.now(), a = t.end.bind(t);
2707
+ t.end = ((...e) => {
2708
+ try {
2709
+ f.emit("request", {
2710
+ url: r.split("?")[0],
2711
+ status: t.statusCode ?? 0,
2712
+ durationMs: Date.now() - i
2713
+ });
2714
+ } catch {}
2715
+ return a(...e);
2716
+ }), n();
2717
+ }), c.name === "voltroDashboard" && o.middlewares.use(async (t, r, i) => {
2718
+ let a = t.url ?? "", o = a.split("?")[0];
2719
+ if (o === "/api/dashboard/proxy") {
2720
+ let i = new URL(a, "http://x").searchParams.get("target");
2721
+ if (!i) {
2722
+ r.statusCode = 400, r.end("missing ?target=");
2723
+ return;
2724
+ }
2725
+ if (!n(i)) {
2726
+ r.statusCode = 400, r.end("target not allowed: must be loopback or an origin configured in VOLTRO_DASHBOARD_APPS");
2727
+ return;
2728
+ }
2729
+ try {
2730
+ let n = { accept: String(t.headers.accept ?? "application/json") };
2731
+ t.headers.authorization ? n.authorization = String(t.headers.authorization) : e(i) && process.env.VOLTRO_INSPECT_TOKEN && (n.authorization = `Bearer ${process.env.VOLTRO_INSPECT_TOKEN}`);
2732
+ let a;
2733
+ if (t.method && t.method !== "GET" && t.method !== "HEAD") {
2734
+ let e = [];
2735
+ for await (let n of t) e.push(n);
2736
+ a = Buffer.concat(e);
2737
+ let r = t.headers["content-type"];
2738
+ r && (n["content-type"] = Array.isArray(r) ? r[0] : String(r));
2739
+ }
2740
+ let o = await fetch(i, {
2741
+ redirect: "manual",
2742
+ ...t.method ? { method: t.method } : {},
2743
+ headers: n,
2744
+ ...a && a.length ? { body: new Uint8Array(a.buffer, a.byteOffset, a.byteLength) } : {}
2745
+ }), s = Buffer.from(await o.arrayBuffer());
2746
+ r.statusCode = o.status, r.setHeader("content-type", o.headers.get("content-type") ?? "application/octet-stream"), r.setHeader("content-length", String(s.length)), r.end(s);
2747
+ } catch (e) {
2748
+ r.statusCode = 502, r.end(`proxy error: ${e.message}`);
2749
+ }
2750
+ return;
2751
+ }
2752
+ if (o === "/api/dashboard/proxy/stream") {
2753
+ let i = new URL(a, "http://x").searchParams.get("target");
2754
+ if (!i) {
2755
+ r.statusCode = 400, r.end("missing ?target=");
2756
+ return;
2757
+ }
2758
+ if (!n(i)) {
2759
+ r.statusCode = 400, r.end("target not allowed: must be loopback or an origin configured in VOLTRO_DASHBOARD_APPS");
2760
+ return;
2761
+ }
2762
+ let o = new AbortController();
2763
+ t.on("close", () => o.abort()), r.on("close", () => o.abort());
2764
+ try {
2765
+ let n = await fetch(i, {
2766
+ redirect: "manual",
2767
+ method: "GET",
2768
+ headers: {
2769
+ accept: "text/event-stream",
2770
+ ...t.headers.authorization ? { authorization: String(t.headers.authorization) } : e(i) && process.env.VOLTRO_INSPECT_TOKEN ? { authorization: `Bearer ${process.env.VOLTRO_INSPECT_TOKEN}` } : {}
2771
+ },
2772
+ signal: o.signal
2773
+ });
2774
+ if (!n.ok || !n.body) {
2775
+ r.statusCode = n.status, r.end(`upstream ${n.status}`);
2776
+ return;
2777
+ }
2778
+ r.writeHead(200, {
2779
+ "content-type": "text/event-stream; charset=utf-8",
2780
+ "cache-control": "no-cache, no-transform",
2781
+ connection: "keep-alive",
2782
+ "x-accel-buffering": "no"
2783
+ });
2784
+ let a = n.body.getReader();
2785
+ try {
2786
+ for (;;) {
2787
+ let { done: e, value: t } = await a.read();
2788
+ if (e) break;
2789
+ t && r.write(Buffer.from(t));
2790
+ }
2791
+ } finally {
2792
+ a.releaseLock(), r.end();
2793
+ }
2794
+ } catch (e) {
2795
+ e.name !== "AbortError" && (r.statusCode = 502, r.end(`proxy stream error: ${e.message}`));
2796
+ }
2797
+ return;
2798
+ }
2799
+ i();
2800
+ }), o.middlewares.use(async (e, n, o) => {
2801
+ let s = e.url ?? "";
2802
+ if (!s.startsWith("/_voltro/inspect")) return o();
2803
+ let l = {};
2804
+ for (let [t, n] of Object.entries(e.headers ?? {})) n !== void 0 && (l[String(t).toLowerCase()] = Array.isArray(n) ? n.join(", ") : String(n));
2805
+ let u = s.split("?")[0];
2806
+ if (e.method === "GET" && (u === "/_voltro/inspect/logs" || s.startsWith("/_voltro/inspect/logs?"))) {
2807
+ let e = a(l.origin), t = nn(s, Vt(), l);
2808
+ n.statusCode = t.status, n.setHeader("content-type", t.contentType);
2809
+ for (let [t, r] of Object.entries(e)) n.setHeader(t, r);
2810
+ n.end(t.body);
2811
+ return;
2812
+ }
2813
+ if (e.method === "POST" && u === "/_voltro/inspect/clientLog") {
2814
+ let r = a(l.origin);
2815
+ if (t()) {
2816
+ n.statusCode = 503, n.setHeader("content-type", "application/json");
2817
+ for (let [e, t] of Object.entries(r)) n.setHeader(e, t);
2818
+ n.end(JSON.stringify({ error: "inspect disabled (VOLTRO_INSPECT=off)" }));
2819
+ return;
2820
+ }
2821
+ let i = "";
2822
+ e.setEncoding("utf-8"), e.on("data", (e) => {
2823
+ i += e;
2824
+ }), e.on("end", () => {
2825
+ let e = Xt(i, f);
2826
+ n.statusCode = e.status, n.setHeader("content-type", e.contentType);
2827
+ for (let [e, t] of Object.entries(r)) n.setHeader(e, t);
2828
+ n.end(e.body);
2829
+ }), e.on("error", () => {
2830
+ n.statusCode = 400, n.setHeader("content-type", "application/json"), n.end(JSON.stringify({ error: "read failed" }));
2831
+ });
2832
+ return;
2833
+ }
2834
+ if (u === "/_voltro/inspect/stream") {
2835
+ let i = a(l.origin);
2836
+ if (t()) {
2837
+ n.statusCode = 503, n.setHeader("content-type", "application/json");
2838
+ for (let [e, t] of Object.entries(i)) n.setHeader(e, t);
2839
+ n.end(JSON.stringify({ error: "inspect disabled (VOLTRO_INSPECT=off)" }));
2840
+ return;
2841
+ }
2842
+ let o = r(l);
2843
+ if (!o.ok) {
2844
+ n.statusCode = 401, n.setHeader("content-type", "application/json");
2845
+ for (let [e, t] of Object.entries(i)) n.setHeader(e, t);
2846
+ n.end(JSON.stringify({
2847
+ error: "unauthorized",
2848
+ reason: o.reason
2849
+ }));
2850
+ return;
2851
+ }
2852
+ n.statusCode = 200, n.setHeader("content-type", "text/event-stream; charset=utf-8"), n.setHeader("cache-control", "no-cache, no-transform"), n.setHeader("connection", "keep-alive"), n.setHeader("x-accel-buffering", "no");
2853
+ for (let [e, t] of Object.entries(i)) n.setHeader(e, t);
2854
+ n.flushHeaders?.(), n.write("retry: 5000\n\n");
2855
+ let c = s.indexOf("?");
2856
+ if (!(c !== -1 && new URLSearchParams(s.slice(c + 1)).get("live") === "1")) for (let e of f.buffered()) n.write(Pt(e));
2857
+ let u = f.subscribe((e) => {
2858
+ try {
2859
+ n.write(Pt(e));
2860
+ } catch {}
2861
+ }), d = setInterval(() => {
2862
+ try {
2863
+ n.write(Ft());
2864
+ } catch {}
2865
+ }, 15e3), p = () => {
2866
+ clearInterval(d), u();
2867
+ };
2868
+ e.on("close", p), n.on("close", p);
2869
+ return;
2870
+ }
2871
+ try {
2872
+ let t = i(s, {
2873
+ kind: "web",
2874
+ meta: {
2875
+ name: c.name ?? "(unnamed)",
2876
+ voltroVersion: Or,
2877
+ port: g,
2878
+ mode: "dev",
2879
+ apis: Object.entries(c.apis ?? {}).map(([e, t]) => {
2880
+ let n = {
2881
+ name: e,
2882
+ package: t.package
2883
+ };
2884
+ return t.url !== void 0 && (n.url = t.url), n;
2885
+ })
2886
+ },
2887
+ routes: await d(),
2888
+ dirs: S,
2889
+ cache: () => ({
2890
+ backend: "memory",
2891
+ size: 0,
2892
+ entries: []
2893
+ }),
2894
+ env: () => et(c.name ?? "app", { contract: se(c.env) ? c.env : void 0 })
2895
+ }, l, { method: e.method ?? "GET" });
2896
+ if (t === null) return o();
2897
+ n.statusCode = t.status, n.setHeader("content-type", t.contentType);
2898
+ for (let [e, r] of Object.entries(t.headers ?? {})) n.setHeader(e, r);
2899
+ n.end(t.body);
2900
+ } catch (e) {
2901
+ n.statusCode = 500, n.setHeader("content-type", "text/plain"), n.end(`inspect handler error: ${e.message}`);
2902
+ }
2903
+ });
2904
+ }
2905
+ }, de = c.name === "voltroDashboard" ? {
2906
+ name: "framework:dashboard-registry",
2907
+ configureServer(e) {
2908
+ e.middlewares.use(async (e, t, n) => {
2909
+ if (!(e.url ?? "").startsWith("/api/dashboard/registry")) return n();
2910
+ try {
2911
+ let e = await Vn();
2912
+ t.statusCode = 200, t.setHeader("content-type", "application/json; charset=utf-8"), t.end(JSON.stringify(e));
2913
+ } catch (e) {
2914
+ t.statusCode = 500, t.setHeader("content-type", "text/plain"), t.end(`registry read error: ${e.message}`);
2915
+ }
2916
+ });
2917
+ }
2918
+ } : null, fe = Yr(b), B = /* @__PURE__ */ new Set(), he = yt(), ge = xt({
2919
+ limit: he,
2920
+ onColdStart: (e) => Z.debug("ssr cold-compile start", { id: e }),
2921
+ onColdEnd: (e) => Z.debug("ssr cold-compile end", { id: e })
2922
+ });
2923
+ Z.debug(`ssr cold-compile concurrency ${he}`, { concurrency: he });
2924
+ let _e = null, ve = async () => (_e === null && (_e = await O.readFile(l(s, ".framework", "index.html"), "utf8")), _e), ye = {
2925
+ name: "framework:ssr",
2926
+ configureServer(e) {
2927
+ let t = (t) => ge.load(t, async () => await e.ssrLoadModule(t));
2928
+ e.middlewares.use(async (n, r, i) => {
2929
+ if (n.method !== "GET" && n.method !== "HEAD") return i();
2930
+ let a = n.url ?? "/", o = a.indexOf("?"), c = (o === -1 ? a : a.slice(0, o)) || "/";
2931
+ if (c.startsWith("/@") || c.startsWith("/node_modules/") || c.startsWith("/.framework/") || c.startsWith("/_voltro/") || c === "/main.tsx" || c === "/index.html" || c === "/sw.js" || c === "/favicon.ico" || c === "/robots.txt" || /\.[a-z0-9]+$/i.test(c)) return i();
2932
+ let u = Xr(c, fe);
2933
+ if (!u) return i();
2934
+ let d = !B.has(u.route.pattern), f = Date.now();
2935
+ d && Z.info(`ssr compiling ${u.route.pattern}`, {
2936
+ pattern: u.route.pattern,
2937
+ pathname: c
2938
+ });
2939
+ let m = {}, h = async (e, t) => {
2940
+ let n = Date.now(), r = await t();
2941
+ return m[e] = (m[e] ?? 0) + (Date.now() - n), r;
2942
+ }, g = async (t, n, r) => {
2943
+ let i = await e.moduleGraph.getModuleById(t);
2944
+ if (!(!i || n.has(t))) {
2945
+ if (n.add(t), i.id && /\.(css|sass|scss|less|stylus|pcss|postcss)(\?|$)/.test(i.id)) {
2946
+ let e = i.url.replace(/\?.*$/, "");
2947
+ r.includes(e) || r.push(e);
2948
+ return;
2949
+ }
2950
+ for (let e of i.importedModules ?? []) e.id && await g(e.id, n, r);
2951
+ }
2952
+ };
2953
+ try {
2954
+ let o = await h("loadPage", async () => await t(l(s, "src", "pages", u.route.file))), _ = Dn(o, l("src", "pages", u.route.file)), v = Wr(x, u.route.dirChain), y = _ === "spa" && v.some((e) => e.hasLayout);
2955
+ if (_ !== "ssr" && _ !== "isr" && !y) return i();
2956
+ let b = {};
2957
+ for (let [e, t] of Object.entries(n.headers ?? {})) typeof t == "string" ? b[e] = t : Array.isArray(t) && (b[e] = t.join(", "));
2958
+ let S = si(oi(p[0], { allowDevProxy: !0 }), b.cookie, { apiName: p[0]?.name }), C = new AbortController(), w = () => C.abort();
2959
+ r.once("close", w);
2960
+ let T = null, E = [], D = {};
2961
+ try {
2962
+ ({chain: E, segmentLoaderData: D} = await h("loadChain", () => Gr({
2963
+ entries: v,
2964
+ loadLayout: (e) => t(l(s, "src", "pages", e.dir, "layout.tsx")),
2965
+ loadError: (e) => t(l(s, "src", "pages", e.dir, "error.tsx")),
2966
+ loadPending: (e) => t(l(s, "src", "pages", e.dir, "loading.tsx")),
2967
+ ctx: {
2968
+ params: u.params,
2969
+ pathname: c,
2970
+ signal: C.signal,
2971
+ headers: b,
2972
+ query: S
2973
+ }
2974
+ })));
2975
+ let e = o.loader;
2976
+ typeof e == "function" && !y && (T = await h("loader", () => e({
2977
+ params: u.params,
2978
+ pathname: c,
2979
+ signal: C.signal,
2980
+ headers: b,
2981
+ query: S
2982
+ })));
2983
+ } finally {
2984
+ r.off("close", w);
2985
+ }
2986
+ let O = await h("loadSsrHelpers", async () => await t("@voltro/web/ssr")), k = {
2987
+ pattern: u.route.pattern,
2988
+ Component: o.default,
2989
+ meta: o.meta,
2990
+ loader: o.loader,
2991
+ ErrorBoundary: o.ErrorBoundary,
2992
+ Pending: o.Pending,
2993
+ renderMode: _,
2994
+ chain: E
2995
+ }, A = {
2996
+ cookies: O.parseCookieHeader(b.cookie),
2997
+ headers: b,
2998
+ url: a
2999
+ }, j = o.interactive ?? "full", M = y ? hr({
3000
+ helpers: O,
3001
+ page: `src/pages/${u.route.file}`,
3002
+ interactive: j,
3003
+ delivery: "stream",
3004
+ renderInput: {
3005
+ descriptor: k,
3006
+ params: u.params,
3007
+ pathname: c,
3008
+ segmentLoaderData: D,
3009
+ requestContext: A
3010
+ }
3011
+ }) : null, N = y ? null : mr({
3012
+ helpers: O,
3013
+ page: `src/pages/${u.route.file}`,
3014
+ pathname: c,
3015
+ renderMode: _,
3016
+ interactive: j,
3017
+ loaderData: T,
3018
+ segmentLoaderData: D,
3019
+ pageLoaderRan: typeof o.loader == "function"
3020
+ }), P = [];
3021
+ await h("collectCss", async () => {
3022
+ let e = /* @__PURE__ */ new Set(), t = [
3023
+ l(s, "src", "pages", u.route.file),
3024
+ ...v.flatMap((e) => [
3025
+ ...e.hasLayout ? [l(s, "src", "pages", e.dir, "layout.tsx")] : [],
3026
+ ...e.hasError ? [l(s, "src", "pages", e.dir, "error.tsx")] : [],
3027
+ ...e.hasPending ? [l(s, "src", "pages", e.dir, "loading.tsx")] : []
3028
+ ]),
3029
+ l(s, ".framework", "main.tsx")
3030
+ ];
3031
+ for (let n of t) await g(n, e, P);
3032
+ });
3033
+ let ee = await h("readShell", ve), F = await h("transformShell", () => e.transformIndexHtml(a, ee)), te = P.map((e) => `<link rel="stylesheet" href="${e}?direct" />`).join("\n "), I = A.cookies["voltro:locale"] ?? "en", L = Date.now();
3034
+ if (M) {
3035
+ let e = (e) => _r({
3036
+ helpers: O,
3037
+ prepared: M,
3038
+ meta: e,
3039
+ interactive: j,
3040
+ extra: [te]
3041
+ });
3042
+ if (M.hasDeferred) Er({
3043
+ res: r,
3044
+ shell: wr({
3045
+ shell: F,
3046
+ inlineModuleScriptsAsync: !0
3047
+ }),
3048
+ htmlLang: I,
3049
+ headers: {
3050
+ "content-type": "text/html; charset=utf-8",
3051
+ "x-voltro-rendered-by": "spa-shell-dev"
3052
+ },
3053
+ headInjection: e,
3054
+ render: (e) => O.renderPageToStream({
3055
+ ...M.renderInput,
3056
+ ...e
3057
+ }),
3058
+ onShellError: (e) => {
3059
+ Z.warn("spa-shell-dev shell render failed; falling back to SPA shell", {
3060
+ pathname: c,
3061
+ pattern: u.route.pattern
3062
+ }, e), i();
3063
+ }
3064
+ });
3065
+ else {
3066
+ let t = gr({
3067
+ helpers: O,
3068
+ prepared: M
3069
+ }), n = F.replace("<div id=\"root\"></div>", `<div id="root">${t.body}</div>`).replace("</head>", ` ${e(t.meta)}\n </head>`).replace(/<html(\s+lang="[^"]*")?/i, `<html lang="${I}"`);
3070
+ r.statusCode = 200, r.setHeader("content-type", "text/html; charset=utf-8"), r.setHeader("x-voltro-rendered-by", "spa-shell-dev"), r.end(n);
3071
+ }
3072
+ } else if (N) {
3073
+ let e = (e) => [
3074
+ te,
3075
+ O.renderMetaToHtml(e),
3076
+ `<meta name="voltro-interactive" content="${j}" />`,
3077
+ ...N.hasDeferred ? [O.renderDeferredRegistryScript()] : [],
3078
+ O.renderRouterStateScript(N.stateInput)
3079
+ ].filter((e) => e.length > 0).join("\n "), t = {
3080
+ descriptor: k,
3081
+ params: u.params,
3082
+ pathname: c,
3083
+ loaderData: N.loaderData,
3084
+ segmentLoaderData: N.segmentLoaderData,
3085
+ requestContext: A
3086
+ };
3087
+ if (_ === "ssr" && j === "full") Er({
3088
+ res: r,
3089
+ shell: wr({
3090
+ shell: F,
3091
+ inlineModuleScriptsAsync: !0
3092
+ }),
3093
+ htmlLang: I,
3094
+ headers: {
3095
+ "content-type": "text/html; charset=utf-8",
3096
+ "x-voltro-rendered-by": "ssr-dev"
3097
+ },
3098
+ headInjection: e,
3099
+ render: (e) => O.renderPageToStream({
3100
+ ...t,
3101
+ ...e
3102
+ }),
3103
+ onShellError: (e) => {
3104
+ Z.warn("ssr-dev shell render failed; falling back to SPA shell", {
3105
+ pathname: c,
3106
+ pattern: u.route.pattern
3107
+ }, e), i();
3108
+ }
3109
+ });
3110
+ else {
3111
+ let { html: n, meta: i } = O.renderPageToHtml(t), a = F.replace("<div id=\"root\"></div>", `<div id="root">${n}</div>`).replace("</head>", ` ${e(i)}\n </head>`).replace(/<html(\s+lang="[^"]*")?/i, `<html lang="${I}"`);
3112
+ r.statusCode = 200, r.setHeader("content-type", "text/html; charset=utf-8"), r.setHeader("x-voltro-rendered-by", "ssr-dev"), r.end(a);
3113
+ }
3114
+ }
3115
+ m.render = Date.now() - L;
3116
+ let R = Date.now() - f;
3117
+ d ? (B.add(u.route.pattern), Z.info(`ssr compiled ${u.route.pattern} in ${R}ms`, {
3118
+ pattern: u.route.pattern,
3119
+ pathname: c,
3120
+ elapsedMs: R,
3121
+ cold: !0,
3122
+ phases: m
3123
+ })) : R > 200 && Z.info(`ssr rendered ${c} in ${R}ms`, {
3124
+ pattern: u.route.pattern,
3125
+ pathname: c,
3126
+ elapsedMs: R,
3127
+ cold: !1,
3128
+ phases: m
3129
+ });
3130
+ } catch (e) {
3131
+ if (pr(e)) {
3132
+ Z.error("ssr-dev render refused", {
3133
+ pathname: c,
3134
+ pattern: u.route.pattern
3135
+ }, e), r.statusCode = 500, r.setHeader("content-type", "text/plain; charset=utf-8"), r.end(e.message);
3136
+ return;
3137
+ }
3138
+ Z.warn("ssr-dev render failed; falling back to SPA shell", {
3139
+ pathname: c,
3140
+ pattern: u.route.pattern
3141
+ }, e), i();
3142
+ }
3143
+ });
3144
+ }
3145
+ }, V = Date.now(), be = E.version ?? "?", xe = await kr(), H = l(s, "node_modules", "@voltro", "ui-shadcn"), U = T(l(H, "package.json")) ? H : null, Se = [], Ce = await (async () => {
3146
+ let e = [];
3147
+ for (let t of p) {
3148
+ if (!t.proxyTarget) continue;
3149
+ let n = await Zr(s, t.pkg);
3150
+ if (n) try {
3151
+ e.push(await O.readFile(l(n, "rpcGroup.generated.ts"), "utf8"));
3152
+ } catch {}
3153
+ }
3154
+ if (e.length === 0) return !1;
3155
+ let t = pe("sha1").update(e.join("\0")).digest("hex"), n = l(A, ".voltro-rpcgroup-optimize"), r = "";
3156
+ try {
3157
+ r = (await O.readFile(n, "utf8")).trim();
3158
+ } catch {}
3159
+ if (r === t) return !1;
3160
+ try {
3161
+ await O.writeFile(n, t);
3162
+ } catch {}
3163
+ return !0;
3164
+ })();
3165
+ Ce && Z.info("rpcGroup changed since last boot — forcing a dep re-optimize so the browser loads the current api client"), await (await E.createServer({
3166
+ root: A,
3167
+ envPrefix: "__VOLTRO_VITE_ENV_DISABLED__",
3168
+ ssr: { noExternal: ["react-intl"] },
3169
+ resolve: {
3170
+ dedupe: ["react", "react-dom"],
3171
+ alias: [
3172
+ ...xe ? [{
3173
+ find: "@voltro/devtools/styles.css",
3174
+ replacement: l(xe, "src/styles.css")
3175
+ }, {
3176
+ find: "@voltro/devtools",
3177
+ replacement: l(xe, "src/index.ts")
3178
+ }] : [],
3179
+ ...U ? [
3180
+ {
3181
+ find: "@voltro/ui-shadcn/tokens.css",
3182
+ replacement: l(U, "src/tokens.css")
3183
+ },
3184
+ {
3185
+ find: "@voltro/ui-shadcn/cn",
3186
+ replacement: l(U, "src/cn.ts")
3187
+ },
3188
+ {
3189
+ find: "@voltro/ui-shadcn/brand",
3190
+ replacement: l(U, "src/brand/voltroLogo.tsx")
3191
+ },
3192
+ {
3193
+ find: "@voltro/ui-shadcn",
3194
+ replacement: l(U, "src/index.ts")
3195
+ }
3196
+ ] : [],
3197
+ ...Ue(s)
3198
+ ]
3199
+ },
3200
+ optimizeDeps: {
3201
+ include: [...p.map((e) => `${e.pkg}/rpcGroup`), ...Se],
3202
+ force: Ce
3203
+ },
3204
+ customLogger: vt(),
3205
+ plugins: [
3206
+ xn(l(s, "src", "pages")),
3207
+ D(),
3208
+ k(),
3209
+ N,
3210
+ I,
3211
+ ae,
3212
+ ce,
3213
+ le,
3214
+ ue,
3215
+ ye,
3216
+ ...de ? [de] : []
3217
+ ],
3218
+ server: {
3219
+ port: g,
3220
+ strictPort: !0,
3221
+ host: !0,
3222
+ allowedHosts: c.allowedHosts === !0 || [...c.allowedHosts ?? []],
3223
+ proxy: z,
3224
+ fs: { allow: [s, ...Fr(s)] }
3225
+ },
3226
+ appType: "spa",
3227
+ cacheDir: l(A, ".vite"),
3228
+ publicDir: l(s, "public")
3229
+ })).listen(), Dr.info(`v${be} ready in ${Date.now() - V}ms`, {
3230
+ version: be,
3231
+ bootMs: Date.now() - V
3232
+ }), Z.info(`listening on http://localhost:${g}`, {
3233
+ port: g,
3234
+ app: c.name ?? "(unnamed)"
3235
+ });
3236
+ for (let e of p) e.proxyTarget && (Z.info(`proxy /ws/${e.name} → ${e.proxyTarget}`, {
3237
+ api: e.name,
3238
+ target: e.proxyTarget
3239
+ }), Z.info(`proxy /_voltro/api/${e.name} → ${e.proxyTarget.replace(/^ws/, "http")}/_voltro/inspect`, { api: e.name }));
3240
+ try {
3241
+ await Hn({
3242
+ id: v,
3243
+ name: _,
3244
+ kind: "web",
3245
+ url: `http://localhost:${g}`,
3246
+ pid: process.pid,
3247
+ status: "live",
3248
+ logFile: y.path
3249
+ });
3250
+ let e = nr(s);
3251
+ if (e) {
3252
+ let t = await dr({ dashboardAppPath: e });
3253
+ t.status === "launched" ? Z.info(`dashboard launched at http://localhost:${t.port}`, { port: t.port }) : t.status === "already-running" && Z.debug(`dashboard already running on :${t.port}`, { port: t.port });
3254
+ }
3255
+ setInterval(() => {
3256
+ Hn({
3257
+ id: v,
3258
+ name: _,
3259
+ kind: "web",
3260
+ url: `http://localhost:${g}`,
3261
+ pid: process.pid,
3262
+ status: "live",
3263
+ logFile: y.path
3264
+ }).catch(() => {});
3265
+ }, 1e4).unref();
3266
+ let t = () => {
3267
+ Un(v), y.dispose();
3268
+ };
3269
+ process.on("SIGINT", t), process.on("SIGTERM", t);
3270
+ } catch (e) {
3271
+ Z.warn("runtime-registry write failed", {}, e);
3272
+ }
3273
+ return C({
3274
+ app: c.name ?? "unnamed",
3275
+ kind: "web",
3276
+ url: `http://localhost:${g}`,
3277
+ bootMs: Date.now() - V
3278
+ }), new Promise(() => {});
3279
+ }, pi = async (e) => {
3280
+ process.env.NODE_ENV || (process.env.NODE_ENV = "production");
3281
+ let t = await di(e);
3282
+ if (!t) return {
3283
+ ran: !1,
3284
+ exitCode: 0
3285
+ };
3286
+ let n = Date.now(), r = Z.child("serve");
3287
+ r.info("booting voltro serve (preview)", { app: t.name ?? "(unnamed)" });
3288
+ let i = await ni(e, t);
3289
+ for (let e of i) r.info("api wired", {
3290
+ name: e.name,
3291
+ pkg: e.pkg
3292
+ });
3293
+ await ci(e, t, i);
3294
+ {
3295
+ let { pages: t } = await $(l(e, "src", "pages"));
3296
+ await jt({
3297
+ appRoot: e,
3298
+ pages: t
3299
+ });
3300
+ }
3301
+ let a = t.port ?? 5173, o = await Ge("vite", () => import("vite")), s = (await import("@vitejs/plugin-react")).default, c = l(e, ".framework");
3302
+ Z.info("running production build"), await o.build({
3303
+ root: c,
3304
+ envPrefix: "__VOLTRO_VITE_ENV_DISABLED__",
3305
+ plugins: [s()],
3306
+ customLogger: vt(),
3307
+ resolve: { dedupe: ["react", "react-dom"] },
3308
+ build: {
3309
+ outDir: "dist",
3310
+ rollupOptions: { output: { manualChunks: Rr } }
3311
+ },
3312
+ publicDir: l(e, "public")
3313
+ });
3314
+ let u = (await o.preview({
3315
+ root: c,
3316
+ envPrefix: "__VOLTRO_VITE_ENV_DISABLED__",
3317
+ preview: { port: a },
3318
+ build: { outDir: "dist" }
3319
+ })).resolvedUrls, d = u?.local[0] ?? `http://localhost:${a}`, f = u?.local.slice(1).map((e) => ({
3320
+ label: "Local",
3321
+ url: e
3322
+ })) ?? [];
3323
+ return C({
3324
+ app: t.name ?? "unnamed",
3325
+ kind: "preview",
3326
+ url: d,
3327
+ extras: f,
3328
+ bootMs: Date.now() - n
3329
+ }), new Promise(() => {});
3330
+ }, mi = 5e3, hi = 6e4, gi = (e, t) => {
3331
+ if (e.length === 0) return 0;
3332
+ if (e.length === 1) return e[0];
3333
+ let n = t * (e.length - 1), r = Math.floor(n), i = Math.ceil(n);
3334
+ if (r === i) return e[r];
3335
+ let a = n - r;
3336
+ return e[r] * (1 - a) + e[i] * a;
3337
+ }, _i = (e) => {
3338
+ if (e.length === 0) return {
3339
+ p50: 0,
3340
+ p95: 0,
3341
+ p99: 0,
3342
+ mean: 0,
3343
+ min: 0,
3344
+ max: 0
3345
+ };
3346
+ let t = e.slice().sort((e, t) => e - t), n = 0;
3347
+ for (let e of t) n += e;
3348
+ return {
3349
+ p50: gi(t, .5),
3350
+ p95: gi(t, .95),
3351
+ p99: gi(t, .99),
3352
+ mean: n / t.length,
3353
+ min: t[0],
3354
+ max: t[t.length - 1]
3355
+ };
3356
+ }, vi = (e = {}) => {
3357
+ let t = e.maxSamples ?? mi, n = e.defaultWindowMs ?? hi, r = [];
3358
+ return {
3359
+ record(e) {
3360
+ te(e), r.push({
3361
+ ...e,
3362
+ ts: Date.now()
3363
+ }), r.length > t && r.shift();
3364
+ },
3365
+ snapshot(e) {
3366
+ let t = e ?? n, i = Date.now(), a = i - t, o = /* @__PURE__ */ new Map(), s = 0;
3367
+ for (let e of r) {
3368
+ if (e.ts < a) continue;
3369
+ s++;
3370
+ let t = `${e.kind}\u0000${e.tag}`, n = o.get(t);
3371
+ n || (n = {
3372
+ kind: e.kind,
3373
+ tag: e.tag,
3374
+ samples: []
3375
+ }, o.set(t, n)), n.samples.push(e);
3376
+ }
3377
+ let c = [];
3378
+ for (let e of o.values()) {
3379
+ let t = e.samples.map((e) => e.durationMs), n = 0;
3380
+ for (let t of e.samples) t.status === "error" && n++;
3381
+ c.push({
3382
+ kind: e.kind,
3383
+ tag: e.tag,
3384
+ count: e.samples.length,
3385
+ errorCount: n,
3386
+ latencyMs: _i(t)
3387
+ });
3388
+ }
3389
+ return c.sort((e, t) => t.count - e.count), {
3390
+ windowMs: t,
3391
+ capturedAt: i,
3392
+ totalSamples: s,
3393
+ buckets: c
3394
+ };
3395
+ }
3396
+ };
3397
+ };
3398
+ //#endregion
3399
+ export { it as $, Un as A, Xt as B, dr as C, Qn as D, Zn as E, Tn as F, Ft as G, Vt as H, Dn as I, yt as J, jt as K, cn as L, Sn as M, On as N, Wn as O, Cn as P, rt as Q, nn as R, tr as S, Xn as T, Pt as U, Ut as V, Nt as W, ct as X, ut as Y, st as Z, mr as _, Gr as a, Qe as at, _r as b, ni as c, Ge as ct, Rr as d, Ve as dt, at as et, $ as f, V as ft, pr as g, Er as h, si as i, tt as it, Hn as j, Vn as k, fi as l, Ue as lt, wr as m, zr as n, K as nt, Wr as o, Xe as ot, ci as p, be as pt, xt as q, oi as r, et as rt, di as s, Ye as st, vi as t, nt as tt, pi as u, Be as ut, hr as v, nr as w, rr as x, gr as y, Qt as z };