@voltro/cli 0.50.1 → 0.52.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 (170) hide show
  1. package/CHANGELOG.md +231 -0
  2. package/dist/{agentsMd-D6yD7IQv.js → agentsMd-0l980yhL.js} +4 -1
  3. package/dist/agentsMd-SDDSkyl4.js +2 -0
  4. package/dist/apiBuild-BYBpL7Pz.js +2 -0
  5. package/dist/{apiBuild-D3s7lx57.js → apiBuild-CSFI8QGq.js} +3 -3
  6. package/dist/appGraph-CFmFKHb2.js +2 -0
  7. package/dist/appGraph-yRuKjOba.js +111 -0
  8. package/dist/bin.js +1 -1
  9. package/dist/build-CPgcMQug.js +793 -0
  10. package/dist/checkCommand-2SbqzukH.js +2 -0
  11. package/dist/{checkCommand-DsKIjL6k.js → checkCommand-COmqc2cB.js} +107 -60
  12. package/dist/{cloudCmd-F4YJeqM3.js → cloudCmd-QUXh-b5w.js} +1 -1
  13. package/dist/codegen-CctkDO-1.js +2 -0
  14. package/dist/{codegen-CrMXs4hb.js → codegen-VF479Cnb.js} +1 -1
  15. package/dist/{codegenCommand-C0S27nbB.js → codegenCommand-DCdG2JN-.js} +12 -12
  16. package/dist/{codemodRunner-DwY8Rjbl.js → codemodRunner-r7J9lIa7.js} +771 -636
  17. package/dist/{commands-Brp4DI8u.js → commands-Cc_nV8WI.js} +37 -36
  18. package/dist/{dashboardCommand-bbLfc9FW.js → dashboardCommand-C-gKvwqh.js} +3 -3
  19. package/dist/{dataCommand-k9mXTXin.js → dataCommand-BgpBHnlB.js} +299 -253
  20. package/dist/dbCommand-DNb6yeOG.js +2 -0
  21. package/dist/{dbCommand-Bf7Cy0mn.js → dbCommand-sHedr-NJ.js} +3 -3
  22. package/dist/dev--A3nsxA3.js +3 -0
  23. package/dist/{dev-C0cbqysu.js → dev-CRHoCEiy.js} +2258 -2219
  24. package/dist/doctorCommand-CqoWA2p5.js +2 -0
  25. package/dist/{doctorCommand-DyViaaCP.js → doctorCommand-DtfJ3FA6.js} +314 -234
  26. package/dist/{dormancyCommand-DMZPA_HW.js → dormancyCommand-Drn7o0No.js} +1 -1
  27. package/dist/{embeddingsCommand-CMxRPkg6.js → embeddingsCommand-Z-jO1fWN.js} +1 -1
  28. package/dist/{envCommand-CDLr-yD4.js → envCommand-D4gCrrTZ.js} +15 -15
  29. package/dist/{evolveCommand-Ct4NesL3.js → evolveCommand-CMROeKeA.js} +2 -2
  30. package/dist/fileConventions-DOqD3lPS.js +34 -0
  31. package/dist/{fileTaxonomy-CJfgOllU.js → fileTaxonomy-DvDUV9wq.js} +1 -1
  32. package/dist/frameworkTableAssembly-C6ETawPR.js +2 -0
  33. package/dist/{frameworkTableAssembly-BwJVEKLr.js → frameworkTableAssembly-w-XnLa3q.js} +1 -1
  34. package/dist/{generateCommand-BDdOxhnv.js → generateCommand-DTNPGjxo.js} +1 -1
  35. package/dist/index.js +1 -1
  36. package/dist/{infoCommand-orsKJKUy.js → infoCommand-DXM868o_.js} +1 -1
  37. package/dist/inspectMetrics-CGF94puw.js +143 -0
  38. package/dist/{metaCommands-CfRLra0s.js → metaCommands-C6RFmF1r.js} +2 -2
  39. package/dist/{migrate-D3MK9BpK.js → migrate-D0F-eTlK.js} +2 -2
  40. package/dist/{pageConvention-cEiRxdab.js → pageConvention-CzUiSbtU.js} +1 -1
  41. package/dist/{privacyCommand-XejDMvmu.js → privacyCommand-DGdopOI6.js} +1 -1
  42. package/dist/{projectScaffold-mIX_DpSe.js → projectScaffold-B4dmTlwT.js} +1 -1
  43. package/dist/{projectScaffold-BIl97_E6.js → projectScaffold-EzlErR4E.js} +1 -1
  44. package/dist/{renderModeScan-D7J1B7Kw.js → renderModeScan-CcH2X1_D.js} +25 -10
  45. package/dist/{renderProfile-1OWWAAtx.js → renderProfile-Ck32Fzxr.js} +2 -2
  46. package/dist/{runtimeTrace-Bo8jWsNe.js → runtimeTrace-BPQyCmC5.js} +1 -1
  47. package/dist/{sdkgen-OZhiT2vz.js → sdkgen-Se88ifTd.js} +1 -1
  48. package/dist/serveCommand-DLc-BznW.js +2 -0
  49. package/dist/{serveCommand-YbD5VgfV.js → serveCommand-DkP3OT0W.js} +885 -868
  50. package/dist/serveEntry.js +1 -1
  51. package/dist/start-DfL3fOiN.js +3 -0
  52. package/dist/start-jw89Xbqy.js +1339 -0
  53. package/dist/startEntry.js +1 -1
  54. package/dist/{staticCommand-Dr2M6tpU.js → staticCommand-BwNEDlSU.js} +1 -1
  55. package/dist/{test-rXFq4S76.js → test-f3amja6a.js} +1 -1
  56. package/dist/updateCommand-5gFVfK5q.js +2 -0
  57. package/dist/{updateCommand-BgH6vTtq.js → updateCommand-BMk2e4ky.js} +1 -1
  58. package/dist/{webDev-BbdkzMbd.js → webDev-BgWL9gKV.js} +1233 -853
  59. package/dist/webDev-CZbTsDcH.js +2 -0
  60. package/dist/{webhooksCommand-DjE6u0r4.js → webhooksCommand-CoIO3jbj.js} +1 -1
  61. package/package.json +48 -17
  62. package/templates/AGENTS.core.md +26 -5
  63. package/templates/AGENTS.md +30 -9
  64. package/templates/agent-docs/_index.md +4 -4
  65. package/templates/agent-docs/_manifest.json +11 -11
  66. package/templates/agent-docs/cli.md +125 -14
  67. package/templates/agent-docs/data.md +210 -7
  68. package/templates/agent-docs/database/schema.md +1 -1
  69. package/templates/agent-docs/database/seedsdialects.md +1 -1
  70. package/templates/agent-docs/deployment.md +22 -3
  71. package/templates/agent-docs/internationalization.md +131 -13
  72. package/templates/agent-docs/introduction.md +46 -0
  73. package/templates/agent-docs/local-first-mobile.md +34 -7
  74. package/templates/agent-docs/plugins/ai-flows.md +1 -1
  75. package/templates/agent-docs/plugins/audit.md +5 -5
  76. package/templates/agent-docs/plugins/cdc-out.md +2 -2
  77. package/templates/agent-docs/plugins/{versioning.md → row-history.md} +22 -22
  78. package/templates/agent-docs/plugins/storage.md +2 -2
  79. package/templates/agent-docs/plugins.md +29 -7
  80. package/templates/agent-docs/reference.md +39 -2
  81. package/templates/agent-docs/routing.md +341 -47
  82. package/templates/agent-docs/schema-driven-ui.md +78 -2
  83. package/templates/agent-docs/security.md +125 -8
  84. package/templates/agent-docs/templates/apibackends.md +14 -14
  85. package/templates/agent-docs/templates/overview.md +1 -1
  86. package/templates/agent-docs/whats-new.md +100 -29
  87. package/templates/apps/api-ai/package.json +6 -7
  88. package/templates/apps/api-ai/tests/summarize.test.ts +1 -1
  89. package/templates/apps/api-auth/package.json +8 -8
  90. package/templates/apps/api-backend/package.json +7 -7
  91. package/templates/apps/api-backend-deactivation/package.json +7 -7
  92. package/templates/apps/api-backend-mail/package.json +8 -8
  93. package/templates/apps/api-backend-mariadb/package.json +9 -9
  94. package/templates/apps/api-backend-sqlite/package.json +8 -8
  95. package/templates/apps/api-backend-storage/package.json +8 -8
  96. package/templates/apps/api-cms/package.json +9 -10
  97. package/templates/apps/api-collab/package.json +8 -8
  98. package/templates/apps/api-data-advanced/package.json +8 -8
  99. package/templates/apps/api-durable/package.json +8 -8
  100. package/templates/apps/api-feature-flags/package.json +9 -9
  101. package/templates/apps/api-governance/package.json +8 -8
  102. package/templates/apps/api-kv/package.json +8 -8
  103. package/templates/apps/api-moderation/package.json +8 -8
  104. package/templates/apps/api-observability/package.json +8 -8
  105. package/templates/apps/api-ratelimit/package.json +8 -8
  106. package/templates/apps/api-rbac/package.json +8 -8
  107. package/templates/apps/api-rest/package.json +7 -7
  108. package/templates/apps/{api-versioning → api-row-history}/README.md +3 -3
  109. package/templates/apps/{api-versioning → api-row-history}/actions/documents.asOf.action.server.ts +1 -1
  110. package/templates/apps/{api-versioning → api-row-history}/actions/documents.history.action.server.ts +1 -1
  111. package/templates/apps/{api-versioning → api-row-history}/app.config.ts +3 -3
  112. package/templates/apps/{api-versioning → api-row-history}/database/schema.ts +1 -1
  113. package/templates/apps/{api-versioning → api-row-history}/mutations/documents.create.mutation.server.ts +1 -1
  114. package/templates/apps/{api-versioning → api-row-history}/mutations/documents.create.mutation.ts +1 -1
  115. package/templates/apps/{api-versioning → api-row-history}/mutations/documents.update.mutation.ts +1 -1
  116. package/templates/apps/{api-versioning → api-row-history}/package.json +8 -8
  117. package/templates/apps/api-row-history/template.json +6 -0
  118. package/templates/apps/{api-versioning → api-row-history}/tests/documents.create.test.ts +1 -1
  119. package/templates/apps/api-saas/app.config.ts +1 -0
  120. package/templates/apps/api-saas/package.json +10 -11
  121. package/templates/apps/api-saas-starter/package.json +10 -10
  122. package/templates/apps/api-search/package.json +8 -8
  123. package/templates/apps/api-status/package.json +8 -8
  124. package/templates/apps/api-webhooks/package.json +9 -9
  125. package/templates/apps/changelog/package.json +6 -6
  126. package/templates/apps/edge-functions/package.json +2 -2
  127. package/templates/apps/frontend-admin/package.json +8 -8
  128. package/templates/apps/frontend-app/package.json +9 -9
  129. package/templates/apps/frontend-auth/package.json +8 -8
  130. package/templates/apps/frontend-blank/package.json +7 -7
  131. package/templates/apps/frontend-cms/package.json +9 -9
  132. package/templates/apps/frontend-collab/package.json +10 -10
  133. package/templates/apps/frontend-collab/src/pages/page.test.tsx +10 -9
  134. package/templates/apps/frontend-collab/src/pages/page.tsx +42 -65
  135. package/templates/apps/frontend-contact/package.json +7 -7
  136. package/templates/apps/frontend-dashboard/package.json +7 -7
  137. package/templates/apps/frontend-docs/package.json +6 -7
  138. package/templates/apps/frontend-i18n/package.json +6 -6
  139. package/templates/apps/frontend-landing/package.json +6 -7
  140. package/templates/apps/frontend-portal/package.json +8 -8
  141. package/templates/apps/frontend-saas/package.json +8 -8
  142. package/templates/apps/frontend-spa/package.json +7 -7
  143. package/templates/apps/frontend-ssr/package.json +7 -7
  144. package/templates/apps/frontend-ssr-api/package.json +8 -8
  145. package/templates/apps/frontend-static-blog/package.json +6 -6
  146. package/templates/apps/frontend-status/package.json +8 -8
  147. package/templates/apps/mobile-app/package.json +4 -4
  148. package/dist/agentsMd-Bu_XQgVf.js +0 -2
  149. package/dist/apiBuild-BZ-plaQN.js +0 -2
  150. package/dist/appGraph-CM9wvUmD.js +0 -2
  151. package/dist/appGraph-Cv2W_wO5.js +0 -111
  152. package/dist/build-CFmqF39c.js +0 -721
  153. package/dist/checkCommand-DomvYDi1.js +0 -2
  154. package/dist/codegen-DiMn2KkZ.js +0 -2
  155. package/dist/dbCommand-Bnl7MSGC.js +0 -2
  156. package/dist/dev-Dz9GqA6P.js +0 -3
  157. package/dist/doctorCommand-BlciWUJb.js +0 -2
  158. package/dist/fileConventions-Cof68_BL.js +0 -33
  159. package/dist/frameworkTableAssembly-CVDB2hCq.js +0 -2
  160. package/dist/inspectMetrics-CfdKLh6t.js +0 -72
  161. package/dist/serveCommand-Bbgg7Paq.js +0 -2
  162. package/dist/start-7b_bL8Uc.js +0 -3
  163. package/dist/start-B1nH9ahf.js +0 -1150
  164. package/dist/updateCommand-BweY17z-.js +0 -2
  165. package/dist/webDev-BcRFTsMA.js +0 -2
  166. package/templates/apps/api-versioning/template.json +0 -6
  167. /package/templates/apps/{api-versioning → api-row-history}/actions/documents.asOf.action.ts +0 -0
  168. /package/templates/apps/{api-versioning → api-row-history}/actions/documents.history.action.ts +0 -0
  169. /package/templates/apps/{api-versioning → api-row-history}/mutations/documents.update.mutation.server.ts +0 -0
  170. /package/templates/apps/{api-versioning → api-row-history}/tsconfig.json +0 -0
