@voltro/cli 0.20.2 → 0.22.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 (75) hide show
  1. package/CHANGELOG.md +398 -0
  2. package/THIRD-PARTY-NOTICES.md +61 -61
  3. package/dist/{apiBuild-qZBEu59d.js → apiBuild-2zRxj2hJ.js} +93 -80
  4. package/dist/apiBuild-sqNmWmY5.js +2 -0
  5. package/dist/bin.js +41 -20
  6. package/dist/{commands-kYbfVoPO.js → commands-DGaeTn2f.js} +3055 -2640
  7. package/dist/dbCommand-CO3eSAZR.js +2 -0
  8. package/dist/{dbCommand-BPp9R0Wc.js → dbCommand-DVASmZj2.js} +305 -249
  9. package/dist/dev-BEYBSGJ7.js +3 -0
  10. package/dist/{dev-OHLsAq4K.js → dev-DeHVUxQx.js} +1732 -1686
  11. package/dist/index.js +1 -1
  12. package/dist/inspect-BA67TF6v.js +2 -0
  13. package/dist/inspect-_ldwsAwH.js +945 -0
  14. package/dist/{inspectMetrics-DvPNXmGA.js → inspectMetrics-4AVPn6IS.js} +584 -571
  15. package/dist/{manifestBuild-P9yuCY2d.js → manifestBuild-Bs1Uw22_.js} +1 -1
  16. package/dist/manifestBuild-i-fRHg_H.js +2 -0
  17. package/dist/serveCommand-DEVTtnLy.js +1161 -0
  18. package/dist/serveEntry.js +2 -2
  19. package/dist/{start-CXQ7WL1W.js → start-BjGUIIvj.js} +389 -389
  20. package/dist/startEntry.js +2 -2
  21. package/package.json +27 -27
  22. package/templates/AGENTS.md +1 -1
  23. package/templates/agent-docs/_index.md +1 -1
  24. package/templates/agent-docs/cli.md +181 -5
  25. package/templates/agent-docs/data.md +58 -0
  26. package/templates/agent-docs/database/migrations.md +175 -31
  27. package/templates/agent-docs/database/schema.md +7 -0
  28. package/templates/agent-docs/database/seedsdialects.md +3 -3
  29. package/templates/agent-docs/plugins.md +1 -1
  30. package/templates/agent-docs/schema-driven-ui.md +2 -2
  31. package/templates/agent-docs/templates/apibackends.md +1 -1
  32. package/templates/agent-docs/whats-new.md +236 -9
  33. package/templates/apps/api-ai/package.json +12 -12
  34. package/templates/apps/api-auth/package.json +13 -13
  35. package/templates/apps/api-backend/package.json +12 -12
  36. package/templates/apps/api-backend-deactivation/package.json +12 -12
  37. package/templates/apps/api-backend-mail/package.json +11 -11
  38. package/templates/apps/api-backend-mariadb/package.json +14 -14
  39. package/templates/apps/api-backend-storage/package.json +11 -11
  40. package/templates/apps/api-data-advanced/package.json +13 -13
  41. package/templates/apps/api-durable/package.json +13 -13
  42. package/templates/apps/api-feature-flags/package.json +14 -14
  43. package/templates/apps/api-governance/package.json +13 -13
  44. package/templates/apps/api-kv/package.json +13 -13
  45. package/templates/apps/api-moderation/package.json +13 -13
  46. package/templates/apps/api-observability/package.json +13 -13
  47. package/templates/apps/api-ratelimit/package.json +13 -13
  48. package/templates/apps/api-rbac/package.json +13 -13
  49. package/templates/apps/api-rest/package.json +12 -12
  50. package/templates/apps/api-saas/package.json +16 -16
  51. package/templates/apps/api-search/package.json +13 -13
  52. package/templates/apps/api-versioning/package.json +13 -13
  53. package/templates/apps/api-webhooks/package.json +14 -14
  54. package/templates/apps/changelog/package.json +8 -8
  55. package/templates/apps/edge-functions/package.json +5 -5
  56. package/templates/apps/frontend-admin/package.json +10 -10
  57. package/templates/apps/frontend-app/package.json +10 -10
  58. package/templates/apps/frontend-blank/package.json +9 -9
  59. package/templates/apps/frontend-contact/package.json +11 -11
  60. package/templates/apps/frontend-dashboard/package.json +9 -9
  61. package/templates/apps/frontend-docs/package.json +9 -9
  62. package/templates/apps/frontend-i18n/package.json +8 -8
  63. package/templates/apps/frontend-landing/package.json +9 -9
  64. package/templates/apps/frontend-spa/package.json +9 -9
  65. package/templates/apps/frontend-ssr/package.json +9 -9
  66. package/templates/apps/frontend-ssr-api/package.json +10 -10
  67. package/templates/apps/frontend-static-blog/package.json +8 -8
  68. package/dist/apiBuild-C9aHz4Yh.js +0 -2
  69. package/dist/dbCommand-DtUe-0dM.js +0 -2
  70. package/dist/dev-2AvdzDg2.js +0 -3
  71. package/dist/inspect-DcZ04OME.js +0 -2
  72. package/dist/inspect-Dwx0_tUj.js +0 -921
  73. package/dist/manifestBuild-D1MzJAiQ.js +0 -2
  74. package/dist/serveCommand-BKqTKWTX.js +0 -1136
  75. /package/templates/patches/{@effect__cluster@0.59.0.patch → @effect__cluster@0.60.0.patch} +0 -0
@@ -1,18 +1,18 @@
1
1
  import { d as e, u as t, x as n } from "./fileConventions-CBNPZVOV.js";
2
- import { D as r, E as i, T as a, a as o, p as s, w as c } from "./inspect-Dwx0_tUj.js";
2
+ import { D as r, E as i, T as a, a as o, p as s, w as c } from "./inspect-_ldwsAwH.js";
3
3
  import { basename as l, dirname as u, isAbsolute as d, join as f, relative as p, resolve as m } from "node:path";
4
4
  import { fileURLToPath as h, pathToFileURL as g } from "node:url";
5
5
  import { FileSystem as _ } from "@effect/platform";
6
6
  import { NodeContext as v, NodeRuntime as y } from "@effect/platform-node";
7
7
  import { Cause as b, Effect as x, Layer as S } from "effect";
8
8
  import { LoggerLayer as C, addSink as w, createLogger as T, printReadyBlock as E } from "@voltro/logger";
9
- import { closeSync as D, existsSync as O, mkdirSync as k, openSync as A, promises as j, readFileSync as M, readdirSync as N, statSync as P, unlinkSync as ee, unwatchFile as F, watchFile as te, writeSync as I } from "node:fs";
10
- import { currentTraceContext as L, recordSample as R, resolveSecret as ne } from "@voltro/runtime";
11
- import { createRequire as re } from "node:module";
9
+ import { closeSync as D, existsSync as O, mkdirSync as ee, openSync as k, promises as A, readFileSync as j, readdirSync as M, statSync as N, unlinkSync as P, unwatchFile as F, watchFile as te, writeSync as I } from "node:fs";
10
+ import { currentTraceContext as ne, recordSample as L, resolveSecret as re } from "@voltro/runtime";
12
11
  import { homedir as ie } from "node:os";
13
- import { FRAMEWORK_ENV_CATALOG as ae, appEnvEntries as oe, checkEnvNaming as se, formatEnvErrors as ce, installEnvSnapshot as z, isEnvContract as le, pluginEnvEntries as ue, renderDotEnvExample as de, resolveEnv as fe } from "@voltro/env";
14
- import { __installPublicEnv as pe } from "@voltro/env/public";
15
- import { mkdir as me, readFile as he, writeFile as ge } from "node:fs/promises";
12
+ import { createRequire as ae } from "node:module";
13
+ import { FRAMEWORK_ENV_CATALOG as oe, appEnvEntries as se, checkEnvNaming as ce, formatEnvErrors as le, installEnvSnapshot as ue, isEnvContract as de, pluginEnvEntries as R, renderDotEnvExample as fe, resolveEnv as pe } from "@voltro/env";
14
+ import { __installPublicEnv as me } from "@voltro/env/public";
15
+ import { mkdir as he, readFile as ge, writeFile as z } from "node:fs/promises";
16
16
  import { createHash as _e } from "node:crypto";
17
17
  import { spawn as ve } from "node:child_process";
18
18
  import { createConnection as ye } from "node:net";
@@ -35,7 +35,7 @@ var xe = [
35
35
  "file",
36
36
  "line",
37
37
  "routine"
38
- ], B = (e, t = 0, n = /* @__PURE__ */ new WeakSet()) => {
38
+ ], Se = (e, t = 0, n = /* @__PURE__ */ new WeakSet()) => {
39
39
  if (t > 10 || typeof e != "object" || !e || n.has(e)) return null;
40
40
  n.add(e);
41
41
  let r = e, i = r.message;
@@ -55,20 +55,20 @@ var xe = [
55
55
  ]) {
56
56
  let i = r[e];
57
57
  if (i !== void 0) {
58
- let e = B(i, t + 1, n);
58
+ let e = Se(i, t + 1, n);
59
59
  if (e) return e;
60
60
  }
61
61
  }
62
62
  if (Array.isArray(r.failures)) for (let e of r.failures) {
63
- let r = B(e, t + 1, n);
63
+ let r = Se(e, t + 1, n);
64
64
  if (r) return r;
65
65
  }
66
66
  return null;
