@voltro/cli 0.25.0 → 0.26.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 (69) hide show
  1. package/CHANGELOG.md +244 -0
  2. package/dist/{apiBuild-BqhCSytw.js → apiBuild-BtrTyKnF.js} +2 -2
  3. package/dist/apiBuild-DDJ0It4j.js +2 -0
  4. package/dist/bin.js +3 -3
  5. package/dist/{commands-7EmYJ9Xg.js → commands-D-9iYF2D.js} +185 -84
  6. package/dist/dbCommand-DrzXimKf.js +2 -0
  7. package/dist/{dbCommand-FUU12FvD.js → dbCommand-uuNCrFAb.js} +238 -238
  8. package/dist/{dev-BvHT7WZa.js → dev-BnWq4jeA.js} +1 -1
  9. package/dist/{dev-MacSQ1Ll.js → dev-Dbm6SWtn.js} +1665 -1463
  10. package/dist/{frameworkTableAssembly-Cw5zJz6n.js → frameworkTableAssembly-BwHU9Euq.js} +10 -6
  11. package/dist/frameworkTableAssembly-lrjZtk0G.js +2 -0
  12. package/dist/index.js +1 -1
  13. package/dist/{inspect-DuLUrZp9.js → inspect-CUCCzw2I.js} +6 -3
  14. package/dist/inspect-gt8bq-Tz.js +2 -0
  15. package/dist/{inspectMetrics-EQwH7BI4.js → inspectMetrics-BU90mvJN.js} +1 -1
  16. package/dist/{manifestBuild-Dneq4_Jx.js → manifestBuild-BnzAxp2O.js} +1 -1
  17. package/dist/manifestBuild-ifczArzr.js +2 -0
  18. package/dist/serveCommand-XBXuwJty.js +1294 -0
  19. package/dist/serveEntry.js +2 -2
  20. package/dist/{start-C-ZWSDpg.js → start-BGXIf6zT.js} +2 -2
  21. package/dist/startEntry.js +2 -2
  22. package/package.json +17 -17
  23. package/templates/agent-docs/data.md +35 -2
  24. package/templates/agent-docs/database/schema.md +47 -0
  25. package/templates/agent-docs/deployment.md +19 -0
  26. package/templates/agent-docs/plugins.md +25 -3
  27. package/templates/agent-docs/whats-new.md +19 -3
  28. package/templates/agent-docs/workflows.md +116 -22
  29. package/templates/apps/api-ai/package.json +7 -7
  30. package/templates/apps/api-auth/package.json +8 -8
  31. package/templates/apps/api-backend/package.json +7 -7
  32. package/templates/apps/api-backend-deactivation/package.json +7 -7
  33. package/templates/apps/api-backend-mail/package.json +8 -8
  34. package/templates/apps/api-backend-mariadb/package.json +9 -9
  35. package/templates/apps/api-backend-storage/package.json +8 -8
  36. package/templates/apps/api-data-advanced/package.json +8 -8
  37. package/templates/apps/api-durable/package.json +8 -8
  38. package/templates/apps/api-feature-flags/package.json +9 -9
  39. package/templates/apps/api-governance/package.json +8 -8
  40. package/templates/apps/api-kv/package.json +8 -8
  41. package/templates/apps/api-moderation/package.json +8 -8
  42. package/templates/apps/api-observability/package.json +8 -8
  43. package/templates/apps/api-ratelimit/package.json +8 -8
  44. package/templates/apps/api-rbac/package.json +8 -8
  45. package/templates/apps/api-rest/package.json +7 -7
  46. package/templates/apps/api-saas/package.json +11 -11
  47. package/templates/apps/api-search/package.json +8 -8
  48. package/templates/apps/api-versioning/package.json +8 -8
  49. package/templates/apps/api-webhooks/package.json +9 -9
  50. package/templates/apps/changelog/package.json +6 -6
  51. package/templates/apps/edge-functions/package.json +2 -2
  52. package/templates/apps/frontend-admin/package.json +8 -8
  53. package/templates/apps/frontend-app/package.json +8 -8
  54. package/templates/apps/frontend-blank/package.json +7 -7
  55. package/templates/apps/frontend-contact/package.json +7 -7
  56. package/templates/apps/frontend-dashboard/package.json +7 -7
  57. package/templates/apps/frontend-docs/package.json +7 -7
  58. package/templates/apps/frontend-i18n/package.json +6 -6
  59. package/templates/apps/frontend-landing/package.json +7 -7
  60. package/templates/apps/frontend-spa/package.json +7 -7
  61. package/templates/apps/frontend-ssr/package.json +7 -7
  62. package/templates/apps/frontend-ssr-api/package.json +8 -8
  63. package/templates/apps/frontend-static-blog/package.json +6 -6
  64. package/dist/apiBuild-N1R4V792.js +0 -2
  65. package/dist/dbCommand-CIrdFLp9.js +0 -2
  66. package/dist/frameworkTableAssembly-BsnCKzQ6.js +0 -2
  67. package/dist/inspect-C9gjHwBk.js +0 -2
  68. package/dist/manifestBuild-BVwS1Z_6.js +0 -2
  69. package/dist/serveCommand-5ZFiNO1R.js +0 -1241
@@ -1,14 +1,14 @@
1
- import { A as e, E as t, I as n, L as r, M as i, N as a, O as o, P as s, S as c, T as l, _t as u, a as d, at as f, b as p, c as m, ct as h, d as g, f as _, ft as v, gt as y, ht as b, it as ee, j as te, k as ne, lt as re, n as ie, o as ae, ot as oe, p as se, q as ce, s as le, st as ue, u as de, ut as fe, v as pe, y as me } from "./inspectMetrics-EQwH7BI4.js";
1
+ import { A as e, E as t, I as n, L as r, M as i, N as a, O as o, P as s, S as c, T as l, _t as u, a as d, at as f, b as p, c as m, ct as h, d as g, f as _, ft as v, gt as y, ht as b, it as ee, j as te, k as ne, lt as re, n as ie, o as ae, ot as oe, p as se, q as ce, s as le, st as ue, u as de, ut as fe, v as pe, y as me } from "./inspectMetrics-BU90mvJN.js";
2
2
  import { s as he } from "./seedRunner-D6eu-u5U.js";