@@ -0,0 +1,2 @@
1
+ import { a as e, i as t, o as n } from "./checkCommand-COmqc2cB.js";
2
+ export { t as offlineManifest, e as runCheckCommand, n as toInput };
@@ -1,19 +1,20 @@
1
1
  import { t as e } from "./cliArgs-D4p8n7EE.js";
2
- import { a as t, l as n } from "./codegen-CrMXs4hb.js";
3
- import { r } from "./appGraph-Cv2W_wO5.js";
2
+ import { a as t, l as n } from "./codegen-VF479Cnb.js";
3
+ import { r } from "./appGraph-yRuKjOba.js";
4
4
  import { n as i } from "./cliOutput-D1tSBoRM.js";
5
5
  import { n as a, o, r as s, t as c } from "./inspectFetch-EMuhTG_9.js";
6
- import { r as l } from "./fileTaxonomy-CJfgOllU.js";
7
- import { S as u } from "./doctorCommand-DyViaaCP.js";
6
+ import { r as l } from "./fileTaxonomy-DvDUV9wq.js";
7
+ import { S as u } from "./doctorCommand-DtfJ3FA6.js";
8
8
  import { resolve as d } from "node:path";
9
9
  import { readdirSync as f, statSync as p } from "node:fs";
10
+ import { isReactivityChannelKey as m } from "@voltro/protocol";
10
11
  //#region src/observedDiff.ts
