@rebasepro/server-postgres 0.23.0 → 0.24.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-DGPL6G_C.js → BranchService-BRt78gfa.js} +35 -18
- package/dist/BranchService-BRt78gfa.js.map +1 -0
- package/dist/PostgresBackendDriver.d.ts +84 -12
- package/dist/auth/services.d.ts +72 -14
- package/dist/{auth-users-columns-D2LBFrMH.js → auth-users-columns-C72EMoDJ.js} +17 -1
- package/dist/{auth-users-columns-D2LBFrMH.js.map → auth-users-columns-C72EMoDJ.js.map} +1 -1
- package/dist/{backup-cli-24v4OlSp.js → backup-cli-DW5p9_zv.js} +2 -2
- package/dist/{backup-cli-24v4OlSp.js.map → backup-cli-DW5p9_zv.js.map} +1 -1
- package/dist/{backup-service-HQ9GC4tN.js → backup-service-EwcDVG-8.js} +7 -9
- package/dist/{backup-service-HQ9GC4tN.js.map → backup-service-EwcDVG-8.js.map} +1 -1
- package/dist/{cli-errors-B8qHg02P.js → cli-errors-DsA-K9uP.js} +96 -1
- package/dist/{cli-errors-B8qHg02P.js.map → cli-errors-DsA-K9uP.js.map} +1 -1
- package/dist/cli-errors.d.ts +42 -0
- package/dist/cli-helpers.d.ts +12 -12
- package/dist/cli.js +91 -37
- package/dist/cli.js.map +1 -1
- package/dist/{column-plan-helpers-DF-8dTVa.js → column-plan-helpers-1-LQD0yI.js} +34 -24
- package/dist/column-plan-helpers-1-LQD0yI.js.map +1 -0
- package/dist/data-transformer.d.ts +0 -8
- package/dist/{doctor-Cb2thZ8s.js → doctor-C-sYWbmt.js} +224 -43
- package/dist/doctor-C-sYWbmt.js.map +1 -0
- package/dist/{ensure-collection-policies-RHUcEp4v.js → ensure-collection-policies-B1ureSIV.js} +73 -18
- package/dist/ensure-collection-policies-B1ureSIV.js.map +1 -0
- package/dist/{ensure-collection-tables-BEEjn5cn.js → ensure-collection-tables-kkkHk8oo.js} +76 -20
- package/dist/ensure-collection-tables-kkkHk8oo.js.map +1 -0
- package/dist/{ensure-tables-Dhn9KM3B.js → ensure-tables-BmI_tRxc.js} +10 -3
- package/dist/ensure-tables-BmI_tRxc.js.map +1 -0
- package/dist/{generate-drizzle-schema-yzY_BLhr.js → generate-drizzle-schema-93M0lUxK.js} +2 -2
- package/dist/{generate-drizzle-schema-yzY_BLhr.js.map → generate-drizzle-schema-93M0lUxK.js.map} +1 -1
- package/dist/{generate-drizzle-schema-logic-BfzK7UQd.js → generate-drizzle-schema-logic-sSFDp6LR.js} +26 -8
- package/dist/generate-drizzle-schema-logic-sSFDp6LR.js.map +1 -0
- package/dist/generate-postgres-ddl-logic-BJsLaVNX.js +152 -0
- package/dist/generate-postgres-ddl-logic-BJsLaVNX.js.map +1 -0
- package/dist/generated-sql.d.ts +28 -0
- package/dist/index.es.js +3415 -917
- package/dist/index.es.js.map +1 -1
- package/dist/{introspect-db-logic-WMuAfxvw.js → introspect-db-logic-kCETE8TY.js} +523 -349
- package/dist/introspect-db-logic-kCETE8TY.js.map +1 -0
- package/dist/introspect-db-queries-C_Q5VgQw.js +317 -0
- package/dist/introspect-db-queries-C_Q5VgQw.js.map +1 -0
- package/dist/{plan-schema-C0fxM8dY.js → plan-schema-DU9exq6C.js} +139 -504
- package/dist/plan-schema-DU9exq6C.js.map +1 -0
- package/dist/{policy-drift-DljYdrpW.js → policy-drift-B-J2hhm0.js} +3 -3
- package/dist/policy-drift-B-J2hhm0.js.map +1 -0
- package/dist/{generate-postgres-ddl-logic-Bt2d2mRH.js → render-ddl-Ds2t_d9V.js} +11 -149
- package/dist/render-ddl-Ds2t_d9V.js.map +1 -0
- package/dist/{rls-bootstrap-sql-B8EclDyM.js → rls-bootstrap-sql-_KNnjanK.js} +263 -39
- package/dist/rls-bootstrap-sql-_KNnjanK.js.map +1 -0
- package/dist/{rls-enforcement-C6Xk0lA6.js → rls-enforcement-CfXOJJaW.js} +10 -2
- package/dist/rls-enforcement-CfXOJJaW.js.map +1 -0
- package/dist/schema/auth-schema.d.ts +170 -0
- package/dist/schema/classify-change.d.ts +29 -1
- package/dist/schema/column-plan-helpers.d.ts +33 -21
- package/dist/schema/destructive-sql.d.ts +20 -1
- package/dist/schema/doctor-cli.js +4 -4
- package/dist/schema/doctor.d.ts +34 -1
- package/dist/schema/ensure-collection-policies.d.ts +22 -0
- package/dist/schema/generate-drizzle-schema.js +1 -1
- package/dist/schema/generate-postgres-ddl-logic.d.ts +5 -5
- package/dist/schema/generate-postgres-ddl.js +1 -1
- package/dist/schema/generate-schema-commit.d.ts +12 -0
- package/dist/schema/introspect-db-logic.d.ts +31 -0
- package/dist/schema/introspect-db-queries.d.ts +1 -1
- package/dist/schema/introspect-db-search.d.ts +22 -0
- package/dist/schema/introspect-db-storage.d.ts +83 -0
- package/dist/schema/introspect-db.js +15 -3
- package/dist/schema/introspect-db.js.map +1 -1
- package/dist/schema/plan/diff-plan.d.ts +1 -1
- package/dist/schema/plan/plan-schema.d.ts +16 -8
- package/dist/schema/plan/render-ddl.d.ts +6 -0
- package/dist/schema/plan/types.d.ts +37 -11
- package/dist/search-column-BM-GV6vH.js +442 -0
- package/dist/search-column-BM-GV6vH.js.map +1 -0
- package/dist/security/policy-drift.d.ts +1 -1
- package/dist/security/rls-enforcement.d.ts +7 -0
- package/dist/services/BranchService.d.ts +22 -1
- package/dist/services/FetchService.d.ts +5 -4
- package/dist/services/RelationService.d.ts +18 -0
- package/dist/services/cdc/CdcListener.d.ts +9 -4
- package/dist/services/cdc/identity-columns.d.ts +19 -0
- package/dist/services/cdc/trigger-cdc.d.ts +45 -7
- package/dist/services/channel-bus/PostgresChannelBus.d.ts +12 -7
- package/dist/services/channel-history.d.ts +17 -1
- package/dist/services/collection-helpers.d.ts +11 -1
- package/dist/services/pg-notify-listener.d.ts +88 -6
- package/dist/services/realtimeService.d.ts +159 -45
- package/dist/services/socket-liveness.d.ts +45 -0
- package/dist/services/soft-delete.d.ts +12 -0
- package/dist/services/sql-script.d.ts +71 -0
- package/dist/services/write-depth.d.ts +16 -0
- package/dist/services/write-transaction-scope.d.ts +6 -3
- package/dist/utils/drizzle-conditions.d.ts +42 -2
- package/dist/utils/sql-redaction.d.ts +21 -0
- package/dist/websocket.d.ts +50 -18
- package/package.json +7 -7
- package/dist/BranchService-DGPL6G_C.js.map +0 -1
- package/dist/column-plan-helpers-DF-8dTVa.js.map +0 -1
- package/dist/doctor-Cb2thZ8s.js.map +0 -1
- package/dist/ensure-collection-policies-RHUcEp4v.js.map +0 -1
- package/dist/ensure-collection-tables-BEEjn5cn.js.map +0 -1
- package/dist/ensure-tables-Dhn9KM3B.js.map +0 -1
- package/dist/generate-drizzle-schema-logic-BfzK7UQd.js.map +0 -1
- package/dist/generate-postgres-ddl-logic-Bt2d2mRH.js.map +0 -1
- package/dist/introspect-db-logic-WMuAfxvw.js.map +0 -1
- package/dist/plan-schema-C0fxM8dY.js.map +0 -1
- package/dist/policy-drift-DljYdrpW.js.map +0 -1
- package/dist/rls-bootstrap-sql-B8EclDyM.js.map +0 -1
- package/dist/rls-enforcement-C6Xk0lA6.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { createRequire as __createRequire } from "module";
|
|
2
2
|
__createRequire(import.meta.url);
|
|
3
3
|
import { a as __toESM } from "./__vite-browser-external-BnuHet1e.js";
|
|
4
|
-
import { a as formatForeignGeneratedColumnBanner, c as reportCommandFailure, i as diagnoseDbError, r as diagnoseAtlasFailure, t as checkDatabaseConnectivity } from "./cli-errors-
|
|
4
|
+
import { a as formatForeignGeneratedColumnBanner, c as reportCommandFailure, i as diagnoseDbError, r as diagnoseAtlasFailure, t as checkDatabaseConnectivity } from "./cli-errors-DsA-K9uP.js";
|
|
5
5
|
import { n as outError, r as outWarn, t as out } from "./cli-output-CNdMql-L.js";
|
|
6
|
-
import { A as resolveLocalBin, C as loadCollectionsForCli, D as readSearchDdl, E as queryGeneratedColumnDependencies, F as
|
|
6
|
+
import { A as resolveLocalBin, B as forLibpq, C as loadCollectionsForCli, D as readSearchDdl, E as queryGeneratedColumnDependencies, F as decidePushSafety, I as detectDestructiveStatements, L as extractPlanStatements, M as GENERATED_SQL_DIR, N as generatedSqlDir, O as readTriggersDdl, P as prepareGeneratedSqlDir, R as fromAlterTable, S as getVectorExcludes, T as queryColumnTypes, _ as getDevDatabaseUrl, a as ExcludeIntrospectionError, b as getTableExcludes, c as applyVectorDdl, d as describeReinstallCommand, f as detectProjectPackageManager, g as ensureDevDatabaseExists, h as dropGeneratedColumns, j as DESIRED_STATE_URL, k as readVectorDdl, l as describeBuildScriptRemedy, m as dropDevDatabase, o as applySearchDdl, p as diagnoseMissingBin, r as dropLegacyAuthSchema, s as applyTriggersDdl, t as RLS_BOOTSTRAP_SQL, u as describeDevAddCommand, v as getForeignIndexExcludes, w as promptConfirm, x as getTriggerExcludes, y as getSearchExcludes, z as execa } from "./rls-bootstrap-sql-_KNnjanK.js";
|
|
7
7
|
import { t as chalk } from "./source-Br7L7GOI.js";
|
|
8
8
|
import { t as require_arg } from "./arg-Dni7MzLB.js";
|
|
9
9
|
import { n as collectionsPathIn, r as parseDriverLine, t as assertKnownFlags } from "./cli-flags-BglvpjHv.js";
|
|
@@ -51,16 +51,6 @@ var ALTER_COLUMN_RE = new RegExp(String.raw`\bALTER\s+(?:COLUMN\s+)?(${IDENT$1})
|
|
|
51
51
|
var DROP_COLUMN_RE$1 = new RegExp(String.raw`\bDROP\s+COLUMN\s+(?:IF\s+EXISTS\s+)?(${IDENT$1})`, "gi");
|
|
52
52
|
var unquote = (ident) => ident.startsWith("\"") ? ident.slice(1, -1) : ident;
|
|
53
53
|
/**
|
|
54
|
-
* Strip Atlas's plan rendering from a statement.
|
|
55
|
-
*
|
|
56
|
-
* What `schema apply --dry-run` prints is not a SQL file: each statement is
|
|
57
|
-
* indented under a `-- modify "posts" table` heading and prefixed with `-> `,
|
|
58
|
-
* with an `-- ok (12µs)` line after it. `splitSqlStatements` drops the comment
|
|
59
|
-
* lines, and this drops the arrow — without it an anchored `^ALTER TABLE`
|
|
60
|
-
* matches nothing at all, which is a silent no-op rather than an error.
|
|
61
|
-
*/
|
|
62
|
-
var stripPlanMarker = (statement) => statement.replace(/^\s*->\s*/, "").trim();
|
|
63
|
-
/**
|
|
64
54
|
* Every column an Atlas plan retypes or drops, with the table it belongs to.
|
|
65
55
|
*
|
|
66
56
|
* One statement carries many clauses — Atlas emits `ALTER TABLE "public"."posts"
|
|
@@ -69,8 +59,8 @@ var stripPlanMarker = (statement) => statement.replace(/^\s*->\s*/, "").trim();
|
|
|
69
59
|
*/
|
|
70
60
|
function parseColumnMutations(planSql) {
|
|
71
61
|
const mutations = [];
|
|
72
|
-
for (const raw of
|
|
73
|
-
const statement =
|
|
62
|
+
for (const raw of extractPlanStatements(planSql)) {
|
|
63
|
+
const statement = fromAlterTable(raw);
|
|
74
64
|
const table = TABLE_RE.exec(statement);
|
|
75
65
|
if (!table) continue;
|
|
76
66
|
const [schema, name] = table[2] ? [unquote(table[1]), unquote(table[2])] : [void 0, unquote(table[1])];
|
|
@@ -705,8 +695,8 @@ var TAKES_A_VALUE = /* @__PURE__ */ new Set([
|
|
|
705
695
|
* `schemaCommand`, `generatePostgresDdlCommand` and the Atlas argv assembly
|
|
706
696
|
* each re-enter the loader with the same line — and then both generators wrote
|
|
707
697
|
* an *empty* schema: `drizzle/schema.sql` truncated to `CREATE SCHEMA IF NOT
|
|
708
|
-
* EXISTS "rebase";`, `src/schema.generated.ts` to ten lines. Both
|
|
709
|
-
* artifacts. The push that followed planned a `DROP TABLE` for every table in
|
|
698
|
+
* EXISTS "rebase";`, `src/schema.generated.ts` to ten lines. Both were committed
|
|
699
|
+
* artifacts then. The push that followed planned a `DROP TABLE` for every table in
|
|
710
700
|
* the database, and the only thing between a typo and that was the destructive
|
|
711
701
|
* gate.
|
|
712
702
|
*
|
|
@@ -1021,7 +1011,7 @@ async function dbCommand(subcommand, rawArgs) {
|
|
|
1021
1011
|
return;
|
|
1022
1012
|
}
|
|
1023
1013
|
if (subcommand === "backup" || subcommand === "restore" || subcommand === "backups") {
|
|
1024
|
-
const { backupCommand, restoreCommand, backupsCommand } = await import("./backup-cli-
|
|
1014
|
+
const { backupCommand, restoreCommand, backupsCommand } = await import("./backup-cli-DW5p9_zv.js");
|
|
1025
1015
|
if (subcommand === "backup" && backupActionOf(rawArgs) === "list") await backupsCommand(rawArgs);
|
|
1026
1016
|
else if (subcommand === "backup") await backupCommand(rawArgs);
|
|
1027
1017
|
else if (subcommand === "restore") await restoreCommand(rawArgs);
|
|
@@ -1048,7 +1038,7 @@ async function dbCommand(subcommand, rawArgs) {
|
|
|
1048
1038
|
"--dir",
|
|
1049
1039
|
"file://drizzle/migrations",
|
|
1050
1040
|
"--to",
|
|
1051
|
-
|
|
1041
|
+
DESIRED_STATE_URL
|
|
1052
1042
|
], collectionsPath);
|
|
1053
1043
|
let wroteNewMigration = listMigrationFiles().length > migrationsBefore.length;
|
|
1054
1044
|
if (wroteNewMigration) wroteNewMigration = await stripCarvedOutFromNewestMigration(collectionsPath);
|
|
@@ -1067,7 +1057,7 @@ async function dbCommand(subcommand, rawArgs) {
|
|
|
1067
1057
|
}
|
|
1068
1058
|
const searchContent = readSearchDdl();
|
|
1069
1059
|
if (searchContent) {
|
|
1070
|
-
const { searchColumnDependencies } = await import("./generate-postgres-ddl-logic-
|
|
1060
|
+
const { searchColumnDependencies } = await import("./generate-postgres-ddl-logic-BJsLaVNX.js").then((n) => n.o);
|
|
1071
1061
|
const migrationConflicts = findGeneratedColumnConflicts(parseColumnMutations(migrationContent), searchColumnDependencies(await loadCollectionsForCli(collectionsPath)));
|
|
1072
1062
|
const preamble = migrationDropPreamble(migrationConflicts);
|
|
1073
1063
|
if (preamble) {
|
|
@@ -1083,7 +1073,7 @@ async function dbCommand(subcommand, rawArgs) {
|
|
|
1083
1073
|
out(chalk.gray(" ✓ Appended `updated_at` triggers to the migration"));
|
|
1084
1074
|
}
|
|
1085
1075
|
fs.writeFileSync(newestMigrationFile, migrationContent, "utf-8");
|
|
1086
|
-
const policiesFile = path.
|
|
1076
|
+
const policiesFile = path.join(generatedSqlDir(), "policies.sql");
|
|
1087
1077
|
if (fs.existsSync(policiesFile)) {
|
|
1088
1078
|
const policiesContent = fs.readFileSync(policiesFile, "utf-8");
|
|
1089
1079
|
fs.appendFileSync(newestMigrationFile, "\n\n" + RLS_BOOTSTRAP_SQL + "\n" + policiesContent);
|
|
@@ -1101,7 +1091,10 @@ async function dbCommand(subcommand, rawArgs) {
|
|
|
1101
1091
|
} catch (err) {
|
|
1102
1092
|
outWarn(chalk.yellow(` ⚠️ Failed to append policies or re-hash migration: ${err instanceof Error ? err.message : String(err)}`));
|
|
1103
1093
|
}
|
|
1104
|
-
if (!wroteNewMigration) out(chalk.gray(
|
|
1094
|
+
if (!wroteNewMigration) out(chalk.gray(` ℹ No migration written — nothing in this change is visible to Atlas.
|
|
1095
|
+
Search, vector, trigger and RLS DDL are applied by \`rebase db push\`, and at
|
|
1096
|
+
boot by the schema ensure. For a migration-only deployment, add
|
|
1097
|
+
${GENERATED_SQL_DIR}/search.sql, vector.sql, triggers.sql and\n policies.sql to a migration by hand.`));
|
|
1105
1098
|
out("");
|
|
1106
1099
|
out(` You can now run ${chalk.bold.green("rebase db migrate")} to apply the migrations to your database.`);
|
|
1107
1100
|
out("");
|
|
@@ -1123,17 +1116,20 @@ async function dbCommand(subcommand, rawArgs) {
|
|
|
1123
1116
|
const plan = await runAtlas("schema", [
|
|
1124
1117
|
"apply",
|
|
1125
1118
|
"--to",
|
|
1126
|
-
|
|
1119
|
+
DESIRED_STATE_URL,
|
|
1127
1120
|
"--dry-run"
|
|
1128
1121
|
], collectionsPath, { captureStdout: true });
|
|
1129
1122
|
const destructive = detectDestructiveStatements(plan, databaseUrl ? await queryColumnTypes(databaseUrl) : []);
|
|
1123
|
+
const unreadable = destructive.some((d) => d.kind === "UNREADABLE PLAN");
|
|
1124
|
+
const planStatements = extractPlanStatements(plan);
|
|
1125
|
+
const planListing = unreadable ? plan.trim() : planStatements.map((statement) => `${statement};`).join("\n");
|
|
1130
1126
|
const { managed: rebuildable, foreign: unowned } = partitionByOwnership(databaseUrl ? findGeneratedColumnConflicts(parseColumnMutations(plan), await queryGeneratedColumnDependencies(databaseUrl)) : [], collectionsPath ? await getSearchExcludes(collectionsPath) : []);
|
|
1131
1127
|
if (dryRun) {
|
|
1132
1128
|
out(chalk.gray(" Step 3/3: --dry-run — nothing was applied."));
|
|
1133
1129
|
out("");
|
|
1134
|
-
if (
|
|
1130
|
+
if (planStatements.length > 0 || unreadable) {
|
|
1135
1131
|
out(chalk.bold(" Planned changes:"));
|
|
1136
|
-
out(chalk.gray(
|
|
1132
|
+
out(chalk.gray(planListing.split("\n").map((l) => ` ${l}`).join("\n")));
|
|
1137
1133
|
} else out(chalk.green(" ✓ No changes: the database already matches these collections."));
|
|
1138
1134
|
out("");
|
|
1139
1135
|
if (rebuildable.length > 0) {
|
|
@@ -1171,7 +1167,7 @@ async function dbCommand(subcommand, rawArgs) {
|
|
|
1171
1167
|
for (const d of destructive) outWarn(chalk.red(` ${d.kind}${d.detail ? ` (${d.detail})` : ""}: `) + chalk.gray(d.statement.replace(/\s+/g, " ")));
|
|
1172
1168
|
outWarn("");
|
|
1173
1169
|
outWarn(chalk.yellow(" Full planned changes:"));
|
|
1174
|
-
outWarn(chalk.gray(
|
|
1170
|
+
outWarn(chalk.gray(planListing.split("\n").map((l) => ` ${l}`).join("\n")));
|
|
1175
1171
|
outWarn("");
|
|
1176
1172
|
if (decision === "refuse") {
|
|
1177
1173
|
outError(chalk.red(" ✗ Aborting: destructive changes require confirmation."));
|
|
@@ -1193,9 +1189,9 @@ async function dbCommand(subcommand, rawArgs) {
|
|
|
1193
1189
|
await runAtlas("schema", [
|
|
1194
1190
|
"apply",
|
|
1195
1191
|
"--to",
|
|
1196
|
-
|
|
1192
|
+
DESIRED_STATE_URL,
|
|
1197
1193
|
"--auto-approve"
|
|
1198
|
-
], collectionsPath);
|
|
1194
|
+
], collectionsPath, { throwOnFailure: true });
|
|
1199
1195
|
} catch (err) {
|
|
1200
1196
|
if (rebuildable.length > 0 && databaseUrl) {
|
|
1201
1197
|
out(chalk.gray(" The apply failed — rebuilding the generated columns it needed out of the way."));
|
|
@@ -1205,6 +1201,7 @@ async function dbCommand(subcommand, rawArgs) {
|
|
|
1205
1201
|
}
|
|
1206
1202
|
out("");
|
|
1207
1203
|
if (databaseUrl) {
|
|
1204
|
+
await lockManagedTables(databaseUrl, collectionsPath);
|
|
1208
1205
|
await ensureAuthTables(databaseUrl, collectionsPath);
|
|
1209
1206
|
await applyVectorDdl(databaseUrl);
|
|
1210
1207
|
await applySearchDdl(databaseUrl);
|
|
@@ -1248,6 +1245,58 @@ async function ensureAuthSchemaAndFunctions(databaseUrl) {
|
|
|
1248
1245
|
}
|
|
1249
1246
|
}
|
|
1250
1247
|
/**
|
|
1248
|
+
* Switch row-level security on for every table the collections declare, right
|
|
1249
|
+
* after Atlas has applied the schema.
|
|
1250
|
+
*
|
|
1251
|
+
* Atlas cannot carry `ENABLE ROW LEVEL SECURITY` in `schema.sql`: its free tier
|
|
1252
|
+
* neither plans it nor reads it back, so a table it creates is born with RLS
|
|
1253
|
+
* off — and `rebase_user`, the role every authenticated request runs as, holds
|
|
1254
|
+
* DML on it from that moment through the schema's default privileges. RLS used
|
|
1255
|
+
* to arrive with the policies, the last step of the push; a refusal from the
|
|
1256
|
+
* vector, search or trigger step in between left the new table readable and
|
|
1257
|
+
* writable by every caller, with no policy, until a later push or boot fixed
|
|
1258
|
+
* it — and a deployment with `REBASE_MIGRATE_ON_BOOT=none` never did. Locked
|
|
1259
|
+
* first, a failure later leaves a table that denies, not one that is open.
|
|
1260
|
+
*
|
|
1261
|
+
* Fatal when a table cannot be locked, and before the steps that follow: the
|
|
1262
|
+
* role provisioning at the end re-grants on every table in the schema, which
|
|
1263
|
+
* would undo the revoke that is the fallback here.
|
|
1264
|
+
*/
|
|
1265
|
+
async function lockManagedTables(databaseUrl, collectionsPath) {
|
|
1266
|
+
let unsecured;
|
|
1267
|
+
let userRole;
|
|
1268
|
+
try {
|
|
1269
|
+
const { lockCollectionTables } = await import("./ensure-collection-policies-B1ureSIV.js");
|
|
1270
|
+
const { loadCollections } = await import("./doctor-C-sYWbmt.js").then((n) => n.t);
|
|
1271
|
+
userRole = (await import("./rls-enforcement-CfXOJJaW.js").then((n) => n.o)).REBASE_USER_ROLE;
|
|
1272
|
+
const collections = await loadCollections(path.resolve(process.cwd(), collectionsPath));
|
|
1273
|
+
const { Client } = await import("pg");
|
|
1274
|
+
const client = new Client({ connectionString: databaseUrl });
|
|
1275
|
+
await client.connect();
|
|
1276
|
+
try {
|
|
1277
|
+
({unsecured} = await lockCollectionTables({ query: async (text) => ({ rows: (await client.query(text)).rows }) }, collections));
|
|
1278
|
+
} finally {
|
|
1279
|
+
await client.end();
|
|
1280
|
+
}
|
|
1281
|
+
} catch (err) {
|
|
1282
|
+
outError(chalk.red(`\n ✗ The schema was applied, but row-level security could not be switched on for its tables: ${err instanceof Error ? err.message : String(err)}`));
|
|
1283
|
+
outError(chalk.gray(" A table this push created may be readable and writable by every authenticated request\n until it is. Re-run `rebase db push` — it locks every collection table before anything else."));
|
|
1284
|
+
process.exit(1);
|
|
1285
|
+
}
|
|
1286
|
+
if (unsecured.length === 0) return;
|
|
1287
|
+
outError(chalk.red("\n ✗ The schema was applied, but row-level security could not be switched on for:"));
|
|
1288
|
+
for (const u of unsecured) {
|
|
1289
|
+
outError(chalk.red(` ${u.table}: ${u.error}`));
|
|
1290
|
+
outError(chalk.gray(u.grantWithdrawn ? ` Its privileges were taken back from ${userRole}, so it is unreachable rather than unprotected.` : ` ${userRole} still holds its privileges: every authenticated request can read and write every row.`));
|
|
1291
|
+
}
|
|
1292
|
+
outError(chalk.gray(" Nothing after the schema apply ran. Fix the cause — the connection role must own these\n tables, or be able to ALTER them — and run `rebase db push` again, or as their owner:"));
|
|
1293
|
+
for (const u of unsecured) {
|
|
1294
|
+
const [schema, ...table] = u.table.split(".");
|
|
1295
|
+
outError(chalk.bold(` ALTER TABLE "${schema}"."${table.join(".")}" ENABLE ROW LEVEL SECURITY;`));
|
|
1296
|
+
}
|
|
1297
|
+
process.exit(1);
|
|
1298
|
+
}
|
|
1299
|
+
/**
|
|
1251
1300
|
* Create the framework auth tables (e.g. `rebase.users`) that the generated RLS
|
|
1252
1301
|
* policies reference, before `applyPolicies` runs. Mirrors what the server does
|
|
1253
1302
|
* at boot (`PostgresBootstrapper.initializeAuth` → `ensureAuthTablesExist`).
|
|
@@ -1261,8 +1310,8 @@ async function ensureAuthSchemaAndFunctions(databaseUrl) {
|
|
|
1261
1310
|
async function ensureAuthTables(databaseUrl, collectionsPath) {
|
|
1262
1311
|
try {
|
|
1263
1312
|
const { drizzle } = await import("drizzle-orm/node-postgres");
|
|
1264
|
-
const { ensureAuthTablesExist } = await import("./ensure-tables-
|
|
1265
|
-
const { loadCollections } = await import("./doctor-
|
|
1313
|
+
const { ensureAuthTablesExist } = await import("./ensure-tables-BmI_tRxc.js").then((n) => n.n);
|
|
1314
|
+
const { loadCollections } = await import("./doctor-C-sYWbmt.js").then((n) => n.t);
|
|
1266
1315
|
const { Client } = await import("pg");
|
|
1267
1316
|
const authCollection = (await loadCollections(path.resolve(process.cwd(), collectionsPath))).find((c) => {
|
|
1268
1317
|
const a = c.auth;
|
|
@@ -1289,7 +1338,7 @@ async function ensureRlsUserRole(databaseUrl) {
|
|
|
1289
1338
|
const schemas = ["public", "rebase"];
|
|
1290
1339
|
let rls;
|
|
1291
1340
|
try {
|
|
1292
|
-
rls = await import("./rls-enforcement-
|
|
1341
|
+
rls = await import("./rls-enforcement-CfXOJJaW.js").then((n) => n.o);
|
|
1293
1342
|
} catch (err) {
|
|
1294
1343
|
outError(chalk.red(`\n ✗ Could not load the RLS provisioning module: ${err instanceof Error ? err.message : String(err)}`));
|
|
1295
1344
|
return;
|
|
@@ -1338,7 +1387,7 @@ async function retireLegacyAuthSchema(databaseUrl) {
|
|
|
1338
1387
|
}
|
|
1339
1388
|
async function applyPolicies(databaseUrl) {
|
|
1340
1389
|
try {
|
|
1341
|
-
const policiesPath = path.
|
|
1390
|
+
const policiesPath = path.join(generatedSqlDir(), "policies.sql");
|
|
1342
1391
|
if (!fs.existsSync(policiesPath)) return;
|
|
1343
1392
|
out(chalk.gray(" Step 3/3: Applying RLS policies to database..."));
|
|
1344
1393
|
out("");
|
|
@@ -1374,8 +1423,8 @@ async function applyPolicies(databaseUrl) {
|
|
|
1374
1423
|
*/
|
|
1375
1424
|
async function reconcilePolicies(databaseUrl, collectionsPath) {
|
|
1376
1425
|
try {
|
|
1377
|
-
const { checkPolicyDrift, dropOrphanedPolicies, formatPolicyDrift, hasDrift } = await import("./policy-drift-
|
|
1378
|
-
const { loadCollections } = await import("./doctor-
|
|
1426
|
+
const { checkPolicyDrift, dropOrphanedPolicies, formatPolicyDrift, hasDrift } = await import("./policy-drift-B-J2hhm0.js").then((n) => n.a);
|
|
1427
|
+
const { loadCollections } = await import("./doctor-C-sYWbmt.js").then((n) => n.t);
|
|
1379
1428
|
const collections = await loadCollections(path.resolve(process.cwd(), collectionsPath));
|
|
1380
1429
|
const { Client } = await import("pg");
|
|
1381
1430
|
const client = new Client({ connectionString: databaseUrl });
|
|
@@ -1457,7 +1506,7 @@ async function branchCommand(rawArgs) {
|
|
|
1457
1506
|
process.exit(1);
|
|
1458
1507
|
}
|
|
1459
1508
|
const { DatabasePoolManager } = await import("./databasePoolManager-Bj5FbeAs.js").then((n) => n.n);
|
|
1460
|
-
const { BranchService } = await import("./BranchService-
|
|
1509
|
+
const { BranchService } = await import("./BranchService-BRt78gfa.js").then((n) => n.n);
|
|
1461
1510
|
const { drizzle } = await import("drizzle-orm/node-postgres");
|
|
1462
1511
|
const { Pool } = await import("pg");
|
|
1463
1512
|
const pool = new Pool({
|
|
@@ -1816,6 +1865,7 @@ async function runAtlas(domain, args, collectionsPath, opts = {}) {
|
|
|
1816
1865
|
latestMigrationVersion: latestMigrationVersion()
|
|
1817
1866
|
}) ?? diagnoseDbError({ message: stderrText }, databaseUrl);
|
|
1818
1867
|
if (hint) outError(hint);
|
|
1868
|
+
if (opts.throwOnFailure) throw Object.assign(/* @__PURE__ */ new Error(`atlas ${domain} ${args.join(" ")} failed`), { alreadyReported: true });
|
|
1819
1869
|
process.exit(1);
|
|
1820
1870
|
}
|
|
1821
1871
|
if (opts.captureStdout) return stdoutText.trim().length > 0 ? stdoutText : stderrText;
|
|
@@ -1837,7 +1887,11 @@ async function generatePostgresDdlCommand(rawArgs) {
|
|
|
1837
1887
|
process.exit(1);
|
|
1838
1888
|
}
|
|
1839
1889
|
const collectionsPath = argsList["--collections"] || path.join("..", "config", "collections");
|
|
1840
|
-
const outputPath = argsList["--output"] || path.join("
|
|
1890
|
+
const outputPath = argsList["--output"] || path.join(".rebase/sql", "schema.sql");
|
|
1891
|
+
if (!argsList["--output"]) {
|
|
1892
|
+
const retired = prepareGeneratedSqlDir();
|
|
1893
|
+
if (retired.length > 0) out(chalk.gray(` Generated SQL is written to ${GENERATED_SQL_DIR}/ now, which is not committed. Removed the old copies — commit the deletion:\n ${retired.join(", ")}`));
|
|
1894
|
+
}
|
|
1841
1895
|
const cmdParts = [
|
|
1842
1896
|
ddl.bin,
|
|
1843
1897
|
ddl.script,
|
|
@@ -1889,9 +1943,9 @@ async function schemaStaleCommand(rawArgs) {
|
|
|
1889
1943
|
const schemaFile = path.resolve(process.cwd(), outputPath);
|
|
1890
1944
|
const fix = Boolean(argsList["--fix"]);
|
|
1891
1945
|
const generatedExists = fs.existsSync(schemaFile);
|
|
1892
|
-
const { loadCollections } = await import("./doctor-
|
|
1946
|
+
const { loadCollections } = await import("./doctor-C-sYWbmt.js").then((n) => n.t);
|
|
1893
1947
|
const { findLegacyForeignKeyNames, compareGeneratedDeclarations, staleVerdict } = await import("./generated-schema-staleness-Di9c4ZxN.js").then((n) => n.r);
|
|
1894
|
-
const { generateSchema } = await import("./generate-drizzle-schema-logic-
|
|
1948
|
+
const { generateSchema } = await import("./generate-drizzle-schema-logic-sSFDp6LR.js").then((n) => n.n);
|
|
1895
1949
|
const { relationalCollections } = await import("@rebasepro/common");
|
|
1896
1950
|
let stale = [];
|
|
1897
1951
|
let differences = [];
|