67
- }, Se = (e = {}) => S.merge(v.layer, C({
67
+ }, B = (e) => ({
68
68
  ...e.scope ? { defaultScope: e.scope } : {},
69
69
  ...e.logger
70
- })), V = async (e, t = {}) => {
71
- let n = e.pipe(x.provide(Se(t)));
70
+ }), Ce = (e = {}) => S.merge(v.layer, C(B(e))), V = async (e, t = {}) => {
71
+ let n = e.pipe(x.provide(v.layer));
72
72
  return await x.runPromise(x.matchCauseEffect(n, {
73
73
  onSuccess: (e) => x.succeed(e),
74
74
  onFailure: (e) => {
@@ -84,7 +84,7 @@ var xe = [
84
84
  }
85
85
  let n = null;
86
86
  for (let e of t) {
87
- let t = B(e);
87
+ let t = Se(e);
88
88
  if (t) {
89
89
  n = t;
90
90
  break;
@@ -103,40 +103,40 @@ var xe = [
103
103
  } : { causePretty: b.pretty(e) };
104
104
  return x.zipRight(x.logError("cli command failed", r), x.succeed(1));
105
105
  }
106
- }).pipe(x.provide(C(t.logger ?? {}))));
107
- }, Ce = (e, t = {}) => {
108
- let n = e.pipe(x.provide(Se(t)));
106
+ }).pipe(x.provide(C(B(t)))));
107
+ }, we = (e, t = {}) => {
108
+ let n = e.pipe(x.provide(Ce(t)));
109
109
  y.runMain(n, { disableErrorReporting: !1 });
110
- }, H = u(h(import.meta.url)), we = [m(H, "..", "templates"), m(H, "..", "..", "templates")], Te = (e) => ({
110
+ }, H = u(h(import.meta.url)), Te = [m(H, "..", "templates"), m(H, "..", "..", "templates")], Ee = (e) => ({
111
111
  _tag: "TemplateNotFoundError",
112
112
  searched: e
113
- }), Ee = ["AGENTS.md", "CLAUDE.md"], De = "voltro:agents-md:keep", Oe = 2048, ke = "<!-- VOLTRO:INDEX -->", U = (e, t) => e.exists(t).pipe(x.orElseSucceed(() => !1)), W = (e, t) => e.readFileString(t).pipe(x.orElseSucceed(() => "")), Ae = (e, t) => e.readFileString(t).pipe(x.map((e) => {
113
+ }), De = ["AGENTS.md", "CLAUDE.md"], Oe = "voltro:agents-md:keep", ke = 2048, Ae = "<!-- VOLTRO:INDEX -->", U = (e, t) => e.exists(t).pipe(x.orElseSucceed(() => !1)), W = (e, t) => e.readFileString(t).pipe(x.orElseSucceed(() => "")), je = (e, t) => e.readFileString(t).pipe(x.map((e) => {
114
114
  try {
115
115
  return JSON.parse(e).workspaces !== void 0;
116
116
  } catch {
117
117
  return !1;
118
118
  }
119
- }), x.orElseSucceed(() => !1)), je = (e) => x.gen(function* () {
119
+ }), x.orElseSucceed(() => !1)), Me = (e) => x.gen(function* () {
120
120
  let t = yield* _.FileSystem, n = m(e);
121
121
  for (;;) {
122
- if ((yield* U(t, f(n, ".git"))) || (yield* U(t, f(n, "pnpm-workspace.yaml"))) || (yield* Ae(t, f(n, "package.json")))) return n;
122
+ if ((yield* U(t, f(n, ".git"))) || (yield* U(t, f(n, "pnpm-workspace.yaml"))) || (yield* je(t, f(n, "package.json")))) return n;
123
123
  let r = u(n);
124
124
  if (r === n) return m(e);
125
125
  n = r;
126
126
  }
127
- }), Me = (e, t, n) => x.gen(function* () {
127
+ }), Ne = (e, t, n) => x.gen(function* () {
128
128
  yield* e.makeDirectory(n, { recursive: !0 }).pipe(x.orElseSucceed(() => void 0));
129
129
  let r = yield* e.readDirectory(t).pipe(x.orElseSucceed(() => []));
130
130
  for (let i of r) {
131
131
  let r = f(t, i), a = f(n, i);
132
- (yield* e.stat(r).pipe(x.orElseSucceed(() => null)))?.type === "Directory" ? yield* Me(e, r, a) : yield* e.copyFile(r, a).pipe(x.orElseSucceed(() => void 0));
132
+ (yield* e.stat(r).pipe(x.orElseSucceed(() => null)))?.type === "Directory" ? yield* Ne(e, r, a) : yield* e.copyFile(r, a).pipe(x.orElseSucceed(() => void 0));
133
133
  }
134
- }), Ne = (e) => typeof e?.name == "string" && e.name.length > 0 ? e.name.split("#")[0] : null, Pe = (e, t) => x.gen(function* () {
134
+ }), Pe = (e) => typeof e?.name == "string" && e.name.length > 0 ? e.name.split("#")[0] : null, Fe = (e, t) => x.gen(function* () {
135
135
  let n = f(t, "app.config.ts");
136
136
  if (!(yield* U(e, n))) return null;
137
137
  let r = (yield* x.tryPromise(() => import(g(n).href)).pipe(x.orElseSucceed(() => null)))?.default;
138
- return !r || r.type && r.type !== "api" ? r?.type === "web" ? [] : null : (r.plugins ?? []).map(Ne).filter((e) => e !== null);
139
- }), Fe = (e, t) => x.gen(function* () {
138
+ return !r || r.type && r.type !== "api" ? r?.type === "web" ? [] : null : (r.plugins ?? []).map(Pe).filter((e) => e !== null);
139
+ }), Ie = (e, t) => x.gen(function* () {
140
140
  let n = [], r = [], i = f(t, "apps");
141
141
  if (!(yield* U(e, i))) return {
142
142
  apis: n,
@@ -155,7 +155,7 @@ var xe = [
155
155
  apis: n,
156
156
  webs: r
157
157
  };
158
- }), Ie = (e) => e.replace(/\|/g, "\\|").replace(/\n/g, " ").trim(), Le = (e, t, n) => {
158
+ }), Le = (e) => e.replace(/\|/g, "\\|").replace(/\n/g, " ").trim(), Re = (e, t, n) => {
159
159
  let r = [
160
160
  "<!-- voltro agent-docs index — regenerated at seed time -->",
161
161
  "## Deep reference (read on demand)",
@@ -167,17 +167,17 @@ var xe = [
167
167
  "",
168
168
  "| Topic | Open | Summary |",
169
169
  "|---|---|---|",
170
- ...e.modules.map((e) => `| ${e.title} | \`${n}${e.path}\` | ${Ie(e.description)} |`),
170
+ ...e.modules.map((e) => `| ${e.title} | \`${n}${e.path}\` | ${Le(e.description)} |`),
171
171
  ""
172
- ], 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\` | ${Ie(e.description)} |`) : t.map((e) => {
172
+ ], 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\` | ${Le(e.description)} |`) : t.map((e) => {
173
173
  let t = i.get(e);
174
- return t ? `| ${t.slug} | \`node_modules/${e}/README.md\` | ${Ie(t.description)} |` : `| ${e.replace(/^@[^/]+\//, "")} | \`node_modules/${e}/README.md\` | (see plugin README) |`;
174
+ return t ? `| ${t.slug} | \`node_modules/${e}/README.md\` | ${Le(t.description)} |` : `| ${e.replace(/^@[^/]+\//, "")} | \`node_modules/${e}/README.md\` | (see plugin README) |`;
175
175
  });
176
176
  return r.push(`### Plugins${t === null ? "" : " (installed)"}`, "", "| Plugin | Open | Summary |", "|---|---|---|"), r.push(a.length ? a.join("\n") : "| _(none installed)_ | | |", ""), r.join("\n");
177
- }, Re = (e, t, n) => {
177
+ }, ze = (e, t, n) => {
178
178
  let r = t.templates?.[e] ?? t.templates?.[e.replace(/^frontend-/, "")];
179
179
  return `\nScaffolded from the \`${e}\` template — see \`${r ? `${n}${r}` : `${n}agent-docs/templates/overview.md`}\`.\n`;
180
- }, ze = {
180
+ }, Be = {
181
181
  api: (e, t, n = "") => `# api — agent notes
182
182
 
183
183
  You are in a Voltro **api** app. Server primitives live here: \`queries/\`,
@@ -217,7 +217,7 @@ You are in a Voltro **web** app. File-based routing under \`src/pages/**\`.
217
217
  Deep reference (paths from the repo root): \`${e}agent-docs/routing.md\`,
218
218
  \`${e}agent-docs/schema-driven-ui.md\`, \`${e}agent-docs/internationalization.md\`.
219
219
  ${t}`
220
- }, Be = [
220
+ }, Ve = [
221
221
  {
222
222
  name: "voltro-schema",
223
223
  description: "Define or change a Voltro database table/schema (columns, mixins, indexes, relations).",
@@ -248,7 +248,7 @@ ${t}`
248
248
  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.",
249
249
  module: "cli.md"
250
250
  }
251
- ], Ve = (e, t) => `---
251
+ ], He = (e, t) => `---
252
252
  name: ${e.name}
253
253
  description: ${e.description}
254
254
  ---
@@ -259,10 +259,10 @@ Open the full reference and follow the patterns there:
259
259
 
260
260
  Also read the repo-root \`AGENTS.md\` for the always-true rules (browser/server
261
261
  boundary, naming, anti-patterns) before editing.
262
- `, He = (e, t, n, r) => x.gen(function* () {
262
+ `, Ue = (e, t, n, r) => x.gen(function* () {
263
263
  let i = yield* U(e, t);
264
264
  if (i) {
265
- if ((yield* W(e, t)).slice(0, Oe).includes("voltro:agents-md:keep")) return {
265
+ if ((yield* W(e, t)).slice(0, ke).includes("voltro:agents-md:keep")) return {
266
266
  path: t,
267
267
  action: "protected"
268
268
  };
@@ -275,64 +275,138 @@ boundary, naming, anti-patterns) before editing.
275
275
  path: t,
276
276
  action: i ? "overwritten" : "created"
277
277
  };
278
- }), Ue = (e, t = {}) => x.gen(function* () {
279
- let n = yield* _.FileSystem, r = yield* je(e), i = null;
280
- for (let e of we) if (yield* U(n, f(e, "AGENTS.core.md"))) {
278
+ }), We = (e, t = {}) => x.gen(function* () {
279
+ let n = yield* _.FileSystem, r = yield* Me(e), i = null;
280
+ for (let e of Te) if (yield* U(n, f(e, "AGENTS.core.md"))) {
281
281
  i = e;
282
282
  break;
283
283
  }
284
284
  if (i === null) {
285
- for (let e of we) if (yield* U(n, f(e, "AGENTS.md"))) {
285
+ for (let e of Te) if (yield* U(n, f(e, "AGENTS.md"))) {
286
286
  let i = yield* W(n, f(e, "AGENTS.md")), a = [];
287
- for (let e of Ee) a.push(yield* He(n, f(r, e), i, t.force ?? !1));
287
+ for (let e of De) a.push(yield* Ue(n, f(r, e), i, t.force ?? !1));
288
288
  return { files: a };
289
289
  }
290
- return yield* x.fail(Te(we.map((e) => f(e, "AGENTS.core.md"))));
290
+ return yield* x.fail(Ee(Te.map((e) => f(e, "AGENTS.core.md"))));
291
291
  }
292
292
  let a = yield* W(n, f(i, "AGENTS.core.md")), o = yield* W(n, f(i, "agent-docs", "_manifest.json")), s = o ? JSON.parse(o) : {
293
293
  modules: [],
294
294
  plugins: []
295
- }, c = (t.preferPointer ?? !1) || (yield* U(n, f(r, "node_modules/@voltro/cli/templates/agent-docs", "_manifest.json"))), l = c ? "node_modules/@voltro/cli/templates/" : "", u = t.force ?? !1, d = Ee.map((e) => f(r, e));
296
- if ((yield* x.forEach(d, (e) => W(n, e).pipe(x.map((e) => e.slice(0, Oe))))).every((e) => e.includes("voltro:agents-md:keep"))) return { files: d.map((e) => ({
295
+ }, c = (t.preferPointer ?? !1) || (yield* U(n, f(r, "node_modules/@voltro/cli/templates/agent-docs", "_manifest.json"))), l = c ? "node_modules/@voltro/cli/templates/" : "", u = t.force ?? !1, d = De.map((e) => f(r, e));
296
+ if ((yield* x.forEach(d, (e) => W(n, e).pipe(x.map((e) => e.slice(0, ke))))).every((e) => e.includes("voltro:agents-md:keep"))) return { files: d.map((e) => ({
297
297
  path: e,
298
298
  action: "protected"
299
299
  })) };
300
- let { apis: p, webs: h } = yield* Fe(n, r), g = /* @__PURE__ */ new Map(), v = /* @__PURE__ */ new Set(), y = !1;
300
+ let { apis: p, webs: h } = yield* Ie(n, r), g = /* @__PURE__ */ new Map(), v = /* @__PURE__ */ new Set(), y = !1;
301
301
  for (let e of p) {
302
- let t = yield* Pe(n, e);
302
+ let t = yield* Fe(n, e);
303
303
  if (g.set(e, t), t !== null) {
304
304
  y = !0;
305
305
  for (let e of t) v.add(e);
306
306
  }
307
307
  }
308
- let b = t.plugins ? t.plugins.map(Ne).filter((e) => e !== null) : y ? [...v] : null, S = a.includes(ke) ? a.replace(ke, Le(s, b, l)) : a, C = [];
309
- for (let e of d) C.push(yield* He(n, e, S, u));
310
- c || (yield* Me(n, f(i, "agent-docs"), f(r, "agent-docs")));
308
+ let b = t.plugins ? t.plugins.map(Pe).filter((e) => e !== null) : y ? [...v] : null, S = a.includes(Ae) ? a.replace(Ae, Re(s, b, l)) : a, C = [];
309
+ for (let e of d) C.push(yield* Ue(n, e, S, u));
310
+ c || (yield* Ne(n, f(i, "agent-docs"), f(r, "agent-docs")));
311
311
  let w = new Map((t.appTemplates ?? []).map((e) => [m(e.dir), e.template])), T = (e) => {
312
312
  let t = w.get(m(e));
313
- return t ? Re(t, s, l) : "";
314
- }, E = (e, t) => x.forEach(Ee, (r) => He(n, f(e, r), t, u));
315
- for (let e of p) C.push(...yield* E(e, ze.api(l, g.get(e) ?? null, T(e)))), (yield* U(n, f(e, "database"))) && C.push(...yield* E(f(e, "database"), ze.database(l)));
316
- for (let e of h) C.push(...yield* E(e, ze.web(l, T(e))));
317
- for (let e of Be) C.push(yield* He(n, f(r, ".claude", "skills", e.name, "SKILL.md"), Ve(e, l), u));
313
+ return t ? ze(t, s, l) : "";
314
+ }, E = (e, t) => x.forEach(De, (r) => Ue(n, f(e, r), t, u));
315
+ for (let e of p) C.push(...yield* E(e, Be.api(l, g.get(e) ?? null, T(e)))), (yield* U(n, f(e, "database"))) && C.push(...yield* E(f(e, "database"), Be.database(l)));
316
+ for (let e of h) C.push(...yield* E(e, Be.web(l, T(e))));
317
+ for (let e of Ve) C.push(yield* Ue(n, f(r, ".claude", "skills", e.name, "SKILL.md"), He(e, l), u));
318
318
  return { files: C };
319
- }), We = (e, t = {}) => x.runPromise(Ue(e, t).pipe(x.provide(v.layer))), Ge = async (e) => {
319
+ }), Ge = (e, t = {}) => x.runPromise(We(e, t).pipe(x.provide(v.layer))), Ke = async (e) => {
320
320
  let t = e.includes("--force"), n = e.find((e) => !e.startsWith("-")) ?? process.cwd();
321
321
  return V(x.gen(function* () {
322
- let e = yield* Ue(n, { force: t });
322
+ let e = yield* We(n, { force: t });
323
323
  for (let t of e.files) {
324
- let e = t.action === "created" ? "wrote" : t.action === "overwritten" ? "overwrote" : t.action === "protected" ? `protected (hand-maintained — has "${De}")` : "present (use --force to overwrite)";
324
+ let e = t.action === "created" ? "wrote" : t.action === "overwritten" ? "overwrote" : t.action === "protected" ? `protected (hand-maintained — has "${Oe}")` : "present (use --force to overwrite)";
325
325
  yield* x.logInfo(`${t.path.split("/").slice(-2).join("/")} ${e}`, { action: t.action });
326
326
  }
327
327
  return 0;
328
328
  }).pipe(x.catchTag("TemplateNotFoundError", (e) => x.gen(function* () {
329
329
  return yield* x.logError("AGENTS.md template not found", { searched: e.searched }), 1;
330
330
  }))), { scope: "voltro:agents-md" });
331
- }, Ke = (e) => e.replace(/\\"|"(?:[^"\\]|\\.)*"|(\/\/[^\n]*|\/\*[\s\S]*?\*\/)/g, (e, t) => t ? "" : e), qe = (e) => {
331
+ }, qe = f(ie(), ".voltro"), Je = f(qe, "runtime-registry.json"), Ye = 3e4, Xe = () => {
332
+ let e = Math.random().toString(36).slice(2, 10);
333
+ return `${Je}.${process.pid}.${Date.now()}.${e}.tmp`;
334
+ }, Ze = async () => {
335
+ await A.mkdir(qe, { recursive: !0 });
336
+ }, Qe = async () => {
337
+ try {
338
+ let e = await A.readFile(Je, "utf8"), t = JSON.parse(e);
339
+ return t.version !== 1 || !Array.isArray(t.apps) ? {
340
+ version: 1,
341
+ apps: []
342
+ } : t;
343
+ } catch {
344
+ return {
345
+ version: 1,
346
+ apps: []
347
+ };
348
+ }
349
+ }, $e = async (e) => {
350
+ await Ze();
351
+ let t = Xe();
352
+ try {
353
+ await A.writeFile(t, JSON.stringify(e, null, 2), {
354
+ encoding: "utf8",
355
+ mode: 384
356
+ }), await A.rename(t, Je), await A.chmod(Je, 384).catch(() => {});
357
+ } catch (e) {
358
+ try {
359
+ await A.unlink(t);
360
+ } catch {}
361
+ throw e;
362
+ }
363
+ }, et = (e) => {
364
+ try {
365
+ return process.kill(e, 0), !0;
366
+ } catch {
367
+ return !1;
368
+ }
369
+ }, tt = (e) => {
370
+ let t = Date.now();
371
+ return e.filter((e) => et(e.pid) ? t - new Date(e.heartbeatAt).getTime() < Ye : !1);
372
+ }, nt = async () => {
373
+ let e = await Qe(), t = tt(e.apps);
374
+ if (t.length === e.apps.length) return e;
375
+ try {
376
+ await $e({
377
+ version: 1,
378
+ apps: t
379
+ });
380
+ } catch {}
381
+ return {
382
+ version: 1,
383
+ apps: t
384
+ };
385
+ }, rt = async (e) => {
386
+ let t = await Qe(), n = (/* @__PURE__ */ new Date()).toISOString(), r = t.apps.findIndex((t) => t.id === e.id), i = e.inspectToken ?? process.env.VOLTRO_INSPECT_TOKEN, a = {
387
+ ...e,
388
+ ...i !== void 0 && i !== "" ? { inspectToken: i } : {},
389
+ registeredAt: r >= 0 ? t.apps[r].registeredAt : n,
390
+ heartbeatAt: n
391
+ };
392
+ await $e({
393
+ version: 1,
394
+ apps: r >= 0 ? t.apps.map((e, t) => t === r ? a : e) : [...t.apps, a]
395
+ });
396
+ }, it = async (e) => {
397
+ try {
398
+ let t = await Qe(), n = t.apps.filter((t) => t.id !== e);
399
+ if (n.length === t.apps.length) return;
400
+ await $e({
401
+ version: 1,
402
+ apps: n
403
+ });
404
+ } catch {}
405
+ }, at = (e, t, n) => `${e}:${t}:${n}`, ot = (e) => e.replace(/\\"|"(?:[^"\\]|\\.)*"|(\/\/[^\n]*|\/\*[\s\S]*?\*\/)/g, (e, t) => t ? "" : e), st = (e) => {
332
406
  try {
333
407
  let t = f(e, "tsconfig.json");
334
408
  if (!O(t)) return [];
335
- let n = JSON.parse(Ke(M(t, "utf8"))).compilerOptions ?? {}, r = n.paths ?? {}, i = m(e, n.baseUrl ?? "."), a = [];
409
+ let n = JSON.parse(ot(j(t, "utf8"))).compilerOptions ?? {}, r = n.paths ?? {}, i = m(e, n.baseUrl ?? "."), a = [];
336
410
  for (let [e, t] of Object.entries(r)) {
337
411
  let n = t[0];
338
412
  if (!n) continue;
@@ -352,17 +426,17 @@ boundary, naming, anti-patterns) before editing.
352
426
  } catch {
353
427
  return [];
354
428
  }
355
- }, Je = (e) => {
429
+ }, ct = (e) => {
356
430
  let t = e;
357
431
  return t?.code === "ERR_MODULE_NOT_FOUND" || /Cannot find (package|module)/.test(String(t?.message ?? ""));
358
- }, Ye = async (e, t) => {
432
+ }, lt = async (e, t) => {
359
433
  try {
360
434
  return await t();
361
435
  } catch (t) {
362
- throw Je(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;
436
+ throw ct(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;
363
437
  }
364
- }, Xe = "// AUTO-GENERATED by Voltro — DO NOT EDIT.\n// Source: app.config.ts `env` (defineEnv). Regenerated on every `voltro dev` boot.\n", Ze = (e, t) => t ? `${e} | undefined` : e, Qe = (e, t) => Object.entries(e.vars).filter(([, e]) => t(e.access)).map(([e, t]) => `${t.description ? ` /** ${t.description} */\n` : ""} readonly ${e}: ${Ze(t.tsType, t.optional)}`).join("\n"), $e = async (e, t) => {
365
- let n = Qe(t, () => !0), r = `${Xe}
438
+ }, ut = "// AUTO-GENERATED by Voltro — DO NOT EDIT.\n// Source: app.config.ts `env` (defineEnv). Regenerated on every `voltro dev` boot.\n", dt = (e, t) => t ? `${e} | undefined` : e, ft = (e, t) => Object.entries(e.vars).filter(([, e]) => t(e.access)).map(([e, t]) => `${t.description ? ` /** ${t.description} */\n` : ""} readonly ${e}: ${dt(t.tsType, t.optional)}`).join("\n"), pt = async (e, t) => {
439
+ let n = ft(t, () => !0), r = `${ut}
366
440
  import '@voltro/env/server'
367
441
 
368
442
  declare module '@voltro/env/server' {
@@ -371,9 +445,9 @@ ${n.length > 0 ? n : " // (no variables declared)"}
371
445
  }
372
446
  }
373
447
  `;
374
- await ge(f(e, "env.generated.d.ts"), r, "utf8");
375
- }, et = async (e, t) => {
376
- let n = Qe(t, (e) => e === "public"), r = `${Xe}
448
+ await z(f(e, "env.generated.d.ts"), r, "utf8");
449
+ }, mt = async (e, t) => {
450
+ let n = ft(t, (e) => e === "public"), r = `${ut}
377
451
  import '@voltro/env/public'
378
452
 
379
453
  declare module '@voltro/env/public' {
@@ -382,9 +456,9 @@ ${n.length > 0 ? n : " // (no public variables declared)"}
382
456
  }
383
457
  }
384
458
  `, i = f(e, "src");
385
- await me(i, { recursive: !0 }), await ge(f(i, "voltro-env.d.ts"), r, "utf8");
386
- }, tt = async (e, t) => {
387
- let n = `${Xe}
459
+ await he(i, { recursive: !0 }), await z(f(i, "voltro-env.d.ts"), r, "utf8");
460
+ }, ht = async (e, t) => {
461
+ let n = `${ut}
388
462
  import { __installPublicEnv } from '@voltro/env/public'
389
463
 
390
464
  export const publicEnvValues = ${JSON.stringify(t, null, 2)} as const
@@ -392,14 +466,14 @@ export const publicEnvValues = ${JSON.stringify(t, null, 2)} as const
392
466
  // Set the browser/SSR-shared global the \`publicEnv\` accessor reads.
393
467
  __installPublicEnv(publicEnvValues)
394
468
  `;
395
- await me(e, { recursive: !0 }), await ge(f(e, "env.public.ts"), n, "utf8");
396
- }, nt = async (e) => {
397
- let t = le(e.rawEnv) ? e.rawEnv : void 0, n = await fe({
469
+ await he(e, { recursive: !0 }), await z(f(e, "env.public.ts"), n, "utf8");
470
+ }, gt = async (e) => {
471
+ let t = de(e.rawEnv) ? e.rawEnv : void 0, n = await pe({
398
472
  contract: t,
399
- resolveSecret: ne
400
- }), r = [...n.errors, ...se(t, e.appType)];
401
- if (r.length > 0) throw Error(ce(r));
402
- z(n.values), e.appType === "web" && pe(n.publicValues);
473
+ resolveSecret: re
474
+ }), r = [...n.errors, ...ce(t, e.appType)];
475
+ if (r.length > 0) throw Error(le(r));
476
+ ue(n.values), e.appType === "web" && me(n.publicValues);
403
477
  let i = t ? Object.keys(t.vars).length : 0;
404
478
  if (i > 0) {
405
479
  let r = Object.keys(n.publicValues).length;
@@ -411,20 +485,20 @@ __installPublicEnv(publicEnvValues)
411
485
  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 });
412
486
  }
413
487
  }