11
- var m = (e) => e === void 0 ? [] : typeof e == "string" ? [e] : e, h = {
12
+ var h = (e) => (e === void 0 ? [] : typeof e == "string" ? [e] : e).filter((e) => !m(e)), g = {
12
13
  insert: ["insert"],
13
14
  update: ["update"],
14
15
  delete: ["delete"],
15
16
  upsert: ["insert", "update"]
16
- }, g = (e) => e !== "read", _ = (e, t) => `{ table: '${e}', op: '${t}' }`, v = (e, t) => {
17
+ }, _ = (e) => e !== "read", v = (e, t) => `{ table: '${e}', op: '${t}' }`, y = (e, t) => {
17
18
  let n = [], r = new Set(t.exercised), i = /* @__PURE__ */ new Map();
18
19
  for (let e of t.edges) {
19
20
  let t = i.get(e.tag);
@@ -25,19 +26,19 @@ var m = (e) => e === void 0 ? [] : typeof e == "string" ? [e] : e, h = {
25
26
  a.push(t.tag);
26
27
  continue;
27
28
  }
28
- let e = `${t.kind}(${t.tag})`, s = t.file, c = i.get(t.tag) ?? [], l = new Set(m(t.source)), u = /* @__PURE__ */ new Map();
29
+ let e = `${t.kind}(${t.tag})`, s = t.file, c = i.get(t.tag) ?? [], l = new Set(h(t.source)), u = /* @__PURE__ */ new Map();
29
30
  for (let e of t.targets ?? []) {
30
31
  let t = u.get(e.table) ?? /* @__PURE__ */ new Set();
31
32
  t.add(e.op), u.set(e.table, t);
32
33
  }
33
- for (let t of c) if (g(t.op)) {
34
- let r = h[t.op], i = u.get(t.table);
34
+ for (let t of c) if (_(t.op)) {
35
+ let r = g[t.op], i = u.get(t.table);
35
36
  if (i === void 0) n.push({
36
37
  rule: "observed/undeclared-write",
37
38
  node: e,
38
39
  ...s === void 0 ? {} : { file: s },
39
40
  breaks: [`writes '${t.table}' (${t.op}) but declares no target for it`, "subscriptions on that table are not invalidated by this mutation"],
40
- fix: `add ${r.map((e) => _(t.table, e)).join(" and ")} to this procedure's targets`,
41
+ fix: `add ${r.map((e) => v(t.table, e)).join(" and ")} to this procedure's targets`,
41
42
  severity: "warn"
42
43
  });
43
44
  else {
@@ -47,7 +48,7 @@ var m = (e) => e === void 0 ? [] : typeof e == "string" ? [e] : e, h = {
47
48
  node: e,
48
49
  ...s === void 0 ? {} : { file: s },
49
50
  breaks: [`declares ${[...i].map((e) => `'${e}'`).join(" + ")} on '${t.table}' but performed '${t.op}'`, "the synthesized optimistic patch has the wrong shape"],
50
- fix: r.length > 1 ? `an upsert is both halves — declare ${r.map((e) => _(t.table, e)).join(" and ")}` : `change the target op for '${t.table}' to '${a[0]}'`,
51
+ fix: r.length > 1 ? `an upsert is both halves — declare ${r.map((e) => v(t.table, e)).join(" and ")}` : `change the target op for '${t.table}' to '${a[0]}'`,
51
52
  severity: "warn"
52
53
  });
53
54
  }
@@ -90,7 +91,7 @@ var m = (e) => e === void 0 ? [] : typeof e == "string" ? [e] : e, h = {
90
91
  total: e.length
91
92
  }
92
93
  };
93
- }, y = (e, n = [], r = 0) => {
94
+ }, b = (e, n = [], r = 0) => {
94
95
  if (r > 12) return n;
95
96
  let i;
96
97
  try {
@@ -114,24 +115,43 @@ var m = (e) => e === void 0 ? [] : typeof e == "string" ? [e] : e, h = {
114
115
  } catch {
115
116
  continue;
116
117
  }
117
- o.isDirectory() ? y(i, n, r + 1) : o.isFile() && t.test(a) && n.push(i);
118
+ o.isDirectory() ? b(i, n, r + 1) : o.isFile() && t.test(a) && n.push(i);
118
119
  }
119
120
  return n;
120
- }, b = /* @__PURE__ */ new Set(["actors", "tenants"]), x = async (e) => {
121
+ }, x = /* @__PURE__ */ new Set(["actors", "tenants"]), S = async (e) => {
121
122
  try {
122
123
  let { readFile: t } = await import("node:fs/promises"), { join: n } = await import("node:path"), r = await t(n(e, "app.graph.observed.generated.json"), "utf8"), i = JSON.parse(r);
123
124
  return i?.version !== 1 || !Array.isArray(i.edges) || !Array.isArray(i.exercised) ? null : i;
124
125
  } catch {
125
126
  return null;
126
127
  }
127
- }, S = (e) => {
128
- let { exercised: t, total: n } = e.coverage, r = `\nobserved: ${t}/${n} procedures exercised (${n === 0 ? 0 : Math.round(t / n * 100)}%)`;
129
- if (e.diagnostics.length === 0) return `${r}\n no declared/observed mismatches${e.unexercised.length > 0 ? `\n ${e.unexercised.length} unexercised no recording, so nothing is claimed about them` : ""}`;
130
- let i = e.diagnostics.map((e) => ` ${e.node}${e.file === void 0 ? "" : ` (${e.file})`}\n` + e.breaks.map((e) => ` ${e}`).join("\n") + `\n fix: ${e.fix}`), a = e.unexercised.length > 0 ? `\n ${e.unexercised.length} unexercised — no recording, so nothing is claimed about them` : "";
131
- return `${r}\n${i.join("\n")}${a}`;
132
- }, C = (e, t) => ({
128
+ }, C = {
129
+ unexercised: (e) => `${e} never ran no observation exists, so nothing is claimed about them`,
130
+ unobservedReads: (e) => `${e} ran with no table access recordedindistinguishable from touching nothing, so nothing is claimed about them either`
131
+ }, w = (e, t) => {
132
+ let n = e.filter((e) => !t.has(e)).sort();
133
+ return n.length === 0 ? `\ndeclared vs live: all ${e.length} source-declared tags are registered on the server` : `\ndeclared vs live: ${n.length} of ${e.length} source-declared tags are NOT registered on the server\n` + n.map((e) => ` ⚠ ${e} — a generated client calls this and gets "Unknown request tag"`).join("\n") + "\n fix: if the server runs older code, redeploy; if it is current, plugin route registration was dropped — check the boot line \"plugin routes registered\"";
134
+ }, T = (e) => {
135
+ let { exercised: t, total: n } = e.coverage;
136
+ if (n === 0) return "\nobserved: no procedures declared — nothing to compare";
137
+ let r = `\nobserved: ${t}/${n} procedures exercised (${Math.round(t / n * 100)}%)`, i = Object.keys(C).map((t) => [t, e[t].length]).filter(([, e]) => e > 0), a = i.reduce((e, [, t]) => e + t, t), o = [...i.map(([e, t]) => ` ${C[e](t)}`), ...a === n ? [] : [` ⚠ ${n - a} of the declared procedures are in none of the counts above — that is a defect in \`voltro check\`, please report it`]].join("\n");
138
+ if (e.diagnostics.length > 0) {
139
+ let n = e.diagnostics.length;
140
+ return [
141
+ r,
142
+ ` ${n} declared/observed mismatch${n === 1 ? "" : "es"} among the ${t} that ran`,
143
+ ...e.diagnostics.map((e) => ` ${e.node}${e.file === void 0 ? "" : ` (${e.file})`}\n` + e.breaks.map((e) => ` ${e}`).join("\n") + `\n fix: ${e.fix}`),
144
+ ...o === "" ? [] : [o]
145
+ ].join("\n");
146
+ }
147
+ return [
148
+ r,
149
+ t === 0 ? " nothing was compared — a declaration is only checked against a procedure that RAN" : ` no declared/observed mismatch among the ${t} that ran`,
150
+ ...o === "" ? [] : [o]
151
+ ].join("\n");
152
+ }, E = (e, t) => ({
133
153
  tables: (t.tables ?? []).map((e) => e.name),
134
- frameworkOwnedTables: (t.tables ?? []).filter((e) => e.framework === !0 || e.name.startsWith("_voltro_") || b.has(e.name)).map((e) => e.name),
154
+ frameworkOwnedTables: (t.tables ?? []).filter((e) => e.framework === !0 || e.name.startsWith("_voltro_") || x.has(e.name)).map((e) => e.name),
135
155
  scopes: e.scopes ?? [],
136
156
  procedures: (e.procedures ?? []).map((e) => {
137
157
  let t = (e.guards ?? []).flatMap((e) => e.kind === "scope" ? e.scope ?? [] : []), n = (e.guards ?? []).find((e) => e.kind === "open")?.reason;
@@ -146,27 +166,41 @@ var m = (e) => e === void 0 ? [] : typeof e == "string" ? [e] : e, h = {
146
166
  ...e.internal === !0 ? { internal: !0 } : {}
147
167
  };
148
168
  })
149
- }), w = (e) => e.length === 0 ? "✓ voltro check: no issues" : e.map((e) => {
169
+ }), D = (e) => e.length === 0 ? "✓ voltro check: no issues" : e.map((e) => {
150
170
  let t = e.severity === "error" ? "✗ error" : "⚠ warn", n = e.file ? ` (${e.file})` : "";
151
171
  return `${t} ${e.rule} ${e.node}${n}\n ${e.breaks.join("; ")}\n fix: ${e.fix}`;
152
- }).join("\n"), T = async (e) => {
153
- let { walk: t, loadDiscovered: n, loadApiConfig: r } = await import("./dev-Dz9GqA6P.js"), { buildRpcEntry: i } = await import("./manifestBuild-CPjhvM62.js"), { buildCapabilityManifest: a } = await import("./inspect-CuGDYES0.js"), { relative: o } = await import("node:path"), s = await n(await t(e)), c = (t, n, r) => i(t, n, o(e, r)), l = [
154
- ...s.queries.map((e) => c(e.descriptor, "query", e.file)),
155
- ...s.mutations.map((e) => c(e.descriptor, "mutation", e.file)),
156
- ...s.actions.map((e) => c(e.descriptor, "action", e.file)),
157
- ...s.streams.map((e) => c(e.descriptor, "stream", e.file))
158
- ], { assembleFrameworkTables: u } = await import("./frameworkTableAssembly-CVDB2hCq.js"), d = await u({ root: e }).catch((e) => (console.warn(`\n⚠ plugin tables could not be collected — this report is INCOMPLETE.\n ${e instanceof Error ? e.message.split("\n")[0] : String(e)}\n`), [])), 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) => ({
172
+ }).join("\n"), O = async (e) => {
173
+ let { walk: t, loadDiscovered: n, loadApiConfig: r } = await import("./dev--A3nsxA3.js"), { buildRpcEntry: i } = await import("./manifestBuild-CPjhvM62.js"), { buildCapabilityManifest: a } = await import("./inspect-CuGDYES0.js"), { relative: o } = await import("node:path"), s = await n(await t(e)), c = await r(e).then((e) => e?.plugins ?? []).catch(() => []);
174
+ try {
175
+ let { mergePluginRoutesInto: e } = await import("./dev--A3nsxA3.js");
176
+ e({
177
+ plugins: c,
178
+ queries: s.queries,
179
+ mutations: s.mutations,
180
+ actions: s.actions,
181
+ streams: s.streams,
182
+ log: { info: () => {} }
183
+ });
184
+ } catch (e) {
185
+ console.warn(`\n⚠ plugin rpc routes could not be merged — this report is INCOMPLETE.\n ${e instanceof Error ? e.message.split("\n")[0] : String(e)}\n`);
186
+ }
187
+ let l = (t, n, r) => i(t, n, r.startsWith("plugin:") ? r : o(e, r)), u = [
188
+ ...s.queries.map((e) => l(e.descriptor, "query", e.file)),
189
+ ...s.mutations.map((e) => l(e.descriptor, "mutation", e.file)),
190
+ ...s.actions.map((e) => l(e.descriptor, "action", e.file)),
191
+ ...s.streams.map((e) => l(e.descriptor, "stream", e.file))
192
+ ], { assembleFrameworkTables: d } = await import("./frameworkTableAssembly-C6ETawPR.js"), f = await d({ root: e }).catch((e) => (console.warn(`\n⚠ plugin tables could not be collected — this report is INCOMPLETE.\n ${e instanceof Error ? e.message.split("\n")[0] : String(e)}\n`), [])), p = new Set(s.tables.map((e) => e.tableName)), m = [...[...p].map((e) => ({ name: e })), ...f.map((e) => e.tableName).filter((e) => !p.has(e)).map((e) => ({
159
193
  name: e,
160
194
  framework: !0
161
- }))], m = await r(e).then((e) => e?.plugins ?? []).catch(() => []);
195
+ }))], h = c;
162
196
  return {
163
- manifest: a(l, s.workflows.map((t) => ({
197
+ manifest: a(u, s.workflows.map((t) => ({
164
198
  tag: t.definition.name ?? "",
165
199
  file: o(e, t.file)
166
- })), [], m),
167
- tables: { tables: p }
200
+ })), [], h),
201
+ tables: { tables: m }
168
202
  };