3
3
  import { a as x, c as ge, i as _e, o as ve, s as ye } from "./devActivity-BhIu6ncs.js";
4
- import { i as be, x as xe } from "./frameworkTableAssembly-Cw5zJz6n.js";
5
- import { A as Se, C as Ce, E as we, O as Te, S as Ee, T as De, b as Oe, c as ke, d as Ae, f as je, i as Me, l as Ne, n as Pe, o as Fe, r as Ie, s as Le, w as Re } from "./fileConventions-3bffWssN.js";
6
- import { C as ze, Z as Be, at as Ve, c as He, f as Ue, i as We, it as Ge, l as Ke, nt as qe, o as Je, ot as Ye, rt as Xe, vt as Ze } from "./dev-MacSQ1Ll.js";
7
- import { i as Qe, n as $e, o as et, r as tt, s as nt, u as rt } from "./apiBuild-BqhCSytw.js";
8
- import { t as it } from "./start-C-ZWSDpg.js";
4
+ import { C as be, Q as xe, at as Se, c as Ce, f as we, i as Te, it as Ee, l as De, o as Oe, ot as ke, rt as Ae, st as je, yt as Me } from "./dev-Dbm6SWtn.js";
5
+ import { i as Ne, x as Pe } from "./frameworkTableAssembly-BwHU9Euq.js";
6
+ import { A as Fe, C as Ie, E as Le, O as Re, S as ze, T as Be, b as Ve, c as He, d as Ue, f as We, i as Ge, l as Ke, n as qe, o as Je, r as Ye, s as Xe, w as Ze } from "./fileConventions-3bffWssN.js";
7
+ import { i as Qe, n as $e, o as et, r as tt, s as nt, u as rt } from "./apiBuild-BtrTyKnF.js";
8
+ import { t as it } from "./start-BGXIf6zT.js";
9
9
  import { a as at, i as ot, n as st, r as ct, t as lt } from "./cliArgs-qdZSElM3.js";
10
- import { n as ut, r as dt } from "./serveCommand-5ZFiNO1R.js";
11
- import { c as ft, r as pt, s as mt } from "./dbCommand-FUU12FvD.js";
10
+ import { n as ut, r as dt } from "./serveCommand-XBXuwJty.js";
11
+ import { c as ft, r as pt, s as mt } from "./dbCommand-uuNCrFAb.js";
12
12
  import { basename as S, dirname as C, isAbsolute as ht, join as w, relative as T, resolve as E, sep as gt } from "node:path";
13
13
  import { fileURLToPath as _t, pathToFileURL as vt } from "node:url";
14
14
  import { FileSystem as yt } from "@effect/platform";
@@ -600,7 +600,7 @@ never mint — inspect stays closed until an operator opens it.`);
600
600
  if (hr.has(a.name)) continue;
601
601
  let i = w(e, a.name);
602
602
  if (a.isDirectory()) await r(i);
603
- else if (a.isFile() && Ae.test(a.name)) {
603
+ else if (a.isFile() && Ue.test(a.name)) {
604
604
  let e = T(t, i), r = await Wt(i, "utf8");
605
605
  n.push({
606
606
  file: e,
@@ -992,10 +992,10 @@ never mint — inspect stays closed until an operator opens it.`);
992
992
  }, Mr = async (e) => {
993
993
  let t = await le(e);
994
994
  if (!t) {
995
- let { loadApiConfig: t } = await import("./dev-BvHT7WZa.js"), n = await t(e);
995
+ let { loadApiConfig: t } = await import("./dev-BnWq4jeA.js"), n = await t(e);
996
996
  if (n) {
997
997
  U.info("building api app", { app: n.name ?? "(unnamed)" });
998
- let { runApiBuild: t, runServeBundleBuild: r } = await import("./apiBuild-N1R4V792.js");
998
+ let { runApiBuild: t, runServeBundleBuild: r } = await import("./apiBuild-DDJ0It4j.js");
999
999
  await t(e);
1000
1000
  try {
1001
1001
  await r(e);
@@ -1175,7 +1175,7 @@ never mint — inspect stays closed until an operator opens it.`);
1175
1175
  }).pipe(D.orDie);
1176
1176
  return t.ran ? t.exitCode : (yield* D.logError("no web app found at this path", { hint: "looked for app.config.ts with `type: 'web'`" }), 1);
1177
1177
  }), Pr = async (e) => {
1178
- let t = e.find((e) => !e.startsWith("-")) ?? process.cwd(), n = await u(Nr(t), { scope: "voltro:build" }), r = Ze(t);
1178
+ let t = e.find((e) => !e.startsWith("-")) ?? process.cwd(), n = await u(Nr(t), { scope: "voltro:build" }), r = Me(t);
1179
1179
  return r.warning !== void 0 && U.warn(r.warning), n;
1180
1180
  }, Fr = (e) => e.source === void 0 ? [] : typeof e.source == "string" ? [e.source] : e.source, Ir = (e) => ({
1181
1181
  tables: new Set(e.tables),
@@ -1421,9 +1421,9 @@ never mint — inspect stays closed until an operator opens it.`);
1421
1421
  }
1422
1422
  })).status === "accepted" ? 0 : 1;
