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