169
- }, E = async (t) => {
203
+ }, k = async (t) => {
170
204
  let f = t.flatMap((e) => e === "--json" ? ["--format", "json"] : [e]), p = a(f);
171
205
  if ("error" in p) return console.error(`voltro check: ${p.error}`), 1;
172
206
  let { process: m, target: h, rest: g } = s(p.rest), _;
@@ -186,56 +220,69 @@ var m = (e) => e === void 0 ? [] : typeof e == "string" ? [e] : e, h = {
186
220
  };
187
221
  else return console.error("voltro check --diff: expected removeTable:<name> | removeProcedure:<tag> | removeScope:<name>"), 1;
188
222
  }
189
- let b = e(g, ["--diff"]) ?? process.cwd(), E = g.includes("--offline"), D = E ? [] : await o(m, h), O, k;
190
- if (D.length === 0) {
191
- if (!E && h !== void 0) return console.error("voltro check: --url given but no api reachable there."), 1;
223
+ let v = e(g, ["--diff"]) ?? process.cwd(), x = g.includes("--offline"), C = x ? [] : await o(m, h), k, A;
224
+ if (C.length === 0) {
225
+ if (!x && h !== void 0) return console.error("voltro check: --url given but no api reachable there."), 1;
192
226
  try {
193
- let e = await T(d(b));
194
- O = e.manifest, k = e.tables;
227
+ let e = await O(d(v));
228
+ k = e.manifest, A = e.tables;
195
229
  } catch (e) {
196
230
  return console.error(`voltro check: could not assemble the graph from source: ${e.message}`), console.error(" Start `voltro dev` to check against a running api instead."), 1;
197
231
  }
198
232
  } else {
199
- let e = D[0], [t, n] = await Promise.all([c(e, "/_voltro/inspect/manifest"), c(e, "/_voltro/inspect/data/tables")]);
233
+ let e = C[0], [t, n] = await Promise.all([c(e, "/_voltro/inspect/manifest"), c(e, "/_voltro/inspect/data/tables")]);
200
234
  if (t.kind === "err") return console.error(`voltro check: manifest fetch failed: ${t.error}`), 1;
201
- O = t.data, k = n.kind === "ok" ? n.data : { tables: [] };
235
+ k = t.data, A = n.kind === "ok" ? n.data : { tables: [] };
202
236
  }
203
- let A = C(O, k), j = r(A, _), M = [...l(b).findings.map((e) => ({
237
+ let j = E(k, A), M = r(j, _), N = "";
238
+ if (C.length > 0) try {
239
+ N = w(((await O(d(v))).manifest.procedures ?? []).map((e) => e.tag), new Set((k.procedures ?? []).map((e) => e.tag)));
240
+ } catch {
241
+ N = "\ndeclared vs live: skipped — no app source at this root to compare against";
242
+ }
243
+ let P = [...l(v).findings.map((e) => ({
204
244
  rule: e.rule,
205
245
  node: e.file,
206
246
  file: e.file,
207
247
  breaks: [e.detail],
208
248
  fix: e.fix,
209
249
  severity: e.severity
210
- })), ...u(b).map((e) => ({
250
+ })), ...u(v).map((e) => ({
211
251
  rule: `page/${e.kind}`,
212
252
  node: e.file,
213
253
  file: e.file,
214
254
  breaks: [e.kind === "suffixed-outside-pages" ? "a page.tsx outside src/pages/ never routes" : "no test beside it"],
215
255
  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",
216
256
  severity: e.kind === "suffixed-outside-pages" ? "error" : "warn"
217
- }))], N = (await n(b, y(b))).map((e) => ({
257
+ }))], F = (await n(v, b(v))).map((e) => ({
218
258
  rule: "client/not-browser-safe",
219
259
  node: e.file,
220
260
  file: e.file,
221
261
  breaks: [`reaches the server-only '${e.violation.specifier}' — chain: ${e.violation.chain.join(" → ")}`],
222
262
  fix: "move the server-only code behind a *.server.ts, or drop the .client suffix — an unmarked file makes no claim",
223
263
  severity: "error"
224
- })), P = [
225
- ...j.diagnostics,
226
- ...M,
227
- ...N
228
- ], F = j.ok && !M.some((e) => e.severity === "error") && N.length === 0, I = await x(d(b)), L = I === null ? null : v(A.procedures, I);
229
- return p.format === "json" ? i(L === null ? {
230
- ...j,
231
- ok: F,
232
- diagnostics: P
233
- } : {
234
- ...j,
235
- ok: F,
236
- diagnostics: P,
237
- observed: L
238
- }) : (console.log(w(P)), L !== null && console.log(S(L)), console.log(F ? "\nvoltro check: OK" : "\nvoltro check: FAILED (errors above)")), +!F;
264
+ })), I = [
265
+ ...M.diagnostics,
266
+ ...P,
267
+ ...F
268
+ ], L = M.ok && !P.some((e) => e.severity === "error") && F.length === 0, R = await S(d(v)), z = R === null ? null : y(j.procedures, R);
269
+ if (p.format === "json") {
270
+ let e = z === null ? {
271
+ ...M,
272
+ ok: L,
273
+ diagnostics: I
274
+ } : {
275
+ ...M,
276
+ ok: L,
277
+ diagnostics: I,
278
+ observed: z
279
+ };
280
+ i(N === "" ? e : {
281
+ ...e,
282
+ declaredVsLive: N.trim()
283
+ });
284
+ } else console.log(D(I)), z !== null && console.log(T(z)), N !== "" && console.log(N), console.log(L ? "\nvoltro check: OK" : "\nvoltro check: FAILED (errors above)");
285
+ return +!L;
239
286
  };
