@voltro/cli 0.40.0 → 0.41.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 +74 -0
- package/dist/{apiBuild-C8xBEYbL.js → apiBuild-B_iH24qf.js} +2 -2
- package/dist/apiBuild-RM5W5YXk.js +2 -0
- package/dist/bin.js +1 -1
- package/dist/{build-CkhFGnKA.js → build-DUdi6F_Q.js} +150 -150
- package/dist/{checkCommand-QbHshOac.js → checkCommand-B2RWrpWi.js} +1 -1
- package/dist/{checkCommand-BcXJa2IS.js → checkCommand-DWL2_PPR.js} +2 -2
- package/dist/{codegenCommand-DF2OJh3O.js → codegenCommand-DkjoJ30Q.js} +2 -2
- package/dist/{codemodRunner-BcOvi4A2.js → codemodRunner-sFuWDETH.js} +520 -460
- package/dist/{commands-7Z7-HOE3.js → commands-D0VR1yBB.js} +22 -22
- package/dist/{dashboardCommand-CUycH6dR.js → dashboardCommand-Bro7Jwts.js} +5 -5
- package/dist/{dataCommand-By78lscK.js → dataCommand-OKC5FscP.js} +183 -172
- package/dist/{dbCommand-DSwGv9wS.js → dbCommand-BHRamDsy.js} +441 -414
- package/dist/dbCommand-C9iE1pd9.js +2 -0
- package/dist/{dev-Dh1NuYx1.js → dev-D4l_YOzI.js} +22 -22
- package/dist/{dev-D8JSKlBM.js → dev-DuqBJC7g.js} +1 -1
- package/dist/doctorCommand-Bw3V4L1j.js +2 -0
- package/dist/{doctorCommand-C-8-Z9D6.js → doctorCommand-TmZTAepc.js} +385 -279
- package/dist/{dormancyCommand-A79Odglm.js → dormancyCommand-CUKhRmGG.js} +1 -1
- package/dist/{embeddingsCommand-CoiyHfkY.js → embeddingsCommand-Db-iQM3l.js} +1 -1
- package/dist/{envCommand-B6d0s-jZ.js → envCommand-DQ_URZq9.js} +12 -12
- package/dist/{evolveCommand-BC5a9lxX.js → evolveCommand-CghRPrGO.js} +2 -2
- package/dist/index.js +1 -1
- package/dist/{infoCommand-ZqSVzJZ4.js → infoCommand-BCs_ZFnl.js} +1 -1
- package/dist/{migrate-BnPw2zC8.js → migrate-DLtPv2_D.js} +1 -1
- package/dist/{runtimeTrace-BslKJjDY.js → runtimeTrace-jFKvOPBz.js} +1 -1
- package/dist/{sdkgen-DQ8uEmmn.js → sdkgen-COQqHB9V.js} +1 -1
- package/dist/{serveCommand-Dqb9Ku1-.js → serveCommand-Cba_M2Su.js} +3 -3
- package/dist/serveCommand-DRbYK646.js +2 -0
- package/dist/serveEntry.js +1 -1
- package/dist/{start-dkNYKtgQ.js → start-BjcuFME_.js} +379 -343
- package/dist/{start-BA7txHhY.js → start-fifc0xpW.js} +1 -1
- package/dist/startEntry.js +1 -1
- package/dist/updateCommand-B2alql9k.js +2 -0
- package/dist/{updateCommand-eoGpZr3E.js → updateCommand-HZQVBU3T.js} +1 -1
- package/dist/webDev-D6QeXw3P.js +2 -0
- package/dist/{webDev-bybjZA0o.js → webDev-Dk8lFUzf.js} +642 -525
- package/dist/{webhooksCommand-DubZWNOx.js → webhooksCommand-D7ZpH7w0.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/_manifest.json +1 -1
- package/templates/agent-docs/cli.md +6 -0
- package/templates/agent-docs/plugins/governance.md +8 -0
- package/templates/agent-docs/routing.md +141 -28
- package/templates/agent-docs/security.md +24 -0
- package/templates/agent-docs/whats-new.md +37 -121
- 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-BIyGkym8.js +0 -2
- package/dist/dbCommand-DcqEyxju.js +0 -2
- package/dist/doctorCommand-FhQ7EVYL.js +0 -2
- package/dist/serveCommand-BmvEQCMS.js +0 -2
- package/dist/updateCommand-BauSVxPp.js +0 -2
- package/dist/webDev-CBbKs4dZ.js +0 -2
|
@@ -1,25 +1,25 @@
|
|
|
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-D4l_YOzI.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-dW-PsfLB.js";
|
|
6
6
|
import { o as c, t as l } from "./inspectFetch-EMuhTG_9.js";
|
|
7
|
-
import { r as u } from "./dbCommand-
|
|
7
|
+
import { r as u } from "./dbCommand-BHRamDsy.js";
|
|
8
8
|
import { createLogger as d } from "@voltro/logger";
|
|
9
9
|
import { Effect as f, Stream as p } from "effect";
|
|
10
10
|
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
|
-
import { STORAGE_REFS_TABLE as
|
|
14
|
-
import { assessLiveImport as
|
|
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 j, storageAssetSource as oe, storageBlobSink as se, storageBlobSource as ce, unpackBundle as le, unpackBundleToDir as M } from "@voltro/data-transfer";
|
|
15
15
|
//#region src/backupStamp.ts
|
|
16
|
-
var
|
|
16
|
+
var N = "voltro-backup-stamp.json", ue = (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
|
+
}), P = (e) => {
|
|
23
23
|
let t;
|
|
24
24
|
try {
|
|
25
25
|
t = JSON.parse(e);
|
|
@@ -37,10 +37,10 @@ var P = "voltro-backup-stamp.json", le = (e) => ({
|
|
|
37
37
|
voltroVersion: n.voltroVersion,
|
|
38
38
|
createdAt: n.createdAt
|
|
39
39
|
};
|
|
40
|
-
},
|
|
40
|
+
}, de = (e) => {
|
|
41
41
|
let { stamp: t, currentDialect: n, currentFingerprint: r } = e;
|
|
42
42
|
if (t === null) return {
|
|
43
|
-
warn: `no ${
|
|
43
|
+
warn: `no ${N} 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 P = "voltro-backup-stamp.json", le = (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
|
+
}, F = (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
|
+
}, fe = (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 = F(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 P = "voltro-backup-stamp.json", le = (e) => ({
|
|
|
72
72
|
ok: !0,
|
|
73
73
|
url: t
|
|
74
74
|
};
|
|
75
|
-
},
|
|
75
|
+
}, pe = (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 P = "voltro-backup-stamp.json", le = (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
|
+
}, I = d({ scope: "voltro:data" }), me = 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
|
+
}, L = async (e) => {
|
|
98
98
|
try {
|
|
99
|
-
return g(await
|
|
99
|
+
return g(await G(e));
|
|
100
100
|
} catch {
|
|
101
101
|
return null;
|
|
102
102
|
}
|
|
103
|
-
},
|
|
103
|
+
}, R = (e) => {
|
|
104
104
|
if (e.event !== "done") return;
|
|
105
105
|
let t = e.total === void 0 ? "" : ` / ${e.total}`;
|
|
106
|
-
|
|
107
|
-
},
|
|
106
|
+
I.info(`${e.phase} [${e.index + 1}/${e.tableCount}] ${e.table}`, { rows: `${e.rowsDone}${t}` });
|
|
107
|
+
}, z = async (e) => {
|
|
108
108
|
let t = (e) => e?.meta?.databaseId;
|
|
109
109
|
if (e) {
|
|
110
110
|
let n = await l({
|
|
@@ -124,26 +124,27 @@ var P = "voltro-backup-stamp.json", le = (e) => ({
|
|
|
124
124
|
};
|
|
125
125
|
}
|
|
126
126
|
return null;
|
|
127
|
-
},
|
|
128
|
-
let t = e.includes("--allow-live"), n = t ? null : await
|
|
129
|
-
dialect:
|
|
127
|
+
}, B = async (e) => {
|
|
128
|
+
let t = e.includes("--allow-live"), n = t ? null : await z(V(e, "--api-url")), i = v({
|
|
129
|
+
dialect: U(),
|
|
130
130
|
...r()
|
|
131
131
|
}), a = y({
|
|
132
|
-
dialect:
|
|
132
|
+
dialect: U(),
|
|
133
133
|
...r()
|
|
134
|
-
}), { refuse: o, message: s } =
|
|
134
|
+
}), { refuse: o, message: s } = te({
|
|
135
135
|
liveInstance: n?.label ?? null,
|
|
136
136
|
allowLive: t,
|
|
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 || (I.error(s ?? "refusing: live instance detected"), !1);
|
|
141
|
+
}, V = i, he = [
|
|
142
142
|
"--api-url",
|
|
143
143
|
"--bundle-key",
|
|
144
144
|
"--compression",
|
|
145
145
|
"--consistency",
|
|
146
146
|
"--drill-url",
|
|
147
|
+
"--exclude",
|
|
147
148
|
"--mode",
|
|
148
149
|
"--on-conflict",
|
|
149
150
|
"--passphrase",
|
|
@@ -152,56 +153,65 @@ var P = "voltro-backup-stamp.json", le = (e) => ({
|
|
|
152
153
|
"--target",
|
|
153
154
|
"--tenant",
|
|
154
155
|
"--token"
|
|
155
|
-
],
|
|
156
|
+
], H = (e) => a(e, he), U = () => {
|
|
156
157
|
let t = (process.env.DB_DIALECT ?? "postgres").toLowerCase();
|
|
157
158
|
if (t === "memory") throw new e("voltro data: requires a real dialect, not DB_DIALECT=memory.");
|
|
158
159
|
return t;
|
|
159
|
-
},
|
|
160
|
+
}, W = async (e, t) => {
|
|
160
161
|
let n = (await o(e)).makeSqlLayer(t);
|
|
161
162
|
return f.runPromise(m.SqlClient.pipe(f.flatMap(_), f.provide(n)));
|
|
162
|
-
},
|
|
163
|
+
}, G = (e) => W(e, r()), ge = () => {
|
|
163
164
|
let e = r(), t = [];
|
|
164
|
-
return e.url && t.push(
|
|
165
|
-
},
|
|
165
|
+
return e.url && t.push(F(e.url)), (e.host || e.database) && t.push(`${(e.host ?? "localhost").toLowerCase()}:${e.port ?? "(default)"}/${e.database ?? ""}`), t;
|
|
166
|
+
}, K = async () => {
|
|
166
167
|
let r = process.cwd(), i = await t(r);
|
|
167
168
|
if (!i) throw new e("voltro data: no app.config.ts found in the current directory.");
|
|
168
|
-
let a = await n(i, void 0), o =
|
|
169
|
+
let a = await n(i, void 0), o = U();
|
|
169
170
|
return {
|
|
170
171
|
store: a,
|
|
171
|
-
snapshot: await
|
|
172
|
+
snapshot: await G(o),
|
|
172
173
|
dialect: o
|
|
173
174
|
};
|
|
174
|
-
},
|
|
175
|
-
table:
|
|
175
|
+
}, q = (e) => x(e, {
|
|
176
|
+
table: ee,
|
|
176
177
|
chunkSize: 500
|
|
177
178
|
}).pipe(p.map((e) => ({
|
|
178
179
|
key: String(e.key),
|
|
179
180
|
contentType: String(e.contentType ?? "application/octet-stream"),
|
|
180
181
|
size: Number(e.size ?? 0)
|
|
181
|
-
}))),
|
|
182
|
+
}))), J = (e) => !!e && e.endsWith(".vbundle"), Y = (e) => V(e, "--passphrase") ?? process.env.VOLTRO_BUNDLE_KEY, _e = (e) => e.includes("--encrypt") || V(e, "--passphrase") !== void 0 || process.env.VOLTRO_BUNDLE_KEY !== void 0, ve = async (e, t) => {
|
|
182
183
|
let { createWriteStream: n } = await import("node:fs"), { pipeline: r } = await import("node:stream/promises"), { Readable: i } = await import("node:stream");
|
|
183
184
|
await r(i.from(e), n(t));
|
|
184
|
-
},
|
|
185
|
+
}, X = (e) => ({ async *[Symbol.asyncIterator]() {
|
|
185
186
|
let { createReadStream: t } = await import("node:fs");
|
|
186
187
|
for await (let n of t(e)) yield n instanceof Uint8Array ? n : new Uint8Array(n);
|
|
187
|
-
} }),
|
|
188
|
-
let
|
|
189
|
-
if (
|
|
188
|
+
} }), Z = (e) => (e ?? "").split(",").map((e) => e.trim()).filter(Boolean), ye = (t, n) => {
|
|
189
|
+
let r = V(t, "--tenant"), i = V(t, "--tables"), a = V(t, "--exclude");
|
|
190
|
+
if (a !== void 0) {
|
|
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
|
+
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.");
|
|
193
|
+
let t = Z(a), o = new Set(n), s = t.filter((e) => !o.has(e));
|
|
194
|
+
if (s.length > 0) throw new e(`voltro data export: --exclude names ${s.length} table(s) that do not exist: ${s.join(", ")}. An exclusion that excludes nothing would leave the run looking like it worked.`);
|
|
195
|
+
let c = new Set(t);
|
|
196
|
+
return {
|
|
197
|
+
kind: "tables",
|
|
198
|
+
tables: n.filter((e) => !c.has(e))
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
return r ? {
|
|
190
202
|
kind: "tenant",
|
|
191
|
-
tenantId:
|
|
192
|
-
}
|
|
193
|
-
let n = H(e, "--tables");
|
|
194
|
-
return n ? {
|
|
203
|
+
tenantId: r
|
|
204
|
+
} : i ? {
|
|
195
205
|
kind: "tables",
|
|
196
|
-
tables:
|
|
206
|
+
tables: Z(i)
|
|
197
207
|
} : { kind: "all" };
|
|
198
|
-
},
|
|
208
|
+
}, be = async () => {
|
|
199
209
|
let e = await u(process.cwd());
|
|
200
|
-
return
|
|
201
|
-
},
|
|
202
|
-
let e = (await u(process.cwd())).filter((e) => (e.appliedMixins ?? []).some((e) => e.id ===
|
|
210
|
+
return re(h(e));
|
|
211
|
+
}, xe = "voltro/tenant", Se = async () => {
|
|
212
|
+
let e = (await u(process.cwd())).filter((e) => (e.appliedMixins ?? []).some((e) => e.id === xe)).map((e) => e.tableName);
|
|
203
213
|
return e.length > 0 ? e : void 0;
|
|
204
|
-
},
|
|
214
|
+
}, Ce = (e) => {
|
|
205
215
|
for (let t of e.tables) if (t.samples.length !== 0) {
|
|
206
216
|
console.log(`\n ${t.table}`);
|
|
207
217
|
for (let e of t.samples) console.log(` ${e.column} [${e.action}] ${JSON.stringify(e.before)} → ${JSON.stringify(e.after)}`);
|
|
@@ -214,20 +224,21 @@ var P = "voltro-backup-stamp.json", le = (e) => ({
|
|
|
214
224
|
console.log("\n ✗ unclassified (would BLOCK a real export — add .sensitive()/.safe() or a policy override):");
|
|
215
225
|
for (let t of e.unclassified) console.log(` ${t}`);
|
|
216
226
|
} else console.log("\n ✓ every exported column is classified — safe to run.");
|
|
217
|
-
},
|
|
218
|
-
let t =
|
|
219
|
-
if (!r && !(t && n)) return
|
|
227
|
+
}, we = async (e) => {
|
|
228
|
+
let t = V(e, "--target") === "api", n = V(e, "--bundle-key"), r = H(e);
|
|
229
|
+
if (!r && !(t && n)) return I.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;
|
|
220
230
|
if (t) {
|
|
221
|
-
let t =
|
|
222
|
-
if (!t) return
|
|
223
|
-
let i =
|
|
224
|
-
if (!i) return
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
...
|
|
231
|
+
let t = V(e, "--api-url");
|
|
232
|
+
if (!t) return I.error("--target api requires --api-url <url> (the running instance)"), 1;
|
|
233
|
+
let i = V(e, "--token") ?? process.env.VOLTRO_DATA_TRANSFER_SECRET;
|
|
234
|
+
if (!i) return I.error("--target api requires --token <secret> (or VOLTRO_DATA_TRANSFER_SECRET) matching the instance secret"), 1;
|
|
235
|
+
if (V(e, "--exclude") !== void 0) return I.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 = V(e, "--tables"), o = {
|
|
237
|
+
...V(e, "--profile") ? { profile: V(e, "--profile") } : {},
|
|
238
|
+
...V(e, "--tenant") ? { tenant: V(e, "--tenant") } : {},
|
|
228
239
|
...a ? { tables: a.split(",").map((e) => e.trim()).filter(Boolean) } : {},
|
|
229
|
-
...
|
|
230
|
-
...
|
|
240
|
+
...V(e, "--consistency") === "snapshot" ? { consistency: "snapshot" } : {},
|
|
241
|
+
...V(e, "--compression") ? { compression: V(e, "--compression") } : {},
|
|
231
242
|
...e.includes("--assets") ? { assets: !0 } : {},
|
|
232
243
|
...n ? { bundleKey: n } : {}
|
|
233
244
|
}, s = await fetch(`${t.replace(/\/+$/, "")}/_voltro/admin/export`, {
|
|
@@ -238,26 +249,26 @@ var P = "voltro-backup-stamp.json", le = (e) => ({
|
|
|
238
249
|
},
|
|
239
250
|
body: JSON.stringify(o)
|
|
240
251
|
});
|
|
241
|
-
if (!s.ok) return
|
|
242
|
-
if (n) return
|
|
252
|
+
if (!s.ok) return I.error(`api export failed: HTTP ${s.status} — ${await s.text()}`), 1;
|
|
253
|
+
if (n) return I.info("api export complete (pushed to storage)", {
|
|
243
254
|
via: t,
|
|
244
255
|
...await s.json()
|
|
245
256
|
}), 0;
|
|
246
257
|
let { resolve: c } = await import("node:path"), l = new Uint8Array(await s.arrayBuffer());
|
|
247
|
-
return await
|
|
258
|
+
return await M((async function* () {
|
|
248
259
|
yield l;
|
|
249
|
-
})(), c(process.cwd(), r)),
|
|
260
|
+
})(), c(process.cwd(), r)), I.info("api export complete (downloaded from the running instance)", {
|
|
250
261
|
outDir: r,
|
|
251
262
|
tables: s.headers.get("x-export-tables") ?? void 0,
|
|
252
263
|
rows: s.headers.get("x-export-rows") ?? void 0,
|
|
253
264
|
masked: s.headers.get("x-export-masked") ?? void 0
|
|
254
265
|
}), 0;
|
|
255
266
|
}
|
|
256
|
-
if (!r) return
|
|
257
|
-
let i =
|
|
267
|
+
if (!r) return I.error("a <outDir> is required for a direct export"), 1;
|
|
268
|
+
let i = V(e, "--profile"), a = i ? await s(i) : {}, { store: o, snapshot: c, dialect: l } = await K(), u = e.includes("--assets") || a.assets === !0, d = u ? S({}) : void 0, p = V(e, "--compression") ?? a.compression, m = V(e, "--consistency") === "snapshot" ? "snapshot" : a.consistency ?? "live", h = a.masking, g = a.subset, _ = a.scope ?? ye(e, c.tables.map((e) => e.name)), v = h ? await be() : void 0, y = _.kind === "tenant" ? await Se() : void 0, b = y ? { tenantTables: y } : {};
|
|
258
269
|
if (e.includes("--dry-run")) {
|
|
259
|
-
if (!h) return
|
|
260
|
-
let e = await f.runPromise(
|
|
270
|
+
if (!h) return I.error("--dry-run previews masking, but the profile sets no masking policy"), 1;
|
|
271
|
+
let e = await f.runPromise(ae({
|
|
261
272
|
store: o,
|
|
262
273
|
snapshot: c,
|
|
263
274
|
masking: h,
|
|
@@ -267,12 +278,12 @@ var P = "voltro-backup-stamp.json", le = (e) => ({
|
|
|
267
278
|
...b
|
|
268
279
|
}
|
|
269
280
|
}));
|
|
270
|
-
return
|
|
281
|
+
return Ce(e), +(e.unclassified.length > 0);
|
|
271
282
|
}
|
|
272
|
-
if (
|
|
283
|
+
if (J(r)) {
|
|
273
284
|
let t = await import("node:os"), n = await import("node:fs/promises"), { resolve: i, join: a } = await import("node:path"), s = await n.mkdtemp(a(t.tmpdir(), "voltro-export-"));
|
|
274
285
|
try {
|
|
275
|
-
let t = await f.runPromise(
|
|
286
|
+
let t = await f.runPromise(O({
|
|
276
287
|
store: o,
|
|
277
288
|
snapshot: c,
|
|
278
289
|
dialect: l,
|
|
@@ -285,17 +296,17 @@ var P = "voltro-backup-stamp.json", le = (e) => ({
|
|
|
285
296
|
...p ? { compression: p } : {},
|
|
286
297
|
...h ? { masking: h } : {},
|
|
287
298
|
...v ? { classification: v } : {},
|
|
288
|
-
onProgress:
|
|
289
|
-
})), n =
|
|
299
|
+
onProgress: R
|
|
300
|
+
})), n = T({
|
|
290
301
|
dir: s,
|
|
291
|
-
...d ? { blobs:
|
|
292
|
-
}), a =
|
|
302
|
+
...d ? { blobs: ce(d, () => q(o)) } : {}
|
|
303
|
+
}), a = _e(e);
|
|
293
304
|
if (a) {
|
|
294
|
-
let t =
|
|
295
|
-
if (!t) return
|
|
296
|
-
n =
|
|
305
|
+
let t = Y(e);
|
|
306
|
+
if (!t) return I.error("--encrypt requires --passphrase <p> or VOLTRO_BUNDLE_KEY (a dedicated key, NOT the transfer secret)"), 1;
|
|
307
|
+
n = ie(n, t);
|
|
297
308
|
}
|
|
298
|
-
return await
|
|
309
|
+
return await ve(n, i(process.cwd(), r)), I.info("export complete (single file)", {
|
|
299
310
|
file: r,
|
|
300
311
|
encrypted: a,
|
|
301
312
|
assets: u,
|
|
@@ -309,7 +320,7 @@ var P = "voltro-backup-stamp.json", le = (e) => ({
|
|
|
309
320
|
});
|
|
310
321
|
}
|
|
311
322
|
}
|
|
312
|
-
let x = await f.runPromise(
|
|
323
|
+
let x = await f.runPromise(O({
|
|
313
324
|
store: o,
|
|
314
325
|
snapshot: c,
|
|
315
326
|
dialect: l,
|
|
@@ -322,10 +333,10 @@ var P = "voltro-backup-stamp.json", le = (e) => ({
|
|
|
322
333
|
...p ? { compression: p } : {},
|
|
323
334
|
...h ? { masking: h } : {},
|
|
324
335
|
...v ? { classification: v } : {},
|
|
325
|
-
...d ? { assets:
|
|
326
|
-
onProgress:
|
|
336
|
+
...d ? { assets: oe(d, () => q(o)) } : {},
|
|
337
|
+
onProgress: R
|
|
327
338
|
}));
|
|
328
|
-
return
|
|
339
|
+
return I.info("export complete", {
|
|
329
340
|
outDir: r,
|
|
330
341
|
tables: x.tables.length,
|
|
331
342
|
rows: x.tables.reduce((e, t) => e + t.rowCount, 0),
|
|
@@ -333,15 +344,15 @@ var P = "voltro-backup-stamp.json", le = (e) => ({
|
|
|
333
344
|
compression: x.compression,
|
|
334
345
|
...x.masking ? { maskedColumns: x.masking.transformed.length } : {}
|
|
335
346
|
}), 0;
|
|
336
|
-
},
|
|
337
|
-
let t =
|
|
338
|
-
if (!i && !(t && n)) return
|
|
339
|
-
let a =
|
|
347
|
+
}, Q = async (e) => {
|
|
348
|
+
let t = V(e, "--target") === "api", n = V(e, "--bundle-key"), i = H(e);
|
|
349
|
+
if (!i && !(t && n)) return I.error("usage: voltro data import <bundleDir> [--target direct|api] [--api-url <url>] [--token <secret>] [--bundle-key <storage-key>] [--mode upsert|append|replace] [--on-conflict skip|fail] [--atomic] [--assets] [--no-verify] [--force] [--allow-live] (--force: import despite schema drift AND cross-dialect warnings)"), 1;
|
|
350
|
+
let a = V(e, "--mode") ?? "upsert", o = V(e, "--on-conflict") ?? "skip";
|
|
340
351
|
if (t) {
|
|
341
|
-
let t =
|
|
342
|
-
if (!t) return
|
|
343
|
-
let r =
|
|
344
|
-
if (!r) return
|
|
352
|
+
let t = V(e, "--api-url");
|
|
353
|
+
if (!t) return I.error("--target api requires --api-url <url> (the running instance)"), 1;
|
|
354
|
+
let r = V(e, "--token") ?? process.env.VOLTRO_DATA_TRANSFER_SECRET;
|
|
355
|
+
if (!r) return I.error("--target api requires --token <secret> (or VOLTRO_DATA_TRANSFER_SECRET) matching the instance secret"), 1;
|
|
345
356
|
let s = {
|
|
346
357
|
authorization: `Bearer ${r}`,
|
|
347
358
|
"x-import-mode": a,
|
|
@@ -350,16 +361,16 @@ var P = "voltro-backup-stamp.json", le = (e) => ({
|
|
|
350
361
|
...e.includes("--force") ? { "x-import-force": "1" } : {}
|
|
351
362
|
}, { resolve: c } = await import("node:path"), l;
|
|
352
363
|
if (n) s["content-type"] = "application/json", l = JSON.stringify({ bundleKey: n });
|
|
353
|
-
else if (
|
|
354
|
-
let t =
|
|
355
|
-
n && (t =
|
|
364
|
+
else if (J(i)) {
|
|
365
|
+
let t = X(c(process.cwd(), i)), n = Y(e);
|
|
366
|
+
n && (t = w(t, n));
|
|
356
367
|
let r = [];
|
|
357
368
|
for await (let e of t) r.push(Buffer.from(e));
|
|
358
369
|
s["content-type"] = "application/octet-stream", l = Buffer.concat(r);
|
|
359
370
|
} else {
|
|
360
|
-
await (await import("node:fs/promises")).access(c(process.cwd(), i, "assets", "index.ndjson")).then(() => !0, () => !1) &&
|
|
371
|
+
await (await import("node:fs/promises")).access(c(process.cwd(), i, "assets", "index.ndjson")).then(() => !0, () => !1) && I.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.");
|
|
361
372
|
let e = [];
|
|
362
|
-
for await (let t of
|
|
373
|
+
for await (let t of T({ dir: c(process.cwd(), i) })) e.push(Buffer.from(t));
|
|
363
374
|
s["content-type"] = "application/octet-stream", l = Buffer.concat(e);
|
|
364
375
|
}
|
|
365
376
|
let u = await fetch(`${t.replace(/\/+$/, "")}/_voltro/admin/import`, {
|
|
@@ -367,39 +378,39 @@ var P = "voltro-backup-stamp.json", le = (e) => ({
|
|
|
367
378
|
body: l,
|
|
368
379
|
headers: s
|
|
369
380
|
});
|
|
370
|
-
return u.ok ? (
|
|
381
|
+
return u.ok ? (I.info("api import complete (imported by the running instance)", {
|
|
371
382
|
via: t,
|
|
372
383
|
...await u.json()
|
|
373
|
-
}), 0) : (
|
|
384
|
+
}), 0) : (I.error(`api import failed: HTTP ${u.status} — ${await u.text()}`), 1);
|
|
374
385
|
}
|
|
375
|
-
if (!i) return
|
|
376
|
-
if (!await
|
|
377
|
-
let { store: s, snapshot: c } = await
|
|
378
|
-
if (
|
|
386
|
+
if (!i) return I.error("a <bundleDir> is required for a direct import"), 1;
|
|
387
|
+
if (!await B(e)) return 1;
|
|
388
|
+
let { store: s, snapshot: c } = await K(), l = e.includes("--force"), u = (e) => I.warn(e), d = e.includes("--assets") ? S({}) : void 0, p = U() === "postgres" ? (await import("@voltro/sql-postgres")).makePgCopySession(r()) : void 0;
|
|
389
|
+
if (J(i)) {
|
|
379
390
|
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-"));
|
|
380
391
|
try {
|
|
381
|
-
let t =
|
|
382
|
-
n && (t =
|
|
392
|
+
let t = X(r(process.cwd(), i)), n = Y(e);
|
|
393
|
+
n && (t = w(t, n)), await le(t, {
|
|
383
394
|
dir: h,
|
|
384
|
-
blobs:
|
|
395
|
+
blobs: se(d ?? S({}))
|
|
385
396
|
});
|
|
386
|
-
let m = await f.runPromise(
|
|
397
|
+
let m = await f.runPromise(k({
|
|
387
398
|
store: s,
|
|
388
399
|
bundleDir: h,
|
|
389
400
|
mode: a,
|
|
390
401
|
onConflict: o,
|
|
391
402
|
atomic: e.includes("--atomic"),
|
|
392
403
|
verify: !e.includes("--no-verify"),
|
|
393
|
-
targetDialect:
|
|
404
|
+
targetDialect: U(),
|
|
394
405
|
allowIncompatible: l,
|
|
395
406
|
targetSnapshot: c,
|
|
396
407
|
force: l,
|
|
397
408
|
onWarn: u,
|
|
398
|
-
onProgress:
|
|
409
|
+
onProgress: R,
|
|
399
410
|
assetsAlreadyRestored: !0,
|
|
400
411
|
...p ? { copyLoader: p } : {}
|
|
401
412
|
}));
|
|
402
|
-
return
|
|
413
|
+
return I.info("import complete (single file)", {
|
|
403
414
|
file: i,
|
|
404
415
|
tables: m.tables.length,
|
|
405
416
|
rows: m.tables.reduce((e, t) => e + t.rowCount, 0)
|
|
@@ -411,23 +422,23 @@ var P = "voltro-backup-stamp.json", le = (e) => ({
|
|
|
411
422
|
});
|
|
412
423
|
}
|
|
413
424
|
}
|
|
414
|
-
let m = await f.runPromise(
|
|
425
|
+
let m = await f.runPromise(k({
|
|
415
426
|
store: s,
|
|
416
427
|
bundleDir: i,
|
|
417
428
|
mode: a,
|
|
418
429
|
onConflict: o,
|
|
419
430
|
atomic: e.includes("--atomic"),
|
|
420
431
|
verify: !e.includes("--no-verify"),
|
|
421
|
-
targetDialect:
|
|
432
|
+
targetDialect: U(),
|
|
422
433
|
allowIncompatible: l,
|
|
423
434
|
targetSnapshot: c,
|
|
424
435
|
force: l,
|
|
425
436
|
onWarn: u,
|
|
426
|
-
onProgress:
|
|
427
|
-
...d ? { assets:
|
|
437
|
+
onProgress: R,
|
|
438
|
+
...d ? { assets: j(d) } : {},
|
|
428
439
|
...p ? { copyLoader: p } : {}
|
|
429
440
|
})).finally(() => p?.close());
|
|
430
|
-
return
|
|
441
|
+
return I.info("import complete", {
|
|
431
442
|
bundleDir: i,
|
|
432
443
|
tables: m.tables.length,
|
|
433
444
|
rows: m.tables.reduce((e, t) => e + t.rowCount, 0),
|
|
@@ -443,98 +454,98 @@ var P = "voltro-backup-stamp.json", le = (e) => ({
|
|
|
443
454
|
...e.password ? { password: e.password } : {},
|
|
444
455
|
...e.database ? { database: e.database } : {}
|
|
445
456
|
};
|
|
446
|
-
},
|
|
447
|
-
let t =
|
|
448
|
-
if (!t) return
|
|
449
|
-
let n =
|
|
457
|
+
}, Te = async (e) => {
|
|
458
|
+
let t = H(e);
|
|
459
|
+
if (!t) return I.error("usage: voltro data backup <outDir> (native pg_dump/mysqldump/… + consistent artifact)"), 1;
|
|
460
|
+
let n = U(), { mkdir: r, writeFile: i } = await import("node:fs/promises"), { join: a } = await import("node:path");
|
|
450
461
|
await r(t, { recursive: !0 });
|
|
451
|
-
let o = a(t,
|
|
452
|
-
await f.runPromise(
|
|
453
|
-
let s =
|
|
462
|
+
let o = a(t, C(n));
|
|
463
|
+
await f.runPromise(A(ne(n, $(), o)));
|
|
464
|
+
let s = ue({
|
|
454
465
|
dialect: n,
|
|
455
|
-
schemaFingerprint: await
|
|
456
|
-
voltroVersion: await
|
|
466
|
+
schemaFingerprint: await L(n),
|
|
467
|
+
voltroVersion: await me(),
|
|
457
468
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
458
469
|
});
|
|
459
|
-
return await i(a(t,
|
|
470
|
+
return await i(a(t, N), `${JSON.stringify(s, null, 2)}\n`, "utf8"), I.info("native backup complete", {
|
|
460
471
|
dialect: n,
|
|
461
472
|
artifact: o,
|
|
462
|
-
stamp:
|
|
473
|
+
stamp: N,
|
|
463
474
|
schemaFingerprint: s.schemaFingerprint ?? "<none>",
|
|
464
475
|
assets: "NOT included — use `voltro data export --assets` for rows + blobs"
|
|
465
476
|
}), 0;
|
|
466
|
-
},
|
|
467
|
-
let n =
|
|
468
|
-
flagUrl:
|
|
477
|
+
}, Ee = async (e, t) => {
|
|
478
|
+
let n = U(), { join: r } = await import("node:path"), { readFile: i } = await import("node:fs/promises"), a = r(e, C(n)), o = fe({
|
|
479
|
+
flagUrl: V(t, "--drill-url"),
|
|
469
480
|
envUrl: process.env.DRILL_DB_URL,
|
|
470
|
-
liveKeys:
|
|
481
|
+
liveKeys: ge()
|
|
471
482
|
});
|
|
472
|
-
if (!o.ok) return
|
|
473
|
-
let s = await i(r(e,
|
|
474
|
-
if (s && s.dialect !== n) return
|
|
475
|
-
|
|
483
|
+
if (!o.ok) return I.error(`restore --drill: ${o.error}`), 1;
|
|
484
|
+
let s = await i(r(e, N), "utf8").then(P, () => null);
|
|
485
|
+
if (s && s.dialect !== n) return I.error(`restore --drill: backup is a ${s.dialect} dump but DB_DIALECT is ${n} — cross-dialect restore is never valid.`), 1;
|
|
486
|
+
I.info("restore drill: restoring into throwaway DB", {
|
|
476
487
|
dialect: n,
|
|
477
|
-
target:
|
|
478
|
-
}), await f.runPromise(
|
|
488
|
+
target: F(o.url)
|
|
489
|
+
}), await f.runPromise(A(D(n, { url: o.url }, a)));
|
|
479
490
|
let c = null, l = 0;
|
|
480
491
|
try {
|
|
481
|
-
let e = await
|
|
492
|
+
let e = await W(n, { url: o.url });
|
|
482
493
|
c = g(e), l = e.tables.length;
|
|
483
494
|
} catch (e) {
|
|
484
|
-
return
|
|
495
|
+
return I.error(`restore --drill: could not introspect the restored DB — ${String(e)}`), 1;
|
|
485
496
|
}
|
|
486
|
-
let u =
|
|
497
|
+
let u = pe({
|
|
487
498
|
stampFingerprint: s?.schemaFingerprint ?? null,
|
|
488
499
|
restoredFingerprint: c,
|
|
489
500
|
restoredTableCount: l
|
|
490
501
|
});
|
|
491
|
-
for (let e of u.lines) u.pass ?
|
|
502
|
+
for (let e of u.lines) u.pass ? I.info(`restore drill: ${e}`) : I.error(`restore drill: ${e}`);
|
|
492
503
|
return +!u.pass;
|
|
493
|
-
},
|
|
494
|
-
let t =
|
|
495
|
-
if (!t) return
|
|
496
|
-
if (e.includes("--drill")) return
|
|
497
|
-
if (!await
|
|
498
|
-
let n =
|
|
499
|
-
stamp: await i(r(t,
|
|
504
|
+
}, De = async (e) => {
|
|
505
|
+
let t = H(e);
|
|
506
|
+
if (!t) return I.error("usage: voltro data restore <backupDir> [--allow-live] [--api-url <url>] [--force] [--drill [--drill-url <url>]] (native pg_restore/mysql/…)"), 1;
|
|
507
|
+
if (e.includes("--drill")) return Ee(t, e);
|
|
508
|
+
if (!await B(e)) return 1;
|
|
509
|
+
let n = U(), { join: r } = await import("node:path"), { readFile: i } = await import("node:fs/promises"), a = r(t, C(n)), o = de({
|
|
510
|
+
stamp: await i(r(t, N), "utf8").then(P, () => null),
|
|
500
511
|
currentDialect: n,
|
|
501
|
-
currentFingerprint: await
|
|
512
|
+
currentFingerprint: await L(n)
|
|
502
513
|
});
|
|
503
|
-
for (let e of o.info)
|
|
504
|
-
if (o.warn &&
|
|
505
|
-
if (!e.includes("--force")) return
|
|
506
|
-
|
|
514
|
+
for (let e of o.info) I.info(`backup stamp: ${e}`);
|
|
515
|
+
if (o.warn && I.warn(o.warn), o.refuse) {
|
|
516
|
+
if (!e.includes("--force")) return I.error(`restore refused: ${o.refuse} (pass --force to override)`), 1;
|
|
517
|
+
I.warn(`restore proceeding despite: ${o.refuse} (--force)`);
|
|
507
518
|
}
|
|
508
|
-
return await f.runPromise(
|
|
519
|
+
return await f.runPromise(A(D(n, $(), a))), I.info("native restore complete", {
|
|
509
520
|
dialect: n,
|
|
510
521
|
artifact: a
|
|
511
522
|
}), 0;
|
|
512
|
-
},
|
|
513
|
-
let t =
|
|
514
|
-
if (!t) return
|
|
515
|
-
let { resolve: n } = await import("node:path"), r = n(process.cwd(), t), i =
|
|
516
|
-
let e =
|
|
517
|
-
return i ?
|
|
523
|
+
}, Oe = async (e) => {
|
|
524
|
+
let t = H(e);
|
|
525
|
+
if (!t) return I.error("usage: voltro data inspect <file.vbundle> [--json] [--passphrase <p>]"), 1;
|
|
526
|
+
let { resolve: n } = await import("node:path"), r = n(process.cwd(), t), i = Y(e), a = () => {
|
|
527
|
+
let e = X(r);
|
|
528
|
+
return i ? w(e, i) : e;
|
|
518
529
|
};
|
|
519
530
|
if (e.includes("--json")) {
|
|
520
|
-
let e = (await
|
|
521
|
-
return e ? (console.log(e.toString("utf8")), 0) : (
|
|
531
|
+
let e = (await E(a(), ["manifest.json"])).get("manifest.json");
|
|
532
|
+
return e ? (console.log(e.toString("utf8")), 0) : (I.error("no manifest.json found in the bundle"), 1);
|
|
522
533
|
}
|
|
523
|
-
let o = (await
|
|
534
|
+
let o = (await E(a(), ["README.md"])).get("README.md");
|
|
524
535
|
if (o) return console.log(o.toString("utf8")), 0;
|
|
525
|
-
let s = (await
|
|
526
|
-
return s ? (console.log(s.toString("utf8")), 0) : (
|
|
527
|
-
},
|
|
528
|
-
let t =
|
|
529
|
-
if (!t || !n) return
|
|
530
|
-
let { resolve: r } = await import("node:path"), i =
|
|
531
|
-
return a && (i =
|
|
536
|
+
let s = (await E(a(), ["manifest.json"])).get("manifest.json");
|
|
537
|
+
return s ? (console.log(s.toString("utf8")), 0) : (I.error("bundle has no README.md or manifest.json"), 1);
|
|
538
|
+
}, ke = async (e) => {
|
|
539
|
+
let t = H(e), n = H(e.filter((e) => e !== t));
|
|
540
|
+
if (!t || !n) return I.error("usage: voltro data unpack <file.vbundle> <dir> [--passphrase <p>]"), 1;
|
|
541
|
+
let { resolve: r } = await import("node:path"), i = X(r(process.cwd(), t)), a = Y(e);
|
|
542
|
+
return a && (i = w(i, a)), await M(i, r(process.cwd(), n)), I.info("unpack complete", {
|
|
532
543
|
file: t,
|
|
533
544
|
dir: n
|
|
534
545
|
}), 0;
|
|
535
|
-
},
|
|
546
|
+
}, Ae = async (e) => {
|
|
536
547
|
let [t, ...n] = e;
|
|
537
|
-
return t === "export" ?
|
|
548
|
+
return t === "export" ? we(n) : t === "import" ? Q(n) : t === "unpack" ? ke(n) : t === "inspect" ? Oe(n) : t === "backup" ? Te(n) : t === "restore" ? De(n) : (I.error("usage: voltro data <export|import|unpack|inspect|backup|restore> … (logical: export/import; native: backup/restore)"), t ? 2 : 1);
|
|
538
549
|
};
|
|
539
550
|
//#endregion
|
|
540
|
-
export {
|
|
551
|
+
export { Ae as runDataCommand };
|