@voltro/cli 0.42.0 → 0.43.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 (106) hide show
  1. package/CHANGELOG.md +91 -0
  2. package/dist/apiBuild-B7NgSMhX.js +2 -0
  3. package/dist/{apiBuild-B_iH24qf.js → apiBuild-DF0f69Gf.js} +2 -2
  4. package/dist/bin.js +1 -1
  5. package/dist/{build-DUdi6F_Q.js → build-LC_IJaHL.js} +7 -7
  6. package/dist/{checkCommand-B2RWrpWi.js → checkCommand-DBpTSK8d.js} +1 -1
  7. package/dist/{checkCommand-DWL2_PPR.js → checkCommand-DDxwJCja.js} +2 -2
  8. package/dist/{codegenCommand-DkjoJ30Q.js → codegenCommand-LjxfK4Am.js} +2 -2
  9. package/dist/{codemodRunner-sFuWDETH.js → codemodRunner-Cnnz4-I7.js} +19 -4
  10. package/dist/{commands-DoTClnSk.js → commands-CbQcuWsE.js} +20 -20
  11. package/dist/{dashboardCommand-Bro7Jwts.js → dashboardCommand-CAHjCe_9.js} +3 -3
  12. package/dist/{dataCommand-Rj57y1vg.js → dataCommand-CrqvbVOv.js} +143 -133
  13. package/dist/{dev-D4l_YOzI.js → dev-B2rZfqxw.js} +2 -2
  14. package/dist/{dev-DuqBJC7g.js → dev-D0E5x2Ue.js} +1 -1
  15. package/dist/doctorCommand-CdsctSwg.js +2 -0
  16. package/dist/{doctorCommand-TmZTAepc.js → doctorCommand-Ct_3BHgd.js} +226 -216
  17. package/dist/{dormancyCommand-CUKhRmGG.js → dormancyCommand-D1DKnYce.js} +1 -1
  18. package/dist/{embeddingsCommand-Db-iQM3l.js → embeddingsCommand-1sZRBKlM.js} +1 -1
  19. package/dist/{envCommand-DQ_URZq9.js → envCommand-7qjlQgLD.js} +2 -2
  20. package/dist/{evolveCommand-CghRPrGO.js → evolveCommand-D5opB48I.js} +2 -2
  21. package/dist/index.js +1 -1
  22. package/dist/{infoCommand-BCs_ZFnl.js → infoCommand-Bs_8RU22.js} +1 -1
  23. package/dist/{runtimeTrace-jFKvOPBz.js → runtimeTrace-Wmi7V-wN.js} +1 -1
  24. package/dist/{sdkgen-COQqHB9V.js → sdkgen-DbTFGCjg.js} +1 -1
  25. package/dist/{serveCommand-C512kzZA.js → serveCommand-C8xzYCwa.js} +4 -4
  26. package/dist/serveCommand-CGNTXafv.js +2 -0
  27. package/dist/serveEntry.js +1 -1
  28. package/dist/{start-fifc0xpW.js → start-BAlGcjF5.js} +1 -1
  29. package/dist/{start-BjcuFME_.js → start-Ds3xyn8R.js} +1 -1
  30. package/dist/startEntry.js +1 -1
  31. package/dist/startup.d.ts +1 -1
  32. package/dist/updateCommand-BvkKlV7D.js +2 -0
  33. package/dist/{updateCommand-HZQVBU3T.js → updateCommand-CrI9B4d7.js} +1 -1
  34. package/dist/{webDev-Dk8lFUzf.js → webDev-101csg6Q.js} +2 -2
  35. package/dist/webDev-BLKBO34K.js +2 -0
  36. package/dist/{webhooksCommand-D7ZpH7w0.js → webhooksCommand-BXUP5YjW.js} +1 -1
  37. package/package.json +23 -17
  38. package/templates/AGENTS.md +1 -1
  39. package/templates/agent-docs/_index.md +1 -1
  40. package/templates/agent-docs/authentication.md +1 -1
  41. package/templates/agent-docs/cli.md +2 -2
  42. package/templates/agent-docs/data.md +14 -12
  43. package/templates/agent-docs/database/migrations.md +1 -1
  44. package/templates/agent-docs/internationalization.md +2 -2
  45. package/templates/agent-docs/observability.md +1 -1
  46. package/templates/agent-docs/plugins/openapi.md +1 -1
  47. package/templates/agent-docs/plugins/versioning.md +1 -1
  48. package/templates/agent-docs/plugins/webhooks.md +1 -1
  49. package/templates/agent-docs/plugins.md +1 -1
  50. package/templates/agent-docs/routing.md +1 -1
  51. package/templates/agent-docs/scheduling.md +1 -1
  52. package/templates/agent-docs/security.md +2 -2
  53. package/templates/agent-docs/templates/apibackends.md +1 -1
  54. package/templates/agent-docs/whats-new.md +49 -55
  55. package/templates/apps/api-ai/package.json +7 -7
  56. package/templates/apps/api-auth/package.json +8 -8
  57. package/templates/apps/api-backend/package.json +7 -7
  58. package/templates/apps/api-backend-deactivation/package.json +7 -7
  59. package/templates/apps/api-backend-mail/package.json +8 -8
  60. package/templates/apps/api-backend-mariadb/package.json +9 -9
  61. package/templates/apps/api-backend-sqlite/package.json +8 -8
  62. package/templates/apps/api-backend-storage/package.json +8 -8
  63. package/templates/apps/api-cms/package.json +10 -10
  64. package/templates/apps/api-collab/package.json +8 -8
  65. package/templates/apps/api-data-advanced/package.json +8 -8
  66. package/templates/apps/api-durable/package.json +8 -8
  67. package/templates/apps/api-feature-flags/package.json +9 -9
  68. package/templates/apps/api-governance/package.json +8 -8
  69. package/templates/apps/api-kv/package.json +8 -8
  70. package/templates/apps/api-moderation/package.json +8 -8
  71. package/templates/apps/api-observability/package.json +8 -8
  72. package/templates/apps/api-ratelimit/package.json +8 -8
  73. package/templates/apps/api-rbac/package.json +8 -8
  74. package/templates/apps/api-rest/package.json +7 -7
  75. package/templates/apps/api-saas/package.json +11 -11
  76. package/templates/apps/api-saas-starter/package.json +10 -10
  77. package/templates/apps/api-search/package.json +8 -8
  78. package/templates/apps/api-status/package.json +8 -8
  79. package/templates/apps/api-versioning/package.json +8 -8
  80. package/templates/apps/api-webhooks/package.json +9 -9
  81. package/templates/apps/changelog/package.json +6 -6
  82. package/templates/apps/edge-functions/package.json +2 -2
  83. package/templates/apps/frontend-admin/package.json +8 -8
  84. package/templates/apps/frontend-app/package.json +9 -9
  85. package/templates/apps/frontend-auth/package.json +8 -8
  86. package/templates/apps/frontend-blank/package.json +7 -7
  87. package/templates/apps/frontend-cms/package.json +9 -9
  88. package/templates/apps/frontend-collab/package.json +10 -10
  89. package/templates/apps/frontend-contact/package.json +7 -7
  90. package/templates/apps/frontend-dashboard/package.json +7 -7
  91. package/templates/apps/frontend-docs/package.json +7 -7
  92. package/templates/apps/frontend-i18n/package.json +6 -6
  93. package/templates/apps/frontend-landing/package.json +7 -7
  94. package/templates/apps/frontend-portal/package.json +8 -8
  95. package/templates/apps/frontend-saas/package.json +8 -8
  96. package/templates/apps/frontend-spa/package.json +7 -7
  97. package/templates/apps/frontend-ssr/package.json +7 -7
  98. package/templates/apps/frontend-ssr-api/package.json +8 -8
  99. package/templates/apps/frontend-static-blog/package.json +6 -6
  100. package/templates/apps/frontend-status/package.json +8 -8
  101. package/templates/apps/mobile-app/package.json +4 -4
  102. package/dist/apiBuild-RM5W5YXk.js +0 -2
  103. package/dist/doctorCommand-Bw3V4L1j.js +0 -2
  104. package/dist/serveCommand-gj7MsqXY.js +0 -2
  105. package/dist/updateCommand-B2alql9k.js +0 -2
  106. package/dist/webDev-D6QeXw3P.js +0 -2