240
287
  //#endregion
241
- export { E as n, C as r, T as t };
288
+ export { k as a, O as i, w as n, E as o, T as r, C as t };
@@ -1,7 +1,7 @@
1
1
  import { a as e, t } from "./cliArgs-D4p8n7EE.js";
2
2
  import { a as n, i as r, n as i, r as a, t as o } from "./cloudClient-DWL-Hw_T.js";
3
3
  import { n as s } from "./cliOutput-D1tSBoRM.js";
4
- import { d as c, f as l, o as u } from "./projectScaffold-mIX_DpSe.js";
4
+ import { d as c, f as l, o as u } from "./projectScaffold-B4dmTlwT.js";
5
5
  import { basename as d, join as f, resolve as p } from "node:path";
6
6
  import { promises as m } from "node:fs";
7
7
  import { ansi as h } from "@voltro/logger";
@@ -0,0 +1,2 @@
1
+ import { t as e } from "./codegen-VF479Cnb.js";
2
+ export { e as checkRpcGroupFreshness };
@@ -1,4 +1,4 @@
1
- import { b as e, o as t, y as n } from "./fileConventions-Cof68_BL.js";
1
+ import { b as e, o as t, y as n } from "./fileConventions-DOqD3lPS.js";
2
2
  import { dirname as r, join as i, relative as a, resolve as o } from "node:path";
