@voltro/cli 0.12.0 → 0.14.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 (189) hide show
  1. package/CHANGELOG.md +378 -0
  2. package/dist/{apiBuild-GefjNI5d.js → apiBuild-370ITNRk.js} +3 -3
  3. package/dist/apiBuild-DatWP5hh.js +2 -0
  4. package/dist/bin.js +3 -3
  5. package/dist/{commands-BmNi1RgZ.js → commands-D-teL_TM.js} +3756 -2539
  6. package/dist/dbCommand-B3CeMU3u.js +2 -0
  7. package/dist/{dbCommand-DNrkb58g.js → dbCommand-Dmi-vHfA.js} +72 -57
  8. package/dist/{dev-d0LjACxE.js → dev-CKyW_LAv.js} +1511 -1331
  9. package/dist/dev-CPKbckaN.js +3 -0
  10. package/dist/fileConventions-COg0ZytD.js +9 -0
  11. package/dist/frameworkTableAssembly-DCLhpHsF.js +601 -0
  12. package/dist/frameworkTableAssembly-DYzb2elg.js +2 -0
  13. package/dist/index.js +1 -1
  14. package/dist/{inspectMetrics-uEfIS1vp.js → inspectMetrics-CyVMeofr.js} +962 -943
  15. package/dist/seedRunner-D6eu-u5U.js +229 -0
  16. package/dist/serveCommand-CU3Sw4ZM.js +1127 -0
  17. package/dist/serveEntry.js +3 -3
  18. package/dist/{start-DKcQd52a.js → start-D8ATvTzo.js} +246 -246
  19. package/dist/startEntry.js +2 -2
  20. package/package.json +17 -17
  21. package/templates/AGENTS.core.md +77 -3
  22. package/templates/AGENTS.md +78 -4
  23. package/templates/agent-docs/_index.md +1 -1
  24. package/templates/agent-docs/_manifest.json +2 -2
  25. package/templates/agent-docs/authentication.md +39 -0
  26. package/templates/agent-docs/cli.md +114 -6
  27. package/templates/agent-docs/configuration.md +48 -0
  28. package/templates/agent-docs/data.md +193 -1
  29. package/templates/agent-docs/database/hosting.md +2 -2
  30. package/templates/agent-docs/database/migrations.md +88 -3
  31. package/templates/agent-docs/database/overview.md +11 -0
  32. package/templates/agent-docs/database/seedsdialects.md +53 -1
  33. package/templates/agent-docs/database/transactions.md +31 -0
  34. package/templates/agent-docs/internationalization.md +3 -3
  35. package/templates/agent-docs/introduction.md +133 -2
  36. package/templates/agent-docs/plugins.md +2 -1
  37. package/templates/agent-docs/reference.md +4 -4
  38. package/templates/agent-docs/routing.md +48 -43
  39. package/templates/agent-docs/schema-driven-ui.md +12 -2
  40. package/templates/agent-docs/templates/apibackends.md +1 -8
  41. package/templates/agent-docs/templates/appshells.md +24 -24
  42. package/templates/agent-docs/testing.md +40 -1
  43. package/templates/agent-docs/whats-new.md +51 -131
  44. package/templates/apps/api-ai/database/schema.ts +0 -2
  45. package/templates/apps/api-ai/package.json +7 -7
  46. package/templates/apps/api-auth/package.json +8 -8
  47. package/templates/apps/api-backend/database/schema.ts +0 -3
  48. package/templates/apps/api-backend/package.json +7 -7
  49. package/templates/apps/api-backend-deactivation/database/schema.ts +0 -1
  50. package/templates/apps/api-backend-deactivation/package.json +7 -7
  51. package/templates/apps/api-backend-deactivation/tests/users.deactivate.test.ts +1 -1
  52. package/templates/apps/api-backend-mail/database/schema.ts +0 -3
  53. package/templates/apps/api-backend-mail/package.json +8 -8
  54. package/templates/apps/api-backend-mariadb/database/schema.ts +0 -3
  55. package/templates/apps/api-backend-mariadb/package.json +9 -9
  56. package/templates/apps/api-backend-storage/database/schema.ts +0 -3
  57. package/templates/apps/api-backend-storage/package.json +8 -8
  58. package/templates/apps/api-data-advanced/database/authors.entity.ts +0 -2
  59. package/templates/apps/api-data-advanced/database/books.entity.ts +0 -1
  60. package/templates/apps/api-data-advanced/package.json +8 -8
  61. package/templates/apps/api-data-advanced/tests/queries.test.ts +6 -1
  62. package/templates/apps/api-durable/database/schema.ts +0 -3
  63. package/templates/apps/api-durable/package.json +8 -8
  64. package/templates/apps/api-feature-flags/database/schema.ts +0 -1
  65. package/templates/apps/api-feature-flags/package.json +9 -9
  66. package/templates/apps/api-governance/app.config.ts +0 -1
  67. package/templates/apps/api-governance/database/schema.ts +0 -1
  68. package/templates/apps/api-governance/package.json +8 -8
  69. package/templates/apps/api-kv/database/schema.ts +0 -3
  70. package/templates/apps/api-kv/package.json +8 -8
  71. package/templates/apps/api-kv/tests/sync.test.ts +2 -2
  72. package/templates/apps/api-moderation/database/schema.ts +0 -2
  73. package/templates/apps/api-moderation/package.json +8 -8
  74. package/templates/apps/api-observability/database/schema.ts +0 -1
  75. package/templates/apps/api-observability/package.json +8 -8
  76. package/templates/apps/api-ratelimit/database/schema.ts +0 -1
  77. package/templates/apps/api-ratelimit/package.json +8 -8
  78. package/templates/apps/api-rbac/README.md +53 -14
  79. package/templates/apps/api-rbac/app.config.ts +24 -26
  80. package/templates/apps/api-rbac/authz.ts +76 -0
  81. package/templates/apps/api-rbac/database/schema.ts +22 -7
  82. package/templates/apps/api-rbac/mutations/notes.create.mutation.server.ts +7 -5
  83. package/templates/apps/api-rbac/mutations/notes.create.mutation.ts +15 -8
  84. package/templates/apps/api-rbac/mutations/notes.delete.mutation.server.ts +54 -0
  85. package/templates/apps/api-rbac/mutations/notes.delete.mutation.ts +43 -0
  86. package/templates/apps/api-rbac/mutations/teams.rename.mutation.server.ts +19 -0
  87. package/templates/apps/api-rbac/mutations/teams.rename.mutation.ts +37 -0
  88. package/templates/apps/api-rbac/package.json +8 -8
  89. package/templates/apps/api-rbac/queries/notes.list.query.server.ts +12 -0
  90. package/templates/apps/api-rbac/queries/notes.list.query.ts +26 -0
  91. package/templates/apps/api-rbac/template.json +2 -2
  92. package/templates/apps/api-rbac/tests/authz.test.ts +233 -0
  93. package/templates/apps/api-rest/database/schema.ts +0 -3
  94. package/templates/apps/api-rest/package.json +7 -7
  95. package/templates/apps/api-saas/database/schema.ts +0 -1
  96. package/templates/apps/api-saas/package.json +11 -11
  97. package/templates/apps/api-search/database/schema.ts +0 -1
  98. package/templates/apps/api-search/package.json +8 -8
  99. package/templates/apps/api-versioning/database/schema.ts +0 -1
  100. package/templates/apps/api-versioning/package.json +8 -8
  101. package/templates/apps/api-webhooks/database/schema.ts +0 -1
  102. package/templates/apps/api-webhooks/package.json +9 -8
  103. package/templates/apps/changelog/package.json +6 -6
  104. package/templates/apps/changelog/src/pages/[locale]/{[slug].tsx → [slug].page.tsx} +2 -2
  105. package/templates/apps/changelog/src/pages/[locale]/{index.tsx → index.page.tsx} +2 -2
  106. package/templates/apps/changelog/src/pages/[locale]/mirrors.test.tsx +2 -2
  107. package/templates/apps/changelog/src/pages/{[slug].test.tsx → [slug].page.test.tsx} +1 -1
  108. package/templates/apps/changelog/src/pages/{index.test.tsx → index.page.test.tsx} +1 -1
  109. package/templates/apps/edge-functions/package.json +2 -2
  110. package/templates/apps/frontend-admin/package.json +8 -8
  111. package/templates/apps/frontend-admin/src/pages/(marketing)/{index.test.tsx → index.page.test.tsx} +1 -1
  112. package/templates/apps/frontend-admin/src/pages/(marketing)/{login.test.tsx → login.page.test.tsx} +1 -1
  113. package/templates/apps/frontend-admin/src/pages/admin/entity.test.tsx +1 -1
  114. package/templates/apps/frontend-admin/src/pages/admin/{index.test.tsx → index.page.test.tsx} +1 -1
  115. package/templates/apps/frontend-app/package.json +8 -8
  116. package/templates/apps/frontend-app/src/pages/{index.test.tsx → index.page.test.tsx} +1 -1
  117. package/templates/apps/frontend-app/src/pages/{schema-ui.test.tsx → schema-ui.page.test.tsx} +1 -1
  118. package/templates/apps/frontend-blank/package.json +7 -7
  119. package/templates/apps/frontend-blank/src/pages/{index.test.tsx → index.page.test.tsx} +1 -1
  120. package/templates/apps/frontend-contact/package.json +7 -7
  121. package/templates/apps/frontend-contact/src/pages/[locale]/{index.tsx → index.page.tsx} +2 -2
  122. package/templates/apps/frontend-contact/src/pages/{index.test.tsx → index.page.test.tsx} +1 -1
  123. package/templates/apps/frontend-dashboard/package.json +7 -7
  124. package/templates/apps/frontend-dashboard/src/pages/(marketing)/{index.test.tsx → index.page.test.tsx} +1 -1
  125. package/templates/apps/frontend-dashboard/src/pages/(marketing)/{login.test.tsx → login.page.test.tsx} +1 -1
  126. package/templates/apps/frontend-dashboard/src/pages/dashboard/{index.test.tsx → index.page.test.tsx} +1 -1
  127. package/templates/apps/frontend-dashboard/src/pages/dashboard/{settings.test.tsx → settings.page.test.tsx} +1 -1
  128. package/templates/apps/frontend-docs/package.json +7 -7
  129. package/templates/apps/frontend-docs/src/pages/[locale]/docs/{[...slug].tsx → [...slug].page.tsx} +3 -3
  130. package/templates/apps/frontend-docs/src/pages/[locale]/{index.tsx → index.page.tsx} +2 -2
  131. package/templates/apps/frontend-docs/src/pages/[locale]/mirrors.test.tsx +2 -2
  132. package/templates/apps/frontend-docs/src/pages/docs/{[...slug].test.tsx → [...slug].page.test.tsx} +1 -1
  133. package/templates/apps/frontend-docs/src/pages/{index.test.tsx → index.page.test.tsx} +1 -1
  134. package/templates/apps/frontend-i18n/package.json +6 -6
  135. package/templates/apps/frontend-i18n/src/pages/[locale]/{about.tsx → about.page.tsx} +2 -2
  136. package/templates/apps/frontend-i18n/src/pages/[locale]/{index.tsx → index.page.tsx} +2 -2
  137. package/templates/apps/frontend-i18n/src/pages/[locale]/mirrors.test.tsx +2 -2
  138. package/templates/apps/frontend-i18n/src/pages/{about.test.tsx → about.page.test.tsx} +1 -1
  139. package/templates/apps/frontend-i18n/src/pages/{index.test.tsx → index.page.test.tsx} +1 -1
  140. package/templates/apps/frontend-landing/package.json +7 -7
  141. package/templates/apps/frontend-landing/src/pages/[locale]/{index.tsx → index.page.tsx} +2 -2
  142. package/templates/apps/frontend-landing/src/pages/[locale]/mirrors.test.tsx +1 -1
  143. package/templates/apps/frontend-landing/src/pages/{index.test.tsx → index.page.test.tsx} +1 -1
  144. package/templates/apps/frontend-spa/package.json +7 -7
  145. package/templates/apps/frontend-spa/src/pages/{index.test.tsx → index.page.test.tsx} +1 -1
  146. package/templates/apps/frontend-ssr/package.json +7 -7
  147. package/templates/apps/frontend-ssr/src/pages/{feed-swr.test.tsx → feed-swr.page.test.tsx} +1 -1
  148. package/templates/apps/frontend-ssr/src/pages/{feed.test.tsx → feed.page.test.tsx} +1 -1
  149. package/templates/apps/frontend-ssr/src/pages/{index.test.tsx → index.page.test.tsx} +1 -1
  150. package/templates/apps/frontend-ssr-api/package.json +8 -8
  151. package/templates/apps/frontend-ssr-api/src/pages/{index.test.tsx → index.page.test.tsx} +1 -1
  152. package/templates/apps/frontend-static-blog/package.json +6 -6
  153. package/templates/apps/frontend-static-blog/src/pages/[locale]/blog/{[slug].tsx → [slug].page.tsx} +2 -2
  154. package/templates/apps/frontend-static-blog/src/pages/[locale]/{index.tsx → index.page.tsx} +2 -2
  155. package/templates/apps/frontend-static-blog/src/pages/[locale]/mirrors.test.tsx +2 -2
  156. package/templates/apps/frontend-static-blog/src/pages/blog/{[slug].test.tsx → [slug].page.test.tsx} +1 -1
  157. package/templates/apps/frontend-static-blog/src/pages/{index.test.tsx → index.page.test.tsx} +1 -1
  158. package/dist/apiBuild-s7swuEU5.js +0 -2
  159. package/dist/dbCommand-Bt6BCG7g.js +0 -2
  160. package/dist/dev-YHbHmeXt.js +0 -3
  161. package/dist/seedRunner-DZmhoqNt.js +0 -821
  162. package/dist/serveCommand-B2-YV9TU.js +0 -1112
  163. package/templates/apps/api-rbac/tests/notes.create.test.ts +0 -80
  164. /package/templates/apps/changelog/src/pages/{[slug].tsx → [slug].page.tsx} +0 -0
  165. /package/templates/apps/changelog/src/pages/{index.tsx → index.page.tsx} +0 -0
  166. /package/templates/apps/frontend-admin/src/pages/(marketing)/{index.tsx → index.page.tsx} +0 -0
  167. /package/templates/apps/frontend-admin/src/pages/(marketing)/{login.tsx → login.page.tsx} +0 -0
  168. /package/templates/apps/frontend-admin/src/pages/admin/{[entity].tsx → [entity].page.tsx} +0 -0
  169. /package/templates/apps/frontend-admin/src/pages/admin/{index.tsx → index.page.tsx} +0 -0
  170. /package/templates/apps/frontend-app/src/pages/{index.tsx → index.page.tsx} +0 -0
  171. /package/templates/apps/frontend-app/src/pages/{schema-ui.tsx → schema-ui.page.tsx} +0 -0
  172. /package/templates/apps/frontend-blank/src/pages/{index.tsx → index.page.tsx} +0 -0
  173. /package/templates/apps/frontend-contact/src/pages/{index.tsx → index.page.tsx} +0 -0
  174. /package/templates/apps/frontend-dashboard/src/pages/(marketing)/{index.tsx → index.page.tsx} +0 -0
  175. /package/templates/apps/frontend-dashboard/src/pages/(marketing)/{login.tsx → login.page.tsx} +0 -0
  176. /package/templates/apps/frontend-dashboard/src/pages/dashboard/{index.tsx → index.page.tsx} +0 -0
  177. /package/templates/apps/frontend-dashboard/src/pages/dashboard/{settings.tsx → settings.page.tsx} +0 -0
  178. /package/templates/apps/frontend-docs/src/pages/docs/{[...slug].tsx → [...slug].page.tsx} +0 -0
  179. /package/templates/apps/frontend-docs/src/pages/{index.tsx → index.page.tsx} +0 -0
  180. /package/templates/apps/frontend-i18n/src/pages/{about.tsx → about.page.tsx} +0 -0
  181. /package/templates/apps/frontend-i18n/src/pages/{index.tsx → index.page.tsx} +0 -0
  182. /package/templates/apps/frontend-landing/src/pages/{index.tsx → index.page.tsx} +0 -0
  183. /package/templates/apps/frontend-spa/src/pages/{index.tsx → index.page.tsx} +0 -0
  184. /package/templates/apps/frontend-ssr/src/pages/{feed-swr.tsx → feed-swr.page.tsx} +0 -0
  185. /package/templates/apps/frontend-ssr/src/pages/{feed.tsx → feed.page.tsx} +0 -0
  186. /package/templates/apps/frontend-ssr/src/pages/{index.tsx → index.page.tsx} +0 -0
  187. /package/templates/apps/frontend-ssr-api/src/pages/{index.tsx → index.page.tsx} +0 -0
  188. /package/templates/apps/frontend-static-blog/src/pages/blog/{[slug].tsx → [slug].page.tsx} +0 -0
  189. /package/templates/apps/frontend-static-blog/src/pages/{index.tsx → index.page.tsx} +0 -0