@@ -1,5 +1,5 @@
1
1
  import { t as e } from "./cliError-BmdYnghb.js";
2
- import { c as t, i as n, o as r } from "./dev-D4l_YOzI.js";
2
+ import { c as t, i as n, o as r } from "./dev-B2rZfqxw.js";
3
3
  import { n as i, t as a } from "./cliArgs-D4p8n7EE.js";
4
4
  import { r as o } from "./dialectDriver-czCHYpeH.js";
5
5
  import { t as s } from "./dataProfile-Cm0YVKSy.js";
@@ -11,15 +11,15 @@ import { SqlClient as m } from "@effect/sql";
11
11
  import { declaredSnapshot as h, fingerprintSchema as g, introspectSchema as _ } from "@voltro/database/sql";
12
12
  import { connectionIdentity as v, normaliseTarget as y, sameDatabase as b, streamTable as x } from "@voltro/database";
13
13
  import { STORAGE_REFS_TABLE as ee, resolveStorageProvider as S } from "@voltro/plugin-storage";
14
- import { assessLiveImport as te, backupArtifactName as C, backupCommand as ne, classificationFromSnapshot as re, decryptStream as w, encryptStream as ie, packBundle as T, peekBundle as E, previewMasking as ae, restoreCommand as D, runExport as O, runImport as k, runNativeStep as A, storageAssetSink as oe, storageAssetSource as se, storageBlobSink as ce, storageBlobSource as le, unpackBundle as ue, unpackBundleToDir as j } from "@voltro/data-transfer";
14
+ import { assessLiveImport as te, backupArtifactName as C, backupCommand as ne, classificationFromSnapshot as re, decryptStream as w, encryptStream as ie, packBundle as T, peekBundle as E, previewMasking as ae, restoreCommand as D, runExport as O, runImport as k, runNativeStep as A, storageAssetSink as oe, storageAssetSource as se, storageBlobSink as ce, storageBlobSource as le, unpackBundle as ue, unpackBundleToDir as de } from "@voltro/data-transfer";
15
15
  //#region src/backupStamp.ts
