@rebasepro/server-postgres 0.22.0 → 0.23.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/dist/{BranchService-CucnFcSE.js → BranchService-DGPL6G_C.js} +2 -2
- package/dist/{BranchService-CucnFcSE.js.map → BranchService-DGPL6G_C.js.map} +1 -1
- package/dist/PostgresBackendDriver.d.ts +41 -1
- package/dist/auth/services.d.ts +27 -8
- package/dist/backup/backup-cli.d.ts +22 -0
- package/dist/{backup-cli-DqBakiMO.js → backup-cli-24v4OlSp.js} +17 -14
- package/dist/backup-cli-24v4OlSp.js.map +1 -0
- package/dist/{backup-service-CaMOS76G.js → backup-service-HQ9GC4tN.js} +2 -2
- package/dist/{backup-service-CaMOS76G.js.map → backup-service-HQ9GC4tN.js.map} +1 -1
- package/dist/{cli-errors-Dka89exj.js → cli-errors-B8qHg02P.js} +6 -1
- package/dist/cli-errors-B8qHg02P.js.map +1 -0
- package/dist/cli-flags-BglvpjHv.js +138 -0
- package/dist/cli-flags-BglvpjHv.js.map +1 -0
- package/dist/cli-flags.d.ts +28 -0
- package/dist/cli-helpers.d.ts +6 -0
- package/dist/cli-scratch-database.d.ts +34 -0
- package/dist/cli.js +97 -261
- package/dist/cli.js.map +1 -1
- package/dist/{column-plan-helpers-CpILzHJS.js → column-plan-helpers-DF-8dTVa.js} +16 -20
- package/dist/column-plan-helpers-DF-8dTVa.js.map +1 -0
- package/dist/{doctor-CU9IogdL.js → doctor-Cb2thZ8s.js} +8 -7
- package/dist/doctor-Cb2thZ8s.js.map +1 -0
- package/dist/{ensure-collection-policies-Dzd-2S81.js → ensure-collection-policies-RHUcEp4v.js} +5 -5
- package/dist/{ensure-collection-policies-Dzd-2S81.js.map → ensure-collection-policies-RHUcEp4v.js.map} +1 -1
- package/dist/{ensure-collection-tables-CpAgy51F.js → ensure-collection-tables-BEEjn5cn.js} +53 -22
- package/dist/ensure-collection-tables-BEEjn5cn.js.map +1 -0
- package/dist/{ensure-tables-Cr5B4UmH.js → ensure-tables-Dhn9KM3B.js} +2 -2
- package/dist/{ensure-tables-Cr5B4UmH.js.map → ensure-tables-Dhn9KM3B.js.map} +1 -1
- package/dist/{generate-drizzle-schema-logic-BcMl7VSy.js → generate-drizzle-schema-logic-BfzK7UQd.js} +2 -2
- package/dist/{generate-drizzle-schema-logic-BcMl7VSy.js.map → generate-drizzle-schema-logic-BfzK7UQd.js.map} +1 -1
- package/dist/{generate-drizzle-schema-B537GIvz.js → generate-drizzle-schema-yzY_BLhr.js} +2 -2
- package/dist/{generate-drizzle-schema-B537GIvz.js.map → generate-drizzle-schema-yzY_BLhr.js.map} +1 -1
- package/dist/{generate-postgres-ddl-logic-D7imhYV8.js → generate-postgres-ddl-logic-Bt2d2mRH.js} +2 -2
- package/dist/{generate-postgres-ddl-logic-D7imhYV8.js.map → generate-postgres-ddl-logic-Bt2d2mRH.js.map} +1 -1
- package/dist/index.es.js +1508 -355
- package/dist/index.es.js.map +1 -1
- package/dist/{introspect-db-logic-C6LQdTxj.js → introspect-db-logic-WMuAfxvw.js} +323 -4
- package/dist/introspect-db-logic-WMuAfxvw.js.map +1 -0
- package/dist/{plan-schema-CboAIwLN.js → plan-schema-C0fxM8dY.js} +158 -31
- package/dist/plan-schema-C0fxM8dY.js.map +1 -0
- package/dist/{policy-drift-xJfy9xG7.js → policy-drift-DljYdrpW.js} +2 -2
- package/dist/{policy-drift-xJfy9xG7.js.map → policy-drift-DljYdrpW.js.map} +1 -1
- package/dist/{rls-bootstrap-sql-H3rCFi3F.js → rls-bootstrap-sql-B8EclDyM.js} +320 -17
- package/dist/rls-bootstrap-sql-B8EclDyM.js.map +1 -0
- package/dist/schema/atlas-argv.d.ts +15 -0
- package/dist/schema/column-plan-helpers.d.ts +23 -4
- package/dist/schema/destructive-sql.d.ts +52 -1
- package/dist/schema/doctor-cli.js +3 -3
- package/dist/schema/generate-drizzle-schema.js +1 -1
- package/dist/schema/generate-postgres-ddl.js +1 -1
- package/dist/schema/introspect-db.js +1 -312
- package/dist/schema/introspect-db.js.map +1 -1
- package/dist/schema/plan/diff-plan.d.ts +3 -2
- package/dist/schema/plan/plan-schema.d.ts +10 -3
- package/dist/schema/plan/types.d.ts +6 -1
- package/dist/services/FetchService.d.ts +97 -28
- package/dist/services/PersistService.d.ts +41 -5
- package/dist/services/RelationService.d.ts +11 -0
- package/dist/services/RelationWriteService.d.ts +6 -0
- package/dist/services/cdc/CdcListener.d.ts +6 -1
- package/dist/services/collection-helpers.d.ts +11 -0
- package/dist/services/dataService.d.ts +3 -20
- package/dist/services/field-op-sql.d.ts +71 -0
- package/dist/services/junction-writes.d.ts +19 -3
- package/dist/services/pg-notify-listener.d.ts +7 -0
- package/dist/services/read-field-access.d.ts +19 -0
- package/dist/services/realtimeService.d.ts +77 -3
- package/dist/services/row-pipeline.d.ts +5 -0
- package/dist/services/soft-delete.d.ts +0 -2
- package/dist/services/write-transaction-scope.d.ts +39 -0
- package/dist/utils/drizzle-conditions.d.ts +7 -2
- package/dist/websocket.d.ts +10 -3
- package/package.json +9 -9
- package/dist/backup-cli-DqBakiMO.js.map +0 -1
- package/dist/cli-errors-Dka89exj.js.map +0 -1
- package/dist/column-plan-helpers-CpILzHJS.js.map +0 -1
- package/dist/doctor-CU9IogdL.js.map +0 -1
- package/dist/ensure-collection-tables-CpAgy51F.js.map +0 -1
- package/dist/introspect-db-logic-C6LQdTxj.js.map +0 -1
- package/dist/plan-schema-CboAIwLN.js.map +0 -1
- package/dist/rls-bootstrap-sql-H3rCFi3F.js.map +0 -1
|
@@ -4,7 +4,7 @@ import { a as __toESM, i as __require, n as __commonJSMin, r as __exportAll, t a
|
|
|
4
4
|
import { o as isRebaseIndexName } from "./collection-index-DdnsxiJ_.js";
|
|
5
5
|
import { r as outWarn, t as out } from "./cli-output-CNdMql-L.js";
|
|
6
6
|
import { t as chalk } from "./source-Br7L7GOI.js";
|
|
7
|
-
import { LEGACY_RLS_SCHEMA, REBASE_SCHEMA
|
|
7
|
+
import { LEGACY_RLS_SCHEMA, REBASE_SCHEMA } from "@rebasepro/types";
|
|
8
8
|
import { sqlRows } from "@rebasepro/common";
|
|
9
9
|
import fs from "fs";
|
|
10
10
|
import path from "path";
|
|
@@ -6252,8 +6252,303 @@ createExeca(mapNode);
|
|
|
6252
6252
|
createExeca(mapScriptAsync, {}, deepScriptOptions, setScriptSync);
|
|
6253
6253
|
var { sendMessage, getOneMessage, getEachMessage, getCancelSignal } = getIpcExport();
|
|
6254
6254
|
//#endregion
|
|
6255
|
-
//#region src/
|
|
6255
|
+
//#region src/schema/destructive-sql.ts
|
|
6256
6256
|
var import___vite_browser_external = /* @__PURE__ */ __toESM(require___vite_browser_external(), 1);
|
|
6257
|
+
/**
|
|
6258
|
+
* Pure helpers that classify an Atlas declarative-apply plan as destructive
|
|
6259
|
+
* or not, and decide what `rebase db push` should do about it.
|
|
6260
|
+
*
|
|
6261
|
+
* `db push` runs `atlas schema apply` to make the live database match the
|
|
6262
|
+
* generated `schema.sql`. Removing a collection field compiles to
|
|
6263
|
+
* `DROP COLUMN`; renaming compiles to drop-then-add — either destroys data.
|
|
6264
|
+
* We first run the apply with `--dry-run` to obtain the planned SQL, scan it
|
|
6265
|
+
* here, and refuse to auto-approve anything destructive without an explicit
|
|
6266
|
+
* opt-in.
|
|
6267
|
+
*
|
|
6268
|
+
* A type change is the one destructive plan that names no DROP. `ALTER COLUMN
|
|
6269
|
+
* "price" TYPE integer` rounds every 19.99 to 20, and `TYPE date` throws away
|
|
6270
|
+
* every timestamp's time of day, in a statement that reads like a routine
|
|
6271
|
+
* alter. So a type change is gated too, unless it is a widening every value
|
|
6272
|
+
* survives unchanged — which needs the column's current type, read from the
|
|
6273
|
+
* catalogue by the caller.
|
|
6274
|
+
*
|
|
6275
|
+
* Everything in this file is side-effect free so it can be unit-tested
|
|
6276
|
+
* without Atlas or a database.
|
|
6277
|
+
*/
|
|
6278
|
+
/**
|
|
6279
|
+
* SQL fragments that destroy data or data-bearing objects. Matched
|
|
6280
|
+
* case-insensitively against each statement of the plan. `IF EXISTS` /
|
|
6281
|
+
* whitespace variations are tolerated by the regexes below.
|
|
6282
|
+
*/
|
|
6283
|
+
var DESTRUCTIVE_PATTERNS = [
|
|
6284
|
+
{
|
|
6285
|
+
label: "DROP TABLE",
|
|
6286
|
+
re: /\bDROP\s+TABLE\b/i
|
|
6287
|
+
},
|
|
6288
|
+
{
|
|
6289
|
+
label: "DROP COLUMN",
|
|
6290
|
+
re: /\bDROP\s+COLUMN\b/i
|
|
6291
|
+
},
|
|
6292
|
+
{
|
|
6293
|
+
label: "DROP SCHEMA",
|
|
6294
|
+
re: /\bDROP\s+SCHEMA\b/i
|
|
6295
|
+
},
|
|
6296
|
+
{
|
|
6297
|
+
label: "DROP VIEW",
|
|
6298
|
+
re: /\bDROP\s+(MATERIALIZED\s+)?VIEW\b/i
|
|
6299
|
+
},
|
|
6300
|
+
{
|
|
6301
|
+
label: "DROP TYPE",
|
|
6302
|
+
re: /\bDROP\s+TYPE\b/i
|
|
6303
|
+
},
|
|
6304
|
+
{
|
|
6305
|
+
label: "TRUNCATE",
|
|
6306
|
+
re: /\bTRUNCATE\b/i
|
|
6307
|
+
}
|
|
6308
|
+
];
|
|
6309
|
+
/**
|
|
6310
|
+
* Split a SQL script into individual statements, dropping blank lines and
|
|
6311
|
+
* `--` comment lines. Deliberately simple: Atlas emits one plain statement
|
|
6312
|
+
* per `;`, without string literals that contain semicolons in a schema DDL
|
|
6313
|
+
* plan, so a naive split is safe and keeps this dependency-free.
|
|
6314
|
+
*/
|
|
6315
|
+
function splitSqlStatements(sql) {
|
|
6316
|
+
return sql.split("\n").filter((line) => !line.trim().startsWith("--")).join("\n").split(";").map((s) => s.trim()).filter((s) => s.length > 0);
|
|
6317
|
+
}
|
|
6318
|
+
/**
|
|
6319
|
+
* Every column of every ordinary table outside the system schemas, with its
|
|
6320
|
+
* type. What {@link detectDestructiveStatements} compares a planned type
|
|
6321
|
+
* change against; `format_type` because it carries the modifier (`(255)`,
|
|
6322
|
+
* `(10,2)`) that decides whether a change widens or narrows.
|
|
6323
|
+
*/
|
|
6324
|
+
var COLUMN_TYPES_SQL = `
|
|
6325
|
+
SELECT n.nspname AS "schema",
|
|
6326
|
+
c.relname AS "table",
|
|
6327
|
+
a.attname AS "column",
|
|
6328
|
+
format_type(a.atttypid, a.atttypmod) AS "type"
|
|
6329
|
+
FROM pg_attribute a
|
|
6330
|
+
JOIN pg_class c ON c.oid = a.attrelid
|
|
6331
|
+
JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
6332
|
+
WHERE c.relkind IN ('r', 'p')
|
|
6333
|
+
AND a.attnum > 0
|
|
6334
|
+
AND NOT a.attisdropped
|
|
6335
|
+
AND n.nspname NOT IN ('pg_catalog', 'information_schema')
|
|
6336
|
+
AND n.nspname NOT LIKE 'pg\\_%'
|
|
6337
|
+
`;
|
|
6338
|
+
/**
|
|
6339
|
+
* Scan an Atlas plan (the SQL printed by `schema apply --dry-run`) and return
|
|
6340
|
+
* the statements that would destroy data. An empty array means the plan is
|
|
6341
|
+
* safe to auto-approve.
|
|
6342
|
+
*
|
|
6343
|
+
* `columnTypes` is what the database holds now. A type change to a column it
|
|
6344
|
+
* does not list is flagged: not knowing what a column is means not knowing
|
|
6345
|
+
* whether the change keeps its values.
|
|
6346
|
+
*/
|
|
6347
|
+
function detectDestructiveStatements(planSql, columnTypes = []) {
|
|
6348
|
+
const found = [];
|
|
6349
|
+
for (const statement of splitSqlStatements(planSql)) {
|
|
6350
|
+
const dropped = DESTRUCTIVE_PATTERNS.find(({ re }) => re.test(statement));
|
|
6351
|
+
if (dropped) {
|
|
6352
|
+
found.push({
|
|
6353
|
+
statement,
|
|
6354
|
+
kind: dropped.label
|
|
6355
|
+
});
|
|
6356
|
+
continue;
|
|
6357
|
+
}
|
|
6358
|
+
const lossy = parseColumnTypeChanges(statement).map((change) => ({
|
|
6359
|
+
change,
|
|
6360
|
+
from: currentTypeOf(change, columnTypes)
|
|
6361
|
+
})).filter(({ change, from }) => from === void 0 || !isLosslessTypeChange(from, change.to));
|
|
6362
|
+
if (lossy.length > 0) found.push({
|
|
6363
|
+
statement,
|
|
6364
|
+
kind: "ALTER COLUMN TYPE",
|
|
6365
|
+
detail: lossy.map(({ change, from }) => `"${change.column}" ${from ?? "(current type unknown)"} → ${change.to}`).join("; ")
|
|
6366
|
+
});
|
|
6367
|
+
}
|
|
6368
|
+
return found;
|
|
6369
|
+
}
|
|
6370
|
+
var IDENT = String.raw`(?:"(?:[^"]|"")+"|[A-Za-z_][A-Za-z0-9_$]*)`;
|
|
6371
|
+
var ALTER_TABLE_RE = new RegExp(String.raw`^ALTER\s+TABLE\s+(?:IF\s+EXISTS\s+)?(?:ONLY\s+)?(${IDENT})(?:\.(${IDENT}))?\s+([\s\S]*)$`, "i");
|
|
6372
|
+
var TYPE_CLAUSE_RE = new RegExp(String.raw`^ALTER\s+(?:COLUMN\s+)?(${IDENT})\s+(?:SET\s+DATA\s+)?TYPE\s+([\s\S]+)$`, "i");
|
|
6373
|
+
var unquote = (ident) => ident.startsWith("\"") ? ident.slice(1, -1).replace(/""/g, "\"") : ident;
|
|
6374
|
+
/**
|
|
6375
|
+
* Split an `ALTER TABLE`'s clause list on its top-level commas — the ones
|
|
6376
|
+
* outside parentheses and quotes, so `TYPE numeric(10, 2)` stays one clause.
|
|
6377
|
+
*/
|
|
6378
|
+
function splitClauses(body) {
|
|
6379
|
+
const clauses = [];
|
|
6380
|
+
let depth = 0;
|
|
6381
|
+
let quote;
|
|
6382
|
+
let start = 0;
|
|
6383
|
+
for (let i = 0; i < body.length; i++) {
|
|
6384
|
+
const ch = body[i];
|
|
6385
|
+
if (quote) {
|
|
6386
|
+
if (ch === quote) quote = void 0;
|
|
6387
|
+
} else if (ch === "\"" || ch === "'") quote = ch;
|
|
6388
|
+
else if (ch === "(") depth++;
|
|
6389
|
+
else if (ch === ")") depth--;
|
|
6390
|
+
else if (ch === "," && depth === 0) {
|
|
6391
|
+
clauses.push(body.slice(start, i).trim());
|
|
6392
|
+
start = i + 1;
|
|
6393
|
+
}
|
|
6394
|
+
}
|
|
6395
|
+
clauses.push(body.slice(start).trim());
|
|
6396
|
+
return clauses.filter((clause) => clause.length > 0);
|
|
6397
|
+
}
|
|
6398
|
+
/**
|
|
6399
|
+
* Every `ALTER COLUMN … [SET DATA] TYPE` in one statement. Atlas prints its
|
|
6400
|
+
* dry-run statements under a `-> ` marker and puts several clauses in one
|
|
6401
|
+
* `ALTER TABLE`, so both are handled.
|
|
6402
|
+
*/
|
|
6403
|
+
function parseColumnTypeChanges(statement) {
|
|
6404
|
+
const table = ALTER_TABLE_RE.exec(statement.replace(/^\s*->\s*/, "").trim());
|
|
6405
|
+
if (!table) return [];
|
|
6406
|
+
const [schema, name] = table[2] ? [unquote(table[1]), unquote(table[2])] : [void 0, unquote(table[1])];
|
|
6407
|
+
const changes = [];
|
|
6408
|
+
for (const clause of splitClauses(table[3])) {
|
|
6409
|
+
const match = TYPE_CLAUSE_RE.exec(clause);
|
|
6410
|
+
if (!match) continue;
|
|
6411
|
+
const to = match[2].split(/\s+(?:USING|COLLATE)\s/i)[0].trim();
|
|
6412
|
+
changes.push({
|
|
6413
|
+
schema,
|
|
6414
|
+
table: name,
|
|
6415
|
+
column: unquote(match[1]),
|
|
6416
|
+
to
|
|
6417
|
+
});
|
|
6418
|
+
}
|
|
6419
|
+
return changes;
|
|
6420
|
+
}
|
|
6421
|
+
/**
|
|
6422
|
+
* The column's current type. A table named without its schema matches in any
|
|
6423
|
+
* schema, but only when every match agrees — two same-named tables with
|
|
6424
|
+
* different types leave the answer unknown.
|
|
6425
|
+
*/
|
|
6426
|
+
function currentTypeOf(change, columnTypes) {
|
|
6427
|
+
const types = new Set(columnTypes.filter((col) => col.table === change.table && col.column === change.column && (change.schema === void 0 || col.schema === change.schema)).map((col) => col.type));
|
|
6428
|
+
return types.size === 1 ? [...types][0] : void 0;
|
|
6429
|
+
}
|
|
6430
|
+
/** Spellings of one type, mapped to one name. Anything absent compares verbatim. */
|
|
6431
|
+
var TYPE_ALIASES = {
|
|
6432
|
+
"int": "integer",
|
|
6433
|
+
"int4": "integer",
|
|
6434
|
+
"int2": "smallint",
|
|
6435
|
+
"int8": "bigint",
|
|
6436
|
+
"character varying": "varchar",
|
|
6437
|
+
"decimal": "numeric",
|
|
6438
|
+
"timestamp without time zone": "timestamp",
|
|
6439
|
+
"timestamp with time zone": "timestamptz",
|
|
6440
|
+
"time without time zone": "time",
|
|
6441
|
+
"time with time zone": "timetz",
|
|
6442
|
+
"bool": "boolean",
|
|
6443
|
+
"float4": "real",
|
|
6444
|
+
"float8": "double precision",
|
|
6445
|
+
"character": "bpchar",
|
|
6446
|
+
"char": "bpchar"
|
|
6447
|
+
};
|
|
6448
|
+
/** Decimal digits each integer type holds, which is what a `numeric` must hold too. */
|
|
6449
|
+
var INTEGER_DIGITS = {
|
|
6450
|
+
smallint: 5,
|
|
6451
|
+
integer: 10,
|
|
6452
|
+
bigint: 19
|
|
6453
|
+
};
|
|
6454
|
+
/** Types whose modifier is a fractional-seconds precision, 6 when absent. */
|
|
6455
|
+
var SECONDS_PRECISION = /* @__PURE__ */ new Set([
|
|
6456
|
+
"timestamp",
|
|
6457
|
+
"timestamptz",
|
|
6458
|
+
"time",
|
|
6459
|
+
"timetz"
|
|
6460
|
+
]);
|
|
6461
|
+
function parseType(raw) {
|
|
6462
|
+
let text = raw.trim().replace(/\s+/g, " ");
|
|
6463
|
+
let dims = 0;
|
|
6464
|
+
for (let suffix = /\s*\[\d*\]$/.exec(text); suffix; suffix = /\s*\[\d*\]$/.exec(text)) {
|
|
6465
|
+
dims++;
|
|
6466
|
+
text = text.slice(0, suffix.index);
|
|
6467
|
+
}
|
|
6468
|
+
if (text.includes("\"")) return {
|
|
6469
|
+
base: text,
|
|
6470
|
+
dims
|
|
6471
|
+
};
|
|
6472
|
+
text = text.toLowerCase().replace(/^pg_catalog\./, "");
|
|
6473
|
+
let args;
|
|
6474
|
+
const modifier = /\(([^)]*)\)/.exec(text);
|
|
6475
|
+
if (modifier) {
|
|
6476
|
+
args = modifier[1].split(",").map((part) => Number(part.trim()));
|
|
6477
|
+
text = `${text.slice(0, modifier.index)} ${text.slice(modifier.index + modifier[0].length)}`.replace(/\s+/g, " ").trim();
|
|
6478
|
+
}
|
|
6479
|
+
return {
|
|
6480
|
+
base: TYPE_ALIASES[text] ?? text,
|
|
6481
|
+
args,
|
|
6482
|
+
dims
|
|
6483
|
+
};
|
|
6484
|
+
}
|
|
6485
|
+
/** Does moving from one modifier to another, on the same type, keep every value? */
|
|
6486
|
+
function modifierWidens(base, from, to) {
|
|
6487
|
+
if (JSON.stringify(from) === JSON.stringify(to)) return true;
|
|
6488
|
+
if (base === "varchar") return to === void 0 || from !== void 0 && to[0] >= from[0];
|
|
6489
|
+
if (base === "numeric") {
|
|
6490
|
+
if (to === void 0) return true;
|
|
6491
|
+
if (from === void 0) return false;
|
|
6492
|
+
const [p1, s1 = 0] = from;
|
|
6493
|
+
const [p2, s2 = 0] = to;
|
|
6494
|
+
return s2 >= s1 && p2 - s2 >= p1 - s1;
|
|
6495
|
+
}
|
|
6496
|
+
if (SECONDS_PRECISION.has(base)) return (to?.[0] ?? 6) >= (from?.[0] ?? 6);
|
|
6497
|
+
return false;
|
|
6498
|
+
}
|
|
6499
|
+
/**
|
|
6500
|
+
* Is `ALTER COLUMN … TYPE to` a widening, one that keeps every value exactly
|
|
6501
|
+
* as it was?
|
|
6502
|
+
*
|
|
6503
|
+
* Deliberately short. Everything not listed needs a confirmation, including
|
|
6504
|
+
* changes that are usually harmless: `timestamp` → `timestamptz` reads each
|
|
6505
|
+
* value in the session's time zone, `json` → `jsonb` drops duplicate keys,
|
|
6506
|
+
* `real` → `double precision` prints 0.1 as 0.100000001490116, and `integer` →
|
|
6507
|
+
* `text` keeps the digits but changes what the column is.
|
|
6508
|
+
*
|
|
6509
|
+
* - the same type, with a modifier at least as wide (`varchar(100)` →
|
|
6510
|
+
* `varchar(255)`, `numeric(10,2)` → `numeric(12,2)` or unbounded,
|
|
6511
|
+
* `timestamptz(3)` → `timestamptz`);
|
|
6512
|
+
* - `smallint` → `integer` → `bigint`, and any of them to a `numeric` with
|
|
6513
|
+
* room for all their digits;
|
|
6514
|
+
* - `varchar(n)` → `text`, and `text` → an unbounded `varchar`.
|
|
6515
|
+
*
|
|
6516
|
+
* Arrays follow their element type, and never gain or lose a dimension.
|
|
6517
|
+
*/
|
|
6518
|
+
function isLosslessTypeChange(from, to) {
|
|
6519
|
+
const a = parseType(from);
|
|
6520
|
+
const b = parseType(to);
|
|
6521
|
+
if (a.dims !== b.dims) return false;
|
|
6522
|
+
if (a.args?.some(Number.isNaN) || b.args?.some(Number.isNaN)) return false;
|
|
6523
|
+
if (a.base === b.base) return modifierWidens(a.base, a.args, b.args);
|
|
6524
|
+
const fromDigits = INTEGER_DIGITS[a.base];
|
|
6525
|
+
if (fromDigits !== void 0) {
|
|
6526
|
+
const toDigits = INTEGER_DIGITS[b.base];
|
|
6527
|
+
if (toDigits !== void 0) return toDigits >= fromDigits;
|
|
6528
|
+
if (b.base === "numeric") return b.args === void 0 || b.args[0] - (b.args[1] ?? 0) >= fromDigits;
|
|
6529
|
+
return false;
|
|
6530
|
+
}
|
|
6531
|
+
if (a.base === "varchar" && b.base === "text") return true;
|
|
6532
|
+
if (a.base === "text" && b.base === "varchar") return b.args === void 0;
|
|
6533
|
+
return false;
|
|
6534
|
+
}
|
|
6535
|
+
/**
|
|
6536
|
+
* Decide how `db push` should proceed given the plan's destructiveness and
|
|
6537
|
+
* the invocation context.
|
|
6538
|
+
*
|
|
6539
|
+
* - No destructive statements → `apply` (safe to auto-approve).
|
|
6540
|
+
* - Destructive + `--allow-destructive` → `apply` (operator opted in).
|
|
6541
|
+
* - Destructive + interactive TTY → `confirm` (prompt before applying).
|
|
6542
|
+
* - Destructive + non-interactive → `refuse` (never silently drop data in
|
|
6543
|
+
* CI / scripts / agents).
|
|
6544
|
+
*/
|
|
6545
|
+
function decidePushSafety(opts) {
|
|
6546
|
+
if (opts.destructiveCount === 0) return "apply";
|
|
6547
|
+
if (opts.allowDestructive) return "apply";
|
|
6548
|
+
return opts.interactive ? "confirm" : "refuse";
|
|
6549
|
+
}
|
|
6550
|
+
//#endregion
|
|
6551
|
+
//#region src/module-dir.ts
|
|
6257
6552
|
var moduleDir = path.dirname(fileURLToPath$1(import.meta.url));
|
|
6258
6553
|
//#endregion
|
|
6259
6554
|
//#region src/cli-helpers.ts
|
|
@@ -6419,7 +6714,7 @@ function resolveLocalBin(binName) {
|
|
|
6419
6714
|
return null;
|
|
6420
6715
|
}
|
|
6421
6716
|
async function getTableIncludesFromCollections(allCollections) {
|
|
6422
|
-
const { getTableName,
|
|
6717
|
+
const { getTableName, relationalCollections, resolveJunctionSpecs } = await import("@rebasepro/common");
|
|
6423
6718
|
const { isPostgresCollectionConfig } = await import("@rebasepro/types");
|
|
6424
6719
|
const collections = relationalCollections(allCollections);
|
|
6425
6720
|
const includes = [];
|
|
@@ -6427,14 +6722,8 @@ async function getTableIncludesFromCollections(allCollections) {
|
|
|
6427
6722
|
const tableName = getTableName(col);
|
|
6428
6723
|
const schema = isPostgresCollectionConfig(col) && col.schema ? col.schema : "public";
|
|
6429
6724
|
if (tableName) includes.push(`${schema}.${tableName}`);
|
|
6430
|
-
const resolvedRelations = resolveCollectionRelations(col);
|
|
6431
|
-
for (const relation of Object.values(resolvedRelations)) if (isManyToMany(relation)) {
|
|
6432
|
-
const junctionTableName = relation.through.table;
|
|
6433
|
-
const targetCollection = relation.target();
|
|
6434
|
-
const targetSchema = isPostgresCollectionConfig(targetCollection) && targetCollection.schema ? targetCollection.schema : "public";
|
|
6435
|
-
includes.push(`${targetSchema}.${junctionTableName}`);
|
|
6436
|
-
}
|
|
6437
6725
|
}
|
|
6726
|
+
for (const junction of resolveJunctionSpecs(collections).values()) includes.push(`${junction.schema}.${junction.table}`);
|
|
6438
6727
|
return Array.from(new Set(includes));
|
|
6439
6728
|
}
|
|
6440
6729
|
async function getTableIncludes(collectionsPath) {
|
|
@@ -6610,7 +6899,7 @@ async function applySearchDdl(databaseUrl, drizzleDir = path.resolve(process.cwd
|
|
|
6610
6899
|
* `search` block, which is every project that has not opted in.
|
|
6611
6900
|
*/
|
|
6612
6901
|
async function getSearchExcludes(collectionsPath) {
|
|
6613
|
-
const { searchExcludePatterns } = await import("./generate-postgres-ddl-logic-
|
|
6902
|
+
const { searchExcludePatterns } = await import("./generate-postgres-ddl-logic-Bt2d2mRH.js").then((n) => n.o);
|
|
6614
6903
|
return searchExcludePatterns(await loadCollectionsForCli(collectionsPath));
|
|
6615
6904
|
}
|
|
6616
6905
|
/**
|
|
@@ -6654,6 +6943,20 @@ async function queryGeneratedColumnDependencies(databaseUrl) {
|
|
|
6654
6943
|
}
|
|
6655
6944
|
}
|
|
6656
6945
|
/**
|
|
6946
|
+
* Every column in the database with its current type, for the destructive
|
|
6947
|
+
* gate to tell a widening `ALTER COLUMN … TYPE` from one that loses data.
|
|
6948
|
+
*/
|
|
6949
|
+
async function queryColumnTypes(databaseUrl) {
|
|
6950
|
+
const { Client } = await import("pg");
|
|
6951
|
+
const client = new Client({ connectionString: databaseUrl });
|
|
6952
|
+
await client.connect();
|
|
6953
|
+
try {
|
|
6954
|
+
return (await client.query(COLUMN_TYPES_SQL)).rows;
|
|
6955
|
+
} finally {
|
|
6956
|
+
await client.end();
|
|
6957
|
+
}
|
|
6958
|
+
}
|
|
6959
|
+
/**
|
|
6657
6960
|
* Drop the generated columns standing in the way of an apply.
|
|
6658
6961
|
*
|
|
6659
6962
|
* Their indexes and their `COMMENT ON COLUMN` stamp go with them, which is
|
|
@@ -6723,7 +7026,7 @@ async function applyVectorDdl(databaseUrl, drizzleDir = path.resolve(process.cwd
|
|
|
6723
7026
|
* `vector` property, which is every project that has not opted in.
|
|
6724
7027
|
*/
|
|
6725
7028
|
async function getVectorExcludes(collectionsPath) {
|
|
6726
|
-
const { vectorExcludePatterns } = await import("./generate-postgres-ddl-logic-
|
|
7029
|
+
const { vectorExcludePatterns } = await import("./generate-postgres-ddl-logic-Bt2d2mRH.js").then((n) => n.o);
|
|
6727
7030
|
return vectorExcludePatterns(await loadCollectionsForCli(collectionsPath));
|
|
6728
7031
|
}
|
|
6729
7032
|
/**
|
|
@@ -6767,7 +7070,7 @@ async function applyTriggersDdl(databaseUrl, drizzleDir = path.resolve(process.c
|
|
|
6767
7070
|
}
|
|
6768
7071
|
/** @see getSearchExcludes */
|
|
6769
7072
|
async function getTriggerExcludes(collectionsPath) {
|
|
6770
|
-
const { triggerExcludePatterns } = await import("./generate-postgres-ddl-logic-
|
|
7073
|
+
const { triggerExcludePatterns } = await import("./generate-postgres-ddl-logic-Bt2d2mRH.js").then((n) => n.o);
|
|
6771
7074
|
return triggerExcludePatterns(await loadCollectionsForCli(collectionsPath));
|
|
6772
7075
|
}
|
|
6773
7076
|
/**
|
|
@@ -6853,8 +7156,8 @@ async function getForeignIndexExcludes(databaseUrl, collectionsPath, deps = {})
|
|
|
6853
7156
|
*/
|
|
6854
7157
|
async function managedIndexNames(collectionsPath) {
|
|
6855
7158
|
const collections = await loadCollectionsForCli(collectionsPath);
|
|
6856
|
-
const { searchExcludePatterns, vectorExcludePatterns } = await import("./generate-postgres-ddl-logic-
|
|
6857
|
-
const { resolveColumnName } = await import("./column-plan-helpers-
|
|
7159
|
+
const { searchExcludePatterns, vectorExcludePatterns } = await import("./generate-postgres-ddl-logic-Bt2d2mRH.js").then((n) => n.o);
|
|
7160
|
+
const { resolveColumnName } = await import("./column-plan-helpers-DF-8dTVa.js").then((n) => n.n);
|
|
6858
7161
|
const { buildCollectionIndexPlan } = await import("./collection-index-DdnsxiJ_.js").then((n) => n.i);
|
|
6859
7162
|
const names = new Set(buildCollectionIndexPlan(collections, resolveColumnName).map((spec) => spec.indexName));
|
|
6860
7163
|
for (const pattern of [...searchExcludePatterns(collections), ...vectorExcludePatterns(collections)]) names.add(pattern.slice(pattern.lastIndexOf(".") + 1));
|
|
@@ -7191,6 +7494,6 @@ async function dropLegacyAuthSchema(run, report) {
|
|
|
7191
7494
|
}
|
|
7192
7495
|
}
|
|
7193
7496
|
//#endregion
|
|
7194
|
-
export {
|
|
7497
|
+
export { resolveLocalBin as A, loadCollectionsForCli as C, readSearchDdl as D, queryGeneratedColumnDependencies as E, forLibpq as F, detectDestructiveStatements as M, splitSqlStatements as N, readTriggersDdl as O, execa as P, getVectorExcludes as S, queryColumnTypes as T, getDevDatabaseUrl as _, ExcludeIntrospectionError as a, getTableExcludes as b, applyVectorDdl as c, describeReinstallCommand as d, detectProjectPackageManager as f, ensureDevDatabaseExists as g, dropGeneratedColumns as h, rls_bootstrap_sql_exports as i, decidePushSafety as j, readVectorDdl as k, describeBuildScriptRemedy as l, dropDevDatabase as m, RLS_BOOTSTRAP_STATEMENTS as n, applySearchDdl as o, diagnoseMissingBin as p, dropLegacyAuthSchema as r, applyTriggersDdl as s, RLS_BOOTSTRAP_SQL as t, describeDevAddCommand as u, getForeignIndexExcludes as v, promptConfirm as w, getTriggerExcludes as x, getSearchExcludes as y };
|
|
7195
7498
|
|
|
7196
|
-
//# sourceMappingURL=rls-bootstrap-sql-
|
|
7499
|
+
//# sourceMappingURL=rls-bootstrap-sql-B8EclDyM.js.map
|