@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.
- package/CHANGELOG.md +91 -0
- package/dist/apiBuild-B7NgSMhX.js +2 -0
- package/dist/{apiBuild-B_iH24qf.js → apiBuild-DF0f69Gf.js} +2 -2
- package/dist/bin.js +1 -1
- package/dist/{build-DUdi6F_Q.js → build-LC_IJaHL.js} +7 -7
- package/dist/{checkCommand-B2RWrpWi.js → checkCommand-DBpTSK8d.js} +1 -1
- package/dist/{checkCommand-DWL2_PPR.js → checkCommand-DDxwJCja.js} +2 -2
- package/dist/{codegenCommand-DkjoJ30Q.js → codegenCommand-LjxfK4Am.js} +2 -2
- package/dist/{codemodRunner-sFuWDETH.js → codemodRunner-Cnnz4-I7.js} +19 -4
- package/dist/{commands-DoTClnSk.js → commands-CbQcuWsE.js} +20 -20
- package/dist/{dashboardCommand-Bro7Jwts.js → dashboardCommand-CAHjCe_9.js} +3 -3
- package/dist/{dataCommand-Rj57y1vg.js → dataCommand-CrqvbVOv.js} +143 -133
- package/dist/{dev-D4l_YOzI.js → dev-B2rZfqxw.js} +2 -2
- package/dist/{dev-DuqBJC7g.js → dev-D0E5x2Ue.js} +1 -1
- package/dist/doctorCommand-CdsctSwg.js +2 -0
- package/dist/{doctorCommand-TmZTAepc.js → doctorCommand-Ct_3BHgd.js} +226 -216
- package/dist/{dormancyCommand-CUKhRmGG.js → dormancyCommand-D1DKnYce.js} +1 -1
- package/dist/{embeddingsCommand-Db-iQM3l.js → embeddingsCommand-1sZRBKlM.js} +1 -1
- package/dist/{envCommand-DQ_URZq9.js → envCommand-7qjlQgLD.js} +2 -2
- package/dist/{evolveCommand-CghRPrGO.js → evolveCommand-D5opB48I.js} +2 -2
- package/dist/index.js +1 -1
- package/dist/{infoCommand-BCs_ZFnl.js → infoCommand-Bs_8RU22.js} +1 -1
- package/dist/{runtimeTrace-jFKvOPBz.js → runtimeTrace-Wmi7V-wN.js} +1 -1
- package/dist/{sdkgen-COQqHB9V.js → sdkgen-DbTFGCjg.js} +1 -1
- package/dist/{serveCommand-C512kzZA.js → serveCommand-C8xzYCwa.js} +4 -4
- package/dist/serveCommand-CGNTXafv.js +2 -0
- package/dist/serveEntry.js +1 -1
- package/dist/{start-fifc0xpW.js → start-BAlGcjF5.js} +1 -1
- package/dist/{start-BjcuFME_.js → start-Ds3xyn8R.js} +1 -1
- package/dist/startEntry.js +1 -1
- package/dist/startup.d.ts +1 -1
- package/dist/updateCommand-BvkKlV7D.js +2 -0
- package/dist/{updateCommand-HZQVBU3T.js → updateCommand-CrI9B4d7.js} +1 -1
- package/dist/{webDev-Dk8lFUzf.js → webDev-101csg6Q.js} +2 -2
- package/dist/webDev-BLKBO34K.js +2 -0
- package/dist/{webhooksCommand-D7ZpH7w0.js → webhooksCommand-BXUP5YjW.js} +1 -1
- package/package.json +23 -17
- package/templates/AGENTS.md +1 -1
- package/templates/agent-docs/_index.md +1 -1
- package/templates/agent-docs/authentication.md +1 -1
- package/templates/agent-docs/cli.md +2 -2
- package/templates/agent-docs/data.md +14 -12
- package/templates/agent-docs/database/migrations.md +1 -1
- package/templates/agent-docs/internationalization.md +2 -2
- package/templates/agent-docs/observability.md +1 -1
- package/templates/agent-docs/plugins/openapi.md +1 -1
- package/templates/agent-docs/plugins/versioning.md +1 -1
- package/templates/agent-docs/plugins/webhooks.md +1 -1
- package/templates/agent-docs/plugins.md +1 -1
- package/templates/agent-docs/routing.md +1 -1
- package/templates/agent-docs/scheduling.md +1 -1
- package/templates/agent-docs/security.md +2 -2
- package/templates/agent-docs/templates/apibackends.md +1 -1
- package/templates/agent-docs/whats-new.md +49 -55
- package/templates/apps/api-ai/package.json +7 -7
- package/templates/apps/api-auth/package.json +8 -8
- package/templates/apps/api-backend/package.json +7 -7
- package/templates/apps/api-backend-deactivation/package.json +7 -7
- package/templates/apps/api-backend-mail/package.json +8 -8
- package/templates/apps/api-backend-mariadb/package.json +9 -9
- package/templates/apps/api-backend-sqlite/package.json +8 -8
- package/templates/apps/api-backend-storage/package.json +8 -8
- package/templates/apps/api-cms/package.json +10 -10
- package/templates/apps/api-collab/package.json +8 -8
- package/templates/apps/api-data-advanced/package.json +8 -8
- package/templates/apps/api-durable/package.json +8 -8
- package/templates/apps/api-feature-flags/package.json +9 -9
- package/templates/apps/api-governance/package.json +8 -8
- package/templates/apps/api-kv/package.json +8 -8
- package/templates/apps/api-moderation/package.json +8 -8
- package/templates/apps/api-observability/package.json +8 -8
- package/templates/apps/api-ratelimit/package.json +8 -8
- package/templates/apps/api-rbac/package.json +8 -8
- package/templates/apps/api-rest/package.json +7 -7
- package/templates/apps/api-saas/package.json +11 -11
- package/templates/apps/api-saas-starter/package.json +10 -10
- package/templates/apps/api-search/package.json +8 -8
- package/templates/apps/api-status/package.json +8 -8
- package/templates/apps/api-versioning/package.json +8 -8
- package/templates/apps/api-webhooks/package.json +9 -9
- package/templates/apps/changelog/package.json +6 -6
- package/templates/apps/edge-functions/package.json +2 -2
- package/templates/apps/frontend-admin/package.json +8 -8
- package/templates/apps/frontend-app/package.json +9 -9
- package/templates/apps/frontend-auth/package.json +8 -8
- package/templates/apps/frontend-blank/package.json +7 -7
- package/templates/apps/frontend-cms/package.json +9 -9
- package/templates/apps/frontend-collab/package.json +10 -10
- package/templates/apps/frontend-contact/package.json +7 -7
- package/templates/apps/frontend-dashboard/package.json +7 -7
- package/templates/apps/frontend-docs/package.json +7 -7
- package/templates/apps/frontend-i18n/package.json +6 -6
- package/templates/apps/frontend-landing/package.json +7 -7
- package/templates/apps/frontend-portal/package.json +8 -8
- package/templates/apps/frontend-saas/package.json +8 -8
- package/templates/apps/frontend-spa/package.json +7 -7
- package/templates/apps/frontend-ssr/package.json +7 -7
- package/templates/apps/frontend-ssr-api/package.json +8 -8
- package/templates/apps/frontend-static-blog/package.json +6 -6
- package/templates/apps/frontend-status/package.json +8 -8
- package/templates/apps/mobile-app/package.json +4 -4
- package/dist/apiBuild-RM5W5YXk.js +0 -2
- package/dist/doctorCommand-Bw3V4L1j.js +0 -2
- package/dist/serveCommand-gj7MsqXY.js +0 -2
- package/dist/updateCommand-B2alql9k.js +0 -2
- 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-
|
|
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
|
|
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
|
|
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
|
-
}),
|
|
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
|
-
},
|
|
40
|
+
}, pe = (e) => {
|
|
41
41
|
let { stamp: t, currentDialect: n, currentFingerprint: r } = e;
|
|
42
42
|
if (t === null) return {
|
|
43
|
-
warn: `no ${
|
|
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
|
-
},
|
|
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
|
-
},
|
|
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 =
|
|
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
|
-
},
|
|
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
|
-
},
|
|
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
|
-
},
|
|
97
|
+
}, F = async (e) => {
|
|
98
98
|
try {
|
|
99
|
-
return g(await
|
|
99
|
+
return g(await H(e));
|
|
100
100
|
} catch {
|
|
101
101
|
return null;
|
|
102
102
|
}
|
|
103
|
-
},
|
|
103
|
+
}, I = (e) => {
|
|
104
104
|
if (e.event !== "done") return;
|
|
105
105
|
let t = e.total === void 0 ? "" : ` / ${e.total}`;
|
|
106
|
-
|
|
107
|
-
},
|
|
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
|
-
},
|
|
128
|
-
let t = e.includes("--allow-live"), n = t ? null : await
|
|
129
|
-
dialect:
|
|
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:
|
|
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 || (
|
|
141
|
-
},
|
|
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
|
-
],
|
|
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
|
-
},
|
|
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
|
-
},
|
|
163
|
+
}, H = (e) => V(e, r()), ye = () => {
|
|
164
164
|
let e = r(), t = [];
|
|
165
|
-
return e.url && t.push(
|
|
166
|
-
},
|
|
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 =
|
|
169
|
+
let a = await n(i, void 0), o = B();
|
|
170
170
|
return {
|
|
171
171
|
store: a,
|
|
172
|
-
snapshot: await
|
|
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) =>
|
|
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 =
|
|
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 =
|
|
229
|
-
if (!r && !(t && n)) return
|
|
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 =
|
|
232
|
-
if (!t) return
|
|
233
|
-
let i =
|
|
234
|
-
if (!i) return
|
|
235
|
-
if (
|
|
236
|
-
let a =
|
|
237
|
-
...
|
|
238
|
-
...
|
|
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
|
-
...
|
|
241
|
-
...
|
|
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
|
|
253
|
-
if (n) return
|
|
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
|
|
258
|
+
return await de((async function* () {
|
|
259
259
|
yield l;
|
|
260
|
-
})(), c(process.cwd(), r)),
|
|
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
|
|
268
|
-
let i =
|
|
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 (
|
|
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
|
-
}),
|
|
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:
|
|
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
|
|
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)),
|
|
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:
|
|
346
|
+
onProgress: I
|
|
347
347
|
}));
|
|
348
|
-
return
|
|
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 =
|
|
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
|
-
|
|
364
|
+
P.info("import DRY RUN — nothing was written", t), P.info(Y());
|
|
365
365
|
return;
|
|
366
366
|
}
|
|
367
|
-
|
|
368
|
-
}, Oe =
|
|
369
|
-
let t =
|
|
370
|
-
if (
|
|
371
|
-
let
|
|
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 =
|
|
374
|
-
if (!t) return
|
|
375
|
-
let r =
|
|
376
|
-
if (!r) return
|
|
377
|
-
let s =
|
|
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) &&
|
|
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
|
|
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") ? (
|
|
414
|
+
return e.includes("--dry-run") ? (P.info("api import DRY RUN — nothing was written", {
|
|
407
415
|
via: t,
|
|
408
416
|
...f
|
|
409
|
-
}),
|
|
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
|
|
415
|
-
if (!await
|
|
416
|
-
let { store: s, snapshot: c } = await
|
|
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:
|
|
440
|
+
targetDialect: B(),
|
|
433
441
|
allowIncompatible: l,
|
|
434
442
|
targetSnapshot: c,
|
|
435
443
|
force: l,
|
|
436
444
|
onWarn: u,
|
|
437
|
-
onProgress:
|
|
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:
|
|
469
|
+
targetDialect: B(),
|
|
462
470
|
allowIncompatible: l,
|
|
463
471
|
targetSnapshot: c,
|
|
464
472
|
force: l,
|
|
465
473
|
onWarn: u,
|
|
466
|
-
onProgress:
|
|
474
|
+
onProgress: I,
|
|
467
475
|
...X(e),
|
|
468
476
|
...d ? { assets: oe(d) } : {},
|
|
469
477
|
...p ? { copyLoader: p } : {}
|
|
470
|
-
})).
|
|
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
|
-
},
|
|
488
|
-
let t =
|
|
489
|
-
if (!t) return
|
|
490
|
-
let n =
|
|
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 =
|
|
504
|
+
let s = fe({
|
|
495
505
|
dialect: n,
|
|
496
|
-
schemaFingerprint: await
|
|
497
|
-
voltroVersion: await
|
|
506
|
+
schemaFingerprint: await F(n),
|
|
507
|
+
voltroVersion: await ge(),
|
|
498
508
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
499
509
|
});
|
|
500
|
-
return await i(a(t,
|
|
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:
|
|
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
|
-
},
|
|
508
|
-
let n =
|
|
509
|
-
flagUrl:
|
|
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:
|
|
521
|
+
liveKeys: ye()
|
|
512
522
|
});
|
|
513
|
-
if (!o.ok) return
|
|
514
|
-
let s = await i(r(e,
|
|
515
|
-
if (s && s.dialect !== n) return
|
|
516
|
-
|
|
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:
|
|
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
|
|
532
|
+
let e = await V(n, { url: o.url });
|
|
523
533
|
c = g(e), l = e.tables.length;
|
|
524
534
|
} catch (e) {
|
|
525
|
-
return
|
|
535
|
+
return P.error(`restore --drill: could not introspect the restored DB — ${String(e)}`), 1;
|
|
526
536
|
}
|
|
527
|
-
let u =
|
|
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 ?
|
|
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
|
-
},
|
|
535
|
-
let t =
|
|
536
|
-
if (!t) return
|
|
537
|
-
if (e.includes("--drill")) return
|
|
538
|
-
if (!await
|
|
539
|
-
let n =
|
|
540
|
-
stamp: await i(r(t,
|
|
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
|
|
552
|
+
currentFingerprint: await F(n)
|
|
543
553
|
});
|
|
544
|
-
for (let e of o.info)
|
|
545
|
-
if (o.warn &&
|
|
546
|
-
if (!e.includes("--force")) return
|
|
547
|
-
|
|
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))),
|
|
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
|
-
},
|
|
554
|
-
let t =
|
|
555
|
-
if (!t) return
|
|
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 ? (
|
|
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) : (
|
|
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) : (
|
|
578
|
-
},
|
|
579
|
-
let t =
|
|
580
|
-
if (!t || !n) return
|
|
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
|
|
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
|
-
},
|
|
654
|
+
}, Fe = (e) => e.split("=")[0], Ie = (e, t) => {
|
|
645
655
|
let n = $[e];
|
|
646
656
|
if (!n) return;
|
|
647
|
-
let r =
|
|
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 =
|
|
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
|
-
},
|
|
670
|
+
}, Le = async (e) => {
|
|
661
671
|
let [t, ...n] = e;
|
|
662
672
|
if (t !== void 0 && $[t] !== void 0) {
|
|
663
|
-
let e =
|
|
664
|
-
if (e) return
|
|
673
|
+
let e = Ie(t, n);
|
|
674
|
+
if (e) return P.error(e), 2;
|
|
665
675
|
}
|
|
666
|
-
return t === "export" ? De(n) : t === "import" ?
|
|
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 {
|
|
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-
|
|
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
|
|
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-
|
|
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 };
|