3
3
  import { promises as s, readFileSync as c } from "node:fs";
4
4
  import { pathToFileURL as l } from "node:url";
@@ -1,7 +1,7 @@
1
- import { B as e, Sn as t, l as n, u as r, xn as i } from "./dev-C0cbqysu.js";
2
- import { dt as a } from "./webDev-BbdkzMbd.js";
3
- import { n as o } from "./frameworkTableAssembly-BwJVEKLr.js";
4
- import { i as s, r as c } from "./codegen-CrMXs4hb.js";
1
+ import { Cn as e, Sn as t, V as n, l as r, u as i } from "./dev-CRHoCEiy.js";
2
+ import { Ct as a } from "./webDev-BgWL9gKV.js";
3
+ import { n as o } from "./frameworkTableAssembly-w-XnLa3q.js";
4
+ import { i as s, r as c } from "./codegen-VF479Cnb.js";
5
5
  import { basename as l, join as u, relative as d, resolve as f } from "node:path";
6
6
  import { promises as p } from "node:fs";
7
7
  import { pathToFileURL as m } from "node:url";
@@ -100,21 +100,21 @@ var h = "voltro.mobile.ts", g = u(".framework", "mobileApis.generated.ts"), _ =
100
100
  file: i,
101
101
  apis: r.map(([e]) => e)
