@rebasepro/server-postgres 0.21.2-canary.g1ea48be → 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.
Files changed (83) hide show
  1. package/dist/{BranchService-CucnFcSE.js → BranchService-DGPL6G_C.js} +2 -2
  2. package/dist/{BranchService-CucnFcSE.js.map → BranchService-DGPL6G_C.js.map} +1 -1
  3. package/dist/PostgresBackendDriver.d.ts +41 -1
  4. package/dist/auth/services.d.ts +27 -8
  5. package/dist/backup/backup-cli.d.ts +22 -0
  6. package/dist/{backup-cli-CkjsJEcu.js → backup-cli-24v4OlSp.js} +17 -14
  7. package/dist/backup-cli-24v4OlSp.js.map +1 -0
  8. package/dist/{backup-service-BNLwvxuy.js → backup-service-HQ9GC4tN.js} +2 -2
  9. package/dist/{backup-service-BNLwvxuy.js.map → backup-service-HQ9GC4tN.js.map} +1 -1
  10. package/dist/{cli-errors-Dka89exj.js → cli-errors-B8qHg02P.js} +6 -1
  11. package/dist/cli-errors-B8qHg02P.js.map +1 -0
  12. package/dist/cli-flags-BglvpjHv.js +138 -0
  13. package/dist/cli-flags-BglvpjHv.js.map +1 -0
  14. package/dist/cli-flags.d.ts +28 -0
  15. package/dist/cli-helpers.d.ts +6 -0
  16. package/dist/cli-scratch-database.d.ts +34 -0
  17. package/dist/cli.js +97 -261
  18. package/dist/cli.js.map +1 -1
  19. package/dist/{column-plan-helpers-CpILzHJS.js → column-plan-helpers-DF-8dTVa.js} +16 -20
  20. package/dist/column-plan-helpers-DF-8dTVa.js.map +1 -0
  21. package/dist/{doctor-Gzzd8wTq.js → doctor-Cb2thZ8s.js} +8 -7
  22. package/dist/doctor-Cb2thZ8s.js.map +1 -0
  23. package/dist/{ensure-collection-policies-B4IDFtQ-.js → ensure-collection-policies-RHUcEp4v.js} +5 -5
  24. package/dist/{ensure-collection-policies-B4IDFtQ-.js.map → ensure-collection-policies-RHUcEp4v.js.map} +1 -1
  25. package/dist/{ensure-collection-tables-Cr2ye5JC.js → ensure-collection-tables-BEEjn5cn.js} +53 -22
  26. package/dist/ensure-collection-tables-BEEjn5cn.js.map +1 -0
  27. package/dist/{ensure-tables-BnEvEJPr.js → ensure-tables-Dhn9KM3B.js} +2 -2
  28. package/dist/{ensure-tables-BnEvEJPr.js.map → ensure-tables-Dhn9KM3B.js.map} +1 -1
  29. package/dist/{generate-drizzle-schema-logic-DFa9qy9u.js → generate-drizzle-schema-logic-BfzK7UQd.js} +2 -2
  30. package/dist/{generate-drizzle-schema-logic-DFa9qy9u.js.map → generate-drizzle-schema-logic-BfzK7UQd.js.map} +1 -1
  31. package/dist/{generate-drizzle-schema-D2MDdJt-.js → generate-drizzle-schema-yzY_BLhr.js} +2 -2
  32. package/dist/{generate-drizzle-schema-D2MDdJt-.js.map → generate-drizzle-schema-yzY_BLhr.js.map} +1 -1
  33. package/dist/{generate-postgres-ddl-logic-CR2xcS7e.js → generate-postgres-ddl-logic-Bt2d2mRH.js} +2 -2
  34. package/dist/{generate-postgres-ddl-logic-CR2xcS7e.js.map → generate-postgres-ddl-logic-Bt2d2mRH.js.map} +1 -1
  35. package/dist/index.es.js +1882 -392
  36. package/dist/index.es.js.map +1 -1
  37. package/dist/{introspect-db-logic-C6LQdTxj.js → introspect-db-logic-WMuAfxvw.js} +323 -4
  38. package/dist/introspect-db-logic-WMuAfxvw.js.map +1 -0
  39. package/dist/{plan-schema-Hgl62S-w.js → plan-schema-C0fxM8dY.js} +170 -38
  40. package/dist/plan-schema-C0fxM8dY.js.map +1 -0
  41. package/dist/{policy-drift-B0GDRh7_.js → policy-drift-DljYdrpW.js} +2 -2
  42. package/dist/{policy-drift-B0GDRh7_.js.map → policy-drift-DljYdrpW.js.map} +1 -1
  43. package/dist/{rls-bootstrap-sql-BHA6jLtj.js → rls-bootstrap-sql-B8EclDyM.js} +320 -17
  44. package/dist/rls-bootstrap-sql-B8EclDyM.js.map +1 -0
  45. package/dist/schema/atlas-argv.d.ts +15 -0
  46. package/dist/schema/column-plan-helpers.d.ts +23 -4
  47. package/dist/schema/destructive-sql.d.ts +52 -1
  48. package/dist/schema/doctor-cli.js +3 -3
  49. package/dist/schema/generate-drizzle-schema.js +1 -1
  50. package/dist/schema/generate-postgres-ddl.js +1 -1
  51. package/dist/schema/introspect-db.js +1 -312
  52. package/dist/schema/introspect-db.js.map +1 -1
  53. package/dist/schema/plan/diff-plan.d.ts +3 -2
  54. package/dist/schema/plan/plan-schema.d.ts +10 -3
  55. package/dist/schema/plan/types.d.ts +6 -1
  56. package/dist/schema/search-column.d.ts +21 -1
  57. package/dist/services/FetchService.d.ts +147 -30
  58. package/dist/services/PersistService.d.ts +56 -5
  59. package/dist/services/RelationService.d.ts +42 -1
  60. package/dist/services/RelationWriteService.d.ts +22 -1
  61. package/dist/services/cdc/CdcListener.d.ts +6 -1
  62. package/dist/services/collection-helpers.d.ts +11 -0
  63. package/dist/services/dataService.d.ts +19 -21
  64. package/dist/services/field-op-sql.d.ts +71 -0
  65. package/dist/services/junction-writes.d.ts +19 -3
  66. package/dist/services/pg-notify-listener.d.ts +7 -0
  67. package/dist/services/read-field-access.d.ts +19 -0
  68. package/dist/services/read-scope.d.ts +100 -0
  69. package/dist/services/realtimeService.d.ts +77 -3
  70. package/dist/services/row-pipeline.d.ts +5 -0
  71. package/dist/services/soft-delete.d.ts +0 -2
  72. package/dist/services/write-transaction-scope.d.ts +39 -0
  73. package/dist/utils/drizzle-conditions.d.ts +63 -8
  74. package/dist/websocket.d.ts +10 -3
  75. package/package.json +9 -9
  76. package/dist/backup-cli-CkjsJEcu.js.map +0 -1
  77. package/dist/cli-errors-Dka89exj.js.map +0 -1
  78. package/dist/column-plan-helpers-CpILzHJS.js.map +0 -1
  79. package/dist/doctor-Gzzd8wTq.js.map +0 -1
  80. package/dist/ensure-collection-tables-Cr2ye5JC.js.map +0 -1
  81. package/dist/introspect-db-logic-C6LQdTxj.js.map +0 -1
  82. package/dist/plan-schema-Hgl62S-w.js.map +0 -1
  83. package/dist/rls-bootstrap-sql-BHA6jLtj.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, isManyToMany } from "@rebasepro/types";
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/module-dir.ts
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, resolveCollectionRelations, relationalCollections } = await import("@rebasepro/common");
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-CR2xcS7e.js").then((n) => n.o);
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-CR2xcS7e.js").then((n) => n.o);
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-CR2xcS7e.js").then((n) => n.o);
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-CR2xcS7e.js").then((n) => n.o);
6857
- const { resolveColumnName } = await import("./column-plan-helpers-CpILzHJS.js").then((n) => n.n);
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 { execa as A, loadCollectionsForCli as C, readTriggersDdl as D, readSearchDdl as E, readVectorDdl as O, getVectorExcludes as S, queryGeneratedColumnDependencies 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, forLibpq as j, resolveLocalBin 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 };
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-BHA6jLtj.js.map
7499
+ //# sourceMappingURL=rls-bootstrap-sql-B8EclDyM.js.map