@rebasepro/server-postgres 0.12.1-canary.gcfa333c → 0.12.1-canary.gddbd489
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/PostgresBackendDriver.d.ts +1 -1
- package/dist/PostgresBootstrapper.d.ts +25 -1
- package/dist/auth/services.d.ts +6 -1
- package/dist/backup/backup-service.d.ts +10 -1
- package/dist/backup/pg-tools.d.ts +47 -0
- package/dist/{backup-service-DH9kPg-E.js → backup-service-CD8o_1Sl.js} +144 -11
- package/dist/backup-service-CD8o_1Sl.js.map +1 -0
- package/dist/cli-helpers.d.ts +39 -0
- package/dist/{connection-B5Wndbr1.js → connection-BuZ97wsr.js} +57 -3
- package/dist/connection-BuZ97wsr.js.map +1 -0
- package/dist/connection.d.ts +42 -0
- package/dist/{ensure-collection-policies-Vl3Cv1Q9.js → ensure-collection-policies-ViG8XiPn.js} +2 -2
- package/dist/{ensure-collection-policies-Vl3Cv1Q9.js.map → ensure-collection-policies-ViG8XiPn.js.map} +1 -1
- package/dist/{ensure-collection-tables-DsDsNl6o.js → ensure-collection-tables-CBQdOETu.js} +72 -12
- package/dist/ensure-collection-tables-CBQdOETu.js.map +1 -0
- package/dist/index.es.js +990 -677
- package/dist/index.es.js.map +1 -1
- package/dist/policy-CeA1JcxP.js +105 -0
- package/dist/policy-CeA1JcxP.js.map +1 -0
- package/dist/schema/ensure-collection-tables.d.ts +21 -1
- package/dist/schema/generate-postgres-ddl-logic.d.ts +19 -0
- package/dist/schema/introspect-db-constraints.d.ts +57 -0
- package/dist/schema/introspect-db-logic.d.ts +94 -5
- package/dist/schema/introspect-db-queries.d.ts +119 -0
- package/dist/schema/introspect-db-structure.d.ts +263 -0
- package/dist/schema/introspect-db-types.d.ts +11 -0
- package/dist/services/FetchService.d.ts +4 -1
- package/dist/services/RelationService.d.ts +24 -1
- package/dist/services/channel-bus/index.d.ts +1 -7
- package/dist/services/collection-helpers.d.ts +36 -2
- package/dist/services/dataService.d.ts +3 -1
- package/dist/services/row-pipeline.d.ts +1 -1
- package/dist/{src-DihrDFuP.js → src-DlPBctw_.js} +217 -101
- package/dist/src-DlPBctw_.js.map +1 -0
- package/dist/utils/connection-string.d.ts +29 -0
- package/dist/utils/drizzle-conditions.d.ts +5 -4
- package/dist/utils/pg-error-utils.d.ts +16 -0
- package/dist/{websocket-BKcGvILX.js → websocket-B2LsrINK.js} +8 -6
- package/dist/websocket-B2LsrINK.js.map +1 -0
- package/package.json +6 -6
- package/src/PostgresAdapter.ts +7 -2
- package/src/PostgresBackendDriver.ts +4 -0
- package/src/PostgresBootstrapper.ts +83 -22
- package/src/auth/services.ts +6 -3
- package/src/backup/backup-cli.ts +41 -2
- package/src/backup/backup-service.ts +38 -5
- package/src/backup/pg-tools.ts +96 -3
- package/src/cli-helpers.ts +70 -0
- package/src/cli.ts +44 -26
- package/src/collections/validate-relations.ts +15 -0
- package/src/connection.ts +73 -0
- package/src/data-transformer.ts +9 -3
- package/src/databasePoolManager.ts +5 -2
- package/src/schema/ensure-collection-tables.ts +81 -10
- package/src/schema/generate-drizzle-schema-logic.ts +35 -3
- package/src/schema/generate-postgres-ddl-logic.ts +50 -6
- package/src/schema/introspect-db-constraints.ts +385 -0
- package/src/schema/introspect-db-inference.ts +18 -8
- package/src/schema/introspect-db-logic.ts +385 -71
- package/src/schema/introspect-db-queries.ts +326 -0
- package/src/schema/introspect-db-structure.ts +670 -0
- package/src/schema/introspect-db-types.ts +56 -0
- package/src/schema/introspect-db.ts +37 -80
- package/src/security/policy-drift.test.ts +11 -3
- package/src/services/FetchService.ts +90 -14
- package/src/services/PersistService.ts +20 -6
- package/src/services/RelationService.ts +211 -45
- package/src/services/channel-bus/index.ts +0 -9
- package/src/services/collection-helpers.ts +69 -3
- package/src/services/dataService.ts +3 -1
- package/src/services/realtimeService.ts +3 -3
- package/src/services/row-pipeline.ts +1 -1
- package/src/utils/connection-string.ts +58 -0
- package/src/utils/drizzle-conditions.ts +31 -6
- package/src/utils/pg-error-utils.ts +19 -0
- package/src/websocket.ts +18 -9
- package/dist/backup-service-DH9kPg-E.js.map +0 -1
- package/dist/connection-B5Wndbr1.js.map +0 -1
- package/dist/ensure-collection-tables-DsDsNl6o.js.map +0 -1
- package/dist/src-DihrDFuP.js.map +0 -1
- package/dist/websocket-BKcGvILX.js.map +0 -1
|
@@ -105,7 +105,7 @@ export declare class PostgresBackendDriver implements DataDriver {
|
|
|
105
105
|
delete<M extends Record<string, unknown>>({ row, collection }: DeleteProps<M>): Promise<void>;
|
|
106
106
|
deleteAll(path: string): Promise<void>;
|
|
107
107
|
checkUniqueField(path: string, name: string, value: unknown, id?: string, collection?: CollectionConfig): Promise<boolean>;
|
|
108
|
-
count<M extends Record<string, unknown>>({ path, collection, filter, searchString }: FetchCollectionProps<M>): Promise<number>;
|
|
108
|
+
count<M extends Record<string, unknown>>({ path, collection, filter, logical, searchString }: FetchCollectionProps<M>): Promise<number>;
|
|
109
109
|
private getTargetDb;
|
|
110
110
|
executeSql(sqlText: string, options?: {
|
|
111
111
|
database?: string;
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Implements the `BackendBootstrapper` interface for PostgreSQL.
|
|
5
5
|
*/
|
|
6
6
|
import { NodePgDatabase } from "drizzle-orm/node-postgres";
|
|
7
|
-
import { BackendBootstrapper, type RealtimeChannelsConfig } from "@rebasepro/types";
|
|
7
|
+
import { BackendBootstrapper, CollectionConfig, type RealtimeChannelsConfig } from "@rebasepro/types";
|
|
8
8
|
import { PostgresBackendDriver } from "./PostgresBackendDriver";
|
|
9
9
|
import { RealtimeService } from "./services/realtimeService";
|
|
10
10
|
import { DatabasePoolManager } from "./databasePoolManager";
|
|
@@ -65,6 +65,30 @@ export interface PostgresDriverInternals {
|
|
|
65
65
|
*/
|
|
66
66
|
provisionCdcForTables?: (tables: CdcTableRef[]) => Promise<void>;
|
|
67
67
|
}
|
|
68
|
+
/**
|
|
69
|
+
* Which table name the boot-time drift check should look for, for one collection.
|
|
70
|
+
*
|
|
71
|
+
* A declared `table` IS the table name, not a hint to be second-guessed. This
|
|
72
|
+
* used to ask the registry whether it had indexed the declared name and fall
|
|
73
|
+
* back to the SLUG when it had not — but "the registry does not know this table"
|
|
74
|
+
* is exactly the condition the drift check exists to report, so the fallback
|
|
75
|
+
* fired precisely when it was most harmful.
|
|
76
|
+
*
|
|
77
|
+
* A collection with `slug: "usage-daily", table: "usage_daily"` was reported as
|
|
78
|
+
* missing table `usage-daily`: a name that does not exist, should never exist,
|
|
79
|
+
* and that nobody can find by looking. Worse, the remediation the caller prints
|
|
80
|
+
* says to run `rebase db push` — which would then CREATE that invented table
|
|
81
|
+
* beside the correct one, the same "second copy" hazard the misplaced-schema
|
|
82
|
+
* branch further down exists to prevent. Seen in production, where a correctly
|
|
83
|
+
* migrated database reported drift on every boot.
|
|
84
|
+
*
|
|
85
|
+
* The slug is used only when nothing was declared, which is the config shape
|
|
86
|
+
* where the slug genuinely is the table name.
|
|
87
|
+
*
|
|
88
|
+
* Exported for its own test: the caller needs a live pool and a real database,
|
|
89
|
+
* and this is the part that was wrong.
|
|
90
|
+
*/
|
|
91
|
+
export declare function resolveDriftCheckName(col: CollectionConfig, registeredTableNames: string[]): string;
|
|
68
92
|
/**
|
|
69
93
|
* Default PostgreSQL bootstrapper.
|
|
70
94
|
*
|
package/dist/auth/services.d.ts
CHANGED
|
@@ -23,8 +23,13 @@ export interface AuthSchemaTables {
|
|
|
23
23
|
*
|
|
24
24
|
* Whitespace goes too: a trailing space survives the fold and reproduces the
|
|
25
25
|
* problem exactly.
|
|
26
|
+
*
|
|
27
|
+
* Re-exported rather than defined here: `@rebasepro/server` and
|
|
28
|
+
* `@rebasepro/server-mongo` write this column too, and a second copy of this
|
|
29
|
+
* rule is the defect it exists to prevent.
|
|
26
30
|
*/
|
|
27
|
-
|
|
31
|
+
import { normalizeEmail } from "@rebasepro/common";
|
|
32
|
+
export { normalizeEmail };
|
|
28
33
|
/**
|
|
29
34
|
* PostgreSQL implementation of UserRepository.
|
|
30
35
|
* Handles all user-related database operations using Drizzle ORM.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { StorageController } from "@rebasepro/server";
|
|
2
|
-
import { BackupDestination, VersionCompatibility } from "./pg-tools";
|
|
2
|
+
import { BackupDestination, type RowSecurityIdentity, VersionCompatibility } from "./pg-tools";
|
|
3
3
|
import { BackupObject, RetentionOptions } from "./retention";
|
|
4
4
|
export declare class BackupToolError extends Error {
|
|
5
5
|
readonly hint?: string | undefined;
|
|
@@ -54,6 +54,15 @@ export declare function createDump(opts: {
|
|
|
54
54
|
inheritStdio?: boolean;
|
|
55
55
|
includeGlobals?: boolean;
|
|
56
56
|
env?: Record<string, string | undefined>;
|
|
57
|
+
/**
|
|
58
|
+
* Dump with row security left on, reading as this identity.
|
|
59
|
+
*
|
|
60
|
+
* The escape hatch for a managed Postgres, where the dumping role owns
|
|
61
|
+
* nothing and has no `BYPASSRLS`. Off by default, and deliberately so: with
|
|
62
|
+
* row security on, `pg_dump` stops erroring on rows it cannot see and
|
|
63
|
+
* simply omits them. See {@link RowSecurityIdentity}.
|
|
64
|
+
*/
|
|
65
|
+
rowSecurity?: RowSecurityIdentity;
|
|
57
66
|
}): Promise<BackupResult>;
|
|
58
67
|
/**
|
|
59
68
|
* Cheap integrity check on a freshly written dump: it must be non-empty and
|
|
@@ -79,6 +79,36 @@ export declare function parseBackupDestination(out: string): BackupDestination;
|
|
|
79
79
|
* doubled slash.
|
|
80
80
|
*/
|
|
81
81
|
export declare function joinStorageKey(prefix: string, fileName: string): string;
|
|
82
|
+
/**
|
|
83
|
+
* The identity `pg_dump` reads rows as, when row security is left on.
|
|
84
|
+
*
|
|
85
|
+
* Not optional, and that is the whole design. `pg_dump --enable-row-security`
|
|
86
|
+
* on its own is the dangerous command in this file: it turns the "query would
|
|
87
|
+
* be affected by row-level security policy" *error* into a dump that exits 0
|
|
88
|
+
* and is silently missing every row the dumping role's policies exclude. A
|
|
89
|
+
* backup that looks fine and restores most of your data is worse than one that
|
|
90
|
+
* refused to run.
|
|
91
|
+
*
|
|
92
|
+
* So the flag is unreachable without a subject to evaluate the policies
|
|
93
|
+
* against. Rebase's generated policies read `app.uid` and `app.user_roles`;
|
|
94
|
+
* supplying an admin role satisfies the `admin_full_access` rule and the dump
|
|
95
|
+
* sees everything that rule sees.
|
|
96
|
+
*/
|
|
97
|
+
export interface RowSecurityIdentity {
|
|
98
|
+
/** Written to `app.uid`. Any non-empty value — it is only an audit trail. */
|
|
99
|
+
uid: string;
|
|
100
|
+
/** Written to `app.user_roles`. Must include a role the policies admit. */
|
|
101
|
+
roles: string[];
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* `PGOPTIONS` carrying an identity, for a libpq tool that has no other way to
|
|
105
|
+
* set a GUC.
|
|
106
|
+
*
|
|
107
|
+
* A backslash escape rather than quoting, which is what libpq's `-c` parsing
|
|
108
|
+
* takes: a space inside a value ends the option otherwise, so a role list is
|
|
109
|
+
* comma-joined and never spaced.
|
|
110
|
+
*/
|
|
111
|
+
export declare function buildRowSecurityPgOptions(identity: RowSecurityIdentity): string;
|
|
82
112
|
/**
|
|
83
113
|
* Assemble the `pg_dump` argument vector. Uses the custom format (`-Fc`),
|
|
84
114
|
* which is compressed and restorable selectively via `pg_restore`.
|
|
@@ -90,7 +120,24 @@ export declare function buildPgDumpArgs(opts: {
|
|
|
90
120
|
excludeSchemas?: string[];
|
|
91
121
|
/** Number of parallel jobs (directory format only; ignored for -Fc). */
|
|
92
122
|
noOwner?: boolean;
|
|
123
|
+
/**
|
|
124
|
+
* Dump with row security on, as this identity. Omit — which is the default
|
|
125
|
+
* — and `pg_dump` errors rather than skipping rows it cannot see.
|
|
126
|
+
*/
|
|
127
|
+
rowSecurity?: RowSecurityIdentity;
|
|
93
128
|
}): string[];
|
|
129
|
+
/**
|
|
130
|
+
* Whether a `pg_dump` failure is the row-security one, and what to do about it.
|
|
131
|
+
*
|
|
132
|
+
* The error text names the table and nothing else, so the first read of it is
|
|
133
|
+
* "why would a backup be affected by RLS at all?" — the answer being that the
|
|
134
|
+
* dumping role is not the tables' owner and has no `BYPASSRLS`, which is the
|
|
135
|
+
* normal state of the `postgres` user on Cloud SQL, RDS and every other managed
|
|
136
|
+
* Postgres. Nothing about that is visible from the message.
|
|
137
|
+
*
|
|
138
|
+
* Returns `null` for any other failure, so the caller reports it unchanged.
|
|
139
|
+
*/
|
|
140
|
+
export declare function diagnoseRowSecurityDumpFailure(error: unknown): string | null;
|
|
94
141
|
/**
|
|
95
142
|
* Assemble the `pg_restore` argument vector for a custom-format dump.
|
|
96
143
|
*/
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire as __createRequire } from "module";
|
|
2
2
|
import process from "process";
|
|
3
3
|
__createRequire(import.meta.url);
|
|
4
|
-
import { c as
|
|
4
|
+
import { c as __exportAll, l as __require, s as __commonJSMin, u as __toESM } from "./connection-BuZ97wsr.js";
|
|
5
5
|
import "./src-DoU9yPqq.js";
|
|
6
6
|
import "@rebasepro/server";
|
|
7
7
|
import fs from "fs";
|
|
@@ -23,9 +23,72 @@ import { appendFileSync, createReadStream, createWriteStream, readFileSync, stat
|
|
|
23
23
|
import { finished } from "node:stream/promises";
|
|
24
24
|
import { Duplex, PassThrough, Readable, Transform, Writable, getDefaultHighWaterMark } from "node:stream";
|
|
25
25
|
import { Buffer as Buffer$1 } from "node:buffer";
|
|
26
|
+
import "module";
|
|
26
27
|
import { fileURLToPath as fileURLToPath$1 } from "url";
|
|
28
|
+
//#region src/utils/connection-string.ts
|
|
29
|
+
/**
|
|
30
|
+
* Connection-string rewrites for the tools Rebase shells out to.
|
|
31
|
+
*
|
|
32
|
+
* Pure and dependency-free: `pg-tools` builds argument vectors without a live
|
|
33
|
+
* server, and these have to be usable from there.
|
|
34
|
+
*/
|
|
35
|
+
/**
|
|
36
|
+
* The `sslmode` values libpq accepts. `no-verify` is conspicuously not one.
|
|
37
|
+
*/
|
|
38
|
+
var LIBPQ_SSLMODES = /* @__PURE__ */ new Set([
|
|
39
|
+
"disable",
|
|
40
|
+
"allow",
|
|
41
|
+
"prefer",
|
|
42
|
+
"require",
|
|
43
|
+
"verify-ca",
|
|
44
|
+
"verify-full"
|
|
45
|
+
]);
|
|
46
|
+
/**
|
|
47
|
+
* Make a connection string safe to hand to a libpq program.
|
|
48
|
+
*
|
|
49
|
+
* `sslmode=no-verify` is a node-postgres convention — encrypt, but do not check
|
|
50
|
+
* the certificate — and libpq does not have it. It does not degrade or warn:
|
|
51
|
+
*
|
|
52
|
+
* psql: error: invalid sslmode value: "no-verify"
|
|
53
|
+
*
|
|
54
|
+
* which means a `DATABASE_URL` that works perfectly for the app makes `psql`,
|
|
55
|
+
* `pg_dump`, `pg_restore` and Atlas all refuse to start, with an error that
|
|
56
|
+
* points at the value rather than at the convention it comes from. It has cost
|
|
57
|
+
* this project time more than once.
|
|
58
|
+
*
|
|
59
|
+
* `require` is the honest translation: libpq's `require` encrypts and does not
|
|
60
|
+
* verify the certificate either, which is exactly what `no-verify` asks for.
|
|
61
|
+
* Nothing is relaxed by the rewrite — `verify-ca` and `verify-full` are left
|
|
62
|
+
* alone, so a connection string that asked for verification still gets it.
|
|
63
|
+
*
|
|
64
|
+
* Only `sslmode` is touched, and only when it is a value libpq would reject.
|
|
65
|
+
* Anything unparseable is returned as given: a connection that works
|
|
66
|
+
* unverified beats one this corrupted.
|
|
67
|
+
*/
|
|
68
|
+
function forLibpq(connectionString) {
|
|
69
|
+
let url;
|
|
70
|
+
try {
|
|
71
|
+
url = new URL(connectionString);
|
|
72
|
+
} catch {
|
|
73
|
+
return connectionString;
|
|
74
|
+
}
|
|
75
|
+
if (url.protocol !== "postgres:" && url.protocol !== "postgresql:") return connectionString;
|
|
76
|
+
const sslmode = url.searchParams.get("sslmode");
|
|
77
|
+
if (sslmode === null || LIBPQ_SSLMODES.has(sslmode)) return connectionString;
|
|
78
|
+
url.searchParams.set("sslmode", "require");
|
|
79
|
+
url.search = Array.from(url.searchParams.entries()).map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`).join("&");
|
|
80
|
+
return url.toString();
|
|
81
|
+
}
|
|
82
|
+
//#endregion
|
|
27
83
|
//#region src/backup/pg-tools.ts
|
|
28
84
|
/**
|
|
85
|
+
* Pure helpers for the backup/restore commands.
|
|
86
|
+
*
|
|
87
|
+
* Everything in this file is side-effect free so it can be unit-tested
|
|
88
|
+
* without a live Postgres server, matching the constraint that CI must
|
|
89
|
+
* not require a database.
|
|
90
|
+
*/
|
|
91
|
+
/**
|
|
29
92
|
* Extract the database name from a Postgres connection string.
|
|
30
93
|
* Returns `null` when the URL has no database path (e.g. bare host).
|
|
31
94
|
*/
|
|
@@ -155,6 +218,22 @@ function joinStorageKey(prefix, fileName) {
|
|
|
155
218
|
return clean.length > 0 ? `${clean}/${fileName}` : fileName;
|
|
156
219
|
}
|
|
157
220
|
/**
|
|
221
|
+
* `PGOPTIONS` carrying an identity, for a libpq tool that has no other way to
|
|
222
|
+
* set a GUC.
|
|
223
|
+
*
|
|
224
|
+
* A backslash escape rather than quoting, which is what libpq's `-c` parsing
|
|
225
|
+
* takes: a space inside a value ends the option otherwise, so a role list is
|
|
226
|
+
* comma-joined and never spaced.
|
|
227
|
+
*/
|
|
228
|
+
function buildRowSecurityPgOptions(identity) {
|
|
229
|
+
const escape = (value) => value.replace(/([\\ ])/g, "\\$1");
|
|
230
|
+
return [
|
|
231
|
+
`-c app.uid=${escape(identity.uid)}`,
|
|
232
|
+
`-c app.user_id=${escape(identity.uid)}`,
|
|
233
|
+
`-c app.user_roles=${escape(identity.roles.join(","))}`
|
|
234
|
+
].join(" ");
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
158
237
|
* Assemble the `pg_dump` argument vector. Uses the custom format (`-Fc`),
|
|
159
238
|
* which is compressed and restorable selectively via `pg_restore`.
|
|
160
239
|
*/
|
|
@@ -165,18 +244,56 @@ function buildPgDumpArgs(opts) {
|
|
|
165
244
|
`--file=${opts.outFile}`
|
|
166
245
|
];
|
|
167
246
|
if (opts.noOwner) args.push("--no-owner");
|
|
247
|
+
if (opts.rowSecurity) args.push("--enable-row-security");
|
|
168
248
|
for (const schema of opts.excludeSchemas ?? []) args.push(`--exclude-schema=${schema}`);
|
|
169
|
-
args.push(opts.connectionString);
|
|
249
|
+
args.push(forLibpq(opts.connectionString));
|
|
170
250
|
return args;
|
|
171
251
|
}
|
|
172
252
|
/**
|
|
253
|
+
* Whether a `pg_dump` failure is the row-security one, and what to do about it.
|
|
254
|
+
*
|
|
255
|
+
* The error text names the table and nothing else, so the first read of it is
|
|
256
|
+
* "why would a backup be affected by RLS at all?" — the answer being that the
|
|
257
|
+
* dumping role is not the tables' owner and has no `BYPASSRLS`, which is the
|
|
258
|
+
* normal state of the `postgres` user on Cloud SQL, RDS and every other managed
|
|
259
|
+
* Postgres. Nothing about that is visible from the message.
|
|
260
|
+
*
|
|
261
|
+
* Returns `null` for any other failure, so the caller reports it unchanged.
|
|
262
|
+
*/
|
|
263
|
+
function diagnoseRowSecurityDumpFailure(error) {
|
|
264
|
+
const text = [error?.stderr, error?.message].map((part) => typeof part === "string" ? part : "").join("\n");
|
|
265
|
+
if (!/row-level security policy/i.test(text)) return null;
|
|
266
|
+
const table = text.match(/for table "([^"]+)"/)?.[1];
|
|
267
|
+
return [
|
|
268
|
+
`pg_dump cannot read ${table ? `"${table}"` : "one of the tables"} because row-level security applies to it.`,
|
|
269
|
+
"",
|
|
270
|
+
" The dumping role is neither the table's owner nor `BYPASSRLS`, which is the normal",
|
|
271
|
+
" state of the `postgres` user on Cloud SQL, RDS and other managed Postgres — there is",
|
|
272
|
+
" no superuser to hand out.",
|
|
273
|
+
"",
|
|
274
|
+
" Two ways out:",
|
|
275
|
+
"",
|
|
276
|
+
" • Grant the dumping role BYPASSRLS, or make it the owner, and run this again. The",
|
|
277
|
+
" dump then contains every row, which is what a backup should mean.",
|
|
278
|
+
"",
|
|
279
|
+
" • Re-run with --enable-row-security to dump as an admin subject instead. Rebase",
|
|
280
|
+
" sets `app.uid`/`app.user_roles` so the generated `admin_full_access` policy",
|
|
281
|
+
" admits the dump. Read the warning it prints: the result contains exactly the",
|
|
282
|
+
" rows those policies admit, and any table whose policies do not include an",
|
|
283
|
+
" admin rule comes out short — with no error.",
|
|
284
|
+
"",
|
|
285
|
+
" Do not reach for a bare `pg_dump --enable-row-security` by hand. Without the",
|
|
286
|
+
" settings above it succeeds and silently omits rows."
|
|
287
|
+
].join("\n");
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
173
290
|
* Assemble the `pg_restore` argument vector for a custom-format dump.
|
|
174
291
|
*/
|
|
175
292
|
function buildPgRestoreArgs(opts) {
|
|
176
293
|
const args = [
|
|
177
294
|
"--format=custom",
|
|
178
295
|
"--no-password",
|
|
179
|
-
`--dbname=${opts.connectionString}`
|
|
296
|
+
`--dbname=${forLibpq(opts.connectionString)}`
|
|
180
297
|
];
|
|
181
298
|
if (opts.clean) args.push("--clean", "--if-exists");
|
|
182
299
|
if (opts.noOwner) args.push("--no-owner");
|
|
@@ -209,7 +326,7 @@ function buildPgDumpallGlobalsArgs(opts) {
|
|
|
209
326
|
"--no-role-passwords",
|
|
210
327
|
"--no-password",
|
|
211
328
|
`--file=${opts.outFile}`,
|
|
212
|
-
`--dbname=${opts.connectionString}`
|
|
329
|
+
`--dbname=${forLibpq(opts.connectionString)}`
|
|
213
330
|
];
|
|
214
331
|
}
|
|
215
332
|
/**
|
|
@@ -6446,6 +6563,11 @@ createExeca(mapNode);
|
|
|
6446
6563
|
createExeca(mapScriptAsync, {}, deepScriptOptions, setScriptSync);
|
|
6447
6564
|
var { sendMessage, getOneMessage, getEachMessage, getCancelSignal } = getIpcExport();
|
|
6448
6565
|
//#endregion
|
|
6566
|
+
//#region __vite-browser-external
|
|
6567
|
+
var require___vite_browser_external = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
6568
|
+
module.exports = {};
|
|
6569
|
+
}));
|
|
6570
|
+
//#endregion
|
|
6449
6571
|
//#region ../../node_modules/.pnpm/color-name@1.1.4/node_modules/color-name/index.js
|
|
6450
6572
|
var require_color_name = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
6451
6573
|
module.exports = {
|
|
@@ -8495,6 +8617,7 @@ var require_source = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
8495
8617
|
chalk.stderr.supportsColor = stderrColor;
|
|
8496
8618
|
module.exports = chalk;
|
|
8497
8619
|
}));
|
|
8620
|
+
require___vite_browser_external();
|
|
8498
8621
|
require_source();
|
|
8499
8622
|
var moduleDir = path.dirname(fileURLToPath$1(import.meta.url));
|
|
8500
8623
|
//#endregion
|
|
@@ -8669,15 +8792,25 @@ async function createDump(opts) {
|
|
|
8669
8792
|
const outDir = opts.outDir ?? fs.mkdtempSync(path.join(os.tmpdir(), "rebase-backup-"));
|
|
8670
8793
|
fs.mkdirSync(outDir, { recursive: true });
|
|
8671
8794
|
const localFile = path.join(outDir, fileName);
|
|
8672
|
-
|
|
8795
|
+
const args = buildPgDumpArgs({
|
|
8673
8796
|
connectionString: opts.connectionString,
|
|
8674
8797
|
outFile: localFile,
|
|
8675
8798
|
excludeSchemas: opts.excludeSchemas,
|
|
8676
|
-
noOwner: opts.noOwner
|
|
8677
|
-
|
|
8678
|
-
stdio: opts.inheritStdio ? "inherit" : "pipe",
|
|
8679
|
-
env: { ...env }
|
|
8799
|
+
noOwner: opts.noOwner,
|
|
8800
|
+
rowSecurity: opts.rowSecurity
|
|
8680
8801
|
});
|
|
8802
|
+
const dumpEnv = { ...env };
|
|
8803
|
+
if (opts.rowSecurity) dumpEnv.PGOPTIONS = [env.PGOPTIONS, buildRowSecurityPgOptions(opts.rowSecurity)].filter(Boolean).join(" ");
|
|
8804
|
+
try {
|
|
8805
|
+
await execa(bin, args, {
|
|
8806
|
+
stdio: opts.inheritStdio ? "inherit" : "pipe",
|
|
8807
|
+
env: dumpEnv
|
|
8808
|
+
});
|
|
8809
|
+
} catch (error) {
|
|
8810
|
+
const diagnosis = diagnoseRowSecurityDumpFailure(error);
|
|
8811
|
+
if (!diagnosis) throw error;
|
|
8812
|
+
throw new BackupToolError(diagnosis, "Run `rebase db backup --help` for the flag, and read what it says about partial dumps.");
|
|
8813
|
+
}
|
|
8681
8814
|
const result = {
|
|
8682
8815
|
localFile,
|
|
8683
8816
|
fileName,
|
|
@@ -8861,6 +8994,6 @@ async function pruneBackups(dest, options, storage) {
|
|
|
8861
8994
|
return toDelete;
|
|
8862
8995
|
}
|
|
8863
8996
|
//#endregion
|
|
8864
|
-
export {
|
|
8997
|
+
export { parsePgToolMajor as A, checkToolServerCompatibility as C, parseBackupDestination as D, joinStorageKey as E, serverVersionNumToMajor as M, splitGlobalsStatements as N, parseBackupTimestamp as O, withDatabaseName as P, buildRowSecurityPgOptions as S, globalsFileForDump as T, buildBackupFilename as _, detectToolMajor as a, buildPgRestoreArgs as b, listBackups as c, resolvePgBinary as d, restoreDump as f, selectBackupsToPrune as g, require_source as h, createDump as i, resolveConnectionString as j, parseDbNameFromUrl as k, preflight as l, validateDump as m, applyGlobals as n, ensureDatabaseExists as o, uploadBackup as p, backup_service_exports as r, getServerVersionMajor as s, BackupToolError as t, pruneBackups as u, buildPgDumpArgs as v, diagnoseRowSecurityDumpFailure as w, buildPgRestoreListArgs as x, buildPgDumpallGlobalsArgs as y };
|
|
8865
8998
|
|
|
8866
|
-
//# sourceMappingURL=backup-service-
|
|
8999
|
+
//# sourceMappingURL=backup-service-CD8o_1Sl.js.map
|