@voltro/cli 0.30.2 → 0.32.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 +278 -0
- package/dist/{apiBuild-BUS1RfPi.js → apiBuild-C4uEbs3s.js} +2 -2
- package/dist/apiBuild-OJEjtwcn.js +2 -0
- package/dist/appGraph-CvQCte0z.js +2 -0
- package/dist/appGraph-gQ_6GkQQ.js +110 -0
- package/dist/bin.js +3 -3
- package/dist/checkCommand-CwMrzAgV.js +2 -0
- package/dist/{checkCommand-D_wdOFhw.js → checkCommand-dm7OHtPt.js} +401 -505
- package/dist/{commands-BgGAUcku.js → commands-C0nEePif.js} +2601 -2498
- package/dist/dbCommand-By__Ev0R.js +2 -0
- package/dist/{dbCommand-CbPRCD1x.js → dbCommand-ifOMafuG.js} +112 -84
- package/dist/{dev-GAOIot9G.js → dev-5ficNnvF.js} +1843 -1832
- package/dist/{dev-tPcOmjPJ.js → dev-rc3fwPSZ.js} +1 -1
- package/dist/index.js +1 -1
- package/dist/{inspectMetrics-BM1vrsga.js → inspectMetrics-BqO4E9G0.js} +1008 -719
- package/dist/{sdkgen-BV4fFucu.js → sdkgen-B_5mHQS2.js} +1 -1
- package/dist/{serveCommand-ClqXCX1y.js → serveCommand-PxMmn96o.js} +454 -454
- package/dist/serveEntry.js +2 -2
- package/dist/{start-CTnNvKlk.js → start-D1-8eKrO.js} +204 -199
- package/dist/startEntry.js +2 -2
- package/package.json +417 -17
- package/templates/AGENTS.md +43 -43
- package/templates/agent-docs/_index.md +43 -43
- package/templates/agent-docs/_manifest.json +84 -42
- package/templates/agent-docs/database/migrations.md +14 -1
- package/templates/agent-docs/internationalization.md +29 -0
- package/templates/agent-docs/plugins/ai-flows.md +148 -0
- package/templates/agent-docs/plugins/analytics-postgres.md +90 -0
- package/templates/agent-docs/plugins/atlassian.md +378 -0
- package/templates/agent-docs/plugins/audit.md +348 -0
- package/templates/agent-docs/plugins/auth-auth0.md +92 -0
- package/templates/agent-docs/plugins/auth-clerk.md +90 -0
- package/templates/agent-docs/plugins/auth-kinde.md +88 -0
- package/templates/agent-docs/plugins/auth-oidc.md +95 -0
- package/templates/agent-docs/plugins/auth-supabase.md +103 -0
- package/templates/agent-docs/plugins/auth-workos.md +105 -0
- package/templates/agent-docs/plugins/auth.md +227 -0
- package/templates/agent-docs/plugins/billing.md +324 -0
- package/templates/agent-docs/plugins/broadcast.md +144 -0
- package/templates/agent-docs/plugins/cdc-out.md +116 -0
- package/templates/agent-docs/plugins/clickhouse.md +91 -0
- package/templates/agent-docs/plugins/datadog.md +105 -0
- package/templates/agent-docs/plugins/deactivation.md +114 -0
- package/templates/agent-docs/plugins/duckdb.md +82 -0
- package/templates/agent-docs/plugins/flags.md +146 -0
- package/templates/agent-docs/plugins/governance.md +143 -0
- package/templates/agent-docs/plugins/licensing.md +74 -0
- package/templates/agent-docs/plugins/logship.md +56 -0
- package/templates/agent-docs/plugins/mail.md +334 -0
- package/templates/agent-docs/plugins/moderation.md +65 -0
- package/templates/agent-docs/plugins/multitenancy.md +99 -0
- package/templates/agent-docs/plugins/notifications.md +252 -0
- package/templates/agent-docs/plugins/openapi.md +94 -0
- package/templates/agent-docs/plugins/postgis.md +140 -0
- package/templates/agent-docs/plugins/posthog.md +91 -0
- package/templates/agent-docs/plugins/presence.md +115 -0
- package/templates/agent-docs/plugins/prometheus.md +124 -0
- package/templates/agent-docs/plugins/ratelimit.md +274 -0
- package/templates/agent-docs/plugins/rbac.md +270 -0
- package/templates/agent-docs/plugins/scim.md +63 -0
- package/templates/agent-docs/plugins/search.md +116 -0
- package/templates/agent-docs/plugins/sentry.md +192 -0
- package/templates/agent-docs/plugins/soft-delete.md +72 -0
- package/templates/agent-docs/plugins/sso-saml.md +132 -0
- package/templates/agent-docs/plugins/storage.md +709 -0
- package/templates/agent-docs/plugins/tinybird.md +92 -0
- package/templates/agent-docs/plugins/versioning.md +226 -0
- package/templates/agent-docs/plugins/webhooks.md +585 -0
- package/templates/agent-docs/security.md +21 -1
- package/templates/agent-docs/whats-new.md +137 -22
- 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 +8 -8
- 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 +9 -9
- 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 +2 -2
- package/dist/apiBuild-DMlxvL8h.js +0 -2
- package/dist/checkCommand-CARZ36Tr.js +0 -2
- package/dist/dbCommand-Ht47LrV-.js +0 -2
|
@@ -10,17 +10,17 @@ import { createLogger as _ } from "@voltro/logger";
|
|
|
10
10
|
import { promises as v, writeSync as y } from "node:fs";
|
|
11
11
|
import { InMemoryDataStore as ee } from "@voltro/runtime";
|
|
12
12
|
import { SqlClient as b } from "@effect/sql";
|
|
13
|
-
import { actorsTable as te, frameworkTables as x, isMigrationDefinition as
|
|
13
|
+
import { actorsTable as te, frameworkTables as x, isMigrationDefinition as S, quoteIdent as ne, registerCoreTables as re } from "@voltro/database";
|
|
14
14
|
import { createHash as ie } from "node:crypto";
|
|
15
|
-
import { DEFAULT_CDC_CHANNEL as ae, applyPlan as
|
|
15
|
+
import { DEFAULT_CDC_CHANNEL as ae, applyPlan as oe, applySchema as C, assessRollingDeployGate as se, declaredSnapshot as ce, destructiveScope as le, detectReactiveTriggerDrift as ue, fingerprintSchema as w, ignoreTablesFromEnv as T, introspectSchema as de, pendingFileMigrationIds as fe, planMigrations as E, reactiveTriggerRepairSql as pe, rollbackFileBasedMigration as me, rollingDeployUnsafeOps as he, runFileBasedMigrations as ge, shortFingerprint as D, squashMigrationPlans as _e, unblockLossy as ve } from "@voltro/database/sql";
|
|
16
16
|
//#region src/cliError.ts
|
|
17
|
-
var
|
|
17
|
+
var O = class extends Error {
|
|
18
18
|
isCliError = !0;
|
|
19
19
|
code;
|
|
20
20
|
constructor(e, t = 1) {
|
|
21
21
|
super(e), this.name = "CliError", this.code = t;
|
|
22
22
|
}
|
|
23
|
-
},
|
|
23
|
+
}, ye = (e) => typeof e == "object" && !!e && e.isCliError === !0, be = (e) => typeof e != "string", xe = (e, t, n, r) => {
|
|
24
24
|
let i = [], a = new Map(t.map((e) => [e.name, e])), o = new Map(n.map((e) => [e.name, e])), s = new Set(e.leaveUnset ?? []);
|
|
25
25
|
r > 0 && i.push({
|
|
26
26
|
kind: "target-not-empty",
|
|
@@ -37,7 +37,7 @@ var k = class extends Error {
|
|
|
37
37
|
});
|
|
38
38
|
continue;
|
|
39
39
|
}
|
|
40
|
-
if (
|
|
40
|
+
if (be(n)) {
|
|
41
41
|
c.push({
|
|
42
42
|
target: t,
|
|
43
43
|
source: n.expr,
|
|
@@ -80,23 +80,23 @@ var k = class extends Error {
|
|
|
80
80
|
remintIds: f,
|
|
81
81
|
fatal: i.some((e) => e.fatal)
|
|
82
82
|
};
|
|
83
|
-
},
|
|
83
|
+
}, Se = (e, t) => [
|
|
84
84
|
`back up '${e.from}' to a restorable dump`,
|
|
85
85
|
`copy rows: INSERT INTO ${e.into} (${t.assignments.map((e) => e.target).join(", ")}) SELECT … FROM ${e.from}`,
|
|
86
86
|
...t.remintIds ? ["record old id → new id in a translation table", `rewrite every reference to '${e.from}', JSON columns included`] : [],
|
|
87
87
|
"verify: row counts match and a sample round-trips",
|
|
88
88
|
`drop '${e.from}' — LAST, and only after the verify`
|
|
89
|
-
],
|
|
89
|
+
], Ce = (e, t, n) => {
|
|
90
90
|
let r = [`adopt · ${e.from} (${n} row(s)) → ${e.into}`, ""];
|
|
91
91
|
for (let e of t.assignments) r.push(` ${e.target.padEnd(24)} ← ${e.raw ? `${e.source} (raw)` : e.source}`);
|
|
92
92
|
t.problems.length > 0 && r.push("");
|
|
93
93
|
for (let e of t.problems) r.push(` ${e.fatal ? "✗" : "⚠"} ${e.detail}`);
|
|
94
94
|
if (r.push(""), t.fatal) return r.push(" REFUSED — fix the problems above. Nothing was written."), r;
|
|
95
95
|
r.push(" would run, in this order:");
|
|
96
|
-
for (let [n, i] of
|
|
96
|
+
for (let [n, i] of Se(e, t).entries()) r.push(` ${n + 1}. ${i}`);
|
|
97
97
|
return r;
|
|
98
|
-
},
|
|
99
|
-
let a =
|
|
98
|
+
}, we = (e) => e === "mysql" || e === "mariadb" ? (e) => `\`${e}\`` : e === "mssql" ? (e) => `[${e}]` : (e) => `"${e}"`, Te = (e) => `${e}__adopt_snapshot`, Ee = (e, t, n, r, i) => {
|
|
99
|
+
let a = we(n), o = Te(e.from), s = t.assignments.map((e) => e.target), c = t.assignments.map((e) => e.raw ? e.source : a(e.source));
|
|
100
100
|
return i !== void 0 && (s.unshift(r), c.unshift(i)), {
|
|
101
101
|
snapshot: n === "mssql" ? `SELECT * INTO ${a(o)} FROM ${a(e.from)}` : `CREATE TABLE ${a(o)} AS SELECT * FROM ${a(e.from)}`,
|
|
102
102
|
copy: `INSERT INTO ${a(e.into)} (${s.map(a).join(", ")}) SELECT ${c.join(", ")} FROM ${a(e.from)}`,
|
|
@@ -106,18 +106,18 @@ var k = class extends Error {
|
|
|
106
106
|
drop: `DROP TABLE ${a(e.from)}`,
|
|
107
107
|
dropSnapshot: `DROP TABLE ${a(o)}`
|
|
108
108
|
};
|
|
109
|
-
},
|
|
109
|
+
}, De = (e) => {
|
|
110
110
|
let t = e[0];
|
|
111
111
|
if (t === void 0) return 0;
|
|
112
112
|
let n = t.n ?? t.N ?? Object.values(t)[0];
|
|
113
113
|
return Number(n ?? 0);
|
|
114
|
-
},
|
|
114
|
+
}, Oe = async (e, t, n, r, i, a, o = {}) => {
|
|
115
115
|
if (t.fatal) throw Error("adopt: the plan was refused — nothing was run");
|
|
116
|
-
let s =
|
|
116
|
+
let s = Ee(e, t, n, r, i), c = Te(e.from), l = De(await a(s.verifySource));
|
|
117
117
|
await a(s.snapshot);
|
|
118
118
|
for (let e of s.translations) await a(e);
|
|
119
119
|
await a(s.copy);
|
|
120
|
-
let u =
|
|
120
|
+
let u = De(await a(s.verifyTarget));
|
|
121
121
|
return u === l ? o.keepSource === !0 ? {
|
|
122
122
|
copied: u,
|
|
123
123
|
sourceRows: l,
|
|
@@ -137,7 +137,7 @@ var k = class extends Error {
|
|
|
137
137
|
snapshotTable: c,
|
|
138
138
|
sourceDropped: !1
|
|
139
139
|
};
|
|
140
|
-
},
|
|
140
|
+
}, k = [
|
|
141
141
|
"token",
|
|
142
142
|
"secret",
|
|
143
143
|
"password",
|
|
@@ -146,10 +146,10 @@ var k = class extends Error {
|
|
|
146
146
|
"credential",
|
|
147
147
|
"privatekey",
|
|
148
148
|
"private_key"
|
|
149
|
-
],
|
|
149
|
+
], ke = [
|
|
150
150
|
{
|
|
151
151
|
table: "_voltro_audit_log",
|
|
152
|
-
column: "
|
|
152
|
+
column: "subject"
|
|
153
153
|
},
|
|
154
154
|
{
|
|
155
155
|
table: "_voltro_audit_log",
|
|
@@ -160,9 +160,25 @@ var k = class extends Error {
|
|
|
160
160
|
column: "scope"
|
|
161
161
|
},
|
|
162
162
|
{
|
|
163
|
-
table: "
|
|
163
|
+
table: "_voltro_audit_log",
|
|
164
|
+
column: "metadata"
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
table: "_voltro_audit_log",
|
|
168
|
+
column: "input"
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
table: "_voltro_audit_log",
|
|
172
|
+
column: "outcome"
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
table: "_voltro_audit_log",
|
|
164
176
|
column: "subjectId"
|
|
165
177
|
},
|
|
178
|
+
{
|
|
179
|
+
table: "_voltro_row_history",
|
|
180
|
+
column: "data"
|
|
181
|
+
},
|
|
166
182
|
{
|
|
167
183
|
table: "_voltro_row_history",
|
|
168
184
|
column: "actor"
|
|
@@ -170,8 +186,12 @@ var k = class extends Error {
|
|
|
170
186
|
{
|
|
171
187
|
table: "_voltro_row_history",
|
|
172
188
|
column: "scope"
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
table: "_voltro_row_history",
|
|
192
|
+
column: "subjectId"
|
|
173
193
|
}
|
|
174
|
-
],
|
|
194
|
+
], Ae = (e, t) => {
|
|
175
195
|
switch (t) {
|
|
176
196
|
case "postgres": return `LOWER(CAST(${e} AS text))`;
|
|
177
197
|
case "mysql":
|
|
@@ -180,7 +200,7 @@ var k = class extends Error {
|
|
|
180
200
|
case "sqlite":
|
|
181
201
|
case "turso": return `LOWER(CAST(${e} AS TEXT))`;
|
|
182
202
|
}
|
|
183
|
-
},
|
|
203
|
+
}, je = (e, t, n = k) => n.map((n) => `${Ae(e, t)} LIKE '%${n}%'`).join("\n OR "), A = async (e, t) => {
|
|
184
204
|
let n = await g.runPromise(e.unsafe(t));
|
|
185
205
|
return Number(Object.values(n[0] ?? { n: 0 })[0] ?? 0);
|
|
186
206
|
}, Me = async (e, t, n, r) => {
|
|
@@ -188,7 +208,7 @@ var k = class extends Error {
|
|
|
188
208
|
for (let a of n) {
|
|
189
209
|
let n = r(a.table), o;
|
|
190
210
|
try {
|
|
191
|
-
o = await
|
|
211
|
+
o = await A(e, `SELECT COUNT(*) AS n FROM ${n}`);
|
|
192
212
|
} catch {
|
|
193
213
|
i.push({
|
|
194
214
|
table: a.table,
|
|
@@ -200,12 +220,20 @@ var k = class extends Error {
|
|
|
200
220
|
continue;
|
|
201
221
|
}
|
|
202
222
|
try {
|
|
203
|
-
let s = await
|
|
223
|
+
let s = await A(e, `SELECT COUNT(*) AS n FROM ${n}\n WHERE ${je(r(a.column), t)}`), c = [];
|
|
224
|
+
if (s > 0) for (let i of k) try {
|
|
225
|
+
let o = await A(e, `SELECT COUNT(*) AS n FROM ${n}\n WHERE ${je(r(a.column), t, [i])}`);
|
|
226
|
+
o > 0 && c.push({
|
|
227
|
+
needle: i,
|
|
228
|
+
rows: o
|
|
229
|
+
});
|
|
230
|
+
} catch {}
|
|
204
231
|
i.push({
|
|
205
232
|
table: a.table,
|
|
206
233
|
column: a.column,
|
|
207
234
|
scanned: o,
|
|
208
|
-
hits: s
|
|
235
|
+
hits: s,
|
|
236
|
+
matchedNeedles: c
|
|
209
237
|
});
|
|
210
238
|
} catch {
|
|
211
239
|
i.push({
|
|
@@ -219,25 +247,25 @@ var k = class extends Error {
|
|
|
219
247
|
}
|
|
220
248
|
return i;
|
|
221
249
|
}, Ne = (e, t) => {
|
|
222
|
-
let n = [`credential scan · dialect ${t}`, ""],
|
|
250
|
+
let n = k.length, r = [`credential scan · dialect ${t}`, ""], i = /* @__PURE__ */ new Set();
|
|
223
251
|
for (let t of e) {
|
|
224
252
|
if (t.unavailable === "column") {
|
|
225
|
-
|
|
253
|
+
r.push(` · ${t.table}.${t.column} — column is not present on this deployment (${t.scanned} row(s) exist but this column was not scanned)`);
|
|
226
254
|
continue;
|
|
227
255
|
}
|
|
228
256
|
if (t.scanned === void 0) {
|
|
229
|
-
|
|
257
|
+
i.has(t.table) || (i.add(t.table), r.push(` · ${t.table} — table not present (nothing scanned)`));
|
|
230
258
|
continue;
|
|
231
259
|
}
|
|
232
260
|
if (t.scanned === 0) {
|
|
233
|
-
|
|
261
|
+
r.push(` · ${t.table} — table is EMPTY (0 rows scanned; this is not a clean bill of health)`);
|
|
234
262
|
continue;
|
|
235
263
|
}
|
|
236
264
|
let e = (t.hits ?? 0) > 0 ? "✗" : "✓";
|
|
237
|
-
|
|
265
|
+
r.push(` ${e} ${t.table}.${t.column} — ${t.hits} of ${t.scanned} row(s) match a credential-shaped key`), (t.matchedNeedles?.length ?? 0) > 0 && r.push(` matched (rows per needle, may overlap): ${t.matchedNeedles.map((e) => `${e.needle} (${e.rows})`).join(", ")}`);
|
|
238
266
|
}
|
|
239
|
-
let
|
|
240
|
-
return
|
|
267
|
+
let a = e.reduce((e, t) => e + (t.hits ?? 0), 0);
|
|
268
|
+
return r.push(""), a > 0 ? r.push(` ${a} row(s) carry something credential-shaped.`, " Purge them AND rotate the credentials — assume anything written to a log", " table has been read. Then stop putting the credential on the Subject:", " `connectionCredentials(...)` keeps it in the framework vault.") : e.every((e) => e.scanned === void 0 || e.scanned === 0 || e.unavailable !== void 0) ? r.push(" NOTHING WAS SCANNED. This run proves nothing about your data.") : r.push(" No credential-shaped keys found in the rows that exist."), r.push("", ` These are NAME heuristics (${n} of them), not proof. A credential in a`, " column whose key is not credential-shaped — `keyValue`, `pat`, `authz` —", " is invisible here. A clean run means \"no credential-SHAPED key found\",", " which is not the same as \"no credential\".", "", " Run this on EVERY environment. A dev database is not a sample of production."), r.join("\n");
|
|
241
269
|
}, Pe = (e) => e.some((e) => (e.hits ?? 0) > 0) ? 1 : e.every((e) => e.unavailable !== void 0 || e.scanned === void 0 || e.scanned === 0) ? 2 : 0, j = /\.migration\.ts$/, M = async (e, t) => {
|
|
242
270
|
let n = [];
|
|
243
271
|
for (let r of e) {
|
|
@@ -248,7 +276,7 @@ var k = class extends Error {
|
|
|
248
276
|
t.warn("migration: failed to import", { file: r }, e);
|
|
249
277
|
continue;
|
|
250
278
|
}
|
|
251
|
-
let i = (e.default &&
|
|
279
|
+
let i = (e.default && S(e.default) ? e.default : void 0) ?? Object.values(e).find(S);
|
|
252
280
|
if (!i) {
|
|
253
281
|
t.warn("migration: no defineMigration export", { file: r });
|
|
254
282
|
continue;
|
|
@@ -268,7 +296,7 @@ var k = class extends Error {
|
|
|
268
296
|
return [...n].sort((e, t) => e.definition.id < t.definition.id ? -1 : 1);
|
|
269
297
|
}, N = (e) => {
|
|
270
298
|
let t = (process.env.DB_DIALECT ?? "postgres").toLowerCase(), n = t === "memory" ? "postgres" : t;
|
|
271
|
-
return g.runPromise(
|
|
299
|
+
return g.runPromise(C(x, n).pipe(g.provide(e)));
|
|
272
300
|
}, P = (e) => g.runPromise(g.gen(function* () {
|
|
273
301
|
let e = yield* (yield* b.SqlClient)`SELECT id, status, hash, "appliedAt" FROM "_voltro_migrations"`.pipe(g.orElseSucceed(() => []));
|
|
274
302
|
return new Map(e.map((e) => [e.id, e]));
|
|
@@ -540,9 +568,9 @@ var k = class extends Error {
|
|
|
540
568
|
return /ERR_OUT_OF_RANGE|out of range/i.test(n) && /pg-protocol|parseDataRow|buffer-reader|BufferReader/i.test(n);
|
|
541
569
|
}, U = "Live-DB introspection got a corrupt / misaligned response from the database. This happens when `voltro db plan` / `apply` / `drift` / `migrate` runs through a connection POOLER (Supabase Supavisor / PgBouncer) on a LARGE schema — the pooler mis-frames a big catalog response. The introspection already batches by table to keep responses small; if a batch still trips it:\n 1. Lower the batch: set `VOLTRO_INTROSPECT_BATCH` to a smaller number of tables (default 20 — try 5 or 1). This keeps `db plan` on the normal pooler, no direct connection needed.\n 2. Or use a DIRECT (non-pooler) connection: set `DB_DIRECT_URL` (or `DB_MIGRATE_URL`) to the direct database URL — the runtime keeps `DB_URL`, so only the migration path is affected. (Supabase: direct = `db.<project-ref>.supabase.co` [IPv6-only on newer projects]; pooler = `aws-0-<region>.pooler.supabase.com`.)", W = () => {
|
|
542
570
|
let e = (process.env.DB_DIALECT ?? "postgres").toLowerCase();
|
|
543
|
-
if (e === "memory") throw new
|
|
571
|
+
if (e === "memory") throw new O("voltro db: subcommands require a real dialect, not DB_DIALECT=memory.");
|
|
544
572
|
return e;
|
|
545
|
-
}, G = (e) =>
|
|
573
|
+
}, G = (e) => ne(e, W()), K = (e) => e === "mysql" || e === "mariadb" ? "table_schema = DATABASE()" : e === "mssql" ? "table_schema = SCHEMA_NAME()" : "table_schema = 'public'", q = async () => (await r(W())).makeSqlLayer(V()), Re = async (e) => {
|
|
546
574
|
let t = B(e), n = e.includes("--dry-run"), r = await M(await z(t, j), R);
|
|
547
575
|
if (r.length === 0) return R.info("no migrations found", { root: t }), 0;
|
|
548
576
|
if (n) {
|
|
@@ -647,19 +675,19 @@ var k = class extends Error {
|
|
|
647
675
|
}
|
|
648
676
|
return [...t.values()];
|
|
649
677
|
}, qe = (e) => {
|
|
650
|
-
let t =
|
|
678
|
+
let t = le(process.env.VOLTRO_DESTRUCTIVE_OK);
|
|
651
679
|
if (t === void 0 || !e.operations.filter((e) => e.blocked).every((e) => e.classification === "lossy")) return {
|
|
652
680
|
plan: e,
|
|
653
681
|
acknowledged: !1
|
|
654
682
|
};
|
|
655
|
-
let n =
|
|
683
|
+
let n = ve(e, t);
|
|
656
684
|
return {
|
|
657
685
|
plan: n,
|
|
658
686
|
acknowledged: !n.operations.some((e) => e.blocked)
|
|
659
687
|
};
|
|
660
688
|
}, J = async (e, t) => g.runPromise(t.pipe(g.provide(e))), Y = async (e) => {
|
|
661
689
|
try {
|
|
662
|
-
return await J(e, b.SqlClient.pipe(g.flatMap(
|
|
690
|
+
return await J(e, b.SqlClient.pipe(g.flatMap(de)));
|
|
663
691
|
} catch (e) {
|
|
664
692
|
let t = String(e?.message ?? e);
|
|
665
693
|
if (H(e) || /connection error/i.test(t)) {
|
|
@@ -751,7 +779,7 @@ var k = class extends Error {
|
|
|
751
779
|
if (i === void 0 || a === void 0) continue;
|
|
752
780
|
let o = 0;
|
|
753
781
|
try {
|
|
754
|
-
let e = await J(t, b.SqlClient.pipe(g.flatMap((e) => e.unsafe(`SELECT COUNT(*) AS n FROM ${
|
|
782
|
+
let e = await J(t, b.SqlClient.pipe(g.flatMap((e) => e.unsafe(`SELECT COUNT(*) AS n FROM ${ne(i, W())}`))));
|
|
755
783
|
o = Number(Object.values(e[0] ?? { n: 0 })[0] ?? 0);
|
|
756
784
|
} catch {
|
|
757
785
|
continue;
|
|
@@ -767,11 +795,11 @@ var k = class extends Error {
|
|
|
767
795
|
if (W() !== "postgres") return;
|
|
768
796
|
let n = ae, r;
|
|
769
797
|
try {
|
|
770
|
-
r = await J(t, b.SqlClient.pipe(g.flatMap((t) =>
|
|
798
|
+
r = await J(t, b.SqlClient.pipe(g.flatMap((t) => ue(t, e, n))));
|
|
771
799
|
} catch {
|
|
772
800
|
return;
|
|
773
801
|
}
|
|
774
|
-
let i =
|
|
802
|
+
let i = pe({
|
|
775
803
|
tables: e,
|
|
776
804
|
dialect: "postgres",
|
|
777
805
|
missing: r.missing,
|
|
@@ -795,17 +823,17 @@ var k = class extends Error {
|
|
|
795
823
|
for (let t of e.operations) console.log(Ye(t));
|
|
796
824
|
console.log(), console.log(` safe: ${t.safe} needs-default: ${t.needsDefault} needs-backfill: ${t.needsBackfill}`), console.log(` rename: ${t.needsRenameAnnotation} lossy: ${t.lossy} blocked: ${t.blocked}`), console.log(` fingerprint: ${e.fromFingerprint.slice(0, 16)} → ${e.toFingerprint.slice(0, 16)}\n`), Ze(e);
|
|
797
825
|
}, Ze = (e) => {
|
|
798
|
-
let t =
|
|
826
|
+
let t = he(e.operations);
|
|
799
827
|
if (t.length !== 0) {
|
|
800
828
|
console.log(` ⚠ ${t.length} operation(s) UNSAFE under a rolling deploy`), console.log(" (old + new instances overlap → old code breaks against the new schema):");
|
|
801
829
|
for (let e of t) console.log(` • ${e.op.op.kind}: ${e.reason}`), console.log(` → ${e.remedy}`);
|
|
802
830
|
console.log(" Deploy with a maintenance window / scale-to-zero, or split into"), console.log(" expand → deploy → contract. See docs: deployment/production-hardening.\n");
|
|
803
831
|
}
|
|
804
832
|
}, Qe = (e, t) => {
|
|
805
|
-
let n =
|
|
833
|
+
let n = se({
|
|
806
834
|
enabled: process.env.VOLTRO_ROLLING_DEPLOY === "1",
|
|
807
835
|
forced: t.includes("--force"),
|
|
808
|
-
unsafeCount:
|
|
836
|
+
unsafeCount: he(e.operations).length
|
|
809
837
|
});
|
|
810
838
|
return n.refuse ? (R.error(`db apply: ${n.message}`), !0) : (n.warnForced && R.warn(`db apply: ${n.message}`), !1);
|
|
811
839
|
}, $e = (e) => {
|
|
@@ -838,11 +866,11 @@ var k = class extends Error {
|
|
|
838
866
|
if (!i.ok) return R.error(`db plan --against: remote returned ${i.status}`, { url: e }), 1;
|
|
839
867
|
let a = (await i.json()).drift?.liveSnapshot;
|
|
840
868
|
if (!a) return R.error("db plan --against: remote inspect payload missing drift.liveSnapshot", { url: e }), 1;
|
|
841
|
-
let s =
|
|
869
|
+
let s = E({
|
|
842
870
|
declared: r,
|
|
843
871
|
live: a,
|
|
844
872
|
dialect: W(),
|
|
845
|
-
...
|
|
873
|
+
...T(),
|
|
846
874
|
...t === void 0 ? {} : { onlineAfter: t }
|
|
847
875
|
});
|
|
848
876
|
return console.log(`\n[--against ${e}] — diff vs remote live schema:\n`), Z(s), s.summary.blocked > 0 ? 2 : 0;
|
|
@@ -850,11 +878,11 @@ var k = class extends Error {
|
|
|
850
878
|
return R.error(`db plan --against: ${e.message}`), 1;
|
|
851
879
|
}
|
|
852
880
|
}
|
|
853
|
-
let a =
|
|
881
|
+
let a = E({
|
|
854
882
|
declared: r,
|
|
855
883
|
live: await Y(await q()),
|
|
856
884
|
dialect: W(),
|
|
857
|
-
...
|
|
885
|
+
...T(),
|
|
858
886
|
...t === void 0 ? {} : { onlineAfter: t }
|
|
859
887
|
});
|
|
860
888
|
return e.includes("--json") ? (y(1, `${JSON.stringify(a, null, 2)}\n`), a.summary.blocked > 0 ? 2 : 0) : (Z(a), a.summary.blocked > 0 ? 2 : 0);
|
|
@@ -870,14 +898,14 @@ var k = class extends Error {
|
|
|
870
898
|
let i = await Q(n);
|
|
871
899
|
if (i === void 0) return R.warn("db apply --plan: no schema files found", { root: n }), 1;
|
|
872
900
|
let a = await q();
|
|
873
|
-
await J(a,
|
|
874
|
-
let o = await J(a, b.SqlClient.pipe(g.flatMap((e) =>
|
|
901
|
+
await J(a, C(x, W()));
|
|
902
|
+
let o = await J(a, b.SqlClient.pipe(g.flatMap((e) => fe(e, n)))).catch(() => []);
|
|
875
903
|
if (o.length > 0) return R.error(`db apply --plan: refusing — ${o.length} pending file-based migration(s).`), console.error(` ${o.join("\n ")}`), console.error(""), console.error(" These perform the changes a state diff cannot infer, so they change the shape"), console.error(" this plan was computed against. Apply them and regenerate the plan:"), console.error(""), console.error(" voltro db files ."), console.error(" voltro db plan --json > plan.json"), console.error(" voltro db apply --plan plan.json"), 1;
|
|
876
|
-
let s =
|
|
904
|
+
let s = E({
|
|
877
905
|
declared: i,
|
|
878
906
|
live: await Y(a),
|
|
879
907
|
dialect: W(),
|
|
880
|
-
...
|
|
908
|
+
...T()
|
|
881
909
|
});
|
|
882
910
|
if (s.fromFingerprint !== r.fromFingerprint) return R.error("db apply --plan: refusing — the live schema has drifted since this plan was generated."), console.error(` plan.from=${r.fromFingerprint.slice(0, 16)} live=${s.fromFingerprint.slice(0, 16)}`), console.error(" Regenerate against the current live schema: `voltro db plan --json > plan.json`"), 2;
|
|
883
911
|
if (s.toFingerprint !== r.toFingerprint) return R.error("db apply --plan: refusing — the declared schema differs from what this plan targets."), console.error(` plan.to=${r.toFingerprint.slice(0, 16)} declared=${s.toFingerprint.slice(0, 16)}`), console.error(" The schema files changed since the plan was generated. Regenerate the plan."), 2;
|
|
@@ -886,17 +914,17 @@ var k = class extends Error {
|
|
|
886
914
|
if (c.acknowledged && R.warn("db apply --plan: proceeding with acknowledged lossy operation(s) (VOLTRO_DESTRUCTIVE_OK)"), Qe(u, t)) return 2;
|
|
887
915
|
if (u.operations.length === 0) return R.info("db apply --plan: schema is up to date — no DDL to apply (change triggers are reconciled separately below)"), await X(i, a), 0;
|
|
888
916
|
Z(u);
|
|
889
|
-
let d = (process.env.NODE_ENV ?? "dev").toLowerCase(), f = l(t, "--note"), p = await J(a, b.SqlClient.pipe(g.flatMap((e) =>
|
|
917
|
+
let d = (process.env.NODE_ENV ?? "dev").toLowerCase(), f = l(t, "--note"), p = await J(a, b.SqlClient.pipe(g.flatMap((e) => oe(e, u, {
|
|
890
918
|
declared: i,
|
|
891
919
|
appliedBy: process.env.USER ? `cli:${process.env.USER}` : "cli:plan",
|
|
892
920
|
environment: d === "production" ? "prod" : d === "staging" ? "staging" : "dev",
|
|
893
921
|
source: "file",
|
|
894
922
|
...f ? { notes: f } : {},
|
|
895
|
-
replan: () => g.promise(() => Y(a)).pipe(g.map((e) =>
|
|
923
|
+
replan: () => g.promise(() => Y(a)).pipe(g.map((e) => E({
|
|
896
924
|
declared: i,
|
|
897
925
|
live: e,
|
|
898
926
|
dialect: W(),
|
|
899
|
-
...
|
|
927
|
+
...T()
|
|
900
928
|
})))
|
|
901
929
|
}))));
|
|
902
930
|
return R.info(`db apply --plan: applied ${p.appliedOps} op(s) in ${p.durationMs}ms`, {
|
|
@@ -911,12 +939,12 @@ var k = class extends Error {
|
|
|
911
939
|
if (i === void 0) return R.warn("db apply: no schema files found", { root: t }), 1;
|
|
912
940
|
let a = await q(), o = await dt(t, a);
|
|
913
941
|
if ("failed" in o) return R.error("db apply: a file-based migration FAILED — the schema diff was NOT run"), console.error(o.failed), console.error("Fix the migration and re-run. `voltro db files` runs them alone."), 1;
|
|
914
|
-
await J(a,
|
|
915
|
-
let s =
|
|
942
|
+
await J(a, C(x, W()));
|
|
943
|
+
let s = E({
|
|
916
944
|
declared: i,
|
|
917
945
|
live: await Y(a),
|
|
918
946
|
dialect: W(),
|
|
919
|
-
...
|
|
947
|
+
...T(),
|
|
920
948
|
...n === void 0 ? {} : { onlineAfter: n }
|
|
921
949
|
});
|
|
922
950
|
Z(s), await Xe(s, a);
|
|
@@ -924,17 +952,17 @@ var k = class extends Error {
|
|
|
924
952
|
if (u.summary.blocked > 0 && !c.acknowledged) return R.error(`db apply: refusing — ${u.summary.blocked} blocked operation(s). See the fix hints above.`), process.env.VOLTRO_DESTRUCTIVE_OK !== void 0 && (R.error(" VOLTRO_DESTRUCTIVE_OK is set but did not cover this plan — it only relaxes"), R.error(" `lossy` operations, and only the tables it names. Anything else stays refused.")), 2;
|
|
925
953
|
if (c.acknowledged && R.warn(`db apply: proceeding with ${s.summary.blocked} acknowledged lossy operation(s) (VOLTRO_DESTRUCTIVE_OK)`), Qe(u, e)) return 2;
|
|
926
954
|
if (u.operations.length === 0) return R.info("db apply: schema is up to date — no DDL to apply (change triggers are reconciled separately below)"), await st(a), l(e, "--note") !== void 0 && (R.warn("db apply: --note was ignored — an empty plan writes no history row to attach it to."), console.error("To record that the CURRENT live schema is the accepted baseline, use `voltro db drift --accept`.")), await X(i, a), 0;
|
|
927
|
-
let d = l(e, "--note"), f = await J(a, b.SqlClient.pipe(g.flatMap((e) =>
|
|
955
|
+
let d = l(e, "--note"), f = await J(a, b.SqlClient.pipe(g.flatMap((e) => oe(e, u, {
|
|
928
956
|
declared: i,
|
|
929
957
|
appliedBy: process.env.USER ? `cli:${process.env.USER}` : "cli:user",
|
|
930
958
|
environment: (process.env.NODE_ENV ?? "dev").toLowerCase() === "staging" ? "staging" : "dev",
|
|
931
959
|
source: "auto-diff",
|
|
932
960
|
...d ? { notes: d } : {},
|
|
933
|
-
replan: () => g.promise(() => Y(a)).pipe(g.map((e) =>
|
|
961
|
+
replan: () => g.promise(() => Y(a)).pipe(g.map((e) => E({
|
|
934
962
|
declared: i,
|
|
935
963
|
live: e,
|
|
936
964
|
dialect: W(),
|
|
937
|
-
...
|
|
965
|
+
...T(),
|
|
938
966
|
...n === void 0 ? {} : { onlineAfter: n }
|
|
939
967
|
})))
|
|
940
968
|
}))));
|
|
@@ -958,7 +986,7 @@ var k = class extends Error {
|
|
|
958
986
|
try {
|
|
959
987
|
t = JSON.parse(ct(e.operations)).length;
|
|
960
988
|
} catch {}
|
|
961
|
-
console.log(` ${e.id} fp=${
|
|
989
|
+
console.log(` ${e.id} fp=${D(e.fingerprint)} env=${e.environment} src=${e.source} ${t} op(s) ${e.durationMs}ms ${$(e.appliedAt)} by=${e.appliedBy}`), e.notes && console.log(` [2mnote: ${e.notes}[0m`);
|
|
962
990
|
}
|
|
963
991
|
return console.log(), 0;
|
|
964
992
|
}, it = async (e) => {
|
|
@@ -1044,22 +1072,22 @@ var k = class extends Error {
|
|
|
1044
1072
|
if (Number.isNaN(new Date(n).getTime())) return console.error(`voltro db squash: --before '${n}' is not a valid ISO date`), 2;
|
|
1045
1073
|
let r = l(e, "--note"), i = B(e), a = await Q(i);
|
|
1046
1074
|
if (a === void 0) return R.warn("db squash: no schema files found", { root: i }), 1;
|
|
1047
|
-
let o =
|
|
1075
|
+
let o = w(ce(a)), s = await q();
|
|
1048
1076
|
try {
|
|
1049
|
-
let e = await J(s,
|
|
1077
|
+
let e = await J(s, _e({
|
|
1050
1078
|
before: n,
|
|
1051
1079
|
fingerprint: o,
|
|
1052
1080
|
appliedBy: process.env.USER ?? "cli",
|
|
1053
1081
|
environment: process.env.NODE_ENV === "production" ? "prod" : "dev",
|
|
1054
1082
|
...r === void 0 ? {} : { note: r }
|
|
1055
1083
|
}));
|
|
1056
|
-
return console.log(`\n✓ squashed ${e.squashedCount} migration plan(s)\n snapshot id: ${e.snapshotId}\n fingerprint: ${
|
|
1084
|
+
return console.log(`\n✓ squashed ${e.squashedCount} migration plan(s)\n snapshot id: ${e.snapshotId}\n fingerprint: ${D(e.snapshotFingerprint)}\n`), 0;
|
|
1057
1085
|
} catch (e) {
|
|
1058
1086
|
return console.error(`squash refused: ${e.message}`), 1;
|
|
1059
1087
|
}
|
|
1060
1088
|
}, st = async (e) => {
|
|
1061
1089
|
try {
|
|
1062
|
-
let t =
|
|
1090
|
+
let t = w(await Y(e));
|
|
1063
1091
|
await J(e, b.SqlClient.pipe(g.flatMap((e) => e`
|
|
1064
1092
|
UPDATE ${e("_voltro_migration_plans")}
|
|
1065
1093
|
SET ${e("liveFingerprint")} = ${t}
|
|
@@ -1086,19 +1114,19 @@ var k = class extends Error {
|
|
|
1086
1114
|
SELECT * FROM ${e("_voltro_migration_plans")}
|
|
1087
1115
|
ORDER BY ${e("appliedAt")} DESC
|
|
1088
1116
|
LIMIT 1
|
|
1089
|
-
`))), i = await Y(n), a =
|
|
1090
|
-
if (r.length === 0) return R.info("db drift: no _voltro_migration_plans rows yet"), console.log(`live user-schema fingerprint: ${
|
|
1117
|
+
`))), i = await Y(n), a = w(i);
|
|
1118
|
+
if (r.length === 0) return R.info("db drift: no _voltro_migration_plans rows yet"), console.log(`live user-schema fingerprint: ${D(a)}`), console.log("No baseline to compare against. Run `voltro db apply` to lock in the current state."), 0;
|
|
1091
1119
|
let o = r[0];
|
|
1092
|
-
if (o.liveFingerprint === null || o.liveFingerprint === void 0) return R.warn("db drift: no drift baseline recorded yet — cannot compare"), console.log(), console.log(` last applied: ${o.id} at ${$(o.appliedAt)}`), console.log(` live now: ${
|
|
1093
|
-
if (o.liveFingerprint === a) return R.info(`db drift: live matches last applied (${
|
|
1120
|
+
if (o.liveFingerprint === null || o.liveFingerprint === void 0) return R.warn("db drift: no drift baseline recorded yet — cannot compare"), console.log(), console.log(` last applied: ${o.id} at ${$(o.appliedAt)}`), console.log(` live now: ${D(a)}`), console.log(), console.log("That row was written before the framework recorded a live-schema baseline,"), console.log("and the value it does carry is the DECLARED snapshot's hash — not comparable"), console.log("with a live one. Run `voltro db apply` once to establish the baseline (a no-op"), console.log("apply backfills it too); use `voltro db plan` meanwhile, which compares declared"), console.log("against live directly."), console.log(), console.log("Exit code 3 — NOT 0. \"Did not compare\" is not \"clean\", and a gate on the exit"), console.log("code has to be able to tell them apart."), 3;
|
|
1121
|
+
if (o.liveFingerprint === a) return R.info(`db drift: live matches last applied (${D(a)})`), 0;
|
|
1094
1122
|
let s = await (async () => {
|
|
1095
1123
|
try {
|
|
1096
1124
|
let t = await Q(B(e));
|
|
1097
|
-
return t === void 0 ? void 0 :
|
|
1125
|
+
return t === void 0 ? void 0 : E({
|
|
1098
1126
|
declared: t,
|
|
1099
1127
|
live: i,
|
|
1100
1128
|
dialect: W(),
|
|
1101
|
-
...
|
|
1129
|
+
...T()
|
|
1102
1130
|
}).operations;
|
|
1103
1131
|
} catch {
|
|
1104
1132
|
return;
|
|
@@ -1121,13 +1149,13 @@ var k = class extends Error {
|
|
|
1121
1149
|
ORDER BY ${e("appliedAt")} DESC LIMIT 1
|
|
1122
1150
|
) AS ${e("newest")}
|
|
1123
1151
|
)
|
|
1124
|
-
`))), R.info(`db drift: accepted the live schema as the baseline (${
|
|
1152
|
+
`))), R.info(`db drift: accepted the live schema as the baseline (${D(a)})`), console.log(), console.log("`voltro db plan` reports 0 operations against this schema, so the live state already"), console.log("matches your declaration — only the ledger did not know. It does now."), console.log(), console.log("No history entry was invented: the latest row's baseline was updated in place,"), console.log("because no migration ran."), 0;
|
|
1125
1153
|
}
|
|
1126
|
-
return R.error("db drift: live schema DIVERGED from last applied state"), console.log(), console.log(` baseline: ${
|
|
1154
|
+
return R.error("db drift: live schema DIVERGED from last applied state"), console.log(), console.log(` baseline: ${D(o.liveFingerprint)} at ${$(o.appliedAt)} (${o.id})`), console.log(` live now: ${D(a)}`), console.log(), console.log("Something changed the live schema after the last apply. This command can see"), console.log("THAT it changed, not what or who — the fingerprints are hashes, not a diff."), console.log(), s === void 0 ? (console.log("No schema files found here, so the declared side could not be compared."), console.log("Run `voltro db plan` from your project root for the actual difference."), 4) : s.length === 0 ? (console.log("Your DECLARED schema is already satisfied — `voltro db plan` reports 0 operations"), console.log("against this database. So the live schema is not wrong, only unrecorded: something"), console.log("applied a change without going through the planner (a hand-run ALTER, a DBA"), console.log("window, a restored dump), or it touched a table your code does not declare."), console.log(), console.log("If that was deliberate and the schema is right, record it:"), console.log(), console.log(" voltro db drift --accept"), console.log(), console.log("It updates the latest ledger row's baseline to the live schema and invents no"), console.log("history entry. Drift then measures from here."), 4) : (console.log(`\`voltro db plan\` reports ${s.length} operation(s) still pending against your`), console.log("declared schema, so this is not merely an unrecorded change — run it for the diff,"), console.log("then `voltro db apply`, which writes a fresh baseline of its own."), 4);
|
|
1127
1155
|
}, dt = async (e, t) => {
|
|
1128
1156
|
let n = (process.env.NODE_ENV ?? "").toLowerCase() === "production" ? "prod" : (process.env.NODE_ENV ?? "").toLowerCase() === "staging" ? "staging" : "dev";
|
|
1129
1157
|
try {
|
|
1130
|
-
let r = await J(t, b.SqlClient.pipe(g.flatMap((t) =>
|
|
1158
|
+
let r = await J(t, b.SqlClient.pipe(g.flatMap((t) => ge(t, {
|
|
1131
1159
|
projectRoot: e,
|
|
1132
1160
|
env: n,
|
|
1133
1161
|
appliedBy: process.env.USER ? `cli:${process.env.USER}` : "cli:user"
|
|
@@ -1138,8 +1166,8 @@ var k = class extends Error {
|
|
|
1138
1166
|
}
|
|
1139
1167
|
}, ft = async (e) => {
|
|
1140
1168
|
let t = B(e), n = await q(), r = (process.env.NODE_ENV ?? "").toLowerCase() === "production" ? "prod" : (process.env.NODE_ENV ?? "").toLowerCase() === "staging" ? "staging" : "dev";
|
|
1141
|
-
await J(n,
|
|
1142
|
-
let i = await J(n, b.SqlClient.pipe(g.flatMap((e) =>
|
|
1169
|
+
await J(n, C(x, W()));
|
|
1170
|
+
let i = await J(n, b.SqlClient.pipe(g.flatMap((e) => ge(e, {
|
|
1143
1171
|
projectRoot: t,
|
|
1144
1172
|
env: r,
|
|
1145
1173
|
appliedBy: process.env.USER ? `cli:${process.env.USER}` : "cli:user"
|
|
@@ -1152,7 +1180,7 @@ var k = class extends Error {
|
|
|
1152
1180
|
let t = B(e), n = e.find((e) => !e.startsWith("--"));
|
|
1153
1181
|
if (!n) return R.error("voltro db rollback-file <migration-id>"), 2;
|
|
1154
1182
|
if ((process.env.NODE_ENV ?? "").toLowerCase() === "production") return R.error("voltro db rollback-file: refusing on prod — schema rollback runs as an explicit deploy step."), 3;
|
|
1155
|
-
let r = await J(await q(), b.SqlClient.pipe(g.flatMap((e) =>
|
|
1183
|
+
let r = await J(await q(), b.SqlClient.pipe(g.flatMap((e) => me(e, {
|
|
1156
1184
|
projectRoot: t,
|
|
1157
1185
|
id: n
|
|
1158
1186
|
}))));
|
|
@@ -1230,18 +1258,18 @@ export default defineMigration({
|
|
|
1230
1258
|
into: r,
|
|
1231
1259
|
map: o.map,
|
|
1232
1260
|
...o.leaveUnset ? { leaveUnset: o.leaveUnset } : {}
|
|
1233
|
-
}, c = W(), l = await q(), u = await J(l, b.SqlClient.pipe(g.flatMap(
|
|
1261
|
+
}, c = W(), l = await q(), u = await J(l, b.SqlClient.pipe(g.flatMap(de))), d = (e) => u.tables.find((t) => t.name === e)?.columns.map((e) => ({
|
|
1234
1262
|
name: e.name,
|
|
1235
1263
|
nullable: e.nullable,
|
|
1236
1264
|
hasDefault: e.defaultValue !== void 0 && e.defaultValue !== null
|
|
1237
1265
|
})), f = d(n), p = d(r);
|
|
1238
1266
|
if (f === void 0) return console.error(`voltro db adopt: '${n}' does not exist in the database`), 1;
|
|
1239
1267
|
if (p === void 0) return console.error(`voltro db adopt: '${r}' does not exist in the database — boot once so the plugin's table is created`), 1;
|
|
1240
|
-
let h = async (e) => await J(l, b.SqlClient.pipe(g.flatMap((t) => t.unsafe(e)))), _ = async (e) => Number(Object.values((await h(`SELECT COUNT(*) AS n FROM "${e}"`))[0] ?? { n: 0 })[0] ?? 0), v =
|
|
1241
|
-
for (let e of
|
|
1268
|
+
let h = async (e) => await J(l, b.SqlClient.pipe(g.flatMap((t) => t.unsafe(e)))), _ = async (e) => Number(Object.values((await h(`SELECT COUNT(*) AS n FROM "${e}"`))[0] ?? { n: 0 })[0] ?? 0), v = xe(s, f, p, await _(r));
|
|
1269
|
+
for (let e of Ce(s, v, await _(n))) console.log(e);
|
|
1242
1270
|
if (v.fatal) return 1;
|
|
1243
1271
|
if (!e.includes("--apply")) return console.log(""), console.log(" (dry run — nothing written. Re-run with --apply.)"), 0;
|
|
1244
|
-
let y = await
|
|
1272
|
+
let y = await Oe(s, v, c, "id", void 0, h, { keepSource: e.includes("--keep-source") });
|
|
1245
1273
|
return console.log(""), console.log(` copied ${y.copied}/${y.sourceRows} row(s)`), console.log(` snapshot: ${y.snapshotTable} — restore from here, then drop it yourself`), y.verified ? (console.log(y.sourceDropped ? ` dropped ${n}` : ` ${n} left in place (--keep-source)`), 0) : (console.error(" ✗ counts DIFFER — the source was NOT dropped. Compare the two tables before doing anything else."), 1);
|
|
1246
1274
|
},
|
|
1247
1275
|
"scan-credentials": async (e) => {
|
|
@@ -1249,14 +1277,14 @@ export default defineMigration({
|
|
|
1249
1277
|
for (let t = 0; t < e.length; t += 1) {
|
|
1250
1278
|
if (e[t] !== "--table") continue;
|
|
1251
1279
|
let r = e[t + 1];
|
|
1252
|
-
if (r === void 0) throw new
|
|
1280
|
+
if (r === void 0) throw new O("voltro db scan-credentials: --table needs a value");
|
|
1253
1281
|
let [i, a = "subject"] = r.split(":");
|
|
1254
1282
|
n.push({
|
|
1255
1283
|
table: i,
|
|
1256
1284
|
column: a
|
|
1257
1285
|
});
|
|
1258
1286
|
}
|
|
1259
|
-
let r = [...
|
|
1287
|
+
let r = [...ke, ...n], i = await J(await q(), b.SqlClient.pipe(g.flatMap((e) => g.promise(() => Me(e, t, r, G)))));
|
|
1260
1288
|
return console.log(Ne(i, t)), Pe(i);
|
|
1261
1289
|
}
|
|
1262
1290
|
}, vt = async (e) => {
|
|
@@ -1280,4 +1308,4 @@ export default defineMigration({
|
|
|
1280
1308
|
}
|
|
1281
1309
|
};
|
|
1282
1310
|
//#endregion
|
|
1283
|
-
export { Ge as a,
|
|
1311
|
+
export { Ge as a, O as c, lt as i, ye as l, V as n, H as o, We as r, vt as s, U as t };
|