@@ -0,0 +1,2 @@
1
+ import { o as e } from "./dbCommand-Dmi-vHfA.js";
2
+ export { e as runDbCommand };
@@ -1,4 +1,6 @@
1
- import { G as e, a as t, i as n, m as r, n as i, r as a, t as o } from "./seedRunner-DZmhoqNt.js";
1
+ import { i as e, n as t, r as n, s as r, t as i } from "./seedRunner-D6eu-u5U.js";
2
+ import { t as a } from "./frameworkTableAssembly-DCLhpHsF.js";
3
+ import { g as o } from "./fileConventions-COg0ZytD.js";
2
4
  import { a as s, n as c, t as l } from "./cliArgs-qdZSElM3.js";
3
5
  import { basename as u, join as d, relative as f, resolve as p } from "node:path";
4
6
  import { pathToFileURL as m } from "node:url";
@@ -321,7 +323,7 @@ var k = class extends Error {
321
323
  let e = (process.env.DB_DIALECT ?? "postgres").toLowerCase();
322
324
  if (e === "memory") throw new k("voltro db: subcommands require a real dialect, not DB_DIALECT=memory.");
323
325
  return e;
324
- }, W = async () => (await e(U())).makeSqlLayer(B()), fe = async (e) => {
326
+ }, W = async () => (await r(U())).makeSqlLayer(B()), fe = async (e) => {
325
327
  let t = z(e), n = e.includes("--dry-run"), r = await j(await R(t, A), L);
326
328
  if (r.length === 0) return L.info("no migrations found", { root: t }), 0;
327
329
  if (n) {
@@ -357,17 +359,17 @@ var k = class extends Error {
357
359
  console.log(` ${t} ${e.id} [${e.status}] ${e.name}${r}${n}`);
358
360
  }
359
361
  return 0;
360
- }, he = async (t) => {
361
- let n = (c(t, "--store") ?? process.env.DB_DIALECT ?? "postgres").toLowerCase();
362
- if (n === "memory") return L.warn("voltro db seed: using in-memory store (explicit opt-in via --store memory / DB_DIALECT=memory)"), L.warn(" rows written by this run will NOT persist beyond the process. set DB_DIALECT=postgres or unset to seed the real DB."), {
362
+ }, he = async (e) => {
363
+ let t = (c(e, "--store") ?? process.env.DB_DIALECT ?? "postgres").toLowerCase();
364
+ if (t === "memory") return L.warn("voltro db seed: using in-memory store (explicit opt-in via --store memory / DB_DIALECT=memory)"), L.warn(" rows written by this run will NOT persist beyond the process. set DB_DIALECT=postgres or unset to seed the real DB."), {
363
365
  store: new ne(),
364
366
  dispose: async () => {},
365
367
  dialectId: "memory"
366
368
  };
367
- let r = await e(n);
368
- L.info(`voltro db seed: target store=${r.id} — rows will persist`);
369
- let i = await r.makeStore({
370
- sqlLayer: r.makeSqlLayer(B()),
369
+ let n = await r(t);
370
+ L.info(`voltro db seed: target store=${n.id} — rows will persist`);
371
+ let i = await n.makeStore({
372
+ sqlLayer: n.makeSqlLayer(B()),
371
373
  changeStrategy: "inline"
372
374
  }), a = i;
373
375
  return {
@@ -375,14 +377,14 @@ var k = class extends Error {
375
377
  dispose: async () => {
376
378
  typeof a.close == "function" && await a.close(5e3);
377
379
  },
378
- dialectId: r.id
380
+ dialectId: n.id
379
381
  };
380
- }, ge = async (e) => {
381
- let t = z(e), r = c(e, "--id"), s = c(e, "--lifecycle"), l = await i(await R(t, o), L);
382
- if (l.length === 0) return L.info("no seeds found", { root: t }), 0;
383
- let { store: u, dispose: d, dialectId: f } = await he(e);
382
+ }, ge = async (r) => {
383
+ let a = z(r), o = c(r, "--id"), s = c(r, "--lifecycle"), l = await t(await R(a, i), L);
384
+ if (l.length === 0) return L.info("no seeds found", { root: a }), 0;
385
+ let { store: u, dispose: d, dialectId: f } = await he(r);
384
386
  try {
385
- return r ? +((await n(l, r, u, L)).status === "failed") : +((await a((s ? l.filter((e) => e.definition.lifecycle === s) : l.filter((e) => e.definition.lifecycle === "boot")).map((e) => ({
387
+ return o ? +((await e(l, o, u, L)).status === "failed") : +((await n((s ? l.filter((e) => e.definition.lifecycle === s) : l.filter((e) => e.definition.lifecycle === "boot")).map((e) => ({
386
388
  ...e,
387
389
  definition: {
388
390
  ...e.definition,
@@ -395,7 +397,7 @@ var k = class extends Error {
395
397
  });
396
398
  }
397
399
  }, _e = (e) => typeof e == "object" && !!e && "tableName" in e && "fields" in e && typeof e.tableName == "string", G = async (e) => {
398
- let t = await R(e, r), n = [];
400
+ let t = await R(e, o), n = [];
399
401
  for (let r of t) {
400
402
  let t;
401
403
  try {
@@ -519,21 +521,21 @@ var k = class extends Error {
519
521
  if (!Number.isInteger(n) || n < 0) throw Error(`--online-after / VOLTRO_ONLINE_THRESHOLD must be a non-negative integer, got "${t}"`);
520
522
  return n;
521
523
  }, be = async (e) => {
522
- let n = Z(e), r = z(e), i = await G(r);
523
- if (i.length === 0) return L.warn("db plan: no schema files found", {
524
- root: r,
524
+ let t = Z(e), n = z(e), r = await G(n);
525
+ if (r.length === 0) return L.warn("db plan: no schema files found", {
526
+ root: n,
525
527
  hint: "looked for *.entity.ts / *.schema.ts / schema.ts"
526
528
  }), 1;
527
- let a = await t({ root: r }), o = K(q([
528
- ...i,
529
+ let i = await a({ root: n }), o = K(q([
530
+ ...r,
529
531
  ...y,
530
- ...a
532
+ ...i
531
533
  ])), s = c(e, "--against");
532
534
  if (s) {
533
- let t = s, r = c(e, "--token") ?? process.env.VOLTRO_INSPECT_TOKEN, i = { accept: "application/json" };
535
+ let n = s, r = c(e, "--token") ?? process.env.VOLTRO_INSPECT_TOKEN, i = { accept: "application/json" };
534
536
  r && (i.authorization = `Bearer ${r}`);
535
537
  try {
536
- let e = t.endsWith("/_voltro/inspect/migrations") ? t : `${t.replace(/\/+$/, "")}/_voltro/inspect/migrations`, r = await fetch(e, { headers: i });
538
+ let e = n.endsWith("/_voltro/inspect/migrations") ? n : `${n.replace(/\/+$/, "")}/_voltro/inspect/migrations`, r = await fetch(e, { headers: i });
537
539
  if (!r.ok) return L.error(`db plan --against: remote returned ${r.status}`, { url: e }), 1;
538
540
  let a = (await r.json()).drift?.liveSnapshot;
539
541
  if (!a) return L.error("db plan --against: remote inspect payload missing drift.liveSnapshot", { url: e }), 1;
@@ -542,7 +544,7 @@ var k = class extends Error {
542
544
  live: a,
543
545
  dialect: U(),
544
546
  ...w(),
545
- ...n === void 0 ? {} : { onlineAfter: n }
547
+ ...t === void 0 ? {} : { onlineAfter: t }
546
548
  });
547
549
  return console.log(`\n[--against ${e}] — diff vs remote live schema:\n`), X(s), s.summary.blocked > 0 ? 2 : 0;
548
550
  } catch (e) {
@@ -554,22 +556,22 @@ var k = class extends Error {
554
556
  live: await Y(await W()),
555
557
  dialect: U(),
556
558
  ...w(),
557
- ...n === void 0 ? {} : { onlineAfter: n }
559
+ ...t === void 0 ? {} : { onlineAfter: t }
558
560
  });
559
561
  return e.includes("--json") ? (te(1, `${JSON.stringify(l, null, 2)}\n`), l.summary.blocked > 0 ? 2 : 0) : (X(l), l.summary.blocked > 0 ? 2 : 0);
560
- }, xe = async (e, n, r) => {
561
- let i;
562
+ }, xe = async (e, t, n) => {
563
+ let r;
562
564
  try {
563
565
  let t = await g.readFile(p(e), "utf8");
564
- i = JSON.parse(t);
566
+ r = JSON.parse(t);
565
567
  } catch (t) {
566
568
  return L.error(`db apply --plan: cannot read/parse plan file '${e}': ${t.message}`), 1;
567
569
  }
568
- if (!Array.isArray(i?.operations) || typeof i?.fromFingerprint != "string" || typeof i?.toFingerprint != "string") return L.error(`db apply --plan: '${e}' is not a valid plan file (expected the output of \`voltro db plan --json\`).`), 1;
569
- let a = await G(r);
570
- if (a.length === 0) return L.warn("db apply --plan: no schema files found", { root: r }), 1;
571
- let o = await t({ root: r }), s = K(q([
572
- ...a,
570
+ if (!Array.isArray(r?.operations) || typeof r?.fromFingerprint != "string" || typeof r?.toFingerprint != "string") return L.error(`db apply --plan: '${e}' is not a valid plan file (expected the output of \`voltro db plan --json\`).`), 1;
571
+ let i = await G(n);
572
+ if (i.length === 0) return L.warn("db apply --plan: no schema files found", { root: n }), 1;
573
+ let o = await a({ root: n }), s = K(q([
574
+ ...i,
573
575
  ...y,
574
576
  ...o
575
577
  ])), l = await W();
@@ -580,30 +582,36 @@ var k = class extends Error {
580
582
  dialect: U(),
581
583
  ...w()
582
584
  });
583
- if (u.fromFingerprint !== i.fromFingerprint) return L.error("db apply --plan: refusing — the live schema has drifted since this plan was generated."), console.error(` plan.from=${i.fromFingerprint.slice(0, 16)} live=${u.fromFingerprint.slice(0, 16)}`), console.error(" Regenerate against the current live schema: `voltro db plan --json > plan.json`"), 2;
584
- if (u.toFingerprint !== i.toFingerprint) return L.error("db apply --plan: refusing — the declared schema differs from what this plan targets."), console.error(` plan.to=${i.toFingerprint.slice(0, 16)} declared=${u.toFingerprint.slice(0, 16)}`), console.error(" The schema files changed since the plan was generated. Regenerate the plan."), 2;
585
+ if (u.fromFingerprint !== r.fromFingerprint) return L.error("db apply --plan: refusing — the live schema has drifted since this plan was generated."), console.error(` plan.from=${r.fromFingerprint.slice(0, 16)} live=${u.fromFingerprint.slice(0, 16)}`), console.error(" Regenerate against the current live schema: `voltro db plan --json > plan.json`"), 2;
586
+ if (u.toFingerprint !== r.toFingerprint) return L.error("db apply --plan: refusing — the declared schema differs from what this plan targets."), console.error(` plan.to=${r.toFingerprint.slice(0, 16)} declared=${u.toFingerprint.slice(0, 16)}`), console.error(" The schema files changed since the plan was generated. Regenerate the plan."), 2;
585
587
  if (u.summary.blocked > 0) return X(u), L.error(`db apply --plan: refusing — ${u.summary.blocked} blocked operation(s). See the fix hints above.`), 2;
586
588
  if (u.operations.length === 0) return L.info("db apply --plan: schema is up to date — nothing to apply"), 0;
587
589
  X(u);
588
- let d = (process.env.NODE_ENV ?? "dev").toLowerCase(), f = c(n, "--note"), m = await J(l, _.SqlClient.pipe(h.flatMap((e) => x(e, u, {
590
+ let d = (process.env.NODE_ENV ?? "dev").toLowerCase(), f = c(t, "--note"), m = await J(l, _.SqlClient.pipe(h.flatMap((e) => x(e, u, {
589
591
  declared: s,
590
592
  appliedBy: process.env.USER ? `cli:${process.env.USER}` : "cli:plan",
591
593
  environment: d === "production" ? "prod" : d === "staging" ? "staging" : "dev",
592
594
  source: "file",
593
- ...f ? { notes: f } : {}
595
+ ...f ? { notes: f } : {},
596
+ replan: () => h.promise(() => Y(l)).pipe(h.map((e) => T({
597
+ declared: s,
598
+ live: e,
599
+ dialect: U(),
600
+ ...w()
601
+ })))
594
602
  }))));
595
- return L.info(`db apply --plan: applied ${u.operations.length} op(s) in ${m.durationMs}ms`, {
603
+ return L.info(`db apply --plan: applied ${m.appliedOps} op(s) in ${m.durationMs}ms`, {
596
604
  id: m.id,
597
605
  fingerprint: m.fingerprint.slice(0, 16)
598
606
  }), 0;
599
607
  }, Se = async (e) => {
600
- let n = z(e), r = Z(e), i = c(e, "--plan");
601
- if (i) return xe(i, e, n);
608
+ let t = z(e), n = Z(e), r = c(e, "--plan");
609
+ if (r) return xe(r, e, t);
602
610
  if ((process.env.NODE_ENV ?? "").toLowerCase() === "production") return L.error("voltro db apply: refusing — auto-apply on prod is not allowed."), console.error("In production, schema changes go through `voltro db plan --json > plan.json`"), console.error("then `voltro db apply --plan plan.json` as an explicit step in your deploy pipeline."), 3;
603
- let a = await G(n);
604
- if (a.length === 0) return L.warn("db apply: no schema files found", { root: n }), 1;
605
- let o = await t({ root: n }), s = K(q([
606
- ...a,
611
+ let i = await G(t);
612
+ if (i.length === 0) return L.warn("db apply: no schema files found", { root: t }), 1;
613
+ let o = await a({ root: t }), s = K(q([
614
+ ...i,
607
615
  ...y,
608
616
  ...o
609
617
  ])), l = await W();
@@ -613,7 +621,7 @@ var k = class extends Error {
613
621
  live: await Y(l),
614
622
  dialect: U(),
615
623
  ...w(),
616
- ...r === void 0 ? {} : { onlineAfter: r }
624
+ ...n === void 0 ? {} : { onlineAfter: n }
617
625
  });
618
626
  if (X(u), u.summary.blocked > 0) return L.error(`db apply: refusing — ${u.summary.blocked} blocked operation(s). See the fix hints above.`), 2;
619
627
  if (u.operations.length === 0) return L.info("db apply: schema is up to date — nothing to apply"), 0;
@@ -622,9 +630,16 @@ var k = class extends Error {
622
630
  appliedBy: process.env.USER ? `cli:${process.env.USER}` : "cli:user",
623
631
  environment: (process.env.NODE_ENV ?? "dev").toLowerCase() === "staging" ? "staging" : "dev",
624
632
  source: "auto-diff",
625
- ...d ? { notes: d } : {}
633
+ ...d ? { notes: d } : {},
634
+ replan: () => h.promise(() => Y(l)).pipe(h.map((e) => T({
635
+ declared: s,
636
+ live: e,
637
+ dialect: U(),
638
+ ...w(),
639
+ ...n === void 0 ? {} : { onlineAfter: n }
640
+ })))
626
641
  }))));
627
- return L.info(`db apply: applied ${u.operations.length} op(s) in ${f.durationMs}ms`, {
642
+ return L.info(`db apply: applied ${f.appliedOps} op(s) in ${f.durationMs}ms`, {
628
643
  id: f.id,
629
644
  fingerprint: f.fingerprint.slice(0, 16)
630
645
  }), 0;
@@ -724,24 +739,24 @@ var k = class extends Error {
724
739
  }
725
740
  return console.log(`\n${i ? `[dry-run] ${u} snapshot(s) would be dropped` : `✓ dropped ${u} snapshot(s)`} (older than ${r}).\n`), 0;
726
741
  }, Q = async (e) => {
727
- let n = c(e, "--before");
728
- if (!n) return console.error("voltro db squash --before <iso-date> [--note \"<text>\"]"), 2;
729
- let r = n;
730
- if (Number.isNaN(new Date(r).getTime())) return console.error(`voltro db squash: --before '${r}' is not a valid ISO date`), 2;
731
- let i = c(e, "--note"), a = z(e), o = await G(a);
732
- if (o.length === 0) return L.warn("db squash: no schema files found", { root: a }), 1;
733
- let s = await t({ root: a }), l = C(ae(K(q([
742
+ let t = c(e, "--before");
743
+ if (!t) return console.error("voltro db squash --before <iso-date> [--note \"<text>\"]"), 2;
744
+ let n = t;
745
+ if (Number.isNaN(new Date(n).getTime())) return console.error(`voltro db squash: --before '${n}' is not a valid ISO date`), 2;
746
+ let r = c(e, "--note"), i = z(e), o = await G(i);
747
+ if (o.length === 0) return L.warn("db squash: no schema files found", { root: i }), 1;
748
+ let s = await a({ root: i }), l = C(ae(K(q([
734
749
  ...o,
735
750
  ...y,
736
751
  ...s
737
752
  ])))), u = await W();
738
753
  try {
739
754
  let e = await J(u, se({
740
- before: r,
755
+ before: n,
741
756
  fingerprint: l,
742
757
  appliedBy: process.env.USER ?? "cli",
743
758
  environment: process.env.NODE_ENV === "production" ? "prod" : "dev",
744
- ...i === void 0 ? {} : { note: i }
759
+ ...r === void 0 ? {} : { note: r }
745
760
  }));
746
761
  return console.log(`\n✓ squashed ${e.squashedCount} migration plan(s)\n snapshot id: ${e.snapshotId}\n fingerprint: ${O(e.snapshotFingerprint)}\n`), 0;
747
762
  } catch (e) {