1423
1423
  }, $r = async (e) => {
1424
- let t = E(e.find((e) => !e.startsWith("-")) ?? process.cwd()), { config: n, present: r, error: i } = await Ke(t);
1424
+ let t = E(e.find((e) => !e.startsWith("-")) ?? process.cwd()), { config: n, present: r, error: i } = await De(t);
1425
1425
  if (r && n === null) return console.error("voltro codegen: app.config.ts exists but could not be loaded — refusing to write."), console.error(" The generated file would omit every plugin's error union and client routes, and would typecheck, so the omission would only surface as a missing error tag at runtime."), i !== void 0 && console.error(` cause: ${i instanceof Error ? i.message : String(i)}`), 1;
1426
- let a = n?.plugins ?? [], { pluginContributions: o, pluginErrorImports: s, pluginRpcImports: c } = await ze(a, n?.name ?? S(t), t), l = await qe({
1426
+ let a = n?.plugins ?? [], { pluginContributions: o, pluginErrorImports: s, pluginRpcImports: c } = await be(a, n?.name ?? S(t), t), l = await Ae({
1427
1427
  root: t,
1428
1428
  ...o.length > 0 ? { pluginContributions: o } : {},
1429
1429
  ...s.length > 0 ? { pluginErrorImports: s } : {},
@@ -1566,45 +1566,45 @@ never mint — inspect stays closed until an operator opens it.`);
1566
1566
  }, ci = (e, t) => t.some((t) => e === t.dir || e.startsWith(`${t.dir}${gt}`)), li = (e, t) => t.map((t) => `${T(e, t.dir) || "."} (${t.source})`), ui = [
1567
1567
  {
1568
1568
  id: "component.ui",
1569
- re: Ie,
1569
+ re: Ye,
1570
1570
  needsTest: !0
1571
1571
  },
1572
1572
  {
1573
1573
  id: "component",
1574
- re: Pe,
1574
+ re: qe,
1575
1575
  needsTest: !0
1576
1576
  },
1577
1577
  {
1578
1578
  id: "hook",
1579
- re: Le,
1579
+ re: Xe,
1580
1580
  needsTest: !0
1581
1581
  },
1582
1582
  {
1583
1583
  id: "tracking",
1584
- re: Ce,
1584
+ re: Ie,
1585
1585
  needsTest: !0
1586
1586
  },
1587
1587
  {
1588
1588
  id: "store",
1589
- re: Oe,
1589
+ re: Ve,
1590
1590
  needsTest: !0
1591
1591
  },
1592
1592
  {
1593
1593
  id: "internal",
1594
- re: ke,
1594
+ re: He,
1595
1595
  needsTest: !0
1596
1596
  },
1597
1597
  {
1598
1598
  id: "fixture",
1599
- re: Fe,
1599
+ re: Je,
1600
1600
  needsTest: !1
1601
1601
  },
1602
1602
  {
1603
1603
  id: "types",
1604
- re: De,
1604
+ re: Be,
1605
1605
  needsTest: !1
1606
1606
  }
1607
- ], di = (e) => ui.find((t) => t.re.test(e))?.id ?? null, fi = (e) => Ee.test(e), pi = /* @__PURE__ */ new Set([
1607
+ ], di = (e) => ui.find((t) => t.re.test(e))?.id ?? null, fi = (e) => ze.test(e), pi = /* @__PURE__ */ new Set([
1608
1608
  "useMutation",
1609
1609
  "useAction",
1610
1610
  "useUpload",
@@ -1893,7 +1893,7 @@ never mint — inspect stays closed until an operator opens it.`);
1893
1893
  });
1894
1894
  let n = f(e), i = n.filter((e) => {
1895
1895
  let t = di(e);
1896
- return t === "component" || t === "component.ui" || Ae.test(e) || je.has(e.slice(e.lastIndexOf(gt) + 1));
1896
+ return t === "component" || t === "component.ui" || Ue.test(e) || We.has(e.slice(e.lastIndexOf(gt) + 1));
1897
1897
  });
1898
1898
  n.length === 0 ? a.push({
1899
1899
  rule: "ui/orphaned",
@@ -2969,7 +2969,7 @@ never mint — inspect stays closed until an operator opens it.`);
2969
2969
  let t = to.get(e);
2970
2970
  if (t !== void 0) return t;
2971
2971
  let n = (async () => {
2972
- let { walk: t, loadDiscovered: n } = await import("./dev-BvHT7WZa.js"), r = await t(e);
2972
+ let { walk: t, loadDiscovered: n } = await import("./dev-BnWq4jeA.js"), r = await t(e);
2973
2973
  return {
2974
2974
  files: r,
2975
2975
  discovered: await n(r)
@@ -3046,7 +3046,7 @@ never mint — inspect stays closed until an operator opens it.`);
3046
3046
  }) => /* @__PURE__ */ new Set([...Qi, ...$i(Ma(e).map(t))]), uo = async (e) => {
3047
3047
  let { discovered: t } = await no(e), n = [];
3048
3048
  try {
3049
- let { loadApiConfig: t } = await import("./dev-BvHT7WZa.js");
3049
+ let { loadApiConfig: t } = await import("./dev-BnWq4jeA.js");
3050
3050
  n = ((await t(e))?.plugins ?? []).map((e) => {
3051
3051
  let t = (e.extendSchema?.tables ?? []).map((e) => {
3052
3052
  let t = e;
@@ -3248,7 +3248,7 @@ never mint — inspect stays closed until an operator opens it.`);
3248
3248
  } catch {
3249
3249
  continue;
3250
3250
  }
3251
- a.isDirectory() ? yo(r, t, n + 1) : a.isFile() && Xe.test(i) && t.push(r);
3251
+ a.isDirectory() ? yo(r, t, n + 1) : a.isFile() && Ee.test(i) && t.push(r);
3252
3252
  }
3253
3253
  return t;
3254
3254
  }, bo = /* @__PURE__ */ new Set(["actors", "tenants"]), xo = async (e) => {
@@ -3282,12 +3282,12 @@ never mint — inspect stays closed until an operator opens it.`);
3282
3282
  let t = e.severity === "error" ? "✗ error" : "⚠ warn", n = e.file ? ` (${e.file})` : "";
3283
3283
  return `${t} ${e.rule} ${e.node}${n}\n ${e.breaks.join("; ")}\n fix: ${e.fix}`;
3284
3284
  }).join("\n"), To = async (e) => {
3285
- let { walk: t, loadDiscovered: n, loadApiConfig: r } = await import("./dev-BvHT7WZa.js"), { buildRpcEntry: i } = await import("./manifestBuild-BVwS1Z_6.js"), { buildCapabilityManifest: a } = await import("./inspect-C9gjHwBk.js"), { relative: o } = await import("node:path"), s = await n(await t(e)), c = (t, n, r) => i(t, n, o(e, r)), l = [
3285
+ let { walk: t, loadDiscovered: n, loadApiConfig: r } = await import("./dev-BnWq4jeA.js"), { buildRpcEntry: i } = await import("./manifestBuild-ifczArzr.js"), { buildCapabilityManifest: a } = await import("./inspect-gt8bq-Tz.js"), { relative: o } = await import("node:path"), s = await n(await t(e)), c = (t, n, r) => i(t, n, o(e, r)), l = [
3286
3286
  ...s.queries.map((e) => c(e.descriptor, "query", e.file)),
3287
3287
  ...s.mutations.map((e) => c(e.descriptor, "mutation", e.file)),
3288
3288
  ...s.actions.map((e) => c(e.descriptor, "action", e.file)),
3289
3289
  ...s.streams.map((e) => c(e.descriptor, "stream", e.file))
3290
- ], { assembleFrameworkTables: u } = await import("./frameworkTableAssembly-BsnCKzQ6.js"), d = await u({ root: e }).catch(() => []), f = new Set(s.tables.map((e) => e.tableName)), p = [...[...f].map((e) => ({ name: e })), ...d.map((e) => e.tableName).filter((e) => !f.has(e)).map((e) => ({
3290
+ ], { assembleFrameworkTables: u } = await import("./frameworkTableAssembly-lrjZtk0G.js"), d = await u({ root: e }).catch(() => []), f = new Set(s.tables.map((e) => e.tableName)), p = [...[...f].map((e) => ({ name: e })), ...d.map((e) => e.tableName).filter((e) => !f.has(e)).map((e) => ({
3291
3291
  name: e,
3292
3292
  framework: !0
3293
3293
  }))], m = await r(e).then((e) => e?.plugins ?? []).catch(() => []);
@@ -3346,7 +3346,7 @@ never mint — inspect stays closed until an operator opens it.`);
3346
3346
  breaks: [e.kind === "suffixed-outside-pages" ? "a page.tsx outside src/pages/ never routes" : "no test beside it"],
3347
3347
  fix: e.kind === "suffixed-outside-pages" ? "move it under src/pages/ into the directory whose route it serves, or rename it — page.tsx is reserved" : "write the test with the file — the name is derivable",
3348
3348
  severity: e.kind === "suffixed-outside-pages" ? "error" : "warn"
3349
- }))], m = (await Ge(o, yo(o))).map((e) => ({
3349
+ }))], m = (await Se(o, yo(o))).map((e) => ({
3350
3350
  rule: "client/not-browser-safe",
3351
3351
  node: e.file,
3352
3352
  file: e.file,
@@ -3382,7 +3382,7 @@ never mint — inspect stays closed until an operator opens it.`);
3382
3382
  from: n,
3383
3383
  mode: r ? "start" : "dev",
3384
3384
  apps: process.env.VOLTRO_DASHBOARD_APPS ? "configured" : "none (set VOLTRO_DASHBOARD_APPS)"
3385
- }), r ? it([n]) : Ue([n]);
3385
+ }), r ? it([n]) : we([n]);
3386
3386
  }, Ao = (e, t) => t ? "type" : e.startsWith("define") ? "primitive" : /^use[A-Z]/.test(e) ? "hook" : /^[A-Z]/.test(e) ? "component" : "value", jo = (e) => {
3387
3387
  let t = /* @__PURE__ */ new Map(), n = (e, n) => {
3388
3388
  (!t.has(e) || !n) && t.set(e, n);
@@ -3506,9 +3506,9 @@ never mint — inspect stays closed until an operator opens it.`);
3506
3506
  let t = A({ scope: "dormancy" }), n = {
3507
3507
  info: (e, n) => t.info(e, n ?? {}),
3508
3508
  warn: (e, n) => t.warn(e, n ?? {})
3509
- }, r = E(e.find((e) => !e.startsWith("-")) ?? process.cwd()), i = await He(r), a = (process.env.DB_DIALECT ?? i?.store ?? "memory").toLowerCase();
3509
+ }, r = E(e.find((e) => !e.startsWith("-")) ?? process.cwd()), i = await Ce(r), a = (process.env.DB_DIALECT ?? i?.store ?? "memory").toLowerCase();
3510
3510
  if (a === "memory") return t.error("voltro dormancy needs a SQL store (postgres/mysql/mariadb/mssql) — the orchestrator and the app share the `_voltro_wakeups` table, which an in-process `memory` store cannot do. Set DB_DIALECT or the app.config `store` field."), 2;
3511
- let o = Number(process.env.PORT ?? Lo(e, "--port") ?? 4e3), s = Number(Lo(e, "--app-port") ?? o + 1), c = Number(Lo(e, "--idle-grace-ms") ?? 6e4), l = Number(Lo(e, "--tick-ms") ?? 1e3), u = await We(i, void 0), d = Et({
3511
+ let o = Number(process.env.PORT ?? Lo(e, "--port") ?? 4e3), s = Number(Lo(e, "--app-port") ?? o + 1), c = Number(Lo(e, "--idle-grace-ms") ?? 6e4), l = Number(Lo(e, "--tick-ms") ?? 1e3), u = await Te(i, void 0), d = Et({
3512
3512
  command: process.execPath,
3513
3513
  args: [
3514
3514
  process.argv[1],
@@ -3654,7 +3654,7 @@ never mint — inspect stays closed until an operator opens it.`);
3654
3654
  ]
3655
3655
  });
3656
3656
  c.push(i), await Bo(o, "web"), W.info(`running ${s.length} test file(s)`, { count: s.length });
3657
- let l = 0, u = Ve(), d = Ye(u);
3657
+ let l = 0, u = ke(), d = je(u);
3658
3658
  d !== void 0 && W.warn(d);
3659
3659
  for (let e of s) {
3660
3660
  let t = await new Promise((t) => {
@@ -3969,7 +3969,7 @@ never mint — inspect stays closed until an operator opens it.`);
3969
3969
  await i.dispose();
3970
3970
  }
3971
3971
  }, G = A({ scope: "voltro:env" }), ls = "# Environment for this app", us = async (e) => {
3972
- let t = await He(e).catch(() => null);
3972
+ let t = await Ce(e).catch(() => null);
3973
3973
  if (!t) return null;
3974
3974
  let n = Vt(t.env) ? t.env : void 0, r = t.type === "api" ? t.plugins ?? [] : void 0;
3975
3975
  return {
@@ -4001,7 +4001,7 @@ never mint — inspect stays closed until an operator opens it.`);
4001
4001
  }
4002
4002
  return await N.writeFile(i, r, "utf8"), G.info("wrote .env.example", { app: n.name }), 0;
4003
4003
  }, hs = async (e) => {
4004
- let t = await He(e).catch(() => null);
4004
+ let t = await Ce(e).catch(() => null);
4005
4005
  if (!t) return G.error("no app.config.ts found in the current directory"), 1;
4006
4006
  let n = Vt(t.env) ? t.env : void 0;
4007
4007
  return n ? (t.type === "web" ? (await ue(e, n), G.info("wrote src/voltro-env.d.ts (publicEnv augmentation)", { app: t.name ?? "app" })) : (await h(e, n), G.info("wrote env.generated.d.ts (serverEnv augmentation)", { app: t.name ?? "app" })), 0) : (G.warn("no `defineEnv` declared in app.config.ts — nothing to generate", { hint: "add `env: defineEnv({ ... })` to app.config.ts (see @voltro/env)" }), 0);
@@ -4117,7 +4117,7 @@ DB_DIALECT=mssql
4117
4117
  let r = w(e, n);
4118
4118
  (n === ".env.example" || j(r)) && await Ms(r) && t.push(`DB_DIALECT=mssql → ${n}`);
4119
4119
  }
4120
- for (let n of await Be(e)) t.push(n);
4120
+ for (let n of await xe(e)) t.push(n);
4121
4121
  return t;
4122
4122
  }, Fs = async (e) => {
4123
4123
  let t = await Ps(e);
@@ -4190,7 +4190,7 @@ DB_DIALECT=mssql
4190
4190
  }, Hs = async (e) => {
4191
4191
  let t = Vs(e);
4192
4192
  if ("error" in t) return console.error(t.error), 1;
4193
- let n = await We(await He(process.cwd()), void 0), r = {
4193
+ let n = await Te(await Ce(process.cwd()), void 0), r = {
4194
4194
  all: (e) => n.query({ table: e }).then((e) => e.map((e) => ({
4195
4195
  ...e,
4196
4196
  id: String(e.id)
@@ -4645,9 +4645,11 @@ DB_DIALECT=mssql
4645
4645
  "retry",
4646
4646
  "cancel",
4647
4647
  "suspend",
4648
- "resume"
4648
+ "resume",
4649
+ "discard",
4650
+ "redrive"
4649
4651
  ], hc = () => {
4650
- console.log("voltro workflows — inspect + operate workflow runs on every running api"), console.log(""), console.log("Usage:"), console.log(" voltro workflows list [--status S] [--tag T] [--tail N] [--process NAME] [--format pretty|json]"), console.log(" voltro workflows start <workflowName> [--payload <json>] [--process NAME] [--format pretty|json]"), console.log(" voltro workflows show <runId> [--process NAME] [--format pretty|json]"), console.log(" voltro workflows retry|cancel|suspend|resume <runId> [--process NAME] [--format pretty|json]"), console.log(" voltro workflows signal <runId> --name <signalName> [--payload <json>] [--process NAME]"), console.log(" voltro workflows update <runId> --name <updateName> [--payload <json>] [--timeout-ms N] [--process NAME]"), console.log(" voltro workflows children <parentExecutionId> [--process NAME] [--format pretty|json]"), console.log(""), console.log("Examples:"), console.log(" voltro workflows list --status running --tail 50"), console.log(" voltro workflows start notes.summarise --payload '{\"noteId\":\"n_1\"}'"), console.log(" voltro workflows show wf_01H..."), console.log(" voltro workflows signal wf_01H... --name approve --payload '{\"by\":\"alice\"}'"), console.log(" voltro workflows update wf_01H... --name approve --payload '{\"decision\":true}'");
4652
+ console.log("voltro workflows — inspect + operate workflow runs on every running api"), console.log(""), console.log("Usage:"), console.log(" voltro workflows list [--status S | --dead-letter] [--tag T] [--tail N] [--process NAME] [--format pretty|json]"), console.log(" voltro workflows start <workflowName> [--payload <json>] [--process NAME] [--format pretty|json]"), console.log(" voltro workflows show <runId> [--process NAME] [--format pretty|json]"), console.log(" voltro workflows retry|cancel|suspend|resume|discard|redrive <runId> [--process NAME] [--format pretty|json]"), console.log(" voltro workflows signal <runId> --name <signalName> [--payload <json>] [--process NAME]"), console.log(" voltro workflows update <runId> --name <updateName> [--payload <json>] [--timeout-ms N] [--process NAME]"), console.log(" voltro workflows children <parentExecutionId> [--process NAME] [--format pretty|json]"), console.log(""), console.log("Examples:"), console.log(" voltro workflows list --status running --tail 50"), console.log(" voltro workflows list --dead-letter # failed runs not yet discarded"), console.log(" voltro workflows discard wf_01H... # acknowledge a failed run"), console.log(" voltro workflows redrive wf_01H... # re-drive a failed run from where it died"), console.log(" voltro workflows start notes.summarise --payload '{\"noteId\":\"n_1\"}'"), console.log(" voltro workflows show wf_01H..."), console.log(" voltro workflows signal wf_01H... --name approve --payload '{\"by\":\"alice\"}'"), console.log(" voltro workflows update wf_01H... --name approve --payload '{\"decision\":true}'");
4651
4653
  }, gc, _c = async (e) => {
4652
4654
  let t = await sr(e, gc);
4653
4655
  return t.length === 0 ? (console.error(e === void 0 ? "voltro workflows: no live api processes found (start one with `voltro dev`)" : `voltro workflows: no live api named '${e}'`), 1) : t;
@@ -4696,7 +4698,7 @@ DB_DIALECT=mssql
4696
4698
  for (let e of s) e.kind === "err" && console.error(k.dim(` # ${e.name}: ${e.error}`));
4697
4699
  return 1;
4698
4700
  }, bc = async (e, t, n) => {
4699
- let r, i, a = 20;
4701
+ let r, i, a = !1, o = 20;
4700
4702
  for (let t = 0; t < e.length; t++) {
4701
4703
  let n = e[t];
4702
4704
  if (n === "--status") {
@@ -4707,41 +4709,45 @@ DB_DIALECT=mssql
4707
4709
  i = e[++t];
4708
4710
  continue;
4709
4711
  }
4712
+ if (n === "--dead-letter" || n === "--failed") {
4713
+ a = !0;
4714
+ continue;
4715
+ }
4710
4716
  if (n === "--tail") {
4711
4717
  let n = e[++t], r = n === void 0 ? NaN : Number(n);
4712
4718
  if (!Number.isFinite(r) || r <= 0) return console.error(`voltro workflows list: --tail expects a positive number, got '${n ?? ""}'`), 2;
4713
- a = Math.floor(r);
4719
+ o = Math.floor(r);
4714
4720
  continue;
4715
4721
  }
4716
4722
  return console.error(`voltro workflows list: unknown flag '${n}'`), 2;
4717
4723
  }
4718
- let o = await _c(t);
4719
- if (typeof o == "number") return o;
4720
- let s = new URLSearchParams();
4721
- r !== void 0 && s.set("status", r), i !== void 0 && s.set("tag", i), s.set("limit", String(a));
4722
- let c = `/_voltro/inspect/workflows/runs?${s.toString()}`, l = await Promise.all(o.map((e) => H(e, c))), u = [], d = [];
4723
- for (let e of l) if (e.kind === "ok") {
4724
+ let s = await _c(t);
4725
+ if (typeof s == "number") return s;
4726
+ let c = new URLSearchParams();
4727
+ a ? c.set("deadLettered", "1") : r !== void 0 && c.set("status", r), i !== void 0 && c.set("tag", i), c.set("limit", String(o));
4728
+ let l = `/_voltro/inspect/workflows/runs?${c.toString()}`, u = await Promise.all(s.map((e) => H(e, l))), d = [], f = [];
4729
+ for (let e of u) if (e.kind === "ok") {
4724
4730
  let t = e.data?.runs;
4725
- Array.isArray(t) && u.push(...t.map((t) => ({
4731
+ Array.isArray(t) && d.push(...t.map((t) => ({
4726
4732
  ...t,
4727
4733
  process: e.name
4728
4734
  })));
4729
- } else d.push({
4735
+ } else f.push({
4730
4736
  name: e.name,
4731
4737
  error: e.error
4732
4738
  });
4733
- let f = u.slice(0, a);
4734
- if (n === "json") return vc(d.length > 0 ? {
4735
- runs: f,
4736
- fetchErrors: d
4737
- } : { runs: f }, +!!l.every((e) => e.kind === "err"));
4738
- for (let e of f) {
4739
- let t = String(e.runId ?? e.id ?? "?"), n = String(e.workflowName ?? e.workflow ?? e.tag ?? "?"), r = String(e.status ?? "?"), i = typeof e.source == "string" && e.source.length > 0 ? ` ${k.dim(String(e.source))}` : "", a = r === "failed" || r === "cancelled" ? k.red(r) : r === "completed" ? k.green(r) : r === "running" ? k.cyan(r) : r;
4740
- console.log(`${t.padEnd(28).slice(0, 28)} ${a.padEnd(12)} ${n}${i} ${k.dim(`@${e.process}`)}`);
4741
- }
4742
- f.length === 0 && console.error("voltro workflows: no runs matched.");
4743
- for (let e of d) console.error(k.dim(`# fetch failed: ${e.name}: ${e.error}`));
4744
- return +!!l.every((e) => e.kind === "err");
4739
+ let p = d.slice(0, o);
4740
+ if (n === "json") return vc(f.length > 0 ? {
4741
+ runs: p,
4742
+ fetchErrors: f
4743
+ } : { runs: p }, +!!u.every((e) => e.kind === "err"));
4744
+ for (let e of p) {
4745
+ let t = String(e.runId ?? e.id ?? "?"), n = String(e.workflowName ?? e.workflow ?? e.tag ?? "?"), r = String(e.status ?? "?"), i = typeof e.source == "string" && e.source.length > 0 ? ` ${k.dim(String(e.source))}` : "", a = r === "failed" || r === "cancelled" ? k.red(r) : r === "completed" ? k.green(r) : r === "running" ? k.cyan(r) : r, o = e.discardedAt == null ? "" : ` ${k.dim("discarded")}`;
4746
+ console.log(`${t.padEnd(28).slice(0, 28)} ${a.padEnd(12)} ${n}${i}${o} ${k.dim(`@${e.process}`)}`);
4747
+ }
4748
+ p.length === 0 && console.error("voltro workflows: no runs matched.");
4749
+ for (let e of f) console.error(k.dim(`# fetch failed: ${e.name}: ${e.error}`));
4750
+ return +!!u.every((e) => e.kind === "err");
4745
4751
  }, xc = async (e, t, n) => {
4746
4752
  let r = await _c(t);
4747
4753
  if (typeof r == "number") return r;
@@ -4889,7 +4895,13 @@ DB_DIALECT=mssql
4889
4895
  process: i.name,
4890
4896
  result: i.data
4891
4897
  }, 0);
4892
- if (i !== void 0) return console.log(`${k.green("ok")} ${e} ${t} @${i.name}`), 0;
4898
+ if (i !== void 0) {
4899
+ if (e === "redrive" && i.data !== null && typeof i.data == "object") {
4900
+ let e = i.data;
4901
+ return e.redriven === !1 ? (console.error(`${k.yellow("skipped")} redrive ${t} @${i.name} — ${e.reason ?? "not re-drivable"}`), 1) : (console.log(`${k.green("ok")} redrive ${t} @${i.name} ` + k.dim(`(reset ${e.activitiesReset ?? 0} failed step(s); completed steps replay)`)), 0);
4902
+ }
4903
+ return console.log(`${k.green("ok")} ${e} ${t} @${i.name}`), 0;
4904
+ }
4893
4905
  console.error(`voltro workflows: ${e} ${t} failed on every api`);
4894
4906
  for (let e of n) e.kind === "err" && console.error(k.dim(` # ${e.name}: ${e.error}`));
4895
4907
  return 1;
@@ -6237,7 +6249,7 @@ replicas = 1
6237
6249
  for (let c of s) {
6238
6250
  if (zu.has(c)) continue;
6239
6251
  let s = w(e, c), l = yield* t.stat(s).pipe(D.orElseSucceed(() => null));
6240
- l && (l.type === "Directory" ? yield* o(s) : l.type === "File" && (Bu.test(c) && n.push(s), (Te.test(c) || Re.test(c)) && (r = !0), Me.test(c) && (i = !0), we.test(c) && (a = !0)));
6252
+ l && (l.type === "Directory" ? yield* o(s) : l.type === "File" && (Bu.test(c) && n.push(s), (Re.test(c) || Ze.test(c)) && (r = !0), Ge.test(c) && (i = !0), Le.test(c) && (a = !0)));
6241
6253
  }
6242
6254
  });
6243
6255
  return yield* o(e), {
@@ -6261,11 +6273,11 @@ replicas = 1
6261
6273
  root: e
6262
6274
  }), 1;
6263
6275
  yield* D.logInfo(`discovered ${t.length} schema file(s)`, { files: t.map((t) => T(e, t)) });
6264
- let a = yield* Uu(t), o = (process.env.DB_DIALECT ?? "postgres").toLowerCase() === "mariadb" && (process.env.CDC ?? "1") !== "0", s = xe({
6276
+ let a = yield* Uu(t), o = (process.env.DB_DIALECT ?? "postgres").toLowerCase() === "mariadb" && (process.env.CDC ?? "1") !== "0", s = Pe({
6265
6277
  workflows: n,
6266
6278
  schedules: r,
6267
6279
  webhooks: i,
6268
- traces: be(),
6280
+ traces: Ne(),
6269
6281
  cdc: o,
6270
6282
  undo: Ot()
6271
6283
  }), c = [...a, ...s];
@@ -6303,7 +6315,7 @@ replicas = 1
6303
6315
  return he(e);
6304
6316
  }, qu = async (e) => {
6305
6317
  if (e.includes("--create-only")) return u(Wu(E(e.find((e) => !e.startsWith("-")) ?? process.cwd())), { scope: "voltro:migrate" });
6306
- let { runDbCommand: t } = await import("./dbCommand-CIrdFLp9.js");
6318
+ let { runDbCommand: t } = await import("./dbCommand-DrzXimKf.js");
6307
6319
  return t(["apply", ...e]);
6308
6320
  }, Ju = "voltro-backup-stamp.json", Yu = (e) => ({
6309
6321
  stampVersion: 1,
@@ -6416,13 +6428,13 @@ replicas = 1
6416
6428
  }, cd = async (e, t) => {
6417
6429
  let n = (await he(e)).makeSqlLayer(t);
6418
6430
  return D.runPromise(Mt.SqlClient.pipe(D.flatMap(Qt), D.provide(n)));
6419
- }, ld = (e) => cd(e, Je()), ud = () => {
6420
- let e = Je(), t = [];
6431
+ }, ld = (e) => cd(e, Oe()), ud = () => {
6432
+ let e = Oe(), t = [];
6421
6433
  return e.url && t.push(Qu(e.url)), (e.host || e.database) && t.push(`${(e.host ?? "localhost").toLowerCase()}:${e.port ?? "(default)"}/${e.database ?? ""}`), t;
6422
6434
  }, dd = async () => {
6423
- let e = await He(process.cwd());
6435
+ let e = await Ce(process.cwd());
6424
6436
  if (!e) throw new ft("voltro data: no app.config.ts found in the current directory.");
6425
- let t = await We(e, void 0), n = sd();
6437
+ let t = await Te(e, void 0), n = sd();
6426
6438
  return {
6427
6439
  store: t,
6428
6440
  snapshot: await ld(n),
@@ -6686,7 +6698,7 @@ replicas = 1
6686
6698
  assets: d.assets.count
6687
6699
  }), 0;
6688
6700
  }, Td = () => {
6689
- let e = Je();
6701
+ let e = Oe();
6690
6702
  return {
6691
6703
  ...e.url ? { url: e.url } : {},
6692
6704
  ...e.host ? { host: e.host } : {},
@@ -8759,7 +8771,7 @@ replicas = 1
8759
8771
  }, $p = /\.page\.tsx$/, em = (e) => {
8760
8772
  let t = e.includes("\\src\\pages\\") ? "\\src\\pages\\" : "/src/pages/", n = e.indexOf(t);
8761
8773
  return n === -1 ? null : e.slice(0, n);
8762
- }, tm = (e) => e.endsWith(".tsx") && !je.has(e) && !n(e) && !/\.island\.tsx$/.test(e) && !$p.test(e), nm = Z({
8774
+ }, tm = (e) => e.endsWith(".tsx") && !We.has(e) && !n(e) && !/\.island\.tsx$/.test(e) && !$p.test(e), nm = Z({
8763
8775
  version: "0.14.0",
8764
8776
  id: "0.14.0/03_pages-suffix",
8765
8777
  title: "Pages are declared with a .page.tsx suffix",
@@ -8809,18 +8821,18 @@ replicas = 1
8809
8821
  }
8810
8822
  }), rm = [
8811
8823
  /\.page\.tsx$/,
8812
- Ne,
8824
+ Ke,
8825
+ Ye,
8826
+ qe,
8827
+ Xe,
8828
+ Be,
8829
+ He,
8830
+ Je,
8813
8831
  Ie,
8814
- Pe,
8815
- Le,
8816
- De,
8817
- ke,
8818
- Fe,
8819
- Ce,
8820
- Ee
8832
+ ze
8821
8833
  ], im = (e) => {
8822
8834
  let t = S(e);
8823
- return !/\.tsx?$/.test(t) || je.has(t) || Se(t) || t === "index.ts" || t === "index.tsx" || t === "app.config.ts" ? !1 : !rm.some((e) => e.test(t));
8835
+ return !/\.tsx?$/.test(t) || We.has(t) || Fe(t) || t === "index.ts" || t === "index.tsx" || t === "app.config.ts" ? !1 : !rm.some((e) => e.test(t));
8824
8836
  }, am = (e) => {
8825
8837
  let t = [], n = [], r = [], i = [];
8826
8838
  for (let [a, o] of e.getExportedDeclarations()) {
@@ -8950,7 +8962,7 @@ replicas = 1
8950
8962
  ].join("\n")
8951
8963
  }), um = (e) => {
8952
8964
  let t = e.replace(/\.component(\.ui)?(\.tsx?)$/, "$2");
8953
- return t === e ? null : Se(t) ? t : null;
8965
+ return t === e ? null : Fe(t) ? t : null;
8954
8966
  }, dm = (e) => {
8955
8967
  for (let [, t] of e.getExportedDeclarations()) if (t[0] !== void 0) return !1;
8956
8968
  return e.getExportDeclarations().length === 0 && e.getExportAssignments().length === 0;
@@ -9726,6 +9738,95 @@ replicas = 1
9726
9738
  for (let e of i) t(` ! ${e} — carried verbatim; CHECK IT: the value is now a PREFIX the framework`), t(" appends ':changes' / ':events:<name>' / ':members' / ':presence' to.");
9727
9739
  }
9728
9740
  }
9741
+ }),
9742
+ Z({
9743
+ version: "0.26.0",
9744
+ id: "0.26.0/01_event-webhook-retry-removed",
9745
+ title: "`defineEvent({ webhook: { retry } })` is gone — it never did anything",
9746
+ kind: "manual",
9747
+ appliesTo: ({ project: e }) => e.getSourceFiles().some((e) => {
9748
+ let t = e.getFullText();
9749
+ return t.includes("defineEvent") && t.includes("webhook") && t.includes("retry");
9750
+ }),
9751
+ note: [
9752
+ "The `retry` field on an event's `webhook` spec has been REMOVED from the type.",
9753
+ "",
9754
+ "It was declared, documented as \"default retry policy for new subscriptions\",",
9755
+ "and read by nothing. Setting it produced no error, no warning and no effect —",
9756
+ "the value was dropped where the event descriptor is projected into an outgoing",
9757
+ "webhook descriptor, and there was a comment there explaining why. The comment",
9758
+ "was a reasonable argument (the plugin's RetryPolicy is a richer shape than the",
9759
+ "two numbers the protocol carried, and inventing the missing fields would put a",
9760
+ "policy in place nobody wrote) but it did not change what a user experienced:",
9761
+ "a typed option that silently does nothing.",
9762
+ "",
9763
+ "This is the third instance of that shape in this feature — `broadcast({ channel })`",
9764
+ "and an event's `guards` were the first two — so the field is deleted rather than",
9765
+ "explained.",
9766
+ "",
9767
+ "WHAT TO DO: if you set it, delete it. Nothing changes at runtime, because",
9768
+ "nothing was reading it. To actually configure retry, set it on the SUBSCRIPTION",
9769
+ "(the webhook target), where the full RetryPolicy shape is available and typed:",
9770
+ "",
9771
+ " webhooks.subscribe({ event: \"order.paid\", url, retry: { maxAttempts: 5, ... } })",
9772
+ "",
9773
+ "If you were relying on the declared value to take effect, note that it never",
9774
+ "did — your deliveries have been using the target default all along."
9775
+ ].join("\n")
9776
+ }),
9777
+ Z({
9778
+ version: "0.26.0",
9779
+ id: "0.26.0/02_step-retry-enforced",
9780
+ title: "workflow step `retry:` is now ENFORCED (was metadata) — drop any redundant manual retry",
9781
+ kind: "manual",
9782
+ appliesTo: ({ project: e }) => e.getSourceFiles().some((e) => {
9783
+ let t = e.getFullText();
9784
+ return t.includes("retry:") ? t.includes("step(") || t.includes("stepModule.retry") || t.includes("Effect.retry") : !1;
9785
+ }),
9786
+ note: [
9787
+ "The `retry:` field on a workflow `step({...})` is now ENFORCED. The framework",
9788
+ "compiles it to an Effect `Schedule` (backoff, jitter, attempt cap, time budget,",
9789
+ "error classification, provider `Retry-After`) and retries `execute` accordingly.",
9790
+ "It used to be metadata only — recorded for the dashboard, applied by nothing.",
9791
+ "",
9792
+ "THE PART TO CHECK FIRST, even if you never wrote a manual retry: a step that",
9793
+ "declared `retry:` and nothing else ran ONCE. It now runs up to `maxAttempts`",
9794
+ "times. If `execute` is not idempotent — a charge, an email, an outbound POST —",
9795
+ "that is real duplicate work that starts on this upgrade, and nothing in your",
9796
+ "code changed to cause it. The 0.25.0 type said so plainly (\"Pure metadata —",
9797
+ "does NOT change retry behavior on its own\"), so trusting it was correct.",
9798
+ "",
9799
+ "Go through every step that declares `retry:` and decide, per step:",
9800
+ " - side effect is idempotent (or guarded by an idempotency key) → keep the",
9801
+ " policy; this is the behaviour you wanted when you wrote it;",
9802
+ " - side effect is NOT idempotent → make it so, or set `maxAttempts: 1`, or",
9803
+ " narrow with `retryableErrors: [...]` so only transient failures retry.",
9804
+ "",
9805
+ "If you followed the old docs and wrapped a step in your OWN retry as well as",
9806
+ "declaring `retry:`, that step now retries TWICE. Fix it — keep ONE:",
9807
+ "",
9808
+ " // before (retry: was metadata; the real retry was the wrapper)",
9809
+ " yield* stepModule.retry(",
9810
+ " step({ name: 'call-provider', retry: { maxAttempts: 5 }, execute }),",
9811
+ " Schedule.exponential('500 millis').pipe(Schedule.recurs(4)),",
9812
+ " )",
9813
+ "",
9814
+ " // after — the declarative policy IS the retry now",
9815
+ " yield* step({",
9816
+ " name: 'call-provider',",
9817
+ " retry: { maxAttempts: 5, strategy: 'exponential', baseDelay: '500 millis' },",
9818
+ " execute,",
9819
+ " })",
9820
+ "",
9821
+ "The declarative form is the one to keep in almost every case — it also drives the",
9822
+ "dashboard. Keep a hand-written `stepModule.retry(…, Schedule)` ONLY when your",
9823
+ "Schedule does something the policy can't express, and then DROP the `retry:` field",
9824
+ "from that step so it is not applied on top.",
9825
+ "",
9826
+ "New conditions worth adopting while you are here: `retryableErrors: ['ProviderDown']`",
9827
+ "(retry transient, fail permanent), `maxElapsed: '5 minutes'` (a total time budget,",
9828
+ "not just a count), `jitter` (on by default), and `respectRetryAfter` (honor a 429)."
9829
+ ].join("\n")
9729
9830
  })
9730
9831
  ], $m = /* @__PURE__ */ new Set([
9731
9832
  "node_modules",
@@ -11459,7 +11560,7 @@ image, use \`voltro serverless serve\` from the project root.
11459
11560
  name: "dev",
11460
11561
  summary: "Start the local development server (auto-discovers routes / mutations).",
11461
11562
  status: "wired",
11462
- run: Ue
11563
+ run: we
11463
11564
  },
11464
11565
  {
11465
11566
  name: "dashboard",
@@ -0,0 +1,2 @@
1
+ import { s as e } from "./dbCommand-uuNCrFAb.js";
2
+ export { e as runDbCommand };