414
- return e.generateTypes && t && (e.appType === "api" ? await $e(e.root, t) : await et(e.root, t)), {
488
+ return e.generateTypes && t && (e.appType === "api" ? await pt(e.root, t) : await mt(e.root, t)), {
415
489
  resolved: n,
416
490
  contract: t
417
491
  };
418
- }, rt = (e) => {
419
- let t = oe(e.contract), n = (e.plugins ?? []).flatMap((e) => ue(e.name, e.declaredEnv)), r = e.includeFramework === !1 ? [] : ae, i = /* @__PURE__ */ new Set(), a = [];
492
+ }, _t = (e) => {
493
+ let t = se(e.contract), n = (e.plugins ?? []).flatMap((e) => R(e.name, e.declaredEnv)), r = e.includeFramework === !1 ? [] : oe, i = /* @__PURE__ */ new Set(), a = [];
420
494
  for (let e of [
421
495
  ...t,
422
496
  ...n,
423
497
  ...r
424
498
  ]) i.has(e.key) || (i.add(e.key), a.push(e));
425
499
  return a;
426
- }, it = (e, t, n = (e) => process.env[e]) => {
427
- let r = rt(t).map((e) => {
500
+ }, vt = (e, t, n = (e) => process.env[e]) => {
501
+ let r = _t(t).map((e) => {
428
502
  let t = n(e.key) !== void 0;
429
503
  return {
430
504
  ...e,
@@ -441,13 +515,13 @@ __installPublicEnv(publicEnvValues)
441
515
  missingRequired: r.filter((e) => e.required && !e.isSet && e.default === void 0).length
442
516
  }
443
517
  };
444
- }, at = (e, t) => de(rt({
518
+ }, yt = (e, t) => fe(_t({
445
519
  ...e,
446
520
  includeFramework: !1
447
521
  }), {
448
522
  includeFramework: e.includeFramework !== !1,
449
523
  ...t ? { header: t } : {}
450
- }), ot = () => {
524
+ }), bt = () => {
451
525
  let e = /* @__PURE__ */ new Map();
452
526
  return {
453
527
  get(t) {
@@ -483,20 +557,20 @@ __installPublicEnv(publicEnvValues)
483
557
  if (!Number.isFinite(n) || n <= 0) return null;
484
558
  let r = t[2].toLowerCase();
485
559
  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;
486
- }, st = (e, t = {}) => {
560
+ }, xt = (e, t = {}) => {
487
561
  let n = [e];
488
562
  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("|");
489
- }, ct = (e, t) => e.expiresAt > t, lt = (e, t) => e.expiresAt <= t && e.servableUntil > t, ut = T({ scope: "voltro:cli" }), dt = (e, t) => {
563
+ }, St = (e, t) => e.expiresAt > t, Ct = (e, t) => e.expiresAt <= t && e.servableUntil > t, wt = T({ scope: "voltro:cli" }), Tt = (e, t) => {
490
564
  if (t?.code !== "EACCES") return "";
491
565
  if (typeof process.getuid != "function") return " — permission denied";
492
566
  try {
493
- let t = P(e);
567
+ let t = N(e);
494
568
  return ` — permission denied: the file is owned by uid ${t.uid} (mode ${(t.mode & 511).toString(8)}) and this process is uid ${process.getuid()}. A container running as root with the workspace bind-mounted writes files the host user cannot read; run it as \`--user <your-uid>:<your-gid>\`, or delete the file and let the owning user recreate it.`;
495
569
  } catch {
496
570
  return " — permission denied (and the file could not be stat-ed either)";
497
571
  }
498
- }, ft = [], pt = (e) => {
499
- ft.length = 0;
572
+ }, Et = [], Dt = (e) => {
573
+ Et.length = 0;
500
574
  let t = e[1] && !e[1].startsWith("-") ? e[1] : void 0, n = t ? d(t) ? t : m(process.cwd(), t) : process.cwd(), r = [], i = n;
501
575
  for (;;) {
502
576
  r.push(i);
@@ -507,9 +581,9 @@ __installPublicEnv(publicEnvValues)
507
581
  for (let e of r) for (let t of [".env.local", ".env"]) {
508
582
  let n = m(e, t);
509
583
  if (O(n)) {
510
- ft.push(n);
584
+ Et.push(n);
511
585
  try {
512
- let e = M(n, "utf8");
586
+ let e = j(n, "utf8");
513
587
  for (let t of e.split(/\r?\n/)) {
514
588
  let e = t.trim();
515
589
  if (e === "" || e.startsWith("#")) continue;
@@ -519,11 +593,11 @@ __installPublicEnv(publicEnvValues)
519
593
  (i.startsWith("\"") && i.endsWith("\"") || i.startsWith("'") && i.endsWith("'")) && (i = i.slice(1, -1)), process.env[r] === void 0 && (process.env[r] = i);
520
594
  }
521
595
  } catch (e) {
522
- ut.warn(`failed to load env file (continuing)${dt(n, e)}`, { path: n }, e);
596
+ wt.warn(`failed to load env file (continuing)${Tt(n, e)}`, { path: n }, e);
523
597
  }
524
598
  }
525
599
  }
526
- }, mt = 500, ht = (e, t, n = {}) => {
600
+ }, Ot = 500, kt = (e, t, n = {}) => {
527
601
  if (e.length === 0) return () => {};
528
602
  let r = (e) => n.root ? p(n.root, e) : e, i = !1, a = (e) => {
529
603
  i || (i = !0, t.warn(`.env changed (${r(e)}) — hard-restarting: process.env is read once at boot, a reload would keep stale values`, { file: r(e) }), Promise.resolve().then(() => n.onBeforeRestart?.()).catch((e) => t.warn(".env restart: onBeforeRestart failed (continuing)", {}, e)).finally(() => {
@@ -541,47 +615,47 @@ __installPublicEnv(publicEnvValues)
541
615
  });
542
616
  }));
543
617
  };
544
- for (let t of e) te(t, { interval: mt }, (e, n) => {
618
+ for (let t of e) te(t, { interval: Ot }, (e, n) => {
545
619
  e.mtimeMs !== n.mtimeMs && a(t);
546
620
  });
547
621
  return t.info("watching .env files for changes", {
548
622
  files: e.map(r),
549
- intervalMs: mt
623
+ intervalMs: Ot
550
624
  }), () => {
551
625
  for (let t of e) F(t);
552
626
  };
553
- }, K = T({ scope: "vite" }), gt = /\x1b\[[0-9;]*m/g, _t = /^\s*\[?vite\]?\s*(\([a-z-]+\)\s*)?/, vt = (e) => e.replace(gt, "").replace(_t, "").trim(), yt = /proxy error/i, bt = [
627
+ }, K = T({ scope: "vite" }), At = /\x1b\[[0-9;]*m/g, jt = /^\s*\[?vite\]?\s*(\([a-z-]+\)\s*)?/, Mt = (e) => e.replace(At, "").replace(jt, "").trim(), Nt = /proxy error/i, Pt = [
554
628
  "ECONNREFUSED",
555
629
  "ECONNRESET",
556
630
  "ECONNABORTED",
557
631
  "EPIPE",
558
632
  "ETIMEDOUT"
559
- ], xt = (e, t = 0) => {
633
+ ], Ft = (e, t = 0) => {
560
634
  if (e == null || t > 5) return !1;
561
635
  let n = e;
562
- return typeof n.code == "string" && bt.includes(n.code) || typeof n.message == "string" && bt.some((e) => n.message.includes(e)) || Array.isArray(n.errors) && n.errors.some((e) => xt(e, t + 1)) ? !0 : xt(n.cause, t + 1);
563
- }, St = 4e3, Ct = () => {
636
+ return typeof n.code == "string" && Pt.includes(n.code) || typeof n.message == "string" && Pt.some((e) => n.message.includes(e)) || Array.isArray(n.errors) && n.errors.some((e) => Ft(e, t + 1)) ? !0 : Ft(n.cause, t + 1);
637
+ }, It = 4e3, Lt = () => {
564
638
  let e = /* @__PURE__ */ new Set(), t = 0, n = {
565
639
  hasWarned: !1,
566
640
  info: (e) => {
567
- let t = vt(e);
641
+ let t = Mt(e);
568
642
  t.length !== 0 && K.info(t);
569
643
  },
570
644
  warn: (e) => {
571
645
  n.hasWarned = !0;
572
- let t = vt(e);
646
+ let t = Mt(e);
573
647
  t.length !== 0 && K.warn(t);
574
648
  },
575
649
  warnOnce: (t) => {
576
- let r = vt(t);
650
+ let r = Mt(t);
577
651
  e.has(r) || (e.add(r), n.hasWarned = !0, r.length !== 0 && K.warn(r));
578
652
  },
579
653
  error: (e, n) => {
580
- let r = vt(e), i = n?.error;
654
+ let r = Mt(e), i = n?.error;
581
655
  if (r.length !== 0) {
582
- if (yt.test(r) && xt(i)) {
656
+ if (Nt.test(r) && Ft(i)) {
583
657
  let e = Date.now();
584
- e - t > St && (t = e, K.info("waiting for api — proxy upstream not accepting connections yet (still starting?)"));
658
+ e - t > It && (t = e, K.info("waiting for api — proxy upstream not accepting connections yet (still starting?)"));
585
659
  return;
586
660
  }
587
661
  K.error(r, {}, i);
@@ -591,12 +665,12 @@ __installPublicEnv(publicEnvValues)
591
665
  hasErrorLogged: (e) => !1
592
666
  };
593
667
  return n;
594
- }, wt = (e = process.env) => {
668
+ }, Rt = (e = process.env) => {
595
669
  let t = e.VOLTRO_DEV_SSR_COMPILE_CONCURRENCY;
596
670
  if (t === void 0 || t.trim() === "") return 4;
597
671
  let n = Number(t);
598
672
  return Number.isFinite(n) && n >= 1 ? Math.floor(n) : 4;
599
- }, Tt = (e) => {
673
+ }, zt = (e) => {
600
674
  let t = Math.max(1, Math.floor(e)), n = 0, r = [], i = () => n < t ? (n++, Promise.resolve()) : new Promise((e) => r.push(e)), a = () => {
601
675
  let e = r.shift();
602
676
  e ? e() : n--;
@@ -614,8 +688,8 @@ __installPublicEnv(publicEnvValues)
614
688
  return n;
615
689
  }
616
690
  };
617
- }, Et = (e) => {
618
- let t = Tt(e.limit), n = /* @__PURE__ */ new Map(), r = /* @__PURE__ */ new Set();
691
+ }, Bt = (e) => {
692
+ let t = zt(e.limit), n = /* @__PURE__ */ new Map(), r = /* @__PURE__ */ new Set();
619
693
  return {
620
694
  load: (i, a) => {
621
695
  if (r.has(i)) return a();
@@ -645,7 +719,7 @@ __installPublicEnv(publicEnvValues)
645
719
  return r.size;
646
720
  }
647
721
  };
648
- }, Dt = (e) => {
722
+ }, Vt = (e) => {
649
723
  let t = [];
650
724
  for (let n of e.split("/").filter(Boolean)) n.startsWith("[[...") && n.endsWith("]]") ? t.push({
651
725
  name: n.slice(5, -2),
@@ -661,12 +735,12 @@ __installPublicEnv(publicEnvValues)
661
735
  optional: !1
662
736
  });
663
737
  return t;
664
- }, Ot = (e) => e.replace(/-([a-z0-9])/g, (e, t) => t.toUpperCase()), kt = async (e) => {
738
+ }, Ht = (e) => e.replace(/-([a-z0-9])/g, (e, t) => t.toUpperCase()), Ut = async (e) => {
665
739
  let t = m(e);
666
740
  for (let e = 0; e < 4; e++) {
667
741
  let e = f(t, "project.json");
668
742
  if (O(e)) try {
669
- let n = await j.readFile(e, "utf8");
743
+ let n = await A.readFile(e, "utf8");
670
744
  return {
671
745
  projectDir: t,
672
746
  manifest: JSON.parse(n)
@@ -679,8 +753,8 @@ __installPublicEnv(publicEnvValues)
679
753
  t = n;
680
754
  }
681
755
  return null;
682
- }, At = async (e) => {
683
- let t = await kt(e);
756
+ }, Wt = async (e) => {
757
+ let t = await Ut(e);
684
758
  if (!t) return [];
685
759
  let { projectDir: n, manifest: r } = t, i = l(e), a = r.apps ?? {}, o = [];
686
760
  for (let [e, t] of Object.entries(a)) {
@@ -692,20 +766,20 @@ __installPublicEnv(publicEnvValues)
692
766
  let { pages: e } = await Q(r);
693
767
  a = e.map((e) => ({
694
768
  pattern: e.pattern,
695
- params: Dt(e.pattern)
769
+ params: Vt(e.pattern)
696
770
  }));
697
771
  } catch {
698
772
  continue;
699
773
  }
700
774
  o.push({
701
- key: Ot(e),
775
+ key: Ht(e),
702
776
  origin: `http://localhost:${t.port}`,
703
777
  ...typeof t.origin == "string" && t.origin.length > 0 ? { prodOrigin: t.origin } : {},
704
778
  routes: a
705
779
  });
706
780
  }
707
781
  return o;
708
- }, jt = (e) => {
782
+ }, Gt = (e) => {
709
783
  if (e.params.length === 0) return `'${e.pattern}'`;
710
784
  let t = e.pattern;
711
785
  for (let n of e.params) {
@@ -713,21 +787,21 @@ __installPublicEnv(publicEnvValues)
713
787
  t = t.replace(e, r);
714
788
  }
715
789
  return "`" + t + "`";
716
- }, Mt = (e) => e.params.length === 0 ? "EmptyParams" : `{ ${e.params.map((e) => {
790
+ }, Kt = (e) => e.params.length === 0 ? "EmptyParams" : `{ ${e.params.map((e) => {
717
791
  let t = "string";
718
792
  return e.optional ? `readonly ${e.name}?: ${t}` : `readonly ${e.name}: ${t}`;
719
- }).join("; ")} }`, Nt = (e, t, n) => {
720
- let r = Mt(e), i = jt(e), a = t ? "VoltroExternalUrl" : "VoltroRouteUrl", o = t && n ? `${n} + ` : "";
793
+ }).join("; ")} }`, qt = (e, t, n) => {
794
+ let r = Kt(e), i = Gt(e), a = t ? "VoltroExternalUrl" : "VoltroRouteUrl", o = t && n ? `${n} + ` : "";
721
795
  return e.params.length === 0 ? `() => (${o}${i}) as ${a}` : `({ ${e.params.map((e) => e.name).join(", ")} }: ${r}) => (${o}${i}) as ${a}`;
722
- }, Pt = (e) => `{\n${[...e].sort((e, t) => e.pattern.localeCompare(t.pattern)).map((e) => ` ${JSON.stringify(e.pattern)}: ${Nt(e, !1)},`).join("\n")}\n}`, Ft = (e, t) => {
796
+ }, Jt = (e) => `{\n${[...e].sort((e, t) => e.pattern.localeCompare(t.pattern)).map((e) => ` ${JSON.stringify(e.pattern)}: ${qt(e, !1)},`).join("\n")}\n}`, Yt = (e, t) => {
723
797
  if (e.routes.length === 0) return ` ${e.key}: {} as Record<string, never>,`;
724
- 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)}: ${Nt(e, !0, i)},`);
798
+ 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)}: ${qt(e, !0, i)},`);
725
799
  return ` ${e.key}: {\n${a.join("\n")}\n },`;
726
- }, It = async (e) => {
800
+ }, Xt = async (e) => {
727
801
  let t = e.pages.map((e) => ({
728
802
  pattern: e.pattern,
729
- params: Dt(e.pattern)
730
- })), n = await At(e.appRoot), r = [
803
+ params: Vt(e.pattern)
804
+ })), n = await Wt(e.appRoot), r = [
731
805
  "// THIS FILE IS GENERATED — DO NOT EDIT BY HAND.",
732
806
  "// Re-emitted by `voltro dev` whenever `src/pages/**` changes.",
733
807
  "// Type-safe route builders consumed by <Link to={...}>.",
@@ -736,20 +810,20 @@ __installPublicEnv(publicEnvValues)
736
810
  "",
737
811
  "type EmptyParams = Record<string, never>",
738
812
  ""
739
- ].join("\n"), i = e.mode ?? "dev", a = `${r}\n${`export const routes = ${Pt(t)} as const\n`}\n${n.length === 0 ? "export const siblingApps = {} as Record<string, never>\n" : `export const siblingApps = {\n${n.map((e) => Ft(e, i)).join("\n")}\n} as const\n`}`, o = f(e.appRoot, ".framework", "routes.generated.ts");
740
- await j.mkdir(u(o), { recursive: !0 });
813
+ ].join("\n"), i = e.mode ?? "dev", a = `${r}\n${`export const routes = ${Jt(t)} as const\n`}\n${n.length === 0 ? "export const siblingApps = {} as Record<string, never>\n" : `export const siblingApps = {\n${n.map((e) => Yt(e, i)).join("\n")}\n} as const\n`}`, o = f(e.appRoot, ".framework", "routes.generated.ts");
814
+ await A.mkdir(u(o), { recursive: !0 });
741
815
  let s = null;
742
816
  try {
743
- s = await j.readFile(o, "utf8");
817
+ s = await A.readFile(o, "utf8");
744
818
  } catch {}
745
819
  return s === a ? {
746
820
  path: o,
747
821
  wrote: !1
748
- } : (await j.writeFile(o, a, "utf8"), {
822
+ } : (await A.writeFile(o, a, "utf8"), {
749
823
  path: o,
750
824
  wrote: !0
751
825
  });
752
- }, Lt = 256, Rt = (e = Lt) => {
826
+ }, Zt = 256, Qt = (e = Zt) => {
753
827
  let t = [], n = /* @__PURE__ */ new Set();
754
828
  return {
755
829
  emit(r, i) {
@@ -772,27 +846,27 @@ __installPublicEnv(publicEnvValues)
772
846
  return t.slice();
773
847
  }
774
848
  };
775
- }, zt = (e) => `event: ${e.channel}\ndata: ${JSON.stringify(e)}\n\n`, Bt = () => `: keep-alive ${Date.now()}\n\n`, Vt = {
849
+ }, $t = (e) => `event: ${e.channel}\ndata: ${JSON.stringify(e)}\n\n`, en = () => `: keep-alive ${Date.now()}\n\n`, tn = {
776
850
  trace: 0,
777
851
  debug: 1,
778
852
  info: 2,
779
853
  warn: 3,
780
854
  error: 4,
781
855
  fatal: 5
782
- }, Ht = 2e3, Ut = 200, Wt = class {
856
+ }, nn = 2e3, rn = 200, an = class {
783
857
  capacity;
784
858
  buffer = [];
785
- constructor(e = Ht) {
859
+ constructor(e = nn) {
786
860
  this.capacity = e;
787
861
  }
788
862
  append(e) {
789
863
  this.buffer.push(e), this.buffer.length > this.capacity && this.buffer.shift();
790
864
  }
791
865
  query(e = {}) {
792
- let t = e.since ?? 0, n = e.until ?? Date.now(), r = Math.min(e.max ?? Ut, this.capacity), i = e.minLevel === void 0 ? Vt.trace : Vt[e.minLevel], a = e.scope?.toLowerCase(), o = e.source, s = e.filter?.toLowerCase(), c = e.traceId, l = [];
866
+ let t = e.since ?? 0, n = e.until ?? Date.now(), r = Math.min(e.max ?? rn, this.capacity), i = e.minLevel === void 0 ? tn.trace : tn[e.minLevel], a = e.scope?.toLowerCase(), o = e.source, s = e.filter?.toLowerCase(), c = e.traceId, l = [];
793
867
  for (let e = this.buffer.length - 1; e >= 0 && l.length < r; e--) {
794
868
  let r = this.buffer[e];
795
- r.ts < t || r.ts > n || Vt[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);
869
+ r.ts < t || r.ts > n || tn[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);
796
870
  }
797
871
  return l.reverse();
798
872
  }
@@ -805,7 +879,7 @@ __installPublicEnv(publicEnvValues)
805
879
  clear() {
806
880
  this.buffer = [];
807
881
  }
808
- }, Gt = null, Kt = () => (Gt === null && (Gt = new Wt()), Gt), qt = (e) => {
882
+ }, on = null, sn = () => (on === null && (on = new an()), on), cn = (e) => {
809
883
  if (typeof e == "string") return e;
810
884
  if (e instanceof Error) return e.message;
811
885
  try {
@@ -813,18 +887,18 @@ __installPublicEnv(publicEnvValues)
813
887
  } catch {
814
888
  return String(e);
815
889
  }
816
- }, Jt = (e) => {
890
+ }, ln = (e) => {
817
891
  let t = {
818
892
  log: console.log.bind(console),
819
893
  info: console.info.bind(console),
820
894
  warn: console.warn.bind(console),
821
895
  error: console.error.bind(console),
822
896
  debug: console.debug.bind(console)
823
- }, n = Kt(), r = !1, i = (i) => (...a) => {
897
+ }, n = sn(), r = !1, i = (i) => (...a) => {
824
898
  if (t[i](...a), !r) {
825
899
  r = !0;
826
900
  try {
827
- let t = a.length > 0 ? qt(a[0]) : "", r = t.length > 500 ? t.slice(0, 500) + "…" : t, o = L();
901
+ let t = a.length > 0 ? cn(a[0]) : "", r = t.length > 500 ? t.slice(0, 500) + "…" : t, o = ne();
828
902
  e.emit("log", {
829
903
  level: i,
830
904
  message: r,
@@ -862,7 +936,7 @@ __installPublicEnv(publicEnvValues)
862
936
  argsCount: 1,
863
937
  ...t.scope === void 0 ? {} : { scope: t.scope }
864
938
  });
865
- let a = L(), o = a !== void 0 && t.fields.traceId === void 0 ? {
939
+ let a = ne(), o = a !== void 0 && t.fields.traceId === void 0 ? {
866
940
  ...t.fields,
867
941
  traceId: a.traceId
868
942
  } : t.fields;
@@ -882,24 +956,24 @@ __installPublicEnv(publicEnvValues)
882
956
  return () => {
883
957
  console.log = t.log, console.info = t.info, console.warn = t.warn, console.error = t.error, console.debug = t.debug, a();
884
958
  };
885
- }, Yt = 2e3, Xt = 8, Zt = 1e3, Qt = 200, q = (e, t) => e.length > t ? `${e.slice(0, t)}…` : e, $t = (e) => {
959
+ }, un = 2e3, dn = 8, fn = 1e3, pn = 200, q = (e, t) => e.length > t ? `${e.slice(0, t)}…` : e, mn = (e) => {
886
960
  switch (e) {
887
961
  case "error": return "error";
888
962
  case "warn": return "warn";
889
963
  case "debug": return "debug";
890
964
  default: return "info";
891
965
  }
892
- }, en = T({ scope: "client" }), tn = (e, t) => {
966
+ }, hn = T({ scope: "client" }), gn = (e, t) => {
893
967
  let n;
894
968
  try {
895
969
  n = JSON.parse(e);
896
970
  } catch {
897
- return nn(400, { error: "invalid JSON body" });
971
+ return _n(400, { error: "invalid JSON body" });
898
972
  }
899
- if (typeof n != "object" || !n) return nn(400, { error: "body must be a JSON object" });
973
+ if (typeof n != "object" || !n) return _n(400, { error: "body must be a JSON object" });
900
974
  let r = n;
901
- if (!Array.isArray(r.entries)) return nn(400, { error: "entries must be an array" });
902
- let i = typeof r.app == "string" ? q(r.app, 120) : void 0, a = typeof r.page == "string" ? q(r.page, 200) : void 0, o = typeof r.ua == "string" ? q(r.ua, 200) : void 0, s = r.entries.slice(0, Qt), c = 0;
975
+ if (!Array.isArray(r.entries)) return _n(400, { error: "entries must be an array" });
976
+ let i = typeof r.app == "string" ? q(r.app, 120) : void 0, a = typeof r.page == "string" ? q(r.page, 200) : void 0, o = typeof r.ua == "string" ? q(r.ua, 200) : void 0, s = r.entries.slice(0, pn), c = 0;
903
977
  for (let e of s) {
904
978
  if (typeof e != "object" || !e) continue;
905
979
  let n = e;
@@ -910,7 +984,7 @@ __installPublicEnv(publicEnvValues)
910
984
  "warn",
911
985
  "error",
912
986
  "debug"
913
- ].includes(n.level) ? n.level : "log", s = typeof n.ts == "number" && Number.isFinite(n.ts) ? n.ts : Date.now(), l = q(n.message, Yt), u = Array.isArray(n.args) ? n.args.slice(0, Xt).filter((e) => typeof e == "string").map((e) => q(e, Zt)) : void 0, d = typeof n.stack == "string" ? q(n.stack, Yt) : void 0;
987
+ ].includes(n.level) ? n.level : "log", s = typeof n.ts == "number" && Number.isFinite(n.ts) ? n.ts : Date.now(), l = q(n.message, un), u = Array.isArray(n.args) ? n.args.slice(0, dn).filter((e) => typeof e == "string").map((e) => q(e, fn)) : void 0, d = typeof n.stack == "string" ? q(n.stack, un) : void 0;
914
988
  t.emit("clientLog", {
915
989
  ts: s,
916
990
  level: r,
@@ -925,41 +999,41 @@ __installPublicEnv(publicEnvValues)
925
999
  ...i === void 0 ? {} : { app: i },
926
1000
  ...a === void 0 ? {} : { page: a },
927
1001
  ...u !== void 0 && u.length > 0 ? { args: u } : {}
928
- }, p = $t(r);
929
- (p === "error" || p === "warn") && d !== void 0 ? en[p](l, f, { stack: d }) : en[p](l, {
1002
+ }, p = mn(r);
1003
+ (p === "error" || p === "warn") && d !== void 0 ? hn[p](l, f, { stack: d }) : hn[p](l, {
930
1004
  ...f,
931
1005
  ...d === void 0 ? {} : { stack: d }
932
1006
  }), c++;
933
1007
  }
934
- return nn(202, {
1008
+ return _n(202, {
935
1009
  accepted: c,
936
1010
  dropped: r.entries.length - c
937
1011
  });
938
- }, nn = (e, t) => ({
1012
+ }, _n = (e, t) => ({
939
1013
  status: e,
940
1014
  contentType: "application/json; charset=utf-8",
941
1015
  body: JSON.stringify(t)
942
- }), rn = "/_voltro/inspect/clientLog", an = [
1016
+ }), vn = "/_voltro/inspect/clientLog", yn = [
943
1017
  "trace",
944
1018
  "debug",
945
1019
  "info",
946
1020
  "warn",
947
1021
  "error",
948
1022
  "fatal"
949
- ], on = {
1023
+ ], bn = {
950
1024
  trace: "TRACE",
951
1025
  debug: "DEBUG",
952
1026
  info: "INFO ",
953
1027
  warn: "WARN ",
954
1028
  error: "ERROR",
955
1029
  fatal: "FATAL"
956
- }, sn = (e) => an.includes(e), cn = (e, t, n = {}) => {
1030
+ }, xn = (e) => yn.includes(e), Sn = (e, t, n = {}) => {
957
1031
  if (i()) return {
958
1032
  status: 503,
959
1033
  contentType: "application/json",
960
1034
  body: JSON.stringify({ error: "inspect disabled (VOLTRO_INSPECT=off)" })
961
1035
  };
962
- let r = o(n);
1036
+ let r = o(n, "GET");
963
1037
  if (!r.ok) return {
964
1038
  status: 401,
965
1039
  contentType: "application/json",
@@ -984,7 +1058,7 @@ __installPublicEnv(publicEnvValues)
984
1058
  Number.isFinite(e) && e > 0 && (c.max = Math.floor(e));
985
1059
  }
986
1060
  let f = s.get("level");
987
- f !== null && sn(f) && (c.minLevel = f);
1061
+ f !== null && xn(f) && (c.minLevel = f);
988
1062
  let p = s.get("source");
989
1063
  (p === "server" || p === "client") && (c.source = p);
990
1064
  let m = s.get("scope");
@@ -997,7 +1071,7 @@ __installPublicEnv(publicEnvValues)
997
1071
  if ((s.get("format") ?? "json") === "text") return {
998
1072
  status: 200,
999
1073
  contentType: "text/plain; charset=utf-8",
1000
- body: _.map(ln).join("\n") + (_.length > 0 ? "\n" : "")
1074
+ body: _.map(Cn).join("\n") + (_.length > 0 ? "\n" : "")
1001
1075
  };
1002
1076
  let v = {
1003
1077
  capturedAt: Date.now(),
@@ -1011,37 +1085,40 @@ __installPublicEnv(publicEnvValues)
1011
1085
  contentType: "application/json; charset=utf-8",
1012
1086
  body: JSON.stringify(v)
1013
1087
  };
1014
- }, ln = (e) => {
1015
- 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 = dn(e.fields);
1016
- return `${n}:${r}:${i}.${a} ${on[e.level]} ${o} ${e.message}${s}`;
1017
- }, un = 80, dn = (e) => {
1088
+ }, Cn = (e) => {
1089
+ 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 = Tn(e.fields);
1090
+ return `${n}:${r}:${i}.${a} ${bn[e.level]} ${o} ${e.message}${s}`;
1091
+ }, wn = 80, Tn = (e) => {
1018
1092
  let t = Object.entries(e);
1019
1093
  if (t.length === 0) return "";
1020
1094
  let n = [];
1021
1095
  for (let [e, r] of t) {
1022
1096
  if (r === void 0) continue;
1023
- let t = fn(r);
1097
+ let t = En(r);
1024
1098
  n.push(`${e}=${t}`);
1025
1099
  }
1026
1100
  return n.length > 0 ? " " + n.join(" ") : "";
1027
- }, fn = (e) => {
1101
+ }, En = (e) => {
1028
1102
  if (typeof e == "string") {
1029
- let t = e.length > un ? e.slice(0, un) + "…" : e;
1103
+ let t = e.length > wn ? e.slice(0, wn) + "…" : e;
1030
1104
  return /[\s=]/.test(t) ? `"${t.replace(/"/g, "\\\"")}"` : t;
1031
1105
  }
1032
1106
  if (e === null) return "null";
1033
1107
  if (typeof e == "number" || typeof e == "boolean") return String(e);
1034
1108
  try {
1035
1109
  let t = JSON.stringify(e);
1036
- return t.length > un ? t.slice(0, un) + "…" : t;
1110
+ return t.length > wn ? t.slice(0, wn) + "…" : t;
1037
1111
  } catch {
1038
1112
  return "[unserialisable]";
1039
1113
  }
1040
- }, pn = "/_voltro/inspect/logs", mn = (e, t, n) => {
1114
+ }, Dn = "/_voltro/inspect/logs", On = (e, t, n) => {
1041
1115
  if (t.headers.authorization !== void 0) return !1;
1042
1116
  let { token: r } = n;
1043
- return r === void 0 || r === "" || !n.isLoopback(n.target) ? !1 : (e.setHeader("authorization", `Bearer ${r}`), !0);
1044
- }, hn = [{
1117
+ if (r === void 0 || r === "" || !n.isLoopback(n.target)) return !1;
1118
+ e.setHeader("authorization", `Bearer ${r}`);
1119
+ let i = n.writeToken;
1120
+ return i !== void 0 && i !== "" && t.headers["x-voltro-inspect-write"] === void 0 && e.setHeader("x-voltro-inspect-write", i), !0;
1121
+ }, kn = [{
1045
1122
  match: (e) => typeof e == "string" && e.startsWith("[BABEL] Note: The code generator has deoptimised"),
1046
1123
  handle: (e, t) => {
1047
1124
  let n = e[0], r = n.match(/deoptimised the styling of (.+?) as it exceeds the max of (\d+\w*B)\.?/);
@@ -1053,13 +1130,13 @@ __installPublicEnv(publicEnvValues)
1053
1130
  });
1054
1131
  } else t.info(n);
1055
1132
  }
1056
- }], gn = () => {
1133
+ }], An = () => {
1057
1134
  let e = {
1058
1135
  warn: console.warn.bind(console),
1059
1136
  error: console.error.bind(console)
1060
1137
  }, t = T({ scope: "babel" }), n = !1, r = (r) => (...i) => {
1061
1138
  if (!n) {
1062
- for (let e of hn) if (e.match(i[0])) {
1139
+ for (let e of kn) if (e.match(i[0])) {
1063
1140
  n = !0;
1064
1141
  try {
1065
1142
  e.handle(i, t);
@@ -1074,7 +1151,7 @@ __installPublicEnv(publicEnvValues)
1074
1151
  return console.warn = r("warn"), console.error = r("error"), () => {
1075
1152
  console.warn = e.warn, console.error = e.error;
1076
1153
  };
1077
- }, _n = {
1154
+ }, jn = {
1078
1155
  loader: "it runs on the server, and the router caches its result per route + params",
1079
1156
  renderMode: "it picks the server render strategy",
1080
1157
  dynamic: "it picks the server render strategy",
@@ -1085,7 +1162,7 @@ __installPublicEnv(publicEnvValues)
1085
1162
  cacheInvalidatesOn: "it wires this page into the ISR cache invalidator",
1086
1163
  interactive: "it decides how much client JS the server ships",
1087
1164
  tenantAware: "it is part of the server-side cache key"
1088
- }, vn = Object.keys(_n), yn = (e) => n.test(e), bn = (e) => e.replace(/page\.tsx$/, "page.test.tsx"), xn = "virtual:voltro-route-refresh", Sn = `\0${xn}`, Cn = /(?:^|&)(raw|url|inline|worker|sharedworker|direct)(?:&|=|$)/, wn = () => `
1165
+ }, Mn = Object.keys(jn), Nn = (e) => n.test(e), Pn = (e) => e.replace(/page\.tsx$/, "page.test.tsx"), Fn = "virtual:voltro-route-refresh", In = `\0${Fn}`, Ln = /(?:^|&)(raw|url|inline|worker|sharedworker|direct)(?:&|=|$)/, Rn = () => `
1089
1166
  // GENERATED by @voltro/cli — the \`voltro dev\` route Fast Refresh runtime.
1090
1167
 
1091
1168
  /** Mirrors react-refresh's own \`isLikelyComponentType\` closely enough for the
@@ -1114,11 +1191,11 @@ const stableForm = (value) => {
1114
1191
  * readers (\`build.ts\` prerender, \`webDev.ts\` dev SSR, \`start.ts\`). A change to
1115
1192
  * one of THESE cannot be hot-applied: the server already ran with the old
1116
1193
  * value. Everything else a page exports is plain client-side data. */
1117
- const serverRelevantExports = ${JSON.stringify(vn)}
1194
+ const serverRelevantExports = ${JSON.stringify(Mn)}
1118
1195
 
1119
1196
  /** Name → the server step that already consumed it, so the reload message can
1120
1197
  * say WHY rather than just WHAT. Injected from the same single source. */
1121
- const serverExportEffect = ${JSON.stringify(_n)}
1198
+ const serverExportEffect = ${JSON.stringify(jn)}
1122
1199
 
1123
1200
  /** The reason \`name\` forces a reload, for the console line. */
1124
1201
  export const serverEffectOf = (name) =>
@@ -1161,7 +1238,7 @@ export const routeUpdateNeedsReload = (prevExports, nextExports) => {
1161
1238
  const previousHook = globalThis.__getReactRefreshIgnoredExports
1162
1239
  globalThis.__getReactRefreshIgnoredExports = (args) =>
1163
1240
  ignoredExports.get(args.id) ?? previousHook?.(args) ?? []
1164
- `, Tn = (e) => `
1241
+ `, zn = (e) => `
1165
1242
  if (import.meta.hot) {
1166
1243
  // Self-import to read our OWN exports, the same technique the react plugin
1167
1244
  // uses; the namespace is only complete after evaluation, hence the promise.
@@ -1188,45 +1265,45 @@ import {
1188
1265
  registerRouteModule as __voltro_registerRouteModule,
1189
1266
  routeUpdateNeedsReload as __voltro_routeUpdateNeedsReload,
1190
1267
  serverEffectOf as __voltro_serverEffect,
1191
- } from '${xn}'
1192
- `, En = (e) => e.replace(/\\/g, "/"), Dn = (n, r) => {
1193
- let [i = "", a] = En(n).split("?");
1194
- if (!i.endsWith(".tsx") || a !== void 0 && Cn.test(a)) return !1;
1195
- let o = En(r).replace(/\/$/, "");
1268
+ } from '${Fn}'
1269
+ `, Bn = (e) => e.replace(/\\/g, "/"), Vn = (n, r) => {
1270
+ let [i = "", a] = Bn(n).split("?");
1271
+ if (!i.endsWith(".tsx") || a !== void 0 && Ln.test(a)) return !1;
1272
+ let o = Bn(r).replace(/\/$/, "");
1196
1273
  return i.startsWith(`${o}/`) ? t.test(i) || e.has(i.slice(i.lastIndexOf("/") + 1)) : !1;
1197
- }, On = (e, t, n) => Dn(t, n) ? `${e}${Tn(En(t).split("?")[0] ?? t)}` : null, kn = (e) => ({
1274
+ }, Hn = (e, t, n) => Vn(t, n) ? `${e}${zn(Bn(t).split("?")[0] ?? t)}` : null, Un = (e) => ({
1198
1275
  name: "voltro:route-fast-refresh",
1199
1276
  enforce: "pre",
1200
- resolveId: (e) => e === "virtual:voltro-route-refresh" ? Sn : void 0,
1201
- load: (e) => e === Sn ? wn() : void 0,
1277
+ resolveId: (e) => e === "virtual:voltro-route-refresh" ? In : void 0,
1278
+ load: (e) => e === In ? Rn() : void 0,
1202
1279
  transform: (t, n, r) => {
1203
1280
  if (r?.ssr === !0) return null;
1204
- let i = On(t, n, e);
1281
+ let i = Hn(t, n, e);
1205
1282
  return i === null ? null : {
1206
1283
  code: i,
1207
1284
  map: null
1208
1285
  };
1209
1286
  }
1210
- }), An = [
1287
+ }), Wn = [
1211
1288
  "static",
1212
1289
  "spa",
1213
1290
  "ssr",
1214
1291
  "isr"
1215
- ], jn = (e) => typeof e == "string" && An.includes(e), Mn = An.map((e) => `'${e}'`).join(" | "), Nn = (e, t) => `[voltro] ${e}: unknown renderMode '${t}'.\n Valid values: ${Mn}.${t === "client" || t === "csr" || t === "browser" ? "\n A page that renders only in the browser is 'spa': it is skipped by the prerender and mounts on the client. If its route has a layout, that layout still renders server-side as an SSR shell." : t === "server" || t === "dynamic" ? "\n A page rendered per request is 'ssr'." : t === "ssg" || t === "prerender" ? "\n A page rendered once at build time is 'static' (the default)." : ""}`, Pn = class extends Error {
1292
+ ], Gn = (e) => typeof e == "string" && Wn.includes(e), Kn = Wn.map((e) => `'${e}'`).join(" | "), qn = (e, t) => `[voltro] ${e}: unknown renderMode '${t}'.\n Valid values: ${Kn}.${t === "client" || t === "csr" || t === "browser" ? "\n A page that renders only in the browser is 'spa': it is skipped by the prerender and mounts on the client. If its route has a layout, that layout still renders server-side as an SSR shell." : t === "server" || t === "dynamic" ? "\n A page rendered per request is 'ssr'." : t === "ssg" || t === "prerender" ? "\n A page rendered once at build time is 'static' (the default)." : ""}`, Jn = class extends Error {
1216
1293
  page;
1217
1294
  value;
1218
1295
  name = "InvalidRenderModeError";
1219
1296
  constructor(e, t) {
1220
- super(Nn(e, t)), this.page = e, this.value = t;
1297
+ super(qn(e, t)), this.page = e, this.value = t;
1221
1298
  }
1222
- }, Fn = (e, t = "<page>") => {
1299
+ }, Yn = (e, t = "<page>") => {
1223
1300
  if (e.renderMode !== void 0 && e.renderMode !== null) {
1224
- if (!jn(e.renderMode)) throw new Pn(t, String(e.renderMode));
1301
+ if (!Gn(e.renderMode)) throw new Jn(t, String(e.renderMode));
1225
1302
  return e.renderMode;
1226
1303
  }
1227
1304
  return e.dynamic === "force-dynamic" ? "ssr" : (e.dynamic, "static");
1228
- }, In = (e, t = "<page>") => ({
1229
- renderMode: Fn(e, t),
1305
+ }, Xn = (e, t = "<page>") => ({
1306
+ renderMode: Yn(e, t),
1230
1307
  tenantAware: e.tenantAware === !0,
1231
1308
  revalidateMs: G(e.revalidate),
1232
1309
  staleWhileRevalidateMs: G(e.staleWhileRevalidate) ?? 0,
@@ -1235,10 +1312,10 @@ import {
1235
1312
  hasLoader: typeof e.loader == "function",
1236
1313
  hasMeta: e.meta != null,
1237
1314
  hasGetStaticPaths: typeof e.getStaticPaths == "function"
1238
- }), Ln = /export\s+const\s+renderMode\s*(?::[^=]+)?=\s*['"]([^'"]*)['"]/, Rn = (e) => Ln.exec(e)?.[1] ?? null, zn = /export\s*\{([^}]*)\}\s*from\s*['"]([^'"]+)['"]/g, Bn = (e) => {
1239
- zn.lastIndex = 0;
1315
+ }), Zn = /export\s+const\s+renderMode\s*(?::[^=]+)?=\s*['"]([^'"]*)['"]/, Qn = (e) => Zn.exec(e)?.[1] ?? null, $n = /export\s*\{([^}]*)\}\s*from\s*['"]([^'"]+)['"]/g, er = (e) => {
1316
+ $n.lastIndex = 0;
1240
1317
  let t;
1241
- for (; (t = zn.exec(e)) !== null;) {
1318
+ for (; (t = $n.exec(e)) !== null;) {
1242
1319
  let e = t[2];
1243
1320
  if (e.startsWith(".")) for (let n of t[1].split(",")) {
1244
1321
  let t = n.lastIndexOf(" as ");
@@ -1246,110 +1323,36 @@ import {
1246
1323
  }
1247
1324
  }
1248
1325
  return null;
1249
- }, Vn = /export\s*\{([^}]*)\}/g, Hn = (e) => {
1326
+ }, tr = /export\s*\{([^}]*)\}/g, nr = (e) => {
1250
1327
  if (/export\s+default\b/.test(e)) return !0;
1251
- Vn.lastIndex = 0;
1328
+ tr.lastIndex = 0;
1252
1329
  let t;
1253
- for (; (t = Vn.exec(e)) !== null;) for (let e of t[1].split(",")) {
1330
+ for (; (t = tr.exec(e)) !== null;) for (let e of t[1].split(",")) {
1254
1331
  let t = e.lastIndexOf(" as ");
1255
1332
  if ((t === -1 ? e : e.slice(t + 4)).trim() === "default") return !0;
1256
1333
  }
1257
1334
  return !1;
1258
- }, Un = async (e, t) => {
1335
+ }, rr = async (e, t) => {
1259
1336
  let n = (await Promise.all(t.map(async (t) => {
1260
1337
  let n;
1261
1338
  try {
1262
- n = await he(f(e, t.file), "utf8");
1339
+ n = await ge(f(e, t.file), "utf8");
1263
1340
  } catch {
1264
1341
  return null;
1265
1342
  }
1266
- let r = Rn(n);
1267
- return r !== null && !jn(r) ? Nn(f("src", "pages", t.file), r) : Hn(n) ? null : `${f("src", "pages", t.file)} is a route (a \`page.tsx\` under src/pages/) but exports no default.\n\n A page's default export IS its component — the router has nothing to render without it,\n and the failure would otherwise surface only in \`voltro build\`'s prerender as\n "SSR received a descriptor with no Component", long after the file was written.\n\n Fix: \`export default function Page() { … }\`, or re-export another page's component\n (\`export { default } from '../page'\`). If this file is NOT a route, rename it —\n only the reserved names route, and anything else under src/pages/ is ordinary code\n that may live beside the page that uses it.`;
1343
+ let r = Qn(n);
1344
+ return r !== null && !Gn(r) ? qn(f("src", "pages", t.file), r) : nr(n) ? null : `${f("src", "pages", t.file)} is a route (a \`page.tsx\` under src/pages/) but exports no default.\n\n A page's default export IS its component — the router has nothing to render without it,\n and the failure would otherwise surface only in \`voltro build\`'s prerender as\n "SSR received a descriptor with no Component", long after the file was written.\n\n Fix: \`export default function Page() { … }\`, or re-export another page's component\n (\`export { default } from '../page'\`). If this file is NOT a route, rename it —\n only the reserved names route, and anything else under src/pages/ is ordinary code\n that may live beside the page that uses it.`;
1268
1345
  }))).filter((e) => e !== null);
1269
1346
  if (n.length !== 0) throw Error(n.join("\n\n"));
1270
- }, Wn = f(ie(), ".voltro"), Gn = f(Wn, "runtime-registry.json"), Kn = 3e4, qn = () => {
1271
- let e = Math.random().toString(36).slice(2, 10);
1272
- return `${Gn}.${process.pid}.${Date.now()}.${e}.tmp`;
1273
- }, Jn = async () => {
1274
- await j.mkdir(Wn, { recursive: !0 });
1275
- }, Yn = async () => {
1276
- try {
1277
- let e = await j.readFile(Gn, "utf8"), t = JSON.parse(e);
1278
- return t.version !== 1 || !Array.isArray(t.apps) ? {
1279
- version: 1,
1280
- apps: []
1281
- } : t;
1282
- } catch {
1283
- return {
1284
- version: 1,
1285
- apps: []
1286
- };
1287
- }
1288
- }, Xn = async (e) => {
1289
- await Jn();
1290
- let t = qn();
1291
- try {
1292
- await j.writeFile(t, JSON.stringify(e, null, 2), {
1293
- encoding: "utf8",
1294
- mode: 384
1295
- }), await j.rename(t, Gn), await j.chmod(Gn, 384).catch(() => {});
1296
- } catch (e) {
1297
- try {
1298
- await j.unlink(t);
1299
- } catch {}
1300
- throw e;
1301
- }
1302
- }, Zn = (e) => {
1303
- try {
1304
- return process.kill(e, 0), !0;
1305
- } catch {
1306
- return !1;
1307
- }
1308
- }, Qn = (e) => {
1309
- let t = Date.now();
1310
- return e.filter((e) => Zn(e.pid) ? t - new Date(e.heartbeatAt).getTime() < Kn : !1);
1311
- }, $n = async () => {
1312
- let e = await Yn(), t = Qn(e.apps);
1313
- if (t.length === e.apps.length) return e;
1314
- try {
1315
- await Xn({
1316
- version: 1,
1317
- apps: t
1318
- });
1319
- } catch {}
1320
- return {
1321
- version: 1,
1322
- apps: t
1323
- };
1324
- }, er = async (e) => {
1325
- let t = await Yn(), n = (/* @__PURE__ */ new Date()).toISOString(), r = t.apps.findIndex((t) => t.id === e.id), i = e.inspectToken ?? process.env.VOLTRO_INSPECT_TOKEN, a = {
1326
- ...e,
1327
- ...i !== void 0 && i !== "" ? { inspectToken: i } : {},
1328
- registeredAt: r >= 0 ? t.apps[r].registeredAt : n,
1329
- heartbeatAt: n
1330
- };
1331
- await Xn({
1332
- version: 1,
1333
- apps: r >= 0 ? t.apps.map((e, t) => t === r ? a : e) : [...t.apps, a]
1334
- });
1335
- }, tr = async (e) => {
1336
- try {
1337
- let t = await Yn(), n = t.apps.filter((t) => t.id !== e);
1338
- if (n.length === t.apps.length) return;
1339
- await Xn({
1340
- version: 1,
1341
- apps: n
1342
- });
1343
- } catch {}
1344
- }, nr = (e, t, n) => `${e}:${t}:${n}`, J = f(ie(), ".voltro", "logs"), rr = () => {
1347
+ }, J = f(ie(), ".voltro", "logs"), ir = () => {
1345
1348
  let e = Number(process.env.VOLTRO_LOG_FILE_TTL_MS);
1346
1349
  return Number.isFinite(e) && e > 0 ? e : 3600 * 1e3;
1347
- }, ir = !1, ar = () => {
1348
- if (ir) return;
1349
- ir = !0;
1350
- let e = Date.now() - rr(), t = [];
1350
+ }, ar = !1, or = () => {
1351
+ if (ar) return;
1352
+ ar = !0;
1353
+ let e = Date.now() - ir(), t = [];
1351
1354
  try {
1352
- t = N(J);
1355
+ t = M(J);
1353
1356
  } catch {
1354
1357
  return;
1355
1358
  }
@@ -1357,13 +1360,13 @@ import {
1357
1360
  if (!n.endsWith(".log")) continue;
1358
1361
  let t = f(J, n);
1359
1362
  try {
1360
- P(t).mtimeMs < e && ee(t);
1363
+ N(t).mtimeMs < e && P(t);
1361
1364
  } catch {}
1362
1365
  }
1363
- }, or = (e) => e.replace(/[^a-zA-Z0-9._-]/g, "_").slice(0, 80), sr = (e, t) => f(J, `${or(e)}-${t}.log`), cr = (e) => {
1364
- let t = or(e), n = [];
1366
+ }, sr = (e) => e.replace(/[^a-zA-Z0-9._-]/g, "_").slice(0, 80), cr = (e, t) => f(J, `${sr(e)}-${t}.log`), lr = (e) => {
1367
+ let t = sr(e), n = [];
1365
1368
  try {
1366
- n = N(J);
1369
+ n = M(J);
1367
1370
  } catch {
1368
1371
  return;
1369
1372
  }
@@ -1373,17 +1376,17 @@ import {
1373
1376
  for (let e of r) {
1374
1377
  let t = f(J, e);
1375
1378
  try {
1376
- let e = P(t);
1379
+ let e = N(t);
1377
1380
  e.mtimeMs > a && (a = e.mtimeMs, i = t);
1378
1381
  } catch {}
1379
1382
  }
1380
1383
  return i;
1381
- }, lr = (e) => {
1384
+ }, ur = (e) => {
1382
1385
  try {
1383
- k(J, { recursive: !0 });
1386
+ ee(J, { recursive: !0 });
1384
1387
  } catch {}
1385
- ar();
1386
- let t = sr(e, process.pid), n = A(t, "w"), r = (e) => {
1388
+ or();
1389
+ let t = cr(e, process.pid), n = k(t, "w"), r = (e) => {
1387
1390
  let t = {
1388
1391
  ts: e.ts.getTime(),
1389
1392
  level: e.level,
@@ -1424,10 +1427,10 @@ import {
1424
1427
  a(), o(), process.off("exit", o), process.off("uncaughtException", s), process.off("unhandledRejection", s);
1425
1428
  }
1426
1429
  };
1427
- }, ur = async (e, t) => {
1430
+ }, dr = async (e, t) => {
1428
1431
  let n;
1429
1432
  try {
1430
- n = await j.readFile(e, "utf8");
1433
+ n = await A.readFile(e, "utf8");
1431
1434
  } catch {
1432
1435
  return [];
1433
1436
  }
@@ -1438,11 +1441,11 @@ import {
1438
1441
  i.push(t);
1439
1442
  } catch {}
1440
1443
  return t?.max !== void 0 && i.length > t.max ? i.slice(i.length - t.max) : i;
1441
- }, dr = T({ scope: "voltro:dashboard" }), fr = re(import.meta.url), pr = 5179, mr = (e) => {
1444
+ }, fr = T({ scope: "voltro:dashboard" }), pr = ae(import.meta.url), mr = 5179, hr = (e) => {
1442
1445
  let t = process.env.VOLTRO_DASHBOARD_PATH;
1443
1446
  if (t && O(f(m(t), "app.config.ts"))) return m(t);
1444
1447
  try {
1445
- let e = u(fr.resolve("@voltro/dashboard/package.json"));
1448
+ let e = u(pr.resolve("@voltro/dashboard/package.json"));
1446
1449
  if (O(f(e, "app.config.ts"))) return e;
1447
1450
  } catch {}
1448
1451
  let n = f("voltro-devtools", "apps", "dashboard"), r = m(e);
@@ -1454,7 +1457,7 @@ import {
1454
1457
  r = t;
1455
1458
  }
1456
1459
  return null;
1457
- }, hr = "VOLTRO_IS_DASHBOARD", gr = (e, t = "127.0.0.1", n = 250) => new Promise((r) => {
1460
+ }, gr = "VOLTRO_IS_DASHBOARD", _r = (e, t = "127.0.0.1", n = 250) => new Promise((r) => {
1458
1461
  let i = ye({
1459
1462
  port: e,
1460
1463
  host: t
@@ -1462,45 +1465,45 @@ import {
1462
1465
  a || (a = !0, i.destroy(), r(e));
1463
1466
  };
1464
1467
  i.once("connect", () => o(!0)), i.once("error", () => o(!1)), setTimeout(() => o(!1), n);
1465
- }), _r = () => !!(process.env.VOLTRO_DASHBOARD === "off" || process.argv.includes("--disable-dashboard")), vr = () => process.env[hr] === "1", yr = () => process.stdout.isTTY === !0, Y = f(ie(), ".voltro", "dashboard-launch.lock"), br = 1e4, xr = async () => {
1468
+ }), vr = () => !!(process.env.VOLTRO_DASHBOARD === "off" || process.argv.includes("--disable-dashboard")), yr = () => process.env[gr] === "1", br = () => process.stdout.isTTY === !0, Y = f(ie(), ".voltro", "dashboard-launch.lock"), xr = 1e4, Sr = async () => {
1466
1469
  try {
1467
- await j.mkdir(u(Y), { recursive: !0 });
1468
- let e = await j.open(Y, "wx");
1470
+ await A.mkdir(u(Y), { recursive: !0 });
1471
+ let e = await A.open(Y, "wx");
1469
1472
  return await e.write(`${process.pid}\n${Date.now()}\n`), await e.close(), !0;
1470
1473
  } catch {
1471
1474
  try {
1472
- let e = await j.stat(Y);
1473
- if (Date.now() - e.mtimeMs > br) return await j.unlink(Y).catch(() => void 0), xr();
1475
+ let e = await A.stat(Y);
1476
+ if (Date.now() - e.mtimeMs > xr) return await A.unlink(Y).catch(() => void 0), Sr();
1474
1477
  } catch {}
1475
1478
  return !1;
1476
1479
  }
1477
- }, Sr = async () => {
1480
+ }, Cr = async () => {
1478
1481
  try {
1479
- await j.unlink(Y);
1482
+ await A.unlink(Y);
1480
1483
  } catch {}
1481
- }, Cr = async (e) => {
1484
+ }, wr = async (e) => {
1482
1485
  let t = e.port ?? 5179;
1483
- if (_r()) return {
1486
+ if (vr()) return {
1484
1487
  status: "skipped",
1485
1488
  reason: "disabled by flag/env",
1486
1489
  port: t
1487
1490
  };
1488
- if (vr()) return {
1491
+ if (yr()) return {
1489
1492
  status: "skipped",
1490
1493
  reason: "this process IS the dashboard",
1491
1494
  port: t
1492
1495
  };
1493
- if (!yr()) return {
1496
+ if (!br()) return {
1494
1497
  status: "skipped",
1495
1498
  reason: "stdout is not a TTY (CI/smoke)",
1496
1499
  port: t
1497
1500
  };
1498
- if (!await xr()) return {
1501
+ if (!await Sr()) return {
1499
1502
  status: "skipped",
1500
1503
  reason: "another voltro process is currently launching the dashboard",
1501
1504
  port: t
1502
1505
  };
1503
- if (await gr(t)) return await Sr(), {
1506
+ if (await _r(t)) return await Cr(), {
1504
1507
  status: "already-running",
1505
1508
  port: t
1506
1509
  };
@@ -1517,7 +1520,7 @@ import {
1517
1520
  stdio: "ignore",
1518
1521
  env: {
1519
1522
  ...process.env,
1520
- [hr]: "1",
1523
+ [gr]: "1",
1521
1524
  VOLTRO_DASHBOARD_PORT: String(t)
1522
1525
  }
1523
1526
  });
@@ -1525,22 +1528,22 @@ import {
1525
1528
  if (a.exitCode === null && a.signalCode === null) try {
1526
1529
  a.kill("SIGTERM");
1527
1530
  } catch {}
1528
- }), dr.info(`auto-launching dashboard at http://localhost:${t}`, {
1531
+ }), fr.info(`auto-launching dashboard at http://localhost:${t}`, {
1529
1532
  port: t,
1530
1533
  mode: i,
1531
1534
  prebuilt: r
1532
- }), r || dr.debug("no pre-built dashboard — running `voltro dev`. Build with `cd voltro-devtools && pnpm build` for a fast prod boot."), dr.debug("disable via --disable-dashboard or VOLTRO_DASHBOARD=off"), setTimeout(() => {
1533
- Sr();
1535
+ }), r || fr.debug("no pre-built dashboard — running `voltro dev`. Build with `cd voltro-devtools && pnpm build` for a fast prod boot."), fr.debug("disable via --disable-dashboard or VOLTRO_DASHBOARD=off"), setTimeout(() => {
1536
+ Cr();
1534
1537
  }, 4e3).unref(), {
1535
1538
  status: "launched",
1536
1539
  port: t
1537
1540
  };
1538
- }, wr = class extends Error {
1541
+ }, Tr = class extends Error {
1539
1542
  _voltroDeferral = !0;
1540
1543
  constructor(e) {
1541
1544
  super(e), this.name = "DeferralNotSupportedError";
1542
1545
  }
1543
- }, Tr = (e) => typeof e == "object" && !!e && e._voltroDeferral === !0, Er = (e) => {
1546
+ }, Er = (e) => typeof e == "object" && !!e && e._voltroDeferral === !0, Dr = (e) => {
1544
1547
  let { helpers: t } = e, n = t.prepareDeferredLoaderData(e.loaderData, "page"), r = {}, i = {}, a = {};
1545
1548
  for (let [n, o] of Object.entries(e.segmentLoaderData)) {
1546
1549
  let e = Number(n), s = t.prepareDeferredLoaderData(o, e);
@@ -1555,7 +1558,7 @@ import {
1555
1558
  ...e.layoutShell ? { layoutShell: e.layoutShell } : {}
1556
1559
  });
1557
1560
  } catch (e) {
1558
- throw new wr(e instanceof Error ? e.message : String(e));
1561
+ throw new Tr(e instanceof Error ? e.message : String(e));
1559
1562
  }
1560
1563
  return {
1561
1564
  loaderData: n.renderData,
@@ -1571,8 +1574,8 @@ import {
1571
1574
  ...Object.keys(a).length > 0 ? { deferredSegmentIds: a } : {}
1572
1575
  }
1573
1576
  };
1574
- }, Dr = (e) => {
1575
- let { helpers: t, renderInput: n } = e, r = Er({
1577
+ }, Or = (e) => {
1578
+ let { helpers: t, renderInput: n } = e, r = Dr({
1576
1579
  helpers: t,
1577
1580
  page: e.page,
1578
1581
  pathname: n.pathname,
@@ -1593,37 +1596,37 @@ import {
1593
1596
  stateScript: t.renderRouterStateScript(r.stateInput),
1594
1597
  hasDeferred: r.hasDeferred
1595
1598
  };
1596
- }, Or = (e) => {
1599
+ }, kr = (e) => {
1597
1600
  let { html: t, meta: n } = e.helpers.renderPageToHtml(e.prepared.renderInput);
1598
1601
  return {
1599
1602
  body: t,
1600
1603
  meta: n
1601
1604
  };
1602
- }, kr = (e) => [
1605
+ }, Ar = (e) => [
1603
1606
  ...e.extra ?? [],
1604
1607
  e.helpers.renderMetaToHtml(e.meta),
1605
1608
  `<meta name="voltro-interactive" content="${e.interactive}" />`,
1606
1609
  ...e.prepared.hasDeferred ? [e.helpers.renderDeferredRegistryScript()] : [],
1607
1610
  e.prepared.stateScript
1608
- ].filter((e) => e.length > 0).join("\n "), Ar = "<div id=\"root\"></div>", jr = "<div id=\"root\">", Mr = "</div>", Nr = /<script\b[^>]*\btype=["']module["'][^>]*><\/script>[ \t]*\n?/gi, Pr = /\bsrc=["']([^"']+)["']/i, Fr = /<script(?![^>]*\basync\b)([^>]*\btype=["']module["'][^>]*)>/gi, Ir = (e) => {
1609
- let t = e.keepScriptInHead ?? ((e) => e.startsWith("/@")), n = [], r = e.shell.replace(Nr, (e) => {
1610
- let r = Pr.exec(e)?.[1];
1611
+ ].filter((e) => e.length > 0).join("\n "), jr = "<div id=\"root\"></div>", Mr = "<div id=\"root\">", Nr = "</div>", Pr = /<script\b[^>]*\btype=["']module["'][^>]*><\/script>[ \t]*\n?/gi, Fr = /\bsrc=["']([^"']+)["']/i, Ir = /<script(?![^>]*\basync\b)([^>]*\btype=["']module["'][^>]*)>/gi, Lr = (e) => {
1612
+ let t = e.keepScriptInHead ?? ((e) => e.startsWith("/@")), n = [], r = e.shell.replace(Pr, (e) => {
1613
+ let r = Fr.exec(e)?.[1];
1611
1614
  return r === void 0 || t(r) ? e : (n.push(r), "");
1612
1615
  });
1613
- e.inlineModuleScriptsAsync && (r = r.replace(Fr, "<script async$1>"));
1614
- let i = r.indexOf(Ar);
1615
- if (i === -1) throw Error(`[voltro] the generated shell has no \`${Ar}\` 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.`);
1616
+ e.inlineModuleScriptsAsync && (r = r.replace(Ir, "<script async$1>"));
1617
+ let i = r.indexOf(jr);
1618
+ if (i === -1) throw Error(`[voltro] the generated shell has no \`${jr}\` 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.`);
1616
1619
  return {
1617
- head: `${r.slice(0, i)}${jr}`,
1618
- tail: `${Mr}${r.slice(i + 21)}`,
1620
+ head: `${r.slice(0, i)}${Mr}`,
1621
+ tail: `${Nr}${r.slice(i + 21)}`,
1619
1622
  bootstrapModules: n
1620
1623
  };
1621
- }, Lr = (e) => e.head.replace("</head>", ` ${e.headInjection}\n </head>`).replace(/<html(\s+lang="[^"]*")?/i, `<html lang="${e.htmlLang}"`), Rr = (e) => {
1624
+ }, Rr = (e) => e.head.replace("</head>", ` ${e.headInjection}\n </head>`).replace(/<html(\s+lang="[^"]*")?/i, `<html lang="${e.htmlLang}"`), zr = (e) => {
1622
1625
  let { res: t, shell: n, htmlLang: r, headInjection: i } = e, a = null, o = !1, s = !1, c = () => {
1623
1626
  if (s || !o || a === null) return;
1624
1627
  s = !0, t.statusCode = e.statusCode ?? 200;
1625
1628
  for (let [n, r] of Object.entries(e.headers ?? {})) t.setHeader(n, r);
1626
- t.flushHeaders?.(), t.write(Lr({
1629
+ t.flushHeaders?.(), t.write(Rr({
1627
1630
  head: n.head,
1628
1631
  headInjection: i(a.meta),
1629
1632
  htmlLang: r
@@ -1653,14 +1656,14 @@ import {
1653
1656
  return;
1654
1657
  }
1655
1658
  c();
1656
- }, X = T({ scope: "voltro:dev:web" }), zr = T({ scope: "vite" }), Br = await (async () => {
1659
+ }, X = T({ scope: "voltro:dev:web" }), Br = T({ scope: "vite" }), Vr = await (async () => {
1657
1660
  try {
1658
- let e = f(u(h(import.meta.url)), "..", "package.json"), t = await j.readFile(e, "utf8");
1661
+ let e = f(u(h(import.meta.url)), "..", "package.json"), t = await A.readFile(e, "utf8");
1659
1662
  return JSON.parse(t).version ?? "0.0.0";
1660
1663
  } catch {
1661
1664
  return "0.0.0";
1662
1665
  }
1663
- })(), Vr = async () => {
1666
+ })(), Hr = async () => {
1664
1667
  try {
1665
1668
  let e = u(h(import.meta.url)), t = m(e, "..", "..", "devtools");
1666
1669
  if (O(f(t, "package.json"))) return t;
@@ -1669,7 +1672,7 @@ import {
1669
1672
  } catch {
1670
1673
  return null;
1671
1674
  }
1672
- }, Hr = (e, t) => e.disableDevtools || !t ? [] : [
1675
+ }, Ur = (e, t) => e.disableDevtools || !t ? [] : [
1673
1676
  "",
1674
1677
  "// Dev-only in-page devtools overlay. The `import.meta.env.DEV` guard is a",
1675
1678
  "// compile-time constant, so prod builds strip this whole `if` block — the",
@@ -1679,12 +1682,12 @@ import {
1679
1682
  " await import('@voltro/devtools/styles.css')",
1680
1683
  " Devtools = (await import('@voltro/devtools')).VoltroDevtools",
1681
1684
  "}"
1682
- ], Ur = (e, t) => e.disableDevtools || !t ? [] : [" ...(Devtools ? { Devtools } : {}),"], Wr = (e) => e.sentry ? ["import { initSentryBrowser } from '@voltro/plugin-sentry/web'"] : [], Gr = (e) => e.sentry ? [
1685
+ ], Wr = (e, t) => e.disableDevtools || !t ? [] : [" ...(Devtools ? { Devtools } : {}),"], Gr = (e) => e.sentry ? ["import { initSentryBrowser } from '@voltro/plugin-sentry/web'"] : [], Kr = (e) => e.sentry ? [
1683
1686
  "",
1684
1687
  "// Browser-side Sentry (frontend half of the deep integration). Errors +",
1685
1688
  "// browser rpc spans flow to Sentry, sharing the server transactions' trace.",
1686
1689
  `await initSentryBrowser(${JSON.stringify(e.sentry)})`
1687
- ] : [], Kr = (e) => e.env ? ["import './env.public'"] : [], qr = (e) => {
1690
+ ] : [], qr = (e) => e.env ? ["import './env.public'"] : [], Jr = (e) => {
1688
1691
  let t = [], n = m(e);
1689
1692
  for (;;) {
1690
1693
  O(f(n, "pnpm-workspace.yaml")) && t.push(n);
@@ -1693,32 +1696,32 @@ import {
1693
1696
  n = e;
1694
1697
  }
1695
1698
  return t;
1696
- }, Jr = yn, Yr = (e) => {
1699
+ }, Yr = Nn, Xr = (e) => {
1697
1700
  if (/\/node_modules\/(?:\.pnpm\/[^/]+\/node_modules\/)?(?:react|react-dom|scheduler)\//.test(e)) return "react";
1698
1701
  let t = /\/([^/]+)\.island\.tsx?$/.exec(e);
1699
1702
  if (t) return `island-${t[1]}`;
1700
- }, Xr = /export\s+(?:async\s+)?(?:const|function|let|var)\s+loader\b/, Zr = (e) => e.startsWith("(") && e.endsWith(")"), Qr = (e) => e.filter((e) => !Zr(e)), $r = (e) => {
1701
- let n = e.replace(t, "").split("/").filter(Boolean).filter((e) => !Zr(e));
1703
+ }, Zr = /export\s+(?:async\s+)?(?:const|function|let|var)\s+loader\b/, Qr = (e) => e.startsWith("(") && e.endsWith(")"), $r = (e) => e.filter((e) => !Qr(e)), ei = (e) => {
1704
+ let n = e.replace(t, "").split("/").filter(Boolean).filter((e) => !Qr(e));
1702
1705
  return n.length === 0 ? "/" : "/" + n.join("/");
1703
- }, ei = (e) => `${e.replace(t, "").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`, Z = (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}`, Q = async (n) => {
1706
+ }, ti = (e) => `${e.replace(t, "").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`, Z = (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}`, Q = async (n) => {
1704
1707
  let r = [], i = [], a = async (n, o) => {
1705
1708
  let s = [];
1706
1709
  try {
1707
- s = await j.readdir(n, { withFileTypes: !0 });
1710
+ s = await A.readdir(n, { withFileTypes: !0 });
1708
1711
  } catch {
1709
1712
  return;
1710
1713
  }
1711
- let c = s.filter((e) => e.isDirectory()).map((e) => e.name).sort(), l = s.filter((e) => e.isFile() && e.name.endsWith(".tsx") && !Jr(e.name)).map((e) => e.name).sort(), u = new Set(l), d = o.join("/");
1714
+ let c = s.filter((e) => e.isDirectory()).map((e) => e.name).sort(), l = s.filter((e) => e.isFile() && e.name.endsWith(".tsx") && !Yr(e.name)).map((e) => e.name).sort(), u = new Set(l), d = o.join("/");
1712
1715
  if (l.some((t) => e.has(t))) {
1713
1716
  let t = u.has("layout.tsx"), r = !1;
1714
1717
  if (t) try {
1715
- let e = await j.readFile(f(n, "layout.tsx"), "utf8");
1716
- r = Xr.test(e);
1718
+ let e = await A.readFile(f(n, "layout.tsx"), "utf8");
1719
+ r = Zr.test(e);
1717
1720
  } catch {}
1718
1721
  i.push({
1719
1722
  dir: d,
1720
1723
  chain: o,
1721
- contributesToUrl: o.length === 0 || !Zr(o[o.length - 1]),
1724
+ contributesToUrl: o.length === 0 || !Qr(o[o.length - 1]),
1722
1725
  hasLayout: t,
1723
1726
  hasLayoutLoader: r,
1724
1727
  hasError: u.has("error.tsx"),
@@ -1732,8 +1735,8 @@ import {
1732
1735
  let n = d ? `${d}/${e}` : e;
1733
1736
  r.push({
1734
1737
  file: n,
1735
- pattern: $r(n),
1736
- ident: ei(n),
1738
+ pattern: ei(n),
1739
+ ident: ti(n),
1737
1740
  dirChain: o
1738
1741
  });
1739
1742
  }
@@ -1752,14 +1755,14 @@ import {
1752
1755
  dirs: s,
1753
1756
  orphanedSpecials: c
1754
1757
  };
1755
- }, ti = (e, t) => {
1758
+ }, ni = (e, t) => {
1756
1759
  let n = [];
1757
1760
  for (let r = 0; r <= t.length; r++) {
1758
1761
  let i = t.slice(0, r).join("/"), a = e.find((e) => e.dir === i);
1759
1762
  a && n.push(a);
1760
1763
  }
1761
1764
  return n;
1762
- }, ni = async (e) => {
1765
+ }, ri = async (e) => {
1763
1766
  let { entries: t, loadLayout: n, loadError: r, loadPending: i, ctx: a } = e, o = {};
1764
1767
  return {
1765
1768
  chain: await Promise.all(t.map(async (e, t) => {
@@ -1781,10 +1784,10 @@ import {
1781
1784
  })),
1782
1785
  segmentLoaderData: o
1783
1786
  };
1784
- }, ri = (e) => {
1785
- let t = Qr(e);
1787
+ }, ii = (e) => {
1788
+ let t = $r(e);
1786
1789
  return t.length === 0 ? "" : "/" + t.join("/");
1787
- }, ii = [
1790
+ }, ai = [
1788
1791
  "// Hot-reload bridge: keep SSR-injected <link rel=\"stylesheet\"> tags",
1789
1792
  "// in sync with Vite's CSS HMR. Without this, edits to .css files",
1790
1793
  "// only update the JS-injected <style> overlay; the underlying <link>",
@@ -1877,7 +1880,7 @@ import {
1877
1880
  " _vdtErrorStart('Build error')",
1878
1881
  " })",
1879
1882
  "}"
1880
- ].join("\n"), ai = (e) => {
1883
+ ].join("\n"), oi = (e) => {
1881
1884
  let t = [], n = 0, r = e.split("/").filter(Boolean), i = [];
1882
1885
  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, "\\$&"));
1883
1886
  let a = i.join("/");
@@ -1886,8 +1889,8 @@ import {
1886
1889
  paramNames: t,
1887
1890
  priority: n
1888
1891
  };
1889
- }, oi = (e) => e.map((e) => {
1890
- let { regex: t, paramNames: n, priority: r } = ai(e.pattern);
1892
+ }, si = (e) => e.map((e) => {
1893
+ let { regex: t, paramNames: n, priority: r } = oi(e.pattern);
1891
1894
  return {
1892
1895
  pattern: e.pattern,
1893
1896
  file: e.file,
@@ -1896,7 +1899,7 @@ import {
1896
1899
  paramNames: n,
1897
1900
  priority: r
1898
1901
  };
1899
- }).slice().sort((e, t) => e.priority - t.priority), si = (e, t) => {
1902
+ }).slice().sort((e, t) => e.priority - t.priority), ci = (e, t) => {
1900
1903
  for (let n of t) {
1901
1904
  let t = n.regex.exec(e);
1902
1905
  if (!t) continue;
@@ -1908,13 +1911,13 @@ import {
1908
1911
  };
1909
1912
  }
1910
1913
  return null;
1911
- }, ci = async (e, t) => {
1914
+ }, li = async (e, t) => {
1912
1915
  let n = e;
1913
1916
  for (;;) {
1914
1917
  let e = f(n, "node_modules", t);
1915
1918
  try {
1916
- if ((await j.stat(e)).isDirectory()) {
1917
- let t = await j.realpath(e);
1919
+ if ((await A.stat(e)).isDirectory()) {
1920
+ let t = await A.realpath(e);
1918
1921
  return t.includes("/node_modules/") ? null : t;
1919
1922
  }
1920
1923
  } catch {}
@@ -1922,7 +1925,7 @@ import {
1922
1925
  if (r === n) return null;
1923
1926
  n = r;
1924
1927
  }
1925
- }, li = async (e) => {
1928
+ }, ui = async (e) => {
1926
1929
  try {
1927
1930
  let t = await import(g(f(e, "app.config.ts")).href), n = t.default?.port, r = typeof n == "number" ? n : 4e3, i = t.default?.transport?.wsPath, a = typeof i == "string" && i.startsWith("/") ? i : void 0;
1928
1931
  return a ? {
@@ -1931,7 +1934,7 @@ import {
1931
1934
  } : { port: r };
1932
1935
  } catch {}
1933
1936
  return { port: 4e3 };
1934
- }, ui = (e, t) => ({
1937
+ }, di = (e, t) => ({
1935
1938
  name: e,
1936
1939
  pkg: t.package,
1937
1940
  browserWsUrl: t.url,
@@ -1939,7 +1942,7 @@ import {
1939
1942
  ...t.serverUrl ? { serverOrigin: t.serverUrl } : {},
1940
1943
  ...t.headers ? { headers: t.headers } : {},
1941
1944
  ...t.authHeaders ? { hasAuthHeaders: !0 } : {}
1942
- }), di = (e, t, n) => {
1945
+ }), fi = (e, t, n) => {
1943
1946
  let r = t.transport?.wsPath ?? n.wsPath;
1944
1947
  return {
1945
1948
  name: e,
@@ -1951,7 +1954,7 @@ import {
1951
1954
  ...t.headers ? { headers: t.headers } : {},
1952
1955
  ...t.authHeaders ? { hasAuthHeaders: !0 } : {}
1953
1956
  };
1954
- }, fi = (e) => {
1957
+ }, pi = (e) => {
1955
1958
  let t = /* @__PURE__ */ new Map();
1956
1959
  for (let n of e) {
1957
1960
  if (n.proxyTarget === void 0) continue;
@@ -1959,43 +1962,43 @@ import {
1959
1962
  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>.`);
1960
1963
  t.set(n.browserWsUrl, n.name);
1961
1964
  }
1962
- }, pi = async (e, t) => {
1965
+ }, mi = async (e, t) => {
1963
1966
  let n = Object.entries(t.apis ?? {}), r = [];
1964
1967
  for (let [t, i] of n) {
1965
1968
  if (i.url) {
1966
- r.push(ui(t, i));
1969
+ r.push(di(t, i));
1967
1970
  continue;
1968
1971
  }
1969
- let n = await ci(e, i.package);
1972
+ let n = await li(e, i.package);
1970
1973
  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.`);
1971
- r.push(di(t, i, await li(n)));
1974
+ r.push(fi(t, i, await ui(n)));
1972
1975
  }
1973
- return fi(r), r;
1974
- }, mi = (e) => {
1976
+ return pi(r), r;
1977
+ }, hi = (e) => {
1975
1978
  if (!(!/^wss?:\/\//.test(e) && !/^https?:\/\//.test(e))) try {
1976
1979
  let t = new URL(e);
1977
1980
  return t.protocol = t.protocol === "wss:" || t.protocol === "https:" ? "https:" : "http:", `${t.protocol}//${t.host}`;
1978
1981
  } catch {
1979
1982
  return;
1980
1983
  }
1981
- }, hi = (e) => `VOLTRO_API_ORIGIN_${e.toUpperCase().replace(/[^A-Z0-9]/g, "_")}`, gi = (e) => process.env[hi(e)] ?? process.env.VOLTRO_API_ORIGIN, _i = (e, t) => {
1984
+ }, gi = (e) => `VOLTRO_API_ORIGIN_${e.toUpperCase().replace(/[^A-Z0-9]/g, "_")}`, _i = (e) => process.env[gi(e)] ?? process.env.VOLTRO_API_ORIGIN, vi = (e, t) => {
1982
1985
  if (!e) return;
1983
- let n = gi(e.name) ?? e.serverOrigin;
1986
+ let n = _i(e.name) ?? e.serverOrigin;
1984
1987
  if (n) {
1985
- let e = mi(n);
1988
+ let e = hi(n);
1986
1989
  if (e) return e;
1987
1990
  }
1988
1991
  if (t?.allowDevProxy && e.proxyTarget) {
1989
- let t = mi(e.proxyTarget);
1992
+ let t = hi(e.proxyTarget);
1990
1993
  if (t) return t;
1991
1994
  }
1992
- if (!e.proxyTarget && /^wss?:\/\//.test(e.browserWsUrl)) return mi(e.browserWsUrl);
1993
- }, vi = (e, t, n) => {
1995
+ if (!e.proxyTarget && /^wss?:\/\//.test(e.browserWsUrl)) return hi(e.browserWsUrl);
1996
+ }, yi = (e, t, n) => {
1994
1997
  if (!e) {
1995
1998
  if (n?.apiName === void 0) return;
1996
1999
  let e = n.apiName;
1997
2000
  return async () => {
1998
- throw Error(`[loader.query] api '${e}' has no server-side origin for SSR. In a split web/api deployment the web pod reaches the api by internal DNS, not the browser's relative wsPath — set ${hi(e)} (or VOLTRO_API_ORIGIN, or apis.${e}.serverUrl in app.config.ts) to the api's internal origin, e.g. http://api.<namespace>.svc.cluster.local. The browser transport is unaffected.`);
2001
+ throw Error(`[loader.query] api '${e}' has no server-side origin for SSR. In a split web/api deployment the web pod reaches the api by internal DNS, not the browser's relative wsPath — set ${gi(e)} (or VOLTRO_API_ORIGIN, or apis.${e}.serverUrl in app.config.ts) to the api's internal origin, e.g. http://api.<namespace>.svc.cluster.local. The browser transport is unaffected.`);
1999
2002
  };
2000
2003
  }
2001
2004
  return async (r, i) => {
@@ -2017,7 +2020,7 @@ import {
2017
2020
  });
2018
2021
  } catch (t) {
2019
2022
  let i = t?.cause?.code ?? String(t?.message ?? t);
2020
- throw Error(`[loader.query] ${r}: could not reach the api at ${e}/rpc (${i}). ${n?.apiName ? `Set ${hi(n.apiName)} / VOLTRO_API_ORIGIN` : "Set the api server origin"} to the api's SSR-reachable origin (internal cluster DNS in a split deployment).`, { cause: t });
2023
+ throw Error(`[loader.query] ${r}: could not reach the api at ${e}/rpc (${i}). ${n?.apiName ? `Set ${gi(n.apiName)} / VOLTRO_API_ORIGIN` : "Set the api server origin"} to the api's SSR-reachable origin (internal cluster DNS in a split deployment).`, { cause: t });
2021
2024
  }
2022
2025
  if (!o.ok) throw Error(`[loader.query] ${r}: HTTP ${o.status} ${await o.text()}`);
2023
2026
  let s = await o.json();
@@ -2036,7 +2039,7 @@ import {
2036
2039
  if (u) return l;
2037
2040
  };
2038
2041
  }, $ = async (e, t, n, r = {}) => {
2039
- let i = t.title ?? t.name ?? "app", a = t.theme === "dark" ? " class=\"dark\"" : t.theme === "light" ? " class=\"light\"" : "", o = O(f(e, "node_modules", "@voltro", "devtools", "package.json")) || await Vr() !== null, s = t.theme === "system" ? [
2042
+ let i = t.title ?? t.name ?? "app", a = t.theme === "dark" ? " class=\"dark\"" : t.theme === "light" ? " class=\"light\"" : "", o = O(f(e, "node_modules", "@voltro", "devtools", "package.json")) || await Hr() !== null, s = t.theme === "system" ? [
2040
2043
  " <script>",
2041
2044
  " (function () {",
2042
2045
  " var root = document.documentElement",
@@ -2075,7 +2078,7 @@ import {
2075
2078
  "</html>",
2076
2079
  ""
2077
2080
  ].join("\n"), l = f(e, "src", "pages"), { pages: u, dirs: d, orphanedSpecials: p } = await Q(l);
2078
- await Un(l, u);
2081
+ await rr(l, u);
2079
2082
  for (let e of p) X.warn(`src/pages/${e.dir || "."}/ contains ${e.files.join(", ")} but no page.tsx at or below it — ${e.files.length > 1 ? "those files are" : "that file is"} inert. A layout/error/loading/not-found file only applies to routes in its own directory tree; if this is an ordinary component, rename it so it does not read as a route boundary.`);
2080
2083
  let m = (e) => `${e.replace(/[^a-zA-Z0-9]/g, "_")}AppGroup`, h = (e) => `${e.replace(/[^a-zA-Z0-9]/g, "_")}AppDescriptors`, g = n.map((e) => `import { appGroup as ${m(e.name)}, appDescriptors as ${h(e.name)} } from '${e.pkg}/rpcGroup'`);
2081
2084
  n.some((e) => e.hasAuthHeaders) && (g.push("import __voltroAppConfig from '../app.config'"), g.push("const __voltroAuthHeaders = (__voltroAppConfig as { readonly apis?: Record<string, { readonly authHeaders?: () => Record<string, string> | Promise<Record<string, string>> }> }).apis"));
@@ -2090,13 +2093,13 @@ import {
2090
2093
  e.hasLayout && e.hasLayoutLoader ? n.push(`import * as ${Z(e.dir, "Layout")}Mod from '${t}/layout.tsx'`) : e.hasLayout && n.push(`import ${Z(e.dir, "Layout")} from '${t}/layout.tsx'`), e.hasError && n.push(`import ${Z(e.dir, "Error")} from '${t}/error.tsx'`), e.hasPending && n.push(`import ${Z(e.dir, "Pending")} from '${t}/loading.tsx'`), e.hasNotFound && n.push(`import ${Z(e.dir, "NotFound")} from '${t}/not-found.tsx'`);
2091
2094
  }
2092
2095
  let r = u.map((e) => {
2093
- let t = ti(d, e.dirChain).map((e) => {
2096
+ let t = ni(d, e.dirChain).map((e) => {
2094
2097
  let t = [`id: ${JSON.stringify(e.dir || "/")}`], n = JSON.stringify(e.dir);
2095
2098
  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(", ")} }`;
2096
2099
  }).join(",\n");
2097
2100
  return ` makePageRoute(${JSON.stringify(e.pattern)}, ${t.length > 0 ? `[\n${t},\n ]` : "undefined"}),`;
2098
2101
  }), i = d.filter((e) => e.hasNotFound).map((e) => {
2099
- let t = ri(e.chain), n = ti(d, e.chain).map((e) => {
2102
+ let t = ii(e.chain), n = ni(d, e.chain).map((e) => {
2100
2103
  let t = [`id: ${JSON.stringify(e.dir || "/")}`], n = JSON.stringify(e.dir);
2101
2104
  return e.hasLayout && t.push(`Layout: refs.layouts[${n}]`), e.hasError && t.push(`Error: refs.errors[${n}]`), ` { ${t.join(", ")} }`;
2102
2105
  }).join(",\n"), r = n.length > 0 ? `\n chain: [\n${n},\n ],` : "";
@@ -2335,14 +2338,14 @@ import {
2335
2338
  "// resolved apis map. Side-effect only — no local component definitions —",
2336
2339
  "// so downstream invalidations (user page edits) terminate at app.tsx.",
2337
2340
  "",
2338
- ...Kr(t),
2341
+ ...qr(t),
2339
2342
  "import { mount } from '@voltro/web'",
2340
2343
  ...g,
2341
2344
  "import { App } from './app'",
2342
2345
  "import { preloadCurrentRoute } from './routeTable'",
2343
- ...Wr(t),
2344
- ...Hr(t, o),
2345
2346
  ...Gr(t),
2347
+ ...Ur(t, o),
2348
+ ...Kr(t),
2346
2349
  "",
2347
2350
  "// Preload the current route's page chunk BEFORE hydration so the first",
2348
2351
  "// client render matches the SSG/SSR-prerendered HTML. Without it, a lazy",
@@ -2359,10 +2362,10 @@ import {
2359
2362
  " apis: {",
2360
2363
  ..._,
2361
2364
  " },",
2362
- ...Ur(t, o),
2365
+ ...Wr(t, o),
2363
2366
  "})",
2364
2367
  "",
2365
- ii
2368
+ ai
2366
2369
  ].join("\n");
2367
2370
  } else v = "", y = "", b = [
2368
2371
  "// GENERATED BY `voltro dev` — do not edit; will be overwritten on next boot.",
@@ -2370,43 +2373,43 @@ import {
2370
2373
  "// and calls mount(). Side-effect only, no component definitions, so the",
2371
2374
  "// user's component file remains the Fast Refresh boundary.",
2372
2375
  "",
2373
- ...Kr(t),
2376
+ ...qr(t),
2374
2377
  "import { mount } from '@voltro/web'",
2375
2378
  ...g,
2376
2379
  "import App from '../src/App'",
2377
- ...Wr(t),
2378
- ...Hr(t, o),
2379
2380
  ...Gr(t),
2381
+ ...Ur(t, o),
2382
+ ...Kr(t),
2380
2383
  "",
2381
2384
  "mount(App, {",
2382
2385
  " apis: {",
2383
2386
  ..._,
2384
2387
  " },",
2385
- ...Ur(t, o),
2388
+ ...Wr(t, o),
2386
2389
  "})",
2387
2390
  "",
2388
- ii
2391
+ ai
2389
2392
  ].join("\n");
2390
2393
  let x = f(e, ".framework");
2391
- await j.mkdir(x, { recursive: !0 }), t.env ? await tt(x, r) : await j.rm(f(x, "env.public.ts"), { force: !0 }), await j.writeFile(f(x, "index.html"), c, "utf8"), await j.writeFile(f(x, "main.tsx"), b, "utf8"), v ? (await j.writeFile(f(x, "app.tsx"), v, "utf8"), await j.writeFile(f(x, "routeTable.ts"), y, "utf8")) : (await j.rm(f(x, "app.tsx"), { force: !0 }), await j.rm(f(x, "routeTable.ts"), { force: !0 }));
2394
+ await A.mkdir(x, { recursive: !0 }), t.env ? await ht(x, r) : await A.rm(f(x, "env.public.ts"), { force: !0 }), await A.writeFile(f(x, "index.html"), c, "utf8"), await A.writeFile(f(x, "main.tsx"), b, "utf8"), v ? (await A.writeFile(f(x, "app.tsx"), v, "utf8"), await A.writeFile(f(x, "routeTable.ts"), y, "utf8")) : (await A.rm(f(x, "app.tsx"), { force: !0 }), await A.rm(f(x, "routeTable.ts"), { force: !0 }));
2392
2395
  let S = f(e, ".gitignore"), C = "";
2393
2396
  try {
2394
- C = await j.readFile(S, "utf8");
2397
+ C = await A.readFile(S, "utf8");
2395
2398
  } catch {}
2396
2399
  let w = ["/.framework/"], T = new Set(C.split("\n").map((e) => e.trim())), E = w.filter((e) => !T.has(e));
2397
2400
  if (E.length > 0) {
2398
2401
  let e = C === "" || C.endsWith("\n") ? "" : "\n";
2399
2402
  try {
2400
- await j.appendFile(S, `${e}${E.join("\n")}\n`, "utf8");
2403
+ await A.appendFile(S, `${e}${E.join("\n")}\n`, "utf8");
2401
2404
  } catch (e) {
2402
2405
  X.warn(`could not add ${E.join(", ")} to ${S} — add it by hand so the generated directory stays out of git. The build is unaffected.`, { reason: e?.message ?? String(e) });
2403
2406
  }
2404
2407
  }
2405
- }, yi = async (e, t) => {
2408
+ }, bi = async (e, t) => {
2406
2409
  try {
2407
2410
  let n = f(u(e), "project.json");
2408
2411
  if (!O(n)) return;
2409
- let r = await j.readFile(n, "utf8"), i = JSON.parse(r).apps ?? {}, a = e.split("/").filter(Boolean).pop() ?? "", o = [];
2412
+ let r = await A.readFile(n, "utf8"), i = JSON.parse(r).apps ?? {}, a = e.split("/").filter(Boolean).pop() ?? "", o = [];
2410
2413
  for (let [e, n] of Object.entries(i)) e !== a && n.port === t && o.push(e);
2411
2414
  if (o.length === 0) return;
2412
2415
  X.warn("sibling app(s) claim the same port — only one boots", {
@@ -2415,36 +2418,36 @@ import {
2415
2418
  projectJson: n
2416
2419
  });
2417
2420
  } catch {}
2418
- }, bi = (e) => f(e, ".framework", "dist", "server", "appConfig.js"), xi = async (e) => {
2419
- let t = bi(e), n = O(t) ? t : f(e, "app.config.ts");
2421
+ }, xi = (e) => f(e, ".framework", "dist", "server", "appConfig.js"), Si = async (e) => {
2422
+ let t = xi(e), n = O(t) ? t : f(e, "app.config.ts");
2420
2423
  try {
2421
2424
  let e = (await import(g(n).href)).default;
2422
2425
  return typeof e == "object" && e && "type" in e && e.type === "web" ? e : null;
2423
2426
  } catch {
2424
2427
  return null;
2425
2428
  }
2426
- }, Si = async (e) => {
2427
- let t = await xi(e);
2429
+ }, Ci = async (e) => {
2430
+ let t = await Si(e);
2428
2431
  if (!t) return {
2429
2432
  ran: !1,
2430
2433
  exitCode: 0
2431
2434
  };
2432
- gn();
2433
- let n = Rt();
2434
- Jt(n), X.info("booting voltro dev (web)", { app: t.name ?? "(unnamed)" });
2435
- let u = await pi(e, t);
2435
+ An();
2436
+ let n = Qt();
2437
+ ln(n), X.info("booting voltro dev (web)", { app: t.name ?? "(unnamed)" });
2438
+ let u = await mi(e, t);
2436
2439
  for (let e of u) X.info("api wired", {
2437
2440
  name: e.name,
2438
2441
  pkg: e.pkg,
2439
2442
  ...e.proxyTarget ? { proxyTo: e.proxyTarget } : { directWs: e.browserWsUrl }
2440
2443
  });
2441
- We(e).then((e) => {
2444
+ Ge(e).then((e) => {
2442
2445
  for (let t of e.files) if (t.action === "created") {
2443
2446
  let e = t.path.split("/").pop() ?? t.path;
2444
2447
  X.info(`${e} seeded`, { path: t.path });
2445
2448
  }
2446
2449
  }).catch(() => {});
2447
- let { resolved: d } = await nt({
2450
+ let { resolved: d } = await gt({
2448
2451
  rawEnv: t.env,
2449
2452
  appType: "web",
2450
2453
  root: e,
@@ -2456,8 +2459,8 @@ import {
2456
2459
  ".framework/main.tsx",
2457
2460
  ...t.env ? [".framework/env.public.ts"] : []
2458
2461
  ] });
2459
- let g = process.env.VOLTRO_IS_DASHBOARD === "1" && process.env.VOLTRO_DASHBOARD_PORT ? Number(process.env.VOLTRO_DASHBOARD_PORT) : t.port ?? 5173, _ = t.name ?? "unnamed", v = nr("web", _, g), y = lr(_);
2460
- await er({
2462
+ let g = process.env.VOLTRO_IS_DASHBOARD === "1" && process.env.VOLTRO_DASHBOARD_PORT ? Number(process.env.VOLTRO_DASHBOARD_PORT) : t.port ?? 5173, _ = t.name ?? "unnamed", v = at("web", _, g), y = ur(_);
2463
+ await rt({
2461
2464
  id: v,
2462
2465
  name: _,
2463
2466
  kind: "web",
@@ -2465,19 +2468,22 @@ import {
2465
2468
  pid: process.pid,
2466
2469
  status: "booting",
2467
2470
  logFile: y.path
2468
- }).catch(() => {}), await yi(e, g);
2469
- let { pages: b, dirs: x } = await Q(f(e, "src", "pages")), S = x.map((e) => ({
2471
+ }).catch(() => {}), await bi(e, g);
2472
+ let { pages: b, dirs: x } = await Q(f(e, "src", "pages")), S = {
2473
+ dirs: x,
2474
+ ssrRoutes: si(b)
2475
+ }, C = x.map((e) => ({
2470
2476
  dir: e.dir,
2471
2477
  hasLayout: e.hasLayout,
2472
2478
  hasError: e.hasError,
2473
2479
  hasPending: e.hasPending,
2474
2480
  hasNotFound: e.hasNotFound
2475
- })), C = await It({
2481
+ })), w = await Xt({
2476
2482
  appRoot: e,
2477
2483
  pages: b
2478
2484
  });
2479
- C.wrote && X.debug("routes codegen wrote", { path: p(e, C.path) });
2480
- let w = await Ye("vite", () => import("vite")), T = (await import("@vitejs/plugin-react")).default, D = (await import("@tailwindcss/vite")).default, k = f(e, ".framework"), A = f(e, "src"), M = /* @__PURE__ */ new Set([
2485
+ w.wrote && X.debug("routes codegen wrote", { path: p(e, w.path) });
2486
+ let T = await lt("vite", () => import("vite")), D = (await import("@vitejs/plugin-react")).default, ee = (await import("@tailwindcss/vite")).default, k = f(e, ".framework"), j = f(e, "src"), M = /* @__PURE__ */ new Set([
2481
2487
  ".framework",
2482
2488
  "node_modules",
2483
2489
  "dist",
@@ -2489,70 +2495,71 @@ import {
2489
2495
  name: "framework:watch-app-sources",
2490
2496
  async configureServer(t) {
2491
2497
  try {
2492
- let n = (await j.readdir(e, { withFileTypes: !0 })).filter((e) => e.isDirectory() && !M.has(e.name));
2498
+ let n = (await A.readdir(e, { withFileTypes: !0 })).filter((e) => e.isDirectory() && !M.has(e.name));
2493
2499
  for (let r of n) t.watcher.add(f(e, r.name));
2494
- n.length === 0 && t.watcher.add(A);
2500
+ n.length === 0 && t.watcher.add(j);
2495
2501
  } catch {
2496
- t.watcher.add(A);
2502
+ t.watcher.add(j);
2497
2503
  }
2498
2504
  try {
2499
- let n = await j.readFile(f(e, "package.json"), "utf8"), r = JSON.parse(n), i = Object.keys({
2505
+ let n = await A.readFile(f(e, "package.json"), "utf8"), r = JSON.parse(n), i = Object.keys({
2500
2506
  ...r.dependencies,
2501
2507
  ...r.devDependencies
2502
2508
  });
2503
2509
  await Promise.all(i.map(async (n) => {
2504
- let r = await ci(e, n);
2510
+ let r = await li(e, n);
2505
2511
  if (!r) return;
2506
2512
  let i = f(r, "src");
2507
2513
  try {
2508
- (await j.stat(i)).isDirectory() && t.watcher.add(i);
2514
+ (await A.stat(i)).isDirectory() && t.watcher.add(i);
2509
2515
  } catch {}
2510
2516
  }));
2511
2517
  } catch {}
2512
2518
  }
2513
- }, P = f(e, "src", "pages"), ee = (e) => e.endsWith(".tsx") && (e === P || e.startsWith(P + "/")), F = (e) => e === P || e.startsWith(P + "/"), te = async (n) => {
2519
+ }, P = f(e, "src", "pages"), F = (e) => e.endsWith(".tsx") && (e === P || e.startsWith(P + "/")), te = (e) => e === P || e.startsWith(P + "/"), I = async (n) => {
2514
2520
  try {
2515
2521
  let r = Date.now();
2516
2522
  await $(e, t, u, h);
2517
- let { pages: i } = await Q(P);
2518
- await It({
2523
+ let { pages: i, dirs: a } = await Q(P);
2524
+ await Xt({
2519
2525
  appRoot: e,
2520
2526
  pages: i
2521
- }), X.info("page tree regenerated", {
2527
+ }), S.dirs = a, S.ssrRoutes = si(i), X.info("page tree regenerated", {
2522
2528
  reason: n,
2523
- ms: Date.now() - r
2529
+ ms: Date.now() - r,
2530
+ routes: S.ssrRoutes.length
2524
2531
  });
2525
2532
  } catch (e) {
2526
2533
  X.error("page tree regen failed", { reason: n }, e);
2527
2534
  }
2528
- }, I = {
2535
+ }, ne = {
2529
2536
  name: "framework:regenerate-on-page-tree-change",
2530
2537
  configureServer(t) {
2531
2538
  let n = null, r = [], i = (e) => {
2532
2539
  r.push(e), n && clearTimeout(n), n = setTimeout(() => {
2533
2540
  n = null;
2534
2541
  let e = r.length === 1 ? r[0] : `${r.length} events (${r[0]}, …)`;
2535
- r.length = 0, te(e);
2542
+ r.length = 0, I(e);
2536
2543
  }, 50);
2537
2544
  };
2538
2545
  t.watcher.on("add", (t) => {
2539
- ee(t) && i(`add ${p(e, t)}`);
2546
+ F(t) && i(`add ${p(e, t)}`);
2540
2547
  }), t.watcher.on("unlink", (t) => {
2541
- ee(t) && i(`unlink ${p(e, t)}`);
2548
+ F(t) && i(`unlink ${p(e, t)}`);
2542
2549
  }), t.watcher.on("addDir", (t) => {
2543
- F(t) && i(`addDir ${p(e, t)}`);
2550
+ te(t) && i(`addDir ${p(e, t)}`);
2544
2551
  }), t.watcher.on("unlinkDir", (t) => {
2545
- F(t) && i(`unlinkDir ${p(e, t)}`);
2552
+ te(t) && i(`unlinkDir ${p(e, t)}`);
2546
2553
  });
2547
2554
  }
2548
- }, L = f(e, "app.config.ts"), R = (e) => {
2549
- if (!le(e.env)) return "";
2555
+ }, L = f(e, "app.config.ts"), re = (e) => {
2556
+ if (!de(e.env)) return "";
2550
2557
  let t = Object.entries(e.env.vars).map(([e, t]) => `${e}:${t.access}`).sort();
2551
2558
  return `${String(e.env.publicPrefix)}|${t.join(",")}`;
2552
- }, ne = (e, t) => {
2559
+ }, ie = (e, t) => {
2553
2560
  let n = [];
2554
- return e.port !== t.port && n.push(`port ${e.port ?? "(default)"} → ${t.port ?? "(default)"}`), JSON.stringify(e.proxies) !== JSON.stringify(t.proxies) && n.push("proxies"), JSON.stringify(e.allowedHosts) !== JSON.stringify(t.allowedHosts) && n.push("allowedHosts"), JSON.stringify(e.apis) !== JSON.stringify(t.apis) && n.push("apis"), R(e) !== R(t) && n.push("env"), n;
2555
- }, re = t, ie = m(L), ae = {
2561
+ 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;
2562
+ }, ae = t, oe = m(L), se = {
2556
2563
  name: "framework:watch-app-config",
2557
2564
  async configureServer(t) {
2558
2565
  t.watcher.add(L), X.info("watching app.config.ts for changes", { path: p(e, L) });
@@ -2581,11 +2588,11 @@ import {
2581
2588
  theme: r.theme,
2582
2589
  port: r.port,
2583
2590
  name: r.name
2584
- }), JSON.stringify(r) === JSON.stringify(re)) {
2591
+ }), JSON.stringify(r) === JSON.stringify(ae)) {
2585
2592
  X.info("app.config.ts onConfigChange: parsed config unchanged — skipping (no-op edit?)");
2586
2593
  return;
2587
2594
  }
2588
- let i = ne(re, r);
2595
+ let i = ie(ae, r);
2589
2596
  if (i.length > 0) {
2590
2597
  X.warn("app.config.ts changed — hard restart required", { fields: i });
2591
2598
  try {
@@ -2607,7 +2614,7 @@ import {
2607
2614
  }
2608
2615
  try {
2609
2616
  let n = Date.now();
2610
- await $(e, r, await pi(e, r)), re = r, t.ws && t.ws.send({
2617
+ await $(e, r, await mi(e, r)), ae = r, t.ws && t.ws.send({
2611
2618
  type: "full-reload",
2612
2619
  path: "*"
2613
2620
  }), X.info("app.config.ts soft-regen", {
@@ -2617,7 +2624,7 @@ import {
2617
2624
  } catch (e) {
2618
2625
  X.error("app.config.ts soft-regen failed", {}, e);
2619
2626
  }
2620
- }, o = (e) => l(e) === "app.config.ts" ? e === L || m(e) === ie : !1;
2627
+ }, o = (e) => l(e) === "app.config.ts" ? e === L || m(e) === oe : !1;
2621
2628
  t.watcher.on("change", (e) => {
2622
2629
  o(e) && (X.info("app.config.ts change event (chokidar)", { file: e }), i());
2623
2630
  }), t.watcher.on("add", (e) => {
@@ -2631,27 +2638,27 @@ import {
2631
2638
  } catch (e) {
2632
2639
  X.warn("app.config.ts polling watcher could not attach", {}, e);
2633
2640
  }
2634
- ht(ft, X, {
2641
+ kt(Et, X, {
2635
2642
  root: e,
2636
2643
  onBeforeRestart: () => t.close()
2637
2644
  });
2638
2645
  }
2639
- }, oe = /\/apps\/[^/]+\/.*\.(route|mutation|workflow|schema)\.tsx?$/, se = {
2646
+ }, ce = /\/apps\/[^/]+\/.*\.(route|mutation|workflow|schema)\.tsx?$/, le = {
2640
2647
  name: "framework:suppress-api-hmr",
2641
2648
  handleHotUpdate(e) {
2642
- if (oe.test(e.file)) return [];
2649
+ if (ce.test(e.file)) return [];
2643
2650
  }
2644
- }, ce = {
2651
+ }, ue = {
2645
2652
  name: "framework:reoptimize-on-rpcgroup-change",
2646
2653
  async configureServer(t) {
2647
2654
  let n = /* @__PURE__ */ new Map();
2648
2655
  for (let r of u) {
2649
2656
  if (!r.proxyTarget) continue;
2650
- let i = await ci(e, r.pkg);
2657
+ let i = await li(e, r.pkg);
2651
2658
  if (!i) continue;
2652
2659
  let a = f(i, "rpcGroup.generated.ts");
2653
2660
  try {
2654
- n.set(a, await j.readFile(a, "utf8"));
2661
+ n.set(a, await A.readFile(a, "utf8"));
2655
2662
  } catch {
2656
2663
  n.set(a, "");
2657
2664
  }
@@ -2666,7 +2673,7 @@ import {
2666
2673
  for (let [e, t] of n) {
2667
2674
  let i;
2668
2675
  try {
2669
- i = await j.readFile(e, "utf8");
2676
+ i = await A.readFile(e, "utf8");
2670
2677
  } catch {
2671
2678
  continue;
2672
2679
  }
@@ -2675,7 +2682,7 @@ import {
2675
2682
  if (r !== null) {
2676
2683
  i = !0, X.info(`rpcGroup changed (${p(e, r)}) — re-bundling the api client + reloading (descriptor edits propagate automatically; no manual restart needed)`);
2677
2684
  try {
2678
- await j.rm(f(k, ".vite", "deps"), {
2685
+ await A.rm(f(k, ".vite", "deps"), {
2679
2686
  recursive: !0,
2680
2687
  force: !0
2681
2688
  }), await t.restart(!0);
@@ -2690,37 +2697,38 @@ import {
2690
2697
  };
2691
2698
  t.watcher.on("change", o), t.watcher.on("add", o);
2692
2699
  }
2693
- }, z = {}, ue = (e) => (t) => {
2700
+ }, R = {}, fe = (e) => (t) => {
2694
2701
  t.on("proxyReq", (t, n) => {
2695
- mn(t, n, {
2702
+ On(t, n, {
2696
2703
  target: e,
2697
2704
  token: process.env.VOLTRO_INSPECT_TOKEN,
2705
+ writeToken: process.env.VOLTRO_INSPECT_WRITE_TOKEN,
2698
2706
  isLoopback: r
2699
2707
  });
2700
2708
  });
2701
2709
  };
2702
2710
  for (let e of u) {
2703
2711
  if (!e.proxyTarget) continue;
2704
- z[e.browserWsUrl] = {
2712
+ R[e.browserWsUrl] = {
2705
2713
  target: e.proxyTarget,
2706
2714
  ws: !0,
2707
2715
  changeOrigin: !0,
2708
2716
  ...e.wsPath ? {} : { rewrite: () => "/ws" }
2709
2717
  };
2710
2718
  let t = e.proxyTarget.replace(/^ws/, "http");
2711
- z[`/_voltro/api/${e.name}`] = {
2719
+ R[`/_voltro/api/${e.name}`] = {
2712
2720
  target: t,
2713
2721
  changeOrigin: !0,
2714
2722
  rewrite: (t) => t.replace(RegExp(`^/_voltro/api/${e.name}`), ""),
2715
- configure: ue(t)
2723
+ configure: fe(t)
2716
2724
  };
2717
2725
  }
2718
2726
  for (let [e, n] of Object.entries(t.proxies ?? {})) {
2719
- if (z[e]) {
2727
+ if (R[e]) {
2720
2728
  X.warn("user proxy ignored — prefix already claimed by an api ws proxy", { prefix: e });
2721
2729
  continue;
2722
2730
  }
2723
- z[e] = {
2731
+ R[e] = {
2724
2732
  target: n.target,
2725
2733
  changeOrigin: n.changeOrigin ?? !0,
2726
2734
  ...n.rewrite === void 0 ? {} : { rewrite: (t) => t.replace(RegExp(`^${e}`), n.rewrite) }
@@ -2730,7 +2738,7 @@ import {
2730
2738
  ...n.rewrite === void 0 ? {} : { rewrite: n.rewrite }
2731
2739
  });
2732
2740
  }
2733
- let de = {
2741
+ let pe = {
2734
2742
  name: "framework:inspect",
2735
2743
  configureServer(l) {
2736
2744
  let u = null, d = async () => {
@@ -2742,7 +2750,7 @@ import {
2742
2750
  pattern: n.pattern,
2743
2751
  file: n.file,
2744
2752
  dirChain: n.dirChain,
2745
- renderMode: Fn(r, f("src", "pages", n.file)),
2753
+ renderMode: Yn(r, f("src", "pages", n.file)),
2746
2754
  interactive: r.interactive ?? "full",
2747
2755
  tenantAware: r.tenantAware === !0,
2748
2756
  revalidateMs: G(r.revalidate),
@@ -2861,7 +2869,7 @@ import {
2861
2869
  for (let [t, n] of Object.entries(e.headers ?? {})) n !== void 0 && (u[String(t).toLowerCase()] = Array.isArray(n) ? n.join(", ") : String(n));
2862
2870
  let f = l.split("?")[0];
2863
2871
  if (e.method === "GET" && (f === "/_voltro/inspect/logs" || l.startsWith("/_voltro/inspect/logs?"))) {
2864
- let e = c(u.origin), t = cn(l, Kt(), u);
2872
+ let e = c(u.origin), t = Sn(l, sn(), u);
2865
2873
  r.statusCode = t.status, r.setHeader("content-type", t.contentType);
2866
2874
  for (let [t, n] of Object.entries(e)) r.setHeader(t, n);
2867
2875
  r.end(t.body);
@@ -2879,7 +2887,7 @@ import {
2879
2887
  e.setEncoding("utf-8"), e.on("data", (e) => {
2880
2888
  a += e;
2881
2889
  }), e.on("end", () => {
2882
- let e = tn(a, n);
2890
+ let e = gn(a, n);
2883
2891
  r.statusCode = e.status, r.setHeader("content-type", e.contentType);
2884
2892
  for (let [e, n] of Object.entries(t)) r.setHeader(e, n);
2885
2893
  r.end(e.body);
@@ -2896,7 +2904,7 @@ import {
2896
2904
  r.end(JSON.stringify({ error: "inspect disabled (VOLTRO_INSPECT=off)" }));
2897
2905
  return;
2898
2906
  }
2899
- let a = o(u);
2907
+ let a = o(u, "GET");
2900
2908
  if (!a.ok) {
2901
2909
  r.statusCode = 401, r.setHeader("content-type", "application/json");
2902
2910
  for (let [e, n] of Object.entries(t)) r.setHeader(e, n);
@@ -2910,14 +2918,14 @@ import {
2910
2918
  for (let [e, n] of Object.entries(t)) r.setHeader(e, n);
2911
2919
  r.flushHeaders?.(), r.write("retry: 5000\n\n");
2912
2920
  let s = l.indexOf("?");
2913
- if (!(s !== -1 && new URLSearchParams(l.slice(s + 1)).get("live") === "1")) for (let e of n.buffered()) r.write(zt(e));
2921
+ if (!(s !== -1 && new URLSearchParams(l.slice(s + 1)).get("live") === "1")) for (let e of n.buffered()) r.write($t(e));
2914
2922
  let d = n.subscribe((e) => {
2915
2923
  try {
2916
- r.write(zt(e));
2924
+ r.write($t(e));
2917
2925
  } catch {}
2918
2926
  }), f = setInterval(() => {
2919
2927
  try {
2920
- r.write(Bt());
2928
+ r.write(en());
2921
2929
  } catch {}
2922
2930
  }, 15e3), p = () => {
2923
2931
  clearInterval(f), d();
@@ -2930,7 +2938,7 @@ import {
2930
2938
  kind: "web",
2931
2939
  meta: {
2932
2940
  name: t.name ?? "(unnamed)",
2933
- voltroVersion: Br,
2941
+ voltroVersion: Vr,
2934
2942
  port: g,
2935
2943
  mode: "dev",
2936
2944
  apis: Object.entries(t.apis ?? {}).map(([e, t]) => {
@@ -2942,13 +2950,13 @@ import {
2942
2950
  })
2943
2951
  },
2944
2952
  routes: await d(),
2945
- dirs: S,
2953
+ dirs: C,
2946
2954
  cache: () => ({
2947
2955
  backend: "memory",
2948
2956
  size: 0,
2949
2957
  entries: []
2950
2958
  }),
2951
- env: () => it(t.name ?? "app", { contract: le(t.env) ? t.env : void 0 })
2959
+ env: () => vt(t.name ?? "app", { contract: de(t.env) ? t.env : void 0 })
2952
2960
  }, u, { method: e.method ?? "GET" });
2953
2961
  if (n === null) return a();
2954
2962
  r.statusCode = n.status, r.setHeader("content-type", n.contentType);
@@ -2959,21 +2967,35 @@ import {
2959
2967
  }
2960
2968
  });
2961
2969
  }
2962
- }, fe = t.name === "voltroDashboard" ? {
2970
+ }, me = t.name === "voltroDashboard" ? {
2963
2971
  name: "framework:dashboard-registry",
2964
2972
  configureServer(e) {
2965
2973
  e.middlewares.use(async (e, t, n) => {
2966
2974
  if (!(e.url ?? "").startsWith("/api/dashboard/registry")) return n();
2967
2975
  try {
2968
- let e = await $n();
2976
+ let e = await nt();
2969
2977
  t.statusCode = 200, t.setHeader("content-type", "application/json; charset=utf-8"), t.end(JSON.stringify(e));
2970
2978
  } catch (e) {
2971
2979
  t.statusCode = 500, t.setHeader("content-type", "text/plain"), t.end(`registry read error: ${e.message}`);
2972
2980
  }
2973
2981
  });
2974
2982
  }
2975
- } : null, pe = oi(b), me = /* @__PURE__ */ new Set(), he = wt(), ge = Et({
2976
- limit: he,
2983
+ } : null, he = /* @__PURE__ */ new Set(), ge = (e, t, n, r, i) => {
2984
+ if (X.error(`${t} render failed`, {
2985
+ pathname: n,
2986
+ pattern: r
2987
+ }, i), e.headersSent) {
2988
+ e.end();
2989
+ return;
2990
+ }
2991
+ e.writeHead(500, {
2992
+ "content-type": "text/plain; charset=utf-8",
2993
+ "x-voltro-rendered-by": `${t}-failed`
2994
+ });
2995
+ let a = i instanceof Error ? i.stack ?? i.message : String(i);
2996
+ e.end(`${t} render failed for ${n}\n\n${a}\n`);
2997
+ }, z = Rt(), ye = Bt({
2998
+ limit: z,
2977
2999
  onColdStart: (e) => X.debug("ssr cold-compile start", { id: e }),
2978
3000
  onColdEnd: (e, { durationMs: t, failed: n }) => X.debug(`ssr cold-compile ${n ? "FAILED" : "end"} ${t}ms`, {
2979
3001
  id: e,
@@ -2981,18 +3003,18 @@ import {
2981
3003
  ...n ? { failed: !0 } : {}
2982
3004
  })
2983
3005
  });
2984
- X.debug(`ssr cold-compile concurrency ${he}`, { concurrency: he });
2985
- let ye = null, be = async () => (ye === null && (ye = await j.readFile(f(e, ".framework", "index.html"), "utf8")), ye), xe = {
3006
+ X.debug(`ssr cold-compile concurrency ${z}`, { concurrency: z });
3007
+ let be = null, xe = async () => (be === null && (be = await A.readFile(f(e, ".framework", "index.html"), "utf8")), be), Se = {
2986
3008
  name: "framework:ssr",
2987
3009
  configureServer(t) {
2988
- let n = (e) => ge.load(e, async () => await t.ssrLoadModule(e));
3010
+ let n = (e) => ye.load(e, async () => await t.ssrLoadModule(e));
2989
3011
  t.middlewares.use(async (r, i, a) => {
2990
3012
  if (r.method !== "GET" && r.method !== "HEAD") return a();
2991
3013
  let o = r.url ?? "/", s = o.indexOf("?"), c = (s === -1 ? o : o.slice(0, s)) || "/";
2992
3014
  if (c.startsWith("/@") || c.startsWith("/node_modules/") || c.startsWith("/.framework/") || c.startsWith("/_voltro/") || c === "/main.tsx" || c === "/index.html" || c === "/sw.js" || c === "/favicon.ico" || c === "/robots.txt" || /\.[a-z0-9]+$/i.test(c)) return a();
2993
- let l = si(c, pe);
3015
+ let l = ci(c, S.ssrRoutes);
2994
3016
  if (!l) return a();
2995
- let d = !me.has(l.route.pattern), p = Date.now();
3017
+ let d = !he.has(l.route.pattern), p = Date.now();
2996
3018
  d && X.info(`ssr compiling ${l.route.pattern}`, {
2997
3019
  pattern: l.route.pattern,
2998
3020
  pathname: c
@@ -3012,15 +3034,15 @@ import {
3012
3034
  }
3013
3035
  };
3014
3036
  try {
3015
- let s = await h("loadPage", async () => await n(f(e, "src", "pages", l.route.file))), _ = Fn(s, f("src", "pages", l.route.file)), v = ti(x, l.route.dirChain), y = _ === "spa" && v.some((e) => e.hasLayout);
3037
+ let s = await h("loadPage", async () => await n(f(e, "src", "pages", l.route.file))), _ = Yn(s, f("src", "pages", l.route.file)), v = ni(S.dirs, l.route.dirChain), y = _ === "spa" && v.some((e) => e.hasLayout);
3016
3038
  if (_ !== "ssr" && _ !== "isr" && !y) return a();
3017
3039
  let b = {};
3018
3040
  for (let [e, t] of Object.entries(r.headers ?? {})) typeof t == "string" ? b[e] = t : Array.isArray(t) && (b[e] = t.join(", "));
3019
- let S = vi(_i(u[0], { allowDevProxy: !0 }), b.cookie, { apiName: u[0]?.name }), C = new AbortController(), w = () => C.abort();
3041
+ let x = yi(vi(u[0], { allowDevProxy: !0 }), b.cookie, { apiName: u[0]?.name }), C = new AbortController(), w = () => C.abort();
3020
3042
  i.once("close", w);
3021
3043
  let T = null, E = [], D = {};
3022
3044
  try {
3023
- (await n("@voltro/web/ssr")).beginStoreSeeds(), {chain: E, segmentLoaderData: D} = await h("loadChain", () => ni({
3045
+ (await n("@voltro/web/ssr")).beginStoreSeeds(), {chain: E, segmentLoaderData: D} = await h("loadChain", () => ri({
3024
3046
  entries: v,
3025
3047
  loadLayout: (t) => n(f(e, "src", "pages", t.dir, "layout.tsx")),
3026
3048
  loadError: (t) => n(f(e, "src", "pages", t.dir, "error.tsx")),
@@ -3030,7 +3052,7 @@ import {
3030
3052
  pathname: c,
3031
3053
  signal: C.signal,
3032
3054
  headers: b,
3033
- query: S
3055
+ query: x
3034
3056
  }
3035
3057
  }));
3036
3058
  let t = s.loader;
@@ -3039,12 +3061,12 @@ import {
3039
3061
  pathname: c,
3040
3062
  signal: C.signal,
3041
3063
  headers: b,
3042
- query: S
3064
+ query: x
3043
3065
  })));
3044
3066
  } finally {
3045
3067
  i.off("close", w);
3046
3068
  }
3047
- let O = await h("loadSsrHelpers", async () => await n("@voltro/web/ssr")), k = {
3069
+ let O = await h("loadSsrHelpers", async () => await n("@voltro/web/ssr")), ee = {
3048
3070
  pattern: l.route.pattern,
3049
3071
  Component: s.default,
3050
3072
  meta: s.meta,
@@ -3053,32 +3075,32 @@ import {
3053
3075
  Pending: s.Pending,
3054
3076
  renderMode: _,
3055
3077
  chain: E
3056
- }, A = {
3078
+ }, k = {
3057
3079
  cookies: O.parseCookieHeader(b.cookie),
3058
3080
  headers: b,
3059
3081
  url: o
3060
- }, j = s.interactive ?? "full", M = y ? Dr({
3082
+ }, A = s.interactive ?? "full", j = y ? Or({
3061
3083
  helpers: O,
3062
3084
  page: `src/pages/${l.route.file}`,
3063
- interactive: j,
3085
+ interactive: A,
3064
3086
  delivery: "stream",
3065
3087
  renderInput: {
3066
- descriptor: k,
3088
+ descriptor: ee,
3067
3089
  params: l.params,
3068
3090
  pathname: c,
3069
3091
  segmentLoaderData: D,
3070
- requestContext: A
3092
+ requestContext: k
3071
3093
  }
3072
- }) : null, N = y ? null : Er({
3094
+ }) : null, M = y ? null : Dr({
3073
3095
  helpers: O,
3074
3096
  page: `src/pages/${l.route.file}`,
3075
3097
  pathname: c,
3076
3098
  renderMode: _,
3077
- interactive: j,
3099
+ interactive: A,
3078
3100
  loaderData: T,
3079
3101
  segmentLoaderData: D,
3080
3102
  pageLoaderRan: typeof s.loader == "function"
3081
- }), P = [];
3103
+ }), N = [];
3082
3104
  await h("collectCss", async () => {
3083
3105
  let t = /* @__PURE__ */ new Set(), n = [
3084
3106
  f(e, "src", "pages", l.route.file),
@@ -3089,20 +3111,20 @@ import {
3089
3111
  ]),
3090
3112
  f(e, ".framework", "main.tsx")
3091
3113
  ];
3092
- for (let e of n) await g(e, t, P);
3114
+ for (let e of n) await g(e, t, N);
3093
3115
  });
3094
- let ee = await h("readShell", be), F = await h("transformShell", () => t.transformIndexHtml(o, ee)), te = P.map((e) => `<link rel="stylesheet" href="${e}?direct" />`).join("\n "), I = A.cookies["voltro:locale"] ?? "en", L = Date.now();
3095
- if (M) {
3096
- let e = (e) => kr({
3116
+ let P = await h("readShell", xe), F = await h("transformShell", () => t.transformIndexHtml(o, P)), te = N.map((e) => `<link rel="stylesheet" href="${e}?direct" />`).join("\n "), I = k.cookies["voltro:locale"] ?? "en", ne = Date.now();
3117
+ if (j) {
3118
+ let e = (e) => Ar({
3097
3119
  helpers: O,
3098
- prepared: M,
3120
+ prepared: j,
3099
3121
  meta: e,
3100
- interactive: j,
3122
+ interactive: A,
3101
3123
  extra: [te]
3102
3124
  });
3103
- if (M.hasDeferred) Rr({
3125
+ if (j.hasDeferred) zr({
3104
3126
  res: i,
3105
- shell: Ir({
3127
+ shell: Lr({
3106
3128
  shell: F,
3107
3129
  inlineModuleScriptsAsync: !0
3108
3130
  }),
@@ -3113,41 +3135,38 @@ import {
3113
3135
  },
3114
3136
  headInjection: e,
3115
3137
  render: (e) => O.renderPageToStream({
3116
- ...M.renderInput,
3138
+ ...j.renderInput,
3117
3139
  ...e
3118
3140
  }),
3119
3141
  onShellError: (e) => {
3120
- X.warn("spa-shell-dev shell render failed; falling back to SPA shell", {
3121
- pathname: c,
3122
- pattern: l.route.pattern
3123
- }, e), a();
3142
+ ge(i, "spa-shell-dev", c, l.route.pattern, e);
3124
3143
  }
3125
3144
  });
3126
3145
  else {
3127
- let t = Or({
3146
+ let t = kr({
3128
3147
  helpers: O,
3129
- prepared: M
3148
+ prepared: j
3130
3149
  }), n = F.replace("<div id=\"root\"></div>", `<div id="root">${t.body}</div>`).replace("</head>", ` ${e(t.meta)}\n </head>`).replace(/<html(\s+lang="[^"]*")?/i, `<html lang="${I}"`);
3131
3150
  i.statusCode = 200, i.setHeader("content-type", "text/html; charset=utf-8"), i.setHeader("x-voltro-rendered-by", "spa-shell-dev"), i.end(n);
3132
3151
  }
3133
- } else if (N) {
3152
+ } else if (M) {
3134
3153
  let e = (e) => [
3135
3154
  te,
3136
3155
  O.renderMetaToHtml(e),
3137
- `<meta name="voltro-interactive" content="${j}" />`,
3138
- ...N.hasDeferred ? [O.renderDeferredRegistryScript()] : [],
3139
- O.renderRouterStateScript(N.stateInput)
3156
+ `<meta name="voltro-interactive" content="${A}" />`,
3157
+ ...M.hasDeferred ? [O.renderDeferredRegistryScript()] : [],
3158
+ O.renderRouterStateScript(M.stateInput)
3140
3159
  ].filter((e) => e.length > 0).join("\n "), t = {
3141
- descriptor: k,
3160
+ descriptor: ee,
3142
3161
  params: l.params,
3143
3162
  pathname: c,
3144
- loaderData: N.loaderData,
3145
- segmentLoaderData: N.segmentLoaderData,
3146
- requestContext: A
3163
+ loaderData: M.loaderData,
3164
+ segmentLoaderData: M.segmentLoaderData,
3165
+ requestContext: k
3147
3166
  };
3148
- if (_ === "ssr" && j === "full") Rr({
3167
+ if (_ === "ssr" && A === "full") zr({
3149
3168
  res: i,
3150
- shell: Ir({
3169
+ shell: Lr({
3151
3170
  shell: F,
3152
3171
  inlineModuleScriptsAsync: !0
3153
3172
  }),
@@ -3162,10 +3181,7 @@ import {
3162
3181
  ...e
3163
3182
  }),
3164
3183
  onShellError: (e) => {
3165
- X.warn("ssr-dev shell render failed; falling back to SPA shell", {
3166
- pathname: c,
3167
- pattern: l.route.pattern
3168
- }, e), a();
3184
+ ge(i, "ssr-dev", c, l.route.pattern, e);
3169
3185
  }
3170
3186
  });
3171
3187
  else {
@@ -3173,57 +3189,54 @@ import {
3173
3189
  i.statusCode = 200, i.setHeader("content-type", "text/html; charset=utf-8"), i.setHeader("x-voltro-rendered-by", "ssr-dev"), i.end(a);
3174
3190
  }
3175
3191
  }
3176
- m.render = Date.now() - L;
3177
- let R = Date.now() - p;
3178
- d ? (me.add(l.route.pattern), X.info(`ssr compiled ${l.route.pattern} in ${R}ms`, {
3192
+ m.render = Date.now() - ne;
3193
+ let L = Date.now() - p;
3194
+ d ? (he.add(l.route.pattern), X.info(`ssr compiled ${l.route.pattern} in ${L}ms`, {
3179
3195
  pattern: l.route.pattern,
3180
3196
  pathname: c,
3181
- elapsedMs: R,
3197
+ elapsedMs: L,
3182
3198
  cold: !0,
3183
3199
  phases: m
3184
- })) : R > 200 && X.info(`ssr rendered ${c} in ${R}ms`, {
3200
+ })) : L > 200 && X.info(`ssr rendered ${c} in ${L}ms`, {
3185
3201
  pattern: l.route.pattern,
3186
3202
  pathname: c,
3187
- elapsedMs: R,
3203
+ elapsedMs: L,
3188
3204
  cold: !1,
3189
3205
  phases: m
3190
3206
  });
3191
3207
  } catch (e) {
3192
- if (Tr(e)) {
3208
+ if (Er(e)) {
3193
3209
  X.error("ssr-dev render refused", {
3194
3210
  pathname: c,
3195
3211
  pattern: l.route.pattern
3196
3212
  }, e), i.statusCode = 500, i.setHeader("content-type", "text/plain; charset=utf-8"), i.end(e.message);
3197
3213
  return;
3198
3214
  }
3199
- X.warn("ssr-dev render failed; falling back to SPA shell", {
3200
- pathname: c,
3201
- pattern: l.route.pattern
3202
- }, e), a();
3215
+ ge(i, "ssr-dev", c, l.route.pattern, e);
3203
3216
  }
3204
3217
  });
3205
3218
  }
3206
- }, B = Date.now(), Se = w.version ?? "?", V = await Vr(), Ce = f(e, "node_modules", "@voltro", "ui-shadcn"), H = O(f(Ce, "package.json")) ? Ce : null, we = [], Te = await (async () => {
3219
+ }, B = Date.now(), Ce = T.version ?? "?", V = await Hr(), we = f(e, "node_modules", "@voltro", "ui-shadcn"), H = O(f(we, "package.json")) ? we : null, Te = [], Ee = await (async () => {
3207
3220
  let t = [];
3208
3221
  for (let n of u) {
3209
3222
  if (!n.proxyTarget) continue;
3210
- let r = await ci(e, n.pkg);
3223
+ let r = await li(e, n.pkg);
3211
3224
  if (r) try {
3212
- t.push(await j.readFile(f(r, "rpcGroup.generated.ts"), "utf8"));
3225
+ t.push(await A.readFile(f(r, "rpcGroup.generated.ts"), "utf8"));
3213
3226
  } catch {}
3214
3227
  }
3215
3228
  if (t.length === 0) return !1;
3216
3229
  let n = _e("sha1").update(t.join("\0")).digest("hex"), r = f(k, ".voltro-rpcgroup-optimize"), i = "";
3217
3230
  try {
3218
- i = (await j.readFile(r, "utf8")).trim();
3231
+ i = (await A.readFile(r, "utf8")).trim();
3219
3232
  } catch {}
3220
3233
  if (i === n) return !1;
3221
3234
  try {
3222
- await j.writeFile(r, n);
3235
+ await A.writeFile(r, n);
3223
3236
  } catch {}
3224
3237
  return !0;
3225
3238
  })();
3226
- Te && X.info("rpcGroup changed since last boot — forcing a dep re-optimize so the browser loads the current api client"), await (await w.createServer({
3239
+ Ee && X.info("rpcGroup changed since last boot — forcing a dep re-optimize so the browser loads the current api client"), await (await T.createServer({
3227
3240
  root: k,
3228
3241
  envPrefix: "__VOLTRO_VITE_ENV_DISABLED__",
3229
3242
  ssr: { noExternal: ["react-intl"] },
@@ -3255,40 +3268,40 @@ import {
3255
3268
  replacement: f(H, "src/index.ts")
3256
3269
  }
3257
3270
  ] : [],
3258
- ...qe(e)
3271
+ ...st(e)
3259
3272
  ]
3260
3273
  },
3261
3274
  optimizeDeps: {
3262
- include: [...u.map((e) => `${e.pkg}/rpcGroup`), ...we],
3263
- force: Te
3275
+ include: [...u.map((e) => `${e.pkg}/rpcGroup`), ...Te],
3276
+ force: Ee
3264
3277
  },
3265
- customLogger: Ct(),
3278
+ customLogger: Lt(),
3266
3279
  plugins: [
3267
- kn(f(e, "src", "pages")),
3268
- T(),
3280
+ Un(f(e, "src", "pages")),
3269
3281
  D(),
3282
+ ee(),
3270
3283
  N,
3271
- I,
3272
- ae,
3284
+ ne,
3273
3285
  se,
3274
- ce,
3275
- de,
3276
- xe,
3277
- ...fe ? [fe] : []
3286
+ le,
3287
+ ue,
3288
+ pe,
3289
+ Se,
3290
+ ...me ? [me] : []
3278
3291
  ],
3279
3292
  server: {
3280
3293
  port: g,
3281
3294
  strictPort: !0,
3282
3295
  host: !0,
3283
3296
  allowedHosts: t.allowedHosts === !0 || [...t.allowedHosts ?? []],
3284
- proxy: z,
3285
- fs: { allow: [e, ...qr(e)] }
3297
+ proxy: R,
3298
+ fs: { allow: [e, ...Jr(e)] }
3286
3299
  },
3287
3300
  appType: "spa",
3288
3301
  cacheDir: f(k, ".vite"),
3289
3302
  publicDir: f(e, "public")
3290
- })).listen(), zr.info(`v${Se} ready in ${Date.now() - B}ms`, {
3291
- version: Se,
3303
+ })).listen(), Br.info(`v${Ce} ready in ${Date.now() - B}ms`, {
3304
+ version: Ce,
3292
3305
  bootMs: Date.now() - B
3293
3306
  }), X.info(`listening on http://localhost:${g}`, {
3294
3307
  port: g,
@@ -3299,7 +3312,7 @@ import {
3299
3312
  target: e.proxyTarget
3300
3313
  }), X.info(`proxy /_voltro/api/${e.name} → ${e.proxyTarget.replace(/^ws/, "http")}/_voltro/inspect`, { api: e.name }));
3301
3314
  try {
3302
- await er({
3315
+ await rt({
3303
3316
  id: v,
3304
3317
  name: _,
3305
3318
  kind: "web",
@@ -3308,13 +3321,13 @@ import {
3308
3321
  status: "live",
3309
3322
  logFile: y.path
3310
3323
  });
3311
- let t = mr(e);
3324
+ let t = hr(e);
3312
3325
  if (t) {
3313
- let e = await Cr({ dashboardAppPath: t });
3326
+ let e = await wr({ dashboardAppPath: t });
3314
3327
  e.status === "launched" ? X.info(`dashboard launched at http://localhost:${e.port}`, { port: e.port }) : e.status === "already-running" && X.debug(`dashboard already running on :${e.port}`, { port: e.port });
3315
3328
  }
3316
3329
  setInterval(() => {
3317
- er({
3330
+ rt({
3318
3331
  id: v,
3319
3332
  name: _,
3320
3333
  kind: "web",
@@ -3325,7 +3338,7 @@ import {
3325
3338
  }).catch(() => {});
3326
3339
  }, 1e4).unref();
3327
3340
  let n = () => {
3328
- tr(v), y.dispose();
3341
+ it(v), y.dispose();
3329
3342
  };
3330
3343
  process.on("SIGINT", n), process.on("SIGTERM", n);
3331
3344
  } catch (e) {
@@ -3337,16 +3350,16 @@ import {
3337
3350
  url: `http://localhost:${g}`,
3338
3351
  bootMs: Date.now() - B
3339
3352
  }), new Promise(() => {});
3340
- }, Ci = async (e) => {
3353
+ }, wi = async (e) => {
3341
3354
  process.env.NODE_ENV || (process.env.NODE_ENV = "production");
3342
- let t = await xi(e);
3355
+ let t = await Si(e);
3343
3356
  if (!t) return {
3344
3357
  ran: !1,
3345
3358
  exitCode: 0
3346
3359
  };
3347
3360
  let n = Date.now(), r = X.child("serve");
3348
3361
  r.info("booting voltro serve (preview)", { app: t.name ?? "(unnamed)" });
3349
- let i = await pi(e, t);
3362
+ let i = await mi(e, t);
3350
3363
  for (let e of i) r.info("api wired", {
3351
3364
  name: e.name,
3352
3365
  pkg: e.pkg
@@ -3354,21 +3367,21 @@ import {
3354
3367
  await $(e, t, i);
3355
3368
  {
3356
3369
  let { pages: t } = await Q(f(e, "src", "pages"));
3357
- await It({
3370
+ await Xt({
3358
3371
  appRoot: e,
3359
3372
  pages: t
3360
3373
  });
3361
3374
  }
3362
- let a = t.port ?? 5173, o = await Ye("vite", () => import("vite")), s = (await import("@vitejs/plugin-react")).default, c = f(e, ".framework");
3375
+ let a = t.port ?? 5173, o = await lt("vite", () => import("vite")), s = (await import("@vitejs/plugin-react")).default, c = f(e, ".framework");
3363
3376
  X.info("running production build"), await o.build({
3364
3377
  root: c,
3365
3378
  envPrefix: "__VOLTRO_VITE_ENV_DISABLED__",
3366
3379
  plugins: [s()],
3367
- customLogger: Ct(),
3380
+ customLogger: Lt(),
3368
3381
  resolve: { dedupe: ["react", "react-dom"] },
3369
3382
  build: {
3370
3383
  outDir: "dist",
3371
- rollupOptions: { output: { manualChunks: Yr } }
3384
+ rollupOptions: { output: { manualChunks: Xr } }
3372
3385
  },
3373
3386
  publicDir: f(e, "public")
3374
3387
  });
@@ -3388,14 +3401,14 @@ import {
3388
3401
  extras: d,
3389
3402
  bootMs: Date.now() - n
3390
3403
  }), new Promise(() => {});
3391
- }, wi = 5e3, Ti = 6e4, Ei = (e, t) => {
3404
+ }, Ti = 5e3, Ei = 6e4, Di = (e, t) => {
3392
3405
  if (e.length === 0) return 0;
3393
3406
  if (e.length === 1) return e[0];
3394
3407
  let n = t * (e.length - 1), r = Math.floor(n), i = Math.ceil(n);
3395
3408
  if (r === i) return e[r];
3396
3409
  let a = n - r;
3397
3410
  return e[r] * (1 - a) + e[i] * a;
3398
- }, Di = (e) => {
3411
+ }, Oi = (e) => {
3399
3412
  if (e.length === 0) return {
3400
3413
  p50: 0,
3401
3414
  p95: 0,
@@ -3407,18 +3420,18 @@ import {
3407
3420
  let t = e.slice().sort((e, t) => e - t), n = 0;
3408
3421
  for (let e of t) n += e;
3409
3422
  return {
3410
- p50: Ei(t, .5),
3411
- p95: Ei(t, .95),
3412
- p99: Ei(t, .99),
3423
+ p50: Di(t, .5),
3424
+ p95: Di(t, .95),
3425
+ p99: Di(t, .99),
3413
3426
  mean: n / t.length,
3414
3427
  min: t[0],
3415
3428
  max: t[t.length - 1]
3416
3429
  };
3417
- }, Oi = (e = {}) => {
3418
- let t = e.maxSamples ?? wi, n = e.defaultWindowMs ?? Ti, r = [];
3430
+ }, ki = (e = {}) => {
3431
+ let t = e.maxSamples ?? Ti, n = e.defaultWindowMs ?? Ei, r = [];
3419
3432
  return {
3420
3433
  record(e) {
3421
- R(e), r.push({
3434
+ L(e), r.push({
3422
3435
  ...e,
3423
3436
  ts: Date.now()
3424
3437
  }), r.length > t && r.shift();
@@ -3444,7 +3457,7 @@ import {
3444
3457
  tag: e.tag,
3445
3458
  count: e.samples.length,
3446
3459
  errorCount: n,
3447
- latencyMs: Di(t)
3460
+ latencyMs: Oi(t)
3448
3461
  });
3449
3462
  }
3450
3463
  return c.sort((e, t) => t.count - e.count), {
@@ -3457,4 +3470,4 @@ import {
3457
3470
  };
3458
3471
  };
3459
3472
  //#endregion
3460
- export { ht as $, tr as A, bn as B, Cr as C, ur as D, lr as E, In as F, Jt as G, cn as H, jn as I, Rt as J, Kt as K, Nn as L, Rn as M, Bn as N, nr as O, An as P, wt as Q, Fn as R, pr as S, cr as T, rn as U, pn as V, tn as W, It as X, Bt as Y, Et as Z, Er as _, Ce as _t, ni as a, ot as at, kr as b, pi as c, at as ct, Yr as d, $e as dt, pt as et, Q as f, Ye as ft, Tr as g, V as gt, Rr as h, Ge as ht, vi as i, lt as it, er as j, $n as k, Si as l, nt as lt, Ir as m, We as mt, Xr as n, st as nt, ti as o, G as ot, $ as p, qe as pt, zt as q, _i as r, ct as rt, xi as s, it as st, Oi as t, ft as tt, Ci as u, et as ut, Dr as v, mr as w, hr as x, Or as y, yn as z };
3473
+ export { St as $, Wn as A, gn as B, wr as C, dr as D, ur as E, Nn as F, en as G, sn as H, Pn as I, Rt as J, Xt as K, Dn as L, Gn as M, qn as N, Qn as O, Yn as P, xt as Q, Sn as R, mr as S, lr as T, $t as U, ln as V, Qt as W, Dt as X, kt as Y, Et as Z, Dr as _, we as _t, ri as a, gt as at, Ar as b, mi as c, lt as ct, Xr as d, nt as dt, Ct as et, Q as f, it as ft, Er as g, V as gt, zr as h, Ke as ht, yi as i, yt as it, Xn as j, er as k, Ci as l, st as lt, Lr as m, Ge as mt, Zr as n, G as nt, ni as o, mt as ot, $ as p, rt as pt, Bt as q, vi as r, vt as rt, Si as s, pt as st, ki as t, bt as tt, wi as u, at as ut, Or as v, hr as w, gr as x, kr as y, vn as z };