102
102
  };
103
- }, x = (e, t) => t.kind === "wrote" ? `voltro codegen: wrote ${d(e, t.file)} (apis ${t.apis.join(", ")})` : t.kind === "refused" ? `voltro codegen: ${t.reason} — refusing to write.` : `voltro codegen: no ${h} here — not a mobile app.`, S = async (r) => {
104
- let { config: i, present: a, error: o } = await n(r);
103
+ }, x = (e, t) => t.kind === "wrote" ? `voltro codegen: wrote ${d(e, t.file)} (apis ${t.apis.join(", ")})` : t.kind === "refused" ? `voltro codegen: ${t.reason} — refusing to write.` : `voltro codegen: no ${h} here — not a mobile app.`, S = async (t) => {
104
+ let { config: i, present: a, error: o } = await r(t);
105
105
  if (a && i === null) return {
106
106
  kind: "refused",
107
107
  reason: "app.config.ts exists but could not be loaded" + (o === void 0 ? "" : ` — ${o instanceof Error ? o.message : String(o)}`)
108
108
  };
109
- let s = i?.plugins ?? [], { pluginContributions: u, pluginErrorImports: d, pluginRpcImports: f } = await e(s, i?.name ?? l(r), r), p = await c({
110
- root: r,
109
+ let s = i?.plugins ?? [], { pluginContributions: u, pluginErrorImports: d, pluginRpcImports: f } = await n(s, i?.name ?? l(t), t), p = await c({
110
+ root: t,
111
111
  ...u.length > 0 ? { pluginContributions: u } : {},
112
112
  ...d.length > 0 ? { pluginErrorImports: d } : {},
113
113
  ...f.length > 0 ? { pluginRpcImports: f } : {},
114
114
  ...i?.name === void 0 ? {} : { apiName: i.name }
115
115
  });
116
116
  if (!p) return { kind: "nothing-to-write" };
117
- let m = await C(r, i), h = await t(p, m);
117
+ let m = await C(t, i), h = await e(p, m);
118
118
  return {
119
119
  kind: "wrote",
120
120
  file: p,
@@ -124,9 +124,9 @@ var h = "voltro.mobile.ts", g = u(".framework", "mobileApis.generated.ts"), _ =
124
124
  tables: m.size,
125
125
  dts: h
126
126
  };
127
- }, C = async (e, t) => {
128
- let n = await s(e), { tables: a } = await r(n), c = await o({ root: e });
129
- return i(a, c, t?.analytics?.tables ?? []);
127
+ }, C = async (e, n) => {
128
+ let r = await s(e), { tables: a } = await i(r), c = await o({ root: e });
129
+ return t(a, c, n?.analytics?.tables ?? []);
130
130
  }, w = async (e) => {
131
131
  let t = f(e.find((e) => !e.startsWith("-")) ?? process.cwd()), n = await b(t);
132
132
  if (n.kind !== "not-a-mobile-app") return console.log(x(t, n)), n.kind === "wrote" ? 0 : 1;