16
- var M = "voltro-backup-stamp.json", de = (e) => ({
16
+ var j = "voltro-backup-stamp.json", fe = (e) => ({
17
17
  stampVersion: 1,
18
18
  dialect: e.dialect,
19
19
  schemaFingerprint: e.schemaFingerprint,
20
20
  voltroVersion: e.voltroVersion,
21
21
  createdAt: e.createdAt
22
- }), N = (e) => {
22
+ }), M = (e) => {
23
23
  let t;
24
24
  try {
25
25
  t = JSON.parse(e);
@@ -37,10 +37,10 @@ var M = "voltro-backup-stamp.json", de = (e) => ({
37
37
  voltroVersion: n.voltroVersion,
38
38
  createdAt: n.createdAt
39
39
  };
40
- }, fe = (e) => {
40
+ }, pe = (e) => {
41
41
  let { stamp: t, currentDialect: n, currentFingerprint: r } = e;
42
42
  if (t === null) return {
43
- warn: `no ${M} beside the dump — an older/handmade backup. Cannot verify dialect or schema version; make sure this dump is a ${n} dump.`,
43
+ warn: `no ${j} beside the dump — an older/handmade backup. Cannot verify dialect or schema version; make sure this dump is a ${n} dump.`,
44
44
  info: []
45
45
  };
46
46
  let i = [`backup produced by @voltro/cli ${t.voltroVersion} at ${t.createdAt}`, `schema fingerprint: ${t.schemaFingerprint ?? "<none recorded>"}`];
@@ -51,20 +51,20 @@ var M = "voltro-backup-stamp.json", de = (e) => ({
51
51
  refuse: `dialect mismatch — backup is a ${t.dialect} dump, but DB_DIALECT is ${n}. A cross-dialect restore is never valid.`,
52
52
  info: i
53
53
  };
54
- }, P = (e) => {
54
+ }, N = (e) => {
55
55
  try {
56
56
  let t = new URL(e), n = t.pathname.replace(/^\//, "");
57
57
  return `${t.hostname.toLowerCase()}:${t.port || "(default)"}/${n}`;
58
58
  } catch {
59
59
  return e.trim();
60
60
  }
61
- }, pe = (e) => {
61
+ }, me = (e) => {
62
62
  let t = e.flagUrl ?? e.envUrl;
63
63
  if (t === void 0 || t.trim() === "") return {
64
64
  ok: !1,
65
65
  error: "no drill target — pass `--drill-url <url>` or set `DRILL_DB_URL`. The drill restores into a THROWAWAY database (never the live one), so it needs its own connection."
66
66
  };
67
- let n = P(t);
67
+ let n = N(t);
68
68
  return e.liveKeys.some((e) => e === n) ? {
69
69
  ok: !1,
70
70
  error: `drill target (${n}) is the LIVE database — a restore drill must target a throwaway DB, never production. It would --clean and overwrite it.`
@@ -72,7 +72,7 @@ var M = "voltro-backup-stamp.json", de = (e) => ({
72
72
  ok: !0,
73
73
  url: t
74
74
  };
75
- }, me = (e) => {
75
+ }, he = (e) => {
76
76
  let { stampFingerprint: t, restoredFingerprint: n, restoredTableCount: r } = e;
77
77
  return r === 0 ? {
78
78
  pass: !1,
@@ -87,24 +87,24 @@ var M = "voltro-backup-stamp.json", de = (e) => ({
87
87
  pass: !0,
88
88
  lines: [`PASS — restored ${r} table(s); schema fingerprint matches the backup stamp (${n.slice(0, 12)}).`]
89
89
  };
90
- }, F = d({ scope: "voltro:data" }), he = async () => {
90
+ }, P = d({ scope: "voltro:data" }), ge = async () => {
91
91
  try {
92
92
  let { createRequire: e } = await import("node:module"), { join: t } = await import("node:path"), { readFileSync: n } = await import("node:fs"), r = e(t(process.cwd(), "package.json")).resolve("@voltro/cli/package.json");
93
93
  return JSON.parse(n(r, "utf8")).version ?? "unknown";
94
94
  } catch {
95
95
  return "unknown";
96
96
  }
97
- }, I = async (e) => {
97
+ }, F = async (e) => {
98
98
  try {
99
- return g(await U(e));
99
+ return g(await H(e));
100
100
  } catch {
101
101
  return null;
102
102
  }
103
- }, L = (e) => {
103
+ }, I = (e) => {
104
104
  if (e.event !== "done") return;
105
105
  let t = e.total === void 0 ? "" : ` / ${e.total}`;
106
- F.info(`${e.phase} [${e.index + 1}/${e.tableCount}] ${e.table}`, { rows: `${e.rowsDone}${t}` });
107
- }, ge = async (e) => {
106
+ P.info(`${e.phase} [${e.index + 1}/${e.tableCount}] ${e.table}`, { rows: `${e.rowsDone}${t}` });
107
+ }, _e = async (e) => {
108
108
  let t = (e) => e?.meta?.databaseId;
109
109
  if (e) {
110
110
  let n = await l({
@@ -124,12 +124,12 @@ var M = "voltro-backup-stamp.json", de = (e) => ({
124
124
  };
125
125
  }
126
126
  return null;
127
- }, R = async (e) => {
128
- let t = e.includes("--allow-live"), n = t ? null : await ge(z(e, "--api-url")), i = v({
129
- dialect: V(),
127
+ }, L = async (e) => {
128
+ let t = e.includes("--allow-live"), n = t ? null : await _e(R(e, "--api-url")), i = v({
129
+ dialect: B(),
130
130
  ...r()
131
131
  }), a = y({
132
- dialect: V(),
132
+ dialect: B(),
133
133
  ...r()
134
134
  }), { refuse: o, message: s } = te({
135
135
  liveInstance: n?.label ?? null,
@@ -137,8 +137,8 @@ var M = "voltro-backup-stamp.json", de = (e) => ({
137
137
  sameTarget: b(i, n?.databaseId),
138
138
  ...a === void 0 ? {} : { targetLabel: `${a.host}:${a.port}/${a.database}` }
139
139
  });
140
- return !o || (F.error(s ?? "refusing: live instance detected"), !1);
141
- }, z = i, _e = [
140
+ return !o || (P.error(s ?? "refusing: live instance detected"), !1);
141
+ }, R = i, ve = [
142
142
  "--api-url",
143
143
  "--bundle-key",
144
144
  "--compression",
@@ -153,23 +153,23 @@ var M = "voltro-backup-stamp.json", de = (e) => ({
153
153
  "--target",
154
154
  "--tenant",
155
155
  "--token"
156
- ], B = (e) => a(e, _e), V = () => {
156
+ ], z = (e) => a(e, ve), B = () => {
157
157
  let t = (process.env.DB_DIALECT ?? "postgres").toLowerCase();
158
158
  if (t === "memory") throw new e("voltro data: requires a real dialect, not DB_DIALECT=memory.");
159
159
  return t;
160
- }, H = async (e, t) => {
160
+ }, V = async (e, t) => {
161
161
  let n = (await o(e)).makeSqlLayer(t);
162
162
  return f.runPromise(m.SqlClient.pipe(f.flatMap(_), f.provide(n)));
163
- }, U = (e) => H(e, r()), ve = () => {
163
+ }, H = (e) => V(e, r()), ye = () => {
164
164
  let e = r(), t = [];
165
- return e.url && t.push(P(e.url)), (e.host || e.database) && t.push(`${(e.host ?? "localhost").toLowerCase()}:${e.port ?? "(default)"}/${e.database ?? ""}`), t;
166
- }, ye = async () => {
165
+ return e.url && t.push(N(e.url)), (e.host || e.database) && t.push(`${(e.host ?? "localhost").toLowerCase()}:${e.port ?? "(default)"}/${e.database ?? ""}`), t;
166
+ }, U = async () => {
167
167
  let r = process.cwd(), i = await t(r);
168
168
  if (!i) throw new e("voltro data: no app.config.ts found in the current directory.");
169
- let a = await n(i, void 0), o = V();
169
+ let a = await n(i, void 0), o = B();
170
170
  return {
171
171
  store: a,
172
- snapshot: await U(o),
172
+ snapshot: await H(o),
173
173
  dialect: o
174
174
  };
175
175
  }, W = (e) => x(e, {
@@ -179,14 +179,14 @@ var M = "voltro-backup-stamp.json", de = (e) => ({
179
179
  key: String(e.key),
180
180
  contentType: String(e.contentType ?? "application/octet-stream"),
181
181
  size: Number(e.size ?? 0)
182
- }))), G = (e) => !!e && e.endsWith(".vbundle"), K = (e) => z(e, "--passphrase") ?? process.env.VOLTRO_BUNDLE_KEY, be = (e) => e.includes("--encrypt") || z(e, "--passphrase") !== void 0 || process.env.VOLTRO_BUNDLE_KEY !== void 0, xe = async (e, t) => {
182
+ }))), G = (e) => !!e && e.endsWith(".vbundle"), K = (e) => R(e, "--passphrase") ?? process.env.VOLTRO_BUNDLE_KEY, be = (e) => e.includes("--encrypt") || R(e, "--passphrase") !== void 0 || process.env.VOLTRO_BUNDLE_KEY !== void 0, xe = async (e, t) => {
183
183
  let { createWriteStream: n } = await import("node:fs"), { pipeline: r } = await import("node:stream/promises"), { Readable: i } = await import("node:stream");
184
184
  await r(i.from(e), n(t));
185
185
  }, q = (e) => ({ async *[Symbol.asyncIterator]() {
186
186
  let { createReadStream: t } = await import("node:fs");
187
187
  for await (let n of t(e)) yield n instanceof Uint8Array ? n : new Uint8Array(n);
188
188
  } }), J = (e) => (e ?? "").split(",").map((e) => e.trim()).filter(Boolean), Se = (t, n) => {
189
- let r = z(t, "--tenant"), i = z(t, "--tables"), a = z(t, "--exclude");
189
+ let r = R(t, "--tenant"), i = R(t, "--tables"), a = R(t, "--exclude");
190
190
  if (a !== void 0) {
191
191
  if (i !== void 0) throw new e("voltro data export: --exclude and --tables are two ways to say the same thing; use one.");
192
192
  if (r !== void 0) throw new e("voltro data export: --exclude does not apply to --tenant, whose table set is derived from the tenant closure.");
@@ -225,20 +225,20 @@ var M = "voltro-backup-stamp.json", de = (e) => ({
225
225
  for (let t of e.unclassified) console.log(` ${t}`);
226
226
  } else console.log("\n ✓ every exported column is classified — safe to run.");
227
227
  }, De = async (e) => {
228
- let t = z(e, "--target") === "api", n = z(e, "--bundle-key"), r = B(e);
229
- if (!r && !(t && n)) return F.error("usage: voltro data export <outDir> [--target direct|api] [--api-url <url>] [--token <secret>] [--profile <name>] [--tenant <id>] [--tables a,b] [--exclude a,b] [--bundle-key <storage-key>] [--assets] [--compression zstd|gzip|none] [--consistency live|snapshot] [--dry-run]"), 1;
228
+ let t = R(e, "--target") === "api", n = R(e, "--bundle-key"), r = z(e);
229
+ if (!r && !(t && n)) return P.error("usage: voltro data export <outDir> [--target direct|api] [--api-url <url>] [--token <secret>] [--profile <name>] [--tenant <id>] [--tables a,b] [--exclude a,b] [--bundle-key <storage-key>] [--assets] [--compression zstd|gzip|none] [--consistency live|snapshot] [--dry-run]"), 1;
230
230
  if (t) {
231
- let t = z(e, "--api-url");
232
- if (!t) return F.error("--target api requires --api-url <url> (the running instance)"), 1;
233
- let i = z(e, "--token") ?? process.env.VOLTRO_DATA_TRANSFER_SECRET;
234
- if (!i) return F.error("--target api requires --token <secret> (or VOLTRO_DATA_TRANSFER_SECRET) matching the instance secret"), 1;
235
- if (z(e, "--exclude") !== void 0) return F.error("--exclude is a direct-target flag: it expands against the live table list, which --target api does not expose. Use --tables with the explicit set."), 1;
236
- let a = z(e, "--tables"), o = {
237
- ...z(e, "--profile") ? { profile: z(e, "--profile") } : {},
238
- ...z(e, "--tenant") ? { tenant: z(e, "--tenant") } : {},
231
+ let t = R(e, "--api-url");
232
+ if (!t) return P.error("--target api requires --api-url <url> (the running instance)"), 1;
233
+ let i = R(e, "--token") ?? process.env.VOLTRO_DATA_TRANSFER_SECRET;
234
+ if (!i) return P.error("--target api requires --token <secret> (or VOLTRO_DATA_TRANSFER_SECRET) matching the instance secret"), 1;
235
+ if (R(e, "--exclude") !== void 0) return P.error("--exclude is a direct-target flag: it expands against the live table list, which --target api does not expose. Use --tables with the explicit set."), 1;
236
+ let a = R(e, "--tables"), o = {
237
+ ...R(e, "--profile") ? { profile: R(e, "--profile") } : {},
238
+ ...R(e, "--tenant") ? { tenant: R(e, "--tenant") } : {},
239
239
  ...a ? { tables: a.split(",").map((e) => e.trim()).filter(Boolean) } : {},
240
- ...z(e, "--consistency") === "snapshot" ? { consistency: "snapshot" } : {},
241
- ...z(e, "--compression") ? { compression: z(e, "--compression") } : {},
240
+ ...R(e, "--consistency") === "snapshot" ? { consistency: "snapshot" } : {},
241
+ ...R(e, "--compression") ? { compression: R(e, "--compression") } : {},
242
242
  ...e.includes("--assets") ? { assets: !0 } : {},
243
243
  ...n ? { bundleKey: n } : {}
244
244
  }, s = await fetch(`${t.replace(/\/+$/, "")}/_voltro/admin/export`, {
@@ -249,26 +249,26 @@ var M = "voltro-backup-stamp.json", de = (e) => ({
249
249
  },
250
250
  body: JSON.stringify(o)
251
251
  });
252
- if (!s.ok) return F.error(`api export failed: HTTP ${s.status} — ${await s.text()}`), 1;
253
- if (n) return F.info("api export complete (pushed to storage)", {
252
+ if (!s.ok) return P.error(`api export failed: HTTP ${s.status} — ${await s.text()}`), 1;
253
+ if (n) return P.info("api export complete (pushed to storage)", {
254
254
  via: t,
255
255
  ...await s.json()
256
256
  }), 0;
257
257
  let { resolve: c } = await import("node:path"), l = new Uint8Array(await s.arrayBuffer());
258
- return await j((async function* () {
258
+ return await de((async function* () {
259
259
  yield l;
260
- })(), c(process.cwd(), r)), F.info("api export complete (downloaded from the running instance)", {
260
+ })(), c(process.cwd(), r)), P.info("api export complete (downloaded from the running instance)", {
261
261
  outDir: r,
262
262
  tables: s.headers.get("x-export-tables") ?? void 0,
263
263
  rows: s.headers.get("x-export-rows") ?? void 0,
264
264
  masked: s.headers.get("x-export-masked") ?? void 0
265
265
  }), 0;
266
266
  }
267
- if (!r) return F.error("a <outDir> is required for a direct export"), 1;
268
- let i = z(e, "--profile"), a = i ? await s(i, { allowPath: !0 }) : {}, { store: o, snapshot: c, dialect: l } = await ye(), u = e.includes("--assets") || a.assets === !0, d = u ? S({}) : void 0, p = z(e, "--compression") ?? a.compression, m = z(e, "--consistency") === "snapshot" ? "snapshot" : a.consistency ?? "live", h = a.masking, g = a.subset, _ = a.scope ?? Se(e, c.tables.map((e) => e.name)), v = h ? await Ce() : void 0, y = _.kind === "tenant" ? await Te() : void 0, b = y ? { tenantTables: y } : {};
267
+ if (!r) return P.error("a <outDir> is required for a direct export"), 1;
268
+ let i = R(e, "--profile"), a = i ? await s(i, { allowPath: !0 }) : {}, { store: o, snapshot: c, dialect: l } = await U(), u = e.includes("--assets") || a.assets === !0, d = u ? S({}) : void 0, p = R(e, "--compression") ?? a.compression, m = R(e, "--consistency") === "snapshot" ? "snapshot" : a.consistency ?? "live", h = a.masking, g = a.subset, _ = a.scope ?? Se(e, c.tables.map((e) => e.name)), v = h ? await Ce() : void 0, y = _.kind === "tenant" ? await Te() : void 0, b = y ? { tenantTables: y } : {};
269
269
  if (e.includes("--dry-run")) {
270
270
  let e = _.kind === "tables" && _.tables ? [..._.tables] : c.tables.map((e) => e.name);
271
- if (F.info("export DRY RUN — nothing was written", {
271
+ if (P.info("export DRY RUN — nothing was written", {
272
272
  outDir: r,
273
273
  tables: e.length,
274
274
  scope: _.kind,
@@ -276,7 +276,7 @@ var M = "voltro-backup-stamp.json", de = (e) => ({
276
276
  compression: p ?? "zstd",
277
277
  assets: u,
278
278
  masking: h ? "profile policy applies" : "none"
279
- }), F.info(`would export: ${e.join(", ")}`), !h) return 0;
279
+ }), P.info(`would export: ${e.join(", ")}`), !h) return 0;
280
280
  let t = await f.runPromise(ae({
281
281
  store: o,
282
282
  snapshot: c,
@@ -305,17 +305,17 @@ var M = "voltro-backup-stamp.json", de = (e) => ({
305
305
  ...p ? { compression: p } : {},
306
306
  ...h ? { masking: h } : {},
307
307
  ...v ? { classification: v } : {},
308
- onProgress: L
308
+ onProgress: I
309
309
  })), n = T({
310
310
  dir: s,
311
311
  ...d ? { blobs: le(d, () => W(o)) } : {}
312
312
  }), a = be(e);
313
313
  if (a) {
314
314
  let t = K(e);
315
- if (!t) return F.error("--encrypt requires --passphrase <p> or VOLTRO_BUNDLE_KEY (a dedicated key, NOT the transfer secret)"), 1;
315
+ if (!t) return P.error("--encrypt requires --passphrase <p> or VOLTRO_BUNDLE_KEY (a dedicated key, NOT the transfer secret)"), 1;
316
316
  n = ie(n, t);
317
317
  }
318
- return await xe(n, i(process.cwd(), r)), F.info("export complete (single file)", {
318
+ return await xe(n, i(process.cwd(), r)), P.info("export complete (single file)", {
319
319
  file: r,
320
320
  encrypted: a,
321
321
  assets: u,
@@ -343,9 +343,9 @@ var M = "voltro-backup-stamp.json", de = (e) => ({
343
343
  ...h ? { masking: h } : {},
344
344
  ...v ? { classification: v } : {},
345
345
  ...d ? { assets: se(d, () => W(o)) } : {},
346
- onProgress: L
346
+ onProgress: I
347
347
  }));
348
- return F.info("export complete", {
348
+ return P.info("export complete", {
349
349
  outDir: r,
350
350
  tables: x.tables.length,
351
351
  rows: x.tables.reduce((e, t) => e + t.rowCount, 0),
@@ -354,27 +354,35 @@ var M = "voltro-backup-stamp.json", de = (e) => ({
354
354
  ...x.masking ? { maskedColumns: x.masking.transformed.length } : {}
355
355
  }), 0;
356
356
  }, Y = () => "dry run checked: schema fit, cross-dialect portability, mode legality, the table selection. It did NOT read per-table checksums (those stream during the load) and cannot see conflicts that depend on the target's current rows.", X = (e) => {
357
- let t = z(e, "--tables");
357
+ let t = R(e, "--tables");
358
358
  return {
359
359
  ...t ? { tables: t.split(",").map((e) => e.trim()).filter(Boolean) } : {},
360
360
  ...e.includes("--dry-run") ? { dryRun: !0 } : {}
361
361
  };
362
362
  }, Z = (e, t) => {
363
363
  if (e.includes("--dry-run")) {
364
- F.info("import DRY RUN — nothing was written", t), F.info(Y());
364
+ P.info("import DRY RUN — nothing was written", t), P.info(Y());
365
365
  return;
366
366
  }
367
- F.info("import complete", t);
368
- }, Oe = async (e) => {
369
- let t = z(e, "--target") === "api", n = z(e, "--bundle-key"), i = B(e);
370
- if (!i && !(t && n)) return F.error("usage: voltro data import <bundleDir> [--target direct|api] [--api-url <url>] [--token <secret>] [--bundle-key <storage-key>] [--tables a,b] [--mode upsert|append|replace] [--on-conflict skip|fail] [--atomic] [--assets] [--no-verify] [--force] [--allow-live] [--dry-run] (--force: import despite schema drift AND cross-dialect warnings; --dry-run: report what would move, write nothing)"), 1;
371
- let a = z(e, "--mode") ?? "upsert", o = z(e, "--on-conflict") ?? "skip";
367
+ P.info("import complete", t);
368
+ }, Oe = (e) => {
369
+ let t = e;
370
+ if (t?._tag !== "RowsRefusedError" || !Array.isArray(t.rows)) return;
371
+ let n = t.rows, r = n.filter((e) => !e.derived), i = Number(t.totalCount ?? n.length), a = Number(t.primaryCount ?? r.length);
372
+ P.error(`import refused ${i} row(s), of which ${a} are the actual failures — the rest could not land because a row they reference did not.`);
373
+ for (let e of r) P.error(` ${e.table} ${e.id} ${e.reason}`);
374
+ let o = i - a;
375
+ o > 0 && P.error(` … and ${o} row(s) behind them. Fix the ${a} above and re-run; they resolve with their parents.`);
376
+ }, ke = async (e) => {
377
+ let t = R(e, "--target") === "api", n = R(e, "--bundle-key"), i = z(e);
378
+ if (!i && !(t && n)) return P.error("usage: voltro data import <bundleDir> [--target direct|api] [--api-url <url>] [--token <secret>] [--bundle-key <storage-key>] [--tables a,b] [--mode upsert|append|replace] [--on-conflict skip|fail] [--atomic] [--assets] [--no-verify] [--force] [--allow-live] [--dry-run] (--force: import despite schema drift AND cross-dialect warnings; --dry-run: report what would move, write nothing)"), 1;
379
+ let a = R(e, "--mode") ?? "upsert", o = R(e, "--on-conflict") ?? "skip";
372
380
  if (t) {
373
- let t = z(e, "--api-url");
374
- if (!t) return F.error("--target api requires --api-url <url> (the running instance)"), 1;
375
- let r = z(e, "--token") ?? process.env.VOLTRO_DATA_TRANSFER_SECRET;
376
- if (!r) return F.error("--target api requires --token <secret> (or VOLTRO_DATA_TRANSFER_SECRET) matching the instance secret"), 1;
377
- let s = z(e, "--tables"), c = {
381
+ let t = R(e, "--api-url");
382
+ if (!t) return P.error("--target api requires --api-url <url> (the running instance)"), 1;
383
+ let r = R(e, "--token") ?? process.env.VOLTRO_DATA_TRANSFER_SECRET;
384
+ if (!r) return P.error("--target api requires --token <secret> (or VOLTRO_DATA_TRANSFER_SECRET) matching the instance secret"), 1;
385
+ let s = R(e, "--tables"), c = {
378
386
  authorization: `Bearer ${r}`,
379
387
  "x-import-mode": a,
380
388
  "x-import-on-conflict": o,
@@ -391,7 +399,7 @@ var M = "voltro-backup-stamp.json", de = (e) => ({
391
399
  for await (let e of t) r.push(Buffer.from(e));
392
400
  c["content-type"] = "application/octet-stream", u = Buffer.concat(r);
393
401
  } else {
394
- await (await import("node:fs/promises")).access(l(process.cwd(), i, "assets", "index.ndjson")).then(() => !0, () => !1) && F.warn("this directory bundle has assets; --target api uploads DATA ONLY. Pack a single-file `.vbundle` (voltro data export <name>.vbundle --assets) to transfer assets over the API.");
402
+ await (await import("node:fs/promises")).access(l(process.cwd(), i, "assets", "index.ndjson")).then(() => !0, () => !1) && P.warn("this directory bundle has assets; --target api uploads DATA ONLY. Pack a single-file `.vbundle` (voltro data export <name>.vbundle --assets) to transfer assets over the API.");
395
403
  let e = [];
396
404
  for await (let t of T({ dir: l(process.cwd(), i) })) e.push(Buffer.from(t));
397
405
  c["content-type"] = "application/octet-stream", u = Buffer.concat(e);
@@ -401,19 +409,19 @@ var M = "voltro-backup-stamp.json", de = (e) => ({
401
409
  body: u,
402
410
  headers: c
403
411
  });
404
- if (!d.ok) return F.error(`api import failed: HTTP ${d.status} — ${await d.text()}`), 1;
412
+ if (!d.ok) return P.error(`api import failed: HTTP ${d.status} — ${await d.text()}`), 1;
405
413
  let f = await d.json();
406
- return e.includes("--dry-run") ? (F.info("api import DRY RUN — nothing was written", {
414
+ return e.includes("--dry-run") ? (P.info("api import DRY RUN — nothing was written", {
407
415
  via: t,
408
416
  ...f
409
- }), F.info(Y()), 0) : (F.info("api import complete (imported by the running instance)", {
417
+ }), P.info(Y()), 0) : (P.info("api import complete (imported by the running instance)", {
410
418
  via: t,
411
419
  ...f
412
420
  }), 0);
413
421
  }
414
- if (!i) return F.error("a <bundleDir> is required for a direct import"), 1;
415
- if (!await R(e)) return 1;
416
- let { store: s, snapshot: c } = await ye(), l = e.includes("--force"), u = (e) => F.warn(e), d = e.includes("--assets") ? S({}) : void 0, p = V() === "postgres" ? (await import("@voltro/sql-postgres")).makePgCopySession(r()) : void 0;
422
+ if (!i) return P.error("a <bundleDir> is required for a direct import"), 1;
423
+ if (!await L(e)) return 1;
424
+ let { store: s, snapshot: c } = await U(), l = e.includes("--force"), u = (e) => P.warn(e), d = e.includes("--assets") ? S({}) : void 0, p = B() === "postgres" ? (await import("@voltro/sql-postgres")).makePgCopySession(r()) : void 0;
417
425
  if (G(i)) {
418
426
  let t = await import("node:os"), n = await import("node:fs/promises"), { resolve: r, join: m } = await import("node:path"), h = await n.mkdtemp(m(t.tmpdir(), "voltro-import-"));
419
427
  try {
@@ -429,12 +437,12 @@ var M = "voltro-backup-stamp.json", de = (e) => ({
429
437
  onConflict: o,
430
438
  atomic: e.includes("--atomic"),
431
439
  verify: !e.includes("--no-verify"),
432
- targetDialect: V(),
440
+ targetDialect: B(),
433
441
  allowIncompatible: l,
434
442
  targetSnapshot: c,
435
443
  force: l,
436
444
  onWarn: u,
437
- onProgress: L,
445
+ onProgress: I,
438
446
  assetsAlreadyRestored: !0,
439
447
  ...X(e),
440
448
  ...p ? { copyLoader: p } : {}
@@ -458,16 +466,18 @@ var M = "voltro-backup-stamp.json", de = (e) => ({
458
466
  onConflict: o,
459
467
  atomic: e.includes("--atomic"),
460
468
  verify: !e.includes("--no-verify"),
461
- targetDialect: V(),
469
+ targetDialect: B(),
462
470
  allowIncompatible: l,
463
471
  targetSnapshot: c,
464
472
  force: l,
465
473
  onWarn: u,
466
- onProgress: L,
474
+ onProgress: I,
467
475
  ...X(e),
468
476
  ...d ? { assets: oe(d) } : {},
469
477
  ...p ? { copyLoader: p } : {}
470
- })).finally(() => p?.close());
478
+ })).catch((e) => {
479
+ throw Oe(e), e;
480
+ }).finally(() => p?.close());
471
481
  return Z(e, {
472
482
  bundleDir: i,
473
483
  tables: m.tables.length,
@@ -484,75 +494,75 @@ var M = "voltro-backup-stamp.json", de = (e) => ({
484
494
  ...e.password ? { password: e.password } : {},
485
495
  ...e.database ? { database: e.database } : {}
486
496
  };
487
- }, ke = async (e) => {
488
- let t = B(e);
489
- if (!t) return F.error("usage: voltro data backup <outDir> (native pg_dump/mysqldump/… + consistent artifact)"), 1;
490
- let n = V(), { mkdir: r, writeFile: i } = await import("node:fs/promises"), { join: a } = await import("node:path");
497
+ }, Ae = async (e) => {
498
+ let t = z(e);
499
+ if (!t) return P.error("usage: voltro data backup <outDir> (native pg_dump/mysqldump/… + consistent artifact)"), 1;
500
+ let n = B(), { mkdir: r, writeFile: i } = await import("node:fs/promises"), { join: a } = await import("node:path");
491
501
  await r(t, { recursive: !0 });
492
502
  let o = a(t, C(n));
493
503
  await f.runPromise(A(ne(n, Q(), o)));
494
- let s = de({
504
+ let s = fe({
495
505
  dialect: n,
496
- schemaFingerprint: await I(n),
497
- voltroVersion: await he(),
506
+ schemaFingerprint: await F(n),
507
+ voltroVersion: await ge(),
498
508
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
499
509
  });
500
- return await i(a(t, M), `${JSON.stringify(s, null, 2)}\n`, "utf8"), F.info("native backup complete", {
510
+ return await i(a(t, j), `${JSON.stringify(s, null, 2)}\n`, "utf8"), P.info("native backup complete", {
501
511
  dialect: n,
502
512
  artifact: o,
503
- stamp: M,
513
+ stamp: j,
504
514
  schemaFingerprint: s.schemaFingerprint ?? "<none>",
505
515
  assets: "NOT included — use `voltro data export --assets` for rows + blobs"
506
516
  }), 0;
507
- }, Ae = async (e, t) => {
508
- let n = V(), { join: r } = await import("node:path"), { readFile: i } = await import("node:fs/promises"), a = r(e, C(n)), o = pe({
509
- flagUrl: z(t, "--drill-url"),
517
+ }, je = async (e, t) => {
518
+ let n = B(), { join: r } = await import("node:path"), { readFile: i } = await import("node:fs/promises"), a = r(e, C(n)), o = me({
519
+ flagUrl: R(t, "--drill-url"),
510
520
  envUrl: process.env.DRILL_DB_URL,
511
- liveKeys: ve()
521
+ liveKeys: ye()
512
522
  });
513
- if (!o.ok) return F.error(`restore --drill: ${o.error}`), 1;
514
- let s = await i(r(e, M), "utf8").then(N, () => null);
515
- if (s && s.dialect !== n) return F.error(`restore --drill: backup is a ${s.dialect} dump but DB_DIALECT is ${n} — cross-dialect restore is never valid.`), 1;
516
- F.info("restore drill: restoring into throwaway DB", {
523
+ if (!o.ok) return P.error(`restore --drill: ${o.error}`), 1;
524
+ let s = await i(r(e, j), "utf8").then(M, () => null);
525
+ if (s && s.dialect !== n) return P.error(`restore --drill: backup is a ${s.dialect} dump but DB_DIALECT is ${n} — cross-dialect restore is never valid.`), 1;
526
+ P.info("restore drill: restoring into throwaway DB", {
517
527
  dialect: n,
518
- target: P(o.url)
528
+ target: N(o.url)
519
529
  }), await f.runPromise(A(D(n, { url: o.url }, a)));
520
530
  let c = null, l = 0;
521
531
  try {
522
- let e = await H(n, { url: o.url });
532
+ let e = await V(n, { url: o.url });
523
533
  c = g(e), l = e.tables.length;
524
534
  } catch (e) {
525
- return F.error(`restore --drill: could not introspect the restored DB — ${String(e)}`), 1;
535
+ return P.error(`restore --drill: could not introspect the restored DB — ${String(e)}`), 1;
526
536
  }
527
- let u = me({
537
+ let u = he({
528
538
  stampFingerprint: s?.schemaFingerprint ?? null,
529
539
  restoredFingerprint: c,
530
540
  restoredTableCount: l
531
541
  });
532
- for (let e of u.lines) u.pass ? F.info(`restore drill: ${e}`) : F.error(`restore drill: ${e}`);
542
+ for (let e of u.lines) u.pass ? P.info(`restore drill: ${e}`) : P.error(`restore drill: ${e}`);
533
543
  return +!u.pass;
534
- }, je = async (e) => {
535
- let t = B(e);
536
- if (!t) return F.error("usage: voltro data restore <backupDir> [--allow-live] [--api-url <url>] [--force] [--drill [--drill-url <url>]] (native pg_restore/mysql/…)"), 1;
537
- if (e.includes("--drill")) return Ae(t, e);
538
- if (!await R(e)) return 1;
539
- let n = V(), { join: r } = await import("node:path"), { readFile: i } = await import("node:fs/promises"), a = r(t, C(n)), o = fe({
540
- stamp: await i(r(t, M), "utf8").then(N, () => null),
544
+ }, Me = async (e) => {
545
+ let t = z(e);
546
+ if (!t) return P.error("usage: voltro data restore <backupDir> [--allow-live] [--api-url <url>] [--force] [--drill [--drill-url <url>]] (native pg_restore/mysql/…)"), 1;
547
+ if (e.includes("--drill")) return je(t, e);
548
+ if (!await L(e)) return 1;
549
+ let n = B(), { join: r } = await import("node:path"), { readFile: i } = await import("node:fs/promises"), a = r(t, C(n)), o = pe({
550
+ stamp: await i(r(t, j), "utf8").then(M, () => null),
541
551
  currentDialect: n,
542
- currentFingerprint: await I(n)
552
+ currentFingerprint: await F(n)
543
553
  });
544
- for (let e of o.info) F.info(`backup stamp: ${e}`);
545
- if (o.warn && F.warn(o.warn), o.refuse) {
546
- if (!e.includes("--force")) return F.error(`restore refused: ${o.refuse} (pass --force to override)`), 1;
547
- F.warn(`restore proceeding despite: ${o.refuse} (--force)`);
554
+ for (let e of o.info) P.info(`backup stamp: ${e}`);
555
+ if (o.warn && P.warn(o.warn), o.refuse) {
556
+ if (!e.includes("--force")) return P.error(`restore refused: ${o.refuse} (pass --force to override)`), 1;
557
+ P.warn(`restore proceeding despite: ${o.refuse} (--force)`);
548
558
  }
549
- return await f.runPromise(A(D(n, Q(), a))), F.info("native restore complete", {
559
+ return await f.runPromise(A(D(n, Q(), a))), P.info("native restore complete", {
550
560
  dialect: n,
551
561
  artifact: a
552
562
  }), 0;
553
- }, Me = async (e) => {
554
- let t = B(e);
555
- if (!t) return F.error("usage: voltro data inspect <file.vbundle|dir> [--json] [--passphrase <p>]"), 1;
563
+ }, Ne = async (e) => {
564
+ let t = z(e);
565
+ if (!t) return P.error("usage: voltro data inspect <file.vbundle|dir> [--json] [--passphrase <p>]"), 1;
556
566
  let { resolve: n, join: r } = await import("node:path"), i = await import("node:fs/promises"), a = n(process.cwd(), t);
557
567
  if ((await i.stat(a).catch(() => void 0))?.isDirectory()) {
558
568
  let n = r(a, "manifest.json"), o = r(a, "README.md");
@@ -561,7 +571,7 @@ var M = "voltro-backup-stamp.json", de = (e) => ({
561
571
  if (e !== void 0) return console.log(e), 0;
562
572
  }
563
573
  let s = await i.readFile(n, "utf8").catch(() => void 0);
564
- return s === void 0 ? (F.error(`'${t}' is a directory but holds no manifest.json — is it an unpacked bundle? (a bundle exported with --target api is always unpacked into a directory, even when the path ends in .vbundle)`), 1) : (console.log(s), 0);
574
+ return s === void 0 ? (P.error(`'${t}' is a directory but holds no manifest.json — is it an unpacked bundle? (a bundle exported with --target api is always unpacked into a directory, even when the path ends in .vbundle)`), 1) : (console.log(s), 0);
565
575
  }
566
576
  let o = K(e), s = () => {
567
577
  let e = q(a);
@@ -569,17 +579,17 @@ var M = "voltro-backup-stamp.json", de = (e) => ({
569
579
  };
570
580
  if (e.includes("--json")) {
571
581
  let e = (await E(s(), ["manifest.json"])).get("manifest.json");
572
- return e ? (console.log(e.toString("utf8")), 0) : (F.error("no manifest.json found in the bundle"), 1);
582
+ return e ? (console.log(e.toString("utf8")), 0) : (P.error("no manifest.json found in the bundle"), 1);
573
583
  }
574
584
  let c = (await E(s(), ["README.md"])).get("README.md");
575
585
  if (c) return console.log(c.toString("utf8")), 0;
576
586
  let l = (await E(s(), ["manifest.json"])).get("manifest.json");
577
- return l ? (console.log(l.toString("utf8")), 0) : (F.error("bundle has no README.md or manifest.json"), 1);
578
- }, Ne = async (e) => {
579
- let t = B(e), n = B(e.filter((e) => e !== t));
580
- if (!t || !n) return F.error("usage: voltro data unpack <file.vbundle> <dir> [--passphrase <p>]"), 1;
587
+ return l ? (console.log(l.toString("utf8")), 0) : (P.error("bundle has no README.md or manifest.json"), 1);
588
+ }, Pe = async (e) => {
589
+ let t = z(e), n = z(e.filter((e) => e !== t));
590
+ if (!t || !n) return P.error("usage: voltro data unpack <file.vbundle> <dir> [--passphrase <p>]"), 1;
581
591
  let { resolve: r } = await import("node:path"), i = q(r(process.cwd(), t)), a = K(e);
582
- return a && (i = w(i, a)), await j(i, r(process.cwd(), n)), F.info("unpack complete", {
592
+ return a && (i = w(i, a)), await de(i, r(process.cwd(), n)), P.info("unpack complete", {
583
593
  file: t,
584
594
  dir: n
585
595
  }), 0;
@@ -641,13 +651,13 @@ var M = "voltro-backup-stamp.json", de = (e) => ({
641
651
  "--drill-url",
642
652
  "--api-url"
643
653
  ] }
644
- }, Pe = (e) => e.split("=")[0], Fe = (e, t) => {
654
+ }, Fe = (e) => e.split("=")[0], Ie = (e, t) => {
645
655
  let n = $[e];
646
656
  if (!n) return;
647
- let r = z(t, "--target") === "api" ? "api" : "direct", i = /* @__PURE__ */ new Set([...n.common, ...r === "api" ? n.apiOnly ?? [] : n.directOnly ?? []]), a = new Set(r === "api" ? n.directOnly ?? [] : n.apiOnly ?? []);
657
+ let r = R(t, "--target") === "api" ? "api" : "direct", i = /* @__PURE__ */ new Set([...n.common, ...r === "api" ? n.apiOnly ?? [] : n.directOnly ?? []]), a = new Set(r === "api" ? n.directOnly ?? [] : n.apiOnly ?? []);
648
658
  for (let n of t) {
649
659
  if (!n.startsWith("--")) continue;
650
- let t = Pe(n);
660
+ let t = Fe(n);
651
661
  if (i.has(t)) continue;
652
662
  if (a.has(t)) return `voltro data ${e}: ${t} is not read with --target ${r} (it is a --target ${r === "api" ? "direct" : "api"} flag). Remove it, or change --target.`;
653
663
  let o = Object.entries($).filter(([n, r]) => n !== e && [
@@ -657,13 +667,13 @@ var M = "voltro-backup-stamp.json", de = (e) => ({
657
667
  ].includes(t)).map(([e]) => e);
658
668
  return o.length > 0 ? `voltro data ${e}: ${t} is not a \`${e}\` flag (it belongs to \`voltro data ${o.join("` / `")}\`). Remove it.` : `voltro data ${e}: unknown flag ${t}. Run \`voltro data --help\` for the flags this command reads.`;
659
669
  }
660
- }, Ie = async (e) => {
670
+ }, Le = async (e) => {
661
671
  let [t, ...n] = e;
662
672
  if (t !== void 0 && $[t] !== void 0) {
663
- let e = Fe(t, n);
664
- if (e) return F.error(e), 2;
673
+ let e = Ie(t, n);
674
+ if (e) return P.error(e), 2;
665
675
  }
666
- return t === "export" ? De(n) : t === "import" ? Oe(n) : t === "unpack" ? Ne(n) : t === "inspect" ? Me(n) : t === "backup" ? ke(n) : t === "restore" ? je(n) : (F.error("usage: voltro data <export|import|unpack|inspect|backup|restore> … (logical: export/import; native: backup/restore)"), t ? 2 : 1);
676
+ return t === "export" ? De(n) : t === "import" ? ke(n) : t === "unpack" ? Pe(n) : t === "inspect" ? Ne(n) : t === "backup" ? Ae(n) : t === "restore" ? Me(n) : (P.error("usage: voltro data <export|import|unpack|inspect|backup|restore> … (logical: export/import; native: backup/restore)"), t ? 2 : 1);
667
677
  };
668
678
  //#endregion
669
- export { Ie as runDataCommand };
679
+ export { Le as runDataCommand };
@@ -4,7 +4,7 @@ import { n } from "./appModuleLoader-C9r9mxZt.js";
4
4
  import { t as r } from "./bootRefusal-pgvDxlrU.js";
5
5
  import { n as i, r as a } from "./startupRunner-CEqQq7ax.js";
6
6
  import { r as o } from "./appPort-B_HpJ_ck.js";
7
- import { H as s, J as c, K as l, V as u, W as d, X as f, Y as p, Z as m, ct as h, ft as g, g as _, ht as v, lt as ee, pt as te, q as y, ut as b } from "./webDev-Dk8lFUzf.js";
7
+ import { H as s, J as c, K as l, V as u, W as d, X as f, Y as p, Z as m, ct as h, ft as g, g as _, ht as v, lt as ee, pt as te, q as y, ut as b } from "./webDev-101csg6Q.js";
8
8
  import { n as x, r as S } from "./dialectDriver-czCHYpeH.js";
9
9
  import { a as C, i as ne, n as re, t as ie } from "./connectionConfig-Bk9IC7D0.js";
10
10
  import { a as ae, c as oe, i as se, n as ce, o as le, r as ue, t as de } from "./seedRunner-IdHEprqf.js";
@@ -6076,7 +6076,7 @@ var ec = (e) => {
6076
6076
  if (e.length === 0) return;
6077
6077
  let t = e.filter((e) => e.kind === "no-producer").map((e) => e.event), n = e.filter((e) => e.kind === "no-consumer").map((e) => e.event), r = [];
6078
6078
  return t.length > 0 && r.push(` ${t.length} declared ${t.length === 1 ? "event is" : "events are"} never published: ${t.join(", ")}`), n.length > 0 && r.push(` ${n.length} declared ${n.length === 1 ? "event has" : "events have"} no \`useEvent\` consumer: ${n.join(", ")}`), `events: declared but not wired
6079
- ${r.join("\n")}\n A consumer with no producer waits forever and looks exactly like a quiet channel —
6079
+ ${r.join("\n")}\n A deployment with no producer waits forever and looks exactly like a quiet channel —
6080
6080
  the shape that hid two dead subscriptions in a real app for months. This is a WARNING,
6081
6081
  not a fault: the other half may be a week away, or in a client this build cannot see.`;
6082
6082
  }, dh = (e, t) => {
@@ -1,3 +1,3 @@
1
- import { c as e, d as t, f as n, i as r, u as i } from "./dev-D4l_YOzI.js";
1
+ import { c as e, d as t, f as n, i as r, u as i } from "./dev-B2rZfqxw.js";
2
2
  import "./dialectDriver-czCHYpeH.js";
3
3
  export { r as buildStore, e as loadApiConfig, i as loadDiscovered, t as runDev, n as walk };
@@ -0,0 +1,2 @@
1
+ import { v as e, y as t } from "./doctorCommand-Ct_3BHgd.js";
2
+ export { e as runDoctorCommand, t as runServePreflight };