@rebasepro/server-postgres 0.25.1 → 0.26.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-ClklxyAQ.js → BranchService-CWBnDhcv.js} +25 -9
- package/dist/BranchService-CWBnDhcv.js.map +1 -0
- package/dist/PostgresBackendDriver.d.ts +13 -0
- package/dist/PostgresBootstrapper.d.ts +7 -0
- package/dist/auth/services.d.ts +8 -1
- package/dist/auth/verify-auth-tables.d.ts +21 -0
- package/dist/{backup-cli-gijeXe0u.js → backup-cli-PoRG-zEq.js} +3 -3
- package/dist/{backup-cli-gijeXe0u.js.map → backup-cli-PoRG-zEq.js.map} +1 -1
- package/dist/{boot-ddl-DYH95Qeg.js → boot-ddl-EsgqDkx0.js} +2 -2
- package/dist/{boot-ddl-DYH95Qeg.js.map → boot-ddl-EsgqDkx0.js.map} +1 -1
- package/dist/branch-diff-CxE4VlxT.js +1396 -0
- package/dist/branch-diff-CxE4VlxT.js.map +1 -0
- package/dist/branch-diff-report-DpvVf7hR.js +48 -0
- package/dist/branch-diff-report-DpvVf7hR.js.map +1 -0
- package/dist/branching/branch-diff-report.d.ts +7 -0
- package/dist/branching/branch-diff.d.ts +115 -0
- package/dist/{cli-console-CQrQ0lAY.js → cli-console-f0k6_TsJ.js} +38 -5
- package/dist/cli-console-f0k6_TsJ.js.map +1 -0
- package/dist/cli-console.d.ts +17 -1
- package/dist/{cli-errors-DiA0XFIS.js → cli-errors-DsYyNYzd.js} +53 -2
- package/dist/cli-errors-DsYyNYzd.js.map +1 -0
- package/dist/cli.js +102 -122
- package/dist/cli.js.map +1 -1
- package/dist/{collections-schema-version-T6cGvrDi.js → collections-schema-version-D7bDI0PJ.js} +13 -9
- package/dist/collections-schema-version-D7bDI0PJ.js.map +1 -0
- package/dist/{deferred-index-build-BE0I6sYU.js → deferred-index-build-CqaOv1Xx.js} +3 -3
- package/dist/{deferred-index-build-BE0I6sYU.js.map → deferred-index-build-CqaOv1Xx.js.map} +1 -1
- package/dist/{doctor-BT--1kq3.js → doctor-DW_mlTzz.js} +81 -33
- package/dist/doctor-DW_mlTzz.js.map +1 -0
- package/dist/{ensure-collection-policies-BnGOURpG.js → ensure-collection-policies-DLWgabQ2.js} +5 -5
- package/dist/{ensure-collection-policies-BnGOURpG.js.map → ensure-collection-policies-DLWgabQ2.js.map} +1 -1
- package/dist/{ensure-collection-tables-Cet4650m.js → ensure-collection-tables-CFIRq8ni.js} +5 -5
- package/dist/{ensure-collection-tables-Cet4650m.js.map → ensure-collection-tables-CFIRq8ni.js.map} +1 -1
- package/dist/{ensure-tables-l_OgFQjN.js → ensure-tables-4nA-tfwi.js} +4 -4
- package/dist/{ensure-tables-l_OgFQjN.js.map → ensure-tables-4nA-tfwi.js.map} +1 -1
- package/dist/{enum-labels-kept-nheku1pB.js → enum-labels-kept-PcPW65xy.js} +2 -2
- package/dist/{enum-labels-kept-nheku1pB.js.map → enum-labels-kept-PcPW65xy.js.map} +1 -1
- package/dist/history/HistoryService.d.ts +7 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.es.js +226 -8
- package/dist/index.es.js.map +1 -1
- package/dist/{db-subcommands-BPoHCxJR.js → migrate-baseline-B-2Ef4Mv.js} +266 -41
- package/dist/migrate-baseline-B-2Ef4Mv.js.map +1 -0
- package/dist/{migrate-policy-stamps-3eqfhes6.js → migrate-policy-stamps-BQtFHApx.js} +5 -5
- package/dist/{migrate-policy-stamps-3eqfhes6.js.map → migrate-policy-stamps-BQtFHApx.js.map} +1 -1
- package/dist/{open-rebase-EmqVmS14.js → open-rebase-C8jQ6s5a.js} +292 -46
- package/dist/open-rebase-C8jQ6s5a.js.map +1 -0
- package/dist/open-rebase.d.ts +9 -1
- package/dist/{pg-error-utils-CFEnm2m9.js → pg-error-utils-DhiUTlVx.js} +2 -2
- package/dist/{pg-error-utils-CFEnm2m9.js.map → pg-error-utils-DhiUTlVx.js.map} +1 -1
- package/dist/{push-index-prebuild-COd7i6wm.js → push-index-prebuild-UTvB5pqH.js} +3 -3
- package/dist/{push-index-prebuild-COd7i6wm.js.map → push-index-prebuild-UTvB5pqH.js.map} +1 -1
- package/dist/push-kept-defaults-BGOlOqRQ.js +137 -0
- package/dist/push-kept-defaults-BGOlOqRQ.js.map +1 -0
- package/dist/{push-legacy-renames-CLgYYwPE.js → push-legacy-renames-BwaKi8xF.js} +3 -3
- package/dist/{push-legacy-renames-CLgYYwPE.js.map → push-legacy-renames-BwaKi8xF.js.map} +1 -1
- package/dist/{push-policy-plan-D2gpQsdv.js → push-policy-plan-DQ2tWceD.js} +2 -2
- package/dist/{push-policy-plan-D2gpQsdv.js.map → push-policy-plan-DQ2tWceD.js.map} +1 -1
- package/dist/{rls-enforcement-DDyNoOSy.js → rls-enforcement-BOHuHVlc.js} +42 -3
- package/dist/rls-enforcement-BOHuHVlc.js.map +1 -0
- package/dist/schema/destructive-sql.d.ts +16 -0
- package/dist/schema/doctor-cli.js +3 -3
- package/dist/schema/introspect-db.js +1 -1
- package/dist/schema/migration-freshness.d.ts +69 -0
- package/dist/schema/push-kept-defaults.d.ts +57 -0
- package/dist/schema/rls-bootstrap-sql.d.ts +47 -10
- package/dist/security/rls-enforcement.d.ts +18 -0
- package/dist/services/FetchService.d.ts +12 -0
- package/dist/services/channel-presence.d.ts +3 -1
- package/dist/services/nested-path.d.ts +16 -0
- package/dist/services/realtimeService.d.ts +18 -1
- package/dist/{websocket-BKZwsjmf.js → websocket-CKYc3V4N.js} +41 -12
- package/dist/websocket-CKYc3V4N.js.map +1 -0
- package/package.json +7 -7
- package/dist/BranchService-ClklxyAQ.js.map +0 -1
- package/dist/cli-console-CQrQ0lAY.js.map +0 -1
- package/dist/cli-errors-DiA0XFIS.js.map +0 -1
- package/dist/collections-schema-version-T6cGvrDi.js.map +0 -1
- package/dist/db-subcommands-BPoHCxJR.js.map +0 -1
- package/dist/doctor-BT--1kq3.js.map +0 -1
- package/dist/open-rebase-EmqVmS14.js.map +0 -1
- package/dist/rls-enforcement-DDyNoOSy.js.map +0 -1
- package/dist/websocket-BKZwsjmf.js.map +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire as __createRequire } from "module";
|
|
2
2
|
__createRequire(import.meta.url);
|
|
3
3
|
import { a as __require, i as __exportAll, n as require_arg, o as __toESM, r as __commonJSMin } from "./cli-prompt-DXG0yk-h.js";
|
|
4
|
-
import {
|
|
4
|
+
import { B as withAppClient, tt as redactConnectionPasswords } from "./cli-errors-DsYyNYzd.js";
|
|
5
5
|
import { LEGACY_RLS_SCHEMA, REBASE_SCHEMA } from "@rebasepro/types";
|
|
6
6
|
import { sqlRows } from "@rebasepro/common";
|
|
7
7
|
import { suggestNearMiss } from "@rebasepro/utils";
|
|
@@ -6194,6 +6194,7 @@ var { sendMessage, getOneMessage, getEachMessage, getCancelSignal } = getIpcExpo
|
|
|
6194
6194
|
//#region src/schema/rls-bootstrap-sql.ts
|
|
6195
6195
|
var rls_bootstrap_sql_exports = /* @__PURE__ */ __exportAll({
|
|
6196
6196
|
DROP_LEGACY_AUTH_SCHEMA_SQL: () => DROP_LEGACY_AUTH_SCHEMA_SQL,
|
|
6197
|
+
LEGACY_AUTH_SCHEMA_CONTENTS_SQL: () => LEGACY_AUTH_SCHEMA_CONTENTS_SQL,
|
|
6197
6198
|
LEGACY_RLS_DEPENDENTS_SQL: () => LEGACY_RLS_DEPENDENTS_SQL,
|
|
6198
6199
|
LEGACY_RLS_FUNCTION_DEPENDENTS_SQL: () => LEGACY_RLS_FUNCTION_DEPENDENTS_SQL,
|
|
6199
6200
|
RLS_BOOTSTRAP_SQL: () => RLS_BOOTSTRAP_SQL,
|
|
@@ -6358,6 +6359,60 @@ async function rlsRuntimeIsCurrent(run) {
|
|
|
6358
6359
|
/** The same statements as one script, for migration files and raw clients. */
|
|
6359
6360
|
var RLS_BOOTSTRAP_SQL = "-- Rebase schema + RLS helper functions (required by the policies below)\n" + RLS_BOOTSTRAP_STATEMENTS.map((s) => `${s};`).join("\n\n") + "\n";
|
|
6360
6361
|
/**
|
|
6362
|
+
* The three functions every pre-1.0 release put in `auth`. (The auth tables
|
|
6363
|
+
* lived in `rebase`, or wherever the users collection was declared.)
|
|
6364
|
+
*
|
|
6365
|
+
* `uid()` is matched on either spelling of the principal because Rebase wrote
|
|
6366
|
+
* both. Until v0.10.0 its body was
|
|
6367
|
+
* `SELECT NULLIF(current_setting('app.user_id', true), '')`; v0.10.0 renamed
|
|
6368
|
+
* the GUC to `app.uid` and kept `app.user_id` as a fallback; v0.14.0 moved the
|
|
6369
|
+
* helpers to `rebase`. A database last booted before v0.10.0 therefore holds an
|
|
6370
|
+
* `auth.uid()` that reads `app.user_id` alone — as does anything that copied
|
|
6371
|
+
* that body, the Rebase control plane included — and matching `app.uid` only
|
|
6372
|
+
* left every one of them in place, with the schema around it.
|
|
6373
|
+
*
|
|
6374
|
+
* This is the one place either spelling is listed: the drop and the report of
|
|
6375
|
+
* what it left are both generated from it, so they cannot disagree about which
|
|
6376
|
+
* functions are Rebase's.
|
|
6377
|
+
*/
|
|
6378
|
+
var LEGACY_AUTH_HELPERS = [
|
|
6379
|
+
{
|
|
6380
|
+
name: "uid",
|
|
6381
|
+
returns: "text",
|
|
6382
|
+
reads: ["app.uid", "app.user_id"]
|
|
6383
|
+
},
|
|
6384
|
+
{
|
|
6385
|
+
name: "jwt",
|
|
6386
|
+
returns: "jsonb",
|
|
6387
|
+
reads: ["app.jwt"]
|
|
6388
|
+
},
|
|
6389
|
+
{
|
|
6390
|
+
name: "roles",
|
|
6391
|
+
returns: "text",
|
|
6392
|
+
reads: ["app.user_roles"]
|
|
6393
|
+
}
|
|
6394
|
+
];
|
|
6395
|
+
/**
|
|
6396
|
+
* `pg_proc p` has a Rebase helper's name, arity and result type: what
|
|
6397
|
+
* `CREATE OR REPLACE` would have left, whatever the body.
|
|
6398
|
+
*
|
|
6399
|
+
* Two things that share that shape are excluded outright: a body reading
|
|
6400
|
+
* `request.jwt` (Supabase's helpers and anything modelled on them) and a
|
|
6401
|
+
* function an extension installed (`pg_session_jwt` puts an `auth.jwt()
|
|
6402
|
+
* RETURNS jsonb` in the same schema).
|
|
6403
|
+
*/
|
|
6404
|
+
var isLegacyHelperShaped = (helper) => `(
|
|
6405
|
+
p.proname = '${helper.name}' AND p.pronargs = 0
|
|
6406
|
+
AND pg_get_function_result(p.oid) = '${helper.returns}'
|
|
6407
|
+
AND strpos(p.prosrc, 'request.jwt') = 0
|
|
6408
|
+
AND NOT EXISTS (
|
|
6409
|
+
SELECT 1 FROM pg_depend e
|
|
6410
|
+
WHERE e.classid = 'pg_proc'::regclass AND e.objid = p.oid AND e.deptype = 'e'
|
|
6411
|
+
))`;
|
|
6412
|
+
/** `pg_proc p` is a helper Rebase wrote: its shape, and a body reading one of its GUCs. */
|
|
6413
|
+
var isLegacyHelper = (helper) => `${isLegacyHelperShaped(helper)}
|
|
6414
|
+
AND (${helper.reads.map((guc) => `strpos(p.prosrc, '${guc}') > 0`).join(" OR ")})`;
|
|
6415
|
+
/**
|
|
6361
6416
|
* Removes the pre-1.0 `auth` schema, but only when Rebase is what put it there.
|
|
6362
6417
|
*
|
|
6363
6418
|
* ## Why this is safe against a Supabase database
|
|
@@ -6365,11 +6420,12 @@ var RLS_BOOTSTRAP_SQL = "-- Rebase schema + RLS helper functions (required by th
|
|
|
6365
6420
|
* Two independent guards, and both have to pass:
|
|
6366
6421
|
*
|
|
6367
6422
|
* 1. **Each function is identified before it is dropped.** Ours returns `text`
|
|
6368
|
-
* and reads the `app.uid` GUC; Supabase's returns `uuid`
|
|
6369
|
-
* `request.jwt.claims`. Nothing is dropped on a signature we did
|
|
6370
|
-
* so a Supabase database — where our `CREATE OR REPLACE` could
|
|
6371
|
-
* succeeded in the first place, Postgres refusing to change a
|
|
6372
|
-
* matches nothing and this is a no-op.
|
|
6423
|
+
* and reads the `app.uid` or `app.user_id` GUC; Supabase's returns `uuid`
|
|
6424
|
+
* and reads `request.jwt.claims`. Nothing is dropped on a signature we did
|
|
6425
|
+
* not write, so a Supabase database — where our `CREATE OR REPLACE` could
|
|
6426
|
+
* never have succeeded in the first place, Postgres refusing to change a
|
|
6427
|
+
* return type — matches nothing and this is a no-op. See
|
|
6428
|
+
* {@link LEGACY_AUTH_HELPERS} for exactly what is matched.
|
|
6373
6429
|
* 2. **`DROP SCHEMA … RESTRICT`**, never CASCADE. If anything else at all still
|
|
6374
6430
|
* lives in `auth` (Supabase's `users` table, its other helpers), the drop
|
|
6375
6431
|
* fails and the schema stays. CASCADE here would be unrecoverable.
|
|
@@ -6390,41 +6446,21 @@ DECLARE
|
|
|
6390
6446
|
BEGIN
|
|
6391
6447
|
-- Each function is matched on its own result type and body, so a schema
|
|
6392
6448
|
-- that merely shares the name keeps everything it has.
|
|
6393
|
-
IF EXISTS (
|
|
6449
|
+
${LEGACY_AUTH_HELPERS.map((helper) => ` IF EXISTS (
|
|
6394
6450
|
SELECT 1 FROM pg_proc p JOIN pg_namespace n ON n.oid = p.pronamespace
|
|
6395
|
-
WHERE n.nspname = '
|
|
6396
|
-
AND pg_get_function_result(p.oid) = 'text'
|
|
6397
|
-
AND p.prosrc LIKE '%app.uid%'
|
|
6451
|
+
WHERE n.nspname = '${LEGACY_RLS_SCHEMA}' AND ${isLegacyHelper(helper)}
|
|
6398
6452
|
) THEN
|
|
6399
|
-
DROP FUNCTION
|
|
6453
|
+
DROP FUNCTION ${LEGACY_RLS_SCHEMA}.${helper.name}();
|
|
6400
6454
|
dropped_any := true;
|
|
6401
|
-
END IF
|
|
6402
|
-
|
|
6403
|
-
IF EXISTS (
|
|
6404
|
-
SELECT 1 FROM pg_proc p JOIN pg_namespace n ON n.oid = p.pronamespace
|
|
6405
|
-
WHERE n.nspname = 'auth' AND p.proname = 'jwt'
|
|
6406
|
-
AND pg_get_function_result(p.oid) = 'jsonb'
|
|
6407
|
-
AND p.prosrc LIKE '%app.jwt%'
|
|
6408
|
-
) THEN
|
|
6409
|
-
DROP FUNCTION auth.jwt();
|
|
6410
|
-
dropped_any := true;
|
|
6411
|
-
END IF;
|
|
6412
|
-
|
|
6413
|
-
IF EXISTS (
|
|
6414
|
-
SELECT 1 FROM pg_proc p JOIN pg_namespace n ON n.oid = p.pronamespace
|
|
6415
|
-
WHERE n.nspname = 'auth' AND p.proname = 'roles'
|
|
6416
|
-
AND pg_get_function_result(p.oid) = 'text'
|
|
6417
|
-
AND p.prosrc LIKE '%app.user_roles%'
|
|
6418
|
-
) THEN
|
|
6419
|
-
DROP FUNCTION auth.roles();
|
|
6420
|
-
dropped_any := true;
|
|
6421
|
-
END IF;
|
|
6455
|
+
END IF;`).join("\n\n")}
|
|
6422
6456
|
|
|
6423
6457
|
-- RESTRICT: only an empty schema goes. Anything else in there — including a
|
|
6424
|
-
-- Supabase installation left untouched above — keeps it.
|
|
6458
|
+
-- Supabase installation left untouched above — keeps it. Swallowed so the
|
|
6459
|
+
-- helpers dropped above stay dropped; dropLegacyAuthSchema looks afterwards
|
|
6460
|
+
-- and says what is left.
|
|
6425
6461
|
IF dropped_any THEN
|
|
6426
6462
|
BEGIN
|
|
6427
|
-
EXECUTE 'DROP SCHEMA
|
|
6463
|
+
EXECUTE 'DROP SCHEMA ${LEGACY_RLS_SCHEMA} RESTRICT';
|
|
6428
6464
|
EXCEPTION WHEN OTHERS THEN
|
|
6429
6465
|
NULL;
|
|
6430
6466
|
END;
|
|
@@ -6433,6 +6469,40 @@ END
|
|
|
6433
6469
|
$rebase_drop_legacy$;
|
|
6434
6470
|
`;
|
|
6435
6471
|
/**
|
|
6472
|
+
* What the `auth` schema holds, one row per object keeping it alive.
|
|
6473
|
+
*
|
|
6474
|
+
* No rows: the schema does not exist. A single row with a `null` object: it
|
|
6475
|
+
* exists and is empty. Read from the namespace entries in `pg_depend`, which
|
|
6476
|
+
* are what `DROP SCHEMA … RESTRICT` itself consults — minus whatever goes with
|
|
6477
|
+
* its owner (a serial's sequence, an identity column's), which Postgres does not
|
|
6478
|
+
* name either.
|
|
6479
|
+
*/
|
|
6480
|
+
var LEGACY_AUTH_SCHEMA_CONTENTS_SQL = `
|
|
6481
|
+
SELECT pg_describe_object(d.classid, d.objid, d.objsubid) AS object,
|
|
6482
|
+
CASE
|
|
6483
|
+
WHEN d.classid <> 'pg_proc'::regclass THEN NULL
|
|
6484
|
+
WHEN EXISTS (
|
|
6485
|
+
SELECT 1 FROM pg_proc p
|
|
6486
|
+
WHERE p.oid = d.objid
|
|
6487
|
+
AND (${LEGACY_AUTH_HELPERS.map((helper) => `(${isLegacyHelper(helper)})`).join(" OR ")})
|
|
6488
|
+
) THEN 'ours'
|
|
6489
|
+
WHEN EXISTS (
|
|
6490
|
+
SELECT 1 FROM pg_proc p
|
|
6491
|
+
WHERE p.oid = d.objid
|
|
6492
|
+
AND (${LEGACY_AUTH_HELPERS.map(isLegacyHelperShaped).join(" OR ")})
|
|
6493
|
+
) THEN 'lookalike'
|
|
6494
|
+
END AS helper
|
|
6495
|
+
FROM pg_namespace n
|
|
6496
|
+
LEFT JOIN pg_depend d
|
|
6497
|
+
ON d.refclassid = 'pg_namespace'::regclass AND d.refobjid = n.oid AND d.deptype = 'n'
|
|
6498
|
+
AND NOT EXISTS (
|
|
6499
|
+
SELECT 1 FROM pg_depend o
|
|
6500
|
+
WHERE o.classid = d.classid AND o.objid = d.objid AND o.deptype IN ('a', 'i')
|
|
6501
|
+
)
|
|
6502
|
+
WHERE n.nspname = '${LEGACY_RLS_SCHEMA}'
|
|
6503
|
+
ORDER BY helper NULLS LAST, object
|
|
6504
|
+
`;
|
|
6505
|
+
/**
|
|
6436
6506
|
* Policies whose body still calls `auth.uid()` / `auth.roles()` / `auth.jwt()`.
|
|
6437
6507
|
*
|
|
6438
6508
|
* Postgres will not drop a function a policy depends on, so this is exactly the
|
|
@@ -6463,11 +6533,12 @@ var LEGACY_RLS_DEPENDENTS_SQL = `
|
|
|
6463
6533
|
* exists, which fails at *query* time rather than at boot.
|
|
6464
6534
|
*
|
|
6465
6535
|
* A downstream project building on these helpers is not hypothetical: the Rebase
|
|
6466
|
-
* control plane
|
|
6536
|
+
* control plane defined `auth.is_org_member(uuid)` and `auth.is_org_admin(uuid)`
|
|
6467
6537
|
* in this very schema, each calling `auth.uid()` in a string body, and eleven of
|
|
6468
|
-
* its row-level-security policies
|
|
6469
|
-
* started failing the first time a recompile left no policy referencing
|
|
6470
|
-
* `auth.uid()` directly — the drop's own precondition.
|
|
6538
|
+
* its row-level-security policies went through them. Every one of those would
|
|
6539
|
+
* have started failing the first time a recompile left no policy referencing
|
|
6540
|
+
* `auth.uid()` directly — the drop's own precondition. (Its migration 0065 has
|
|
6541
|
+
* since moved both to `public`, calling `rebase.uid()`.)
|
|
6471
6542
|
*
|
|
6472
6543
|
* Matching on the body text is the only option available, and it is deliberately
|
|
6473
6544
|
* broad: a false positive costs a schema that stays one release longer and says
|
|
@@ -6491,8 +6562,30 @@ var LEGACY_RLS_FUNCTION_DEPENDENTS_SQL = `
|
|
|
6491
6562
|
* table not recompiled *yet* — and wrong for the one that never resolves: a
|
|
6492
6563
|
* hand-written policy nothing will ever rewrite. Then the schema stays forever
|
|
6493
6564
|
* and nothing ever says why.
|
|
6565
|
+
*
|
|
6566
|
+
* The drop itself had the same blind spot. A helper it did not recognise as
|
|
6567
|
+
* Rebase's stayed, and so did anything else in the schema, behind a
|
|
6568
|
+
* `DROP SCHEMA … RESTRICT` whose failure is swallowed so the helpers it did
|
|
6569
|
+
* drop stay dropped. The control plane's `auth.uid()` was one such: it read
|
|
6570
|
+
* `app.user_id` alone, the drop looked for `app.uid`, and the schema stayed
|
|
6571
|
+
* with no word said. So the schema is read twice. Before, so that one with no
|
|
6572
|
+
* Rebase helper in it is left alone: one already gone, as on every boot after
|
|
6573
|
+
* the drop, or one that was never Rebase's, like Supabase's — whose own
|
|
6574
|
+
* policies the checks below would otherwise report as blockers. After, to name
|
|
6575
|
+
* whatever is still there.
|
|
6494
6576
|
*/
|
|
6495
6577
|
async function dropLegacyAuthSchema(run, report) {
|
|
6578
|
+
let before;
|
|
6579
|
+
try {
|
|
6580
|
+
before = sqlRows(await run(LEGACY_AUTH_SCHEMA_CONTENTS_SQL));
|
|
6581
|
+
} catch {
|
|
6582
|
+
return;
|
|
6583
|
+
}
|
|
6584
|
+
if (!before.some((o) => o.helper !== null)) return;
|
|
6585
|
+
if (!before.some((o) => o.helper === "ours")) {
|
|
6586
|
+
report.warn(describeLegacyAuthLeftovers(before, void 0));
|
|
6587
|
+
return;
|
|
6588
|
+
}
|
|
6496
6589
|
let blockers;
|
|
6497
6590
|
try {
|
|
6498
6591
|
blockers = sqlRows(await run(LEGACY_RLS_DEPENDENTS_SQL));
|
|
@@ -6513,11 +6606,42 @@ async function dropLegacyAuthSchema(run, report) {
|
|
|
6513
6606
|
report.warn(`The pre-1.0 \`${LEGACY_RLS_SCHEMA}\` schema cannot be removed yet: ${borrowers.length} ${borrowers.length === 1 ? "function calls" : "functions call"} \`${LEGACY_RLS_SCHEMA}.uid()\` and friends from its own body. Postgres records no dependency for that — a SQL body written as a string literal is never parsed — so dropping the helpers would leave these pointing at nothing, and they would fail when a query reached them rather than now. Repoint them at \`${REBASE_SCHEMA}.uid()\`, after which the schema goes on its own:\n` + borrowers.map((b) => ` • ${b.schema}.${b.function}()`).join("\n"));
|
|
6514
6607
|
return;
|
|
6515
6608
|
}
|
|
6609
|
+
let failure;
|
|
6516
6610
|
try {
|
|
6517
6611
|
await run(DROP_LEGACY_AUTH_SCHEMA_SQL);
|
|
6518
6612
|
} catch (err) {
|
|
6519
|
-
|
|
6613
|
+
const detail = err instanceof Error && "detail" in err && typeof err.detail === "string" ? err.detail : "";
|
|
6614
|
+
failure = (err instanceof Error ? err.message : String(err)) + (detail ? ` (${detail.replace(/\n/g, "; ")})` : "");
|
|
6520
6615
|
}
|
|
6616
|
+
let left;
|
|
6617
|
+
try {
|
|
6618
|
+
left = sqlRows(await run(LEGACY_AUTH_SCHEMA_CONTENTS_SQL));
|
|
6619
|
+
} catch {
|
|
6620
|
+
if (failure) report.info(`Left the \`${LEGACY_RLS_SCHEMA}\` schema in place: ${failure}`);
|
|
6621
|
+
return;
|
|
6622
|
+
}
|
|
6623
|
+
if (left.length === 0) return;
|
|
6624
|
+
report.warn(describeLegacyAuthLeftovers(left, failure));
|
|
6625
|
+
}
|
|
6626
|
+
/** At most this many objects are named; a schema this full is plainly in use. */
|
|
6627
|
+
var MAX_LEFTOVERS_NAMED = 20;
|
|
6628
|
+
/**
|
|
6629
|
+
* The warning for an `auth` schema the drop left standing.
|
|
6630
|
+
*
|
|
6631
|
+
* Said once for objects that are not Rebase's: on the next boot the schema holds
|
|
6632
|
+
* no helper, so {@link dropLegacyAuthSchema} leaves it alone — it is somebody
|
|
6633
|
+
* else's schema by then. A helper that is still there, Rebase's or a lookalike,
|
|
6634
|
+
* keeps it said on every boot until it goes.
|
|
6635
|
+
*/
|
|
6636
|
+
function describeLegacyAuthLeftovers(left, failure) {
|
|
6637
|
+
const schema = LEGACY_RLS_SCHEMA;
|
|
6638
|
+
const objects = left.filter((o) => o.object !== null);
|
|
6639
|
+
if (objects.length === 0) return `The pre-1.0 \`${schema}\` schema is empty, but this connection could not drop it — most likely because it does not own the schema. Run \`DROP SCHEMA ${schema};\` as its owner.`;
|
|
6640
|
+
const why = failure ? `dropping Rebase's old helpers from it failed: ${failure}.` : "`DROP SCHEMA … RESTRICT` refuses a schema that is not empty, and Rebase drops only the helpers it can tell are its own.";
|
|
6641
|
+
const lines = objects.slice(0, MAX_LEFTOVERS_NAMED).map((o) => o.helper === "ours" ? ` • ${o.object} — Rebase's old helper, which could not be dropped` : o.helper === "lookalike" ? ` • ${o.object} — named and typed like Rebase's old helper, but no release wrote this body, so it was left alone; drop it by hand if nothing of yours calls it` : ` • ${o.object}`);
|
|
6642
|
+
if (objects.length > MAX_LEFTOVERS_NAMED) lines.push(` • …and ${objects.length - MAX_LEFTOVERS_NAMED} more`);
|
|
6643
|
+
return `The pre-1.0 \`${schema}\` schema is still here: ${why} Still in it:\n` + lines.join("\n") + `
|
|
6644
|
+
Anything of yours can stay where it is — Rebase no longer uses this schema — or move out with \`ALTER … SET SCHEMA\`. Once the schema is empty, \`DROP SCHEMA ${schema};\` removes it.`;
|
|
6521
6645
|
}
|
|
6522
6646
|
//#endregion
|
|
6523
6647
|
//#region src/cli-flags.ts
|
|
@@ -6836,6 +6960,10 @@ var BRANCH_ACTION_FLAGS = {
|
|
|
6836
6960
|
},
|
|
6837
6961
|
list: {},
|
|
6838
6962
|
info: {},
|
|
6963
|
+
diff: {
|
|
6964
|
+
"--json": Boolean,
|
|
6965
|
+
"--sample-limit": Number
|
|
6966
|
+
},
|
|
6839
6967
|
delete: {
|
|
6840
6968
|
"--force": Boolean,
|
|
6841
6969
|
"--yes": Boolean,
|
|
@@ -6937,6 +7065,7 @@ function unexpectedBranchArgs(words) {
|
|
|
6937
7065
|
var TAKES_A_VALUE = /* @__PURE__ */ new Set([
|
|
6938
7066
|
"--from",
|
|
6939
7067
|
"--older-than",
|
|
7068
|
+
"--sample-limit",
|
|
6940
7069
|
"--database-url"
|
|
6941
7070
|
]);
|
|
6942
7071
|
//#endregion
|
|
@@ -6970,6 +7099,102 @@ function isDriverDbSubcommand(word) {
|
|
|
6970
7099
|
return DRIVER_DB_SUBCOMMANDS.some((subcommand) => subcommand === word);
|
|
6971
7100
|
}
|
|
6972
7101
|
//#endregion
|
|
6973
|
-
|
|
7102
|
+
//#region src/schema/migrate-baseline.ts
|
|
7103
|
+
/**
|
|
7104
|
+
* What `rebase db migrate --baseline <version>` does, given the history the
|
|
7105
|
+
* database already has.
|
|
7106
|
+
*
|
|
7107
|
+
* The flag promises to record `<version>` as applied and migrate from the next
|
|
7108
|
+
* one. Atlas's own `migrate apply --baseline` keeps that promise only on a
|
|
7109
|
+
* database with no revision history: once one row exists it ignores the flag
|
|
7110
|
+
* without a word, applies the migration anyway, and the CLI had already printed
|
|
7111
|
+
* "Recording … as already applied". That is the normal second time: a project
|
|
7112
|
+
* baselines once, then `rebase dev` adds a column at boot, `db generate` writes
|
|
7113
|
+
* the migration for it, and `db migrate` fails on `column … already exists
|
|
7114
|
+
* (42701)` however the baseline is spelled.
|
|
7115
|
+
*
|
|
7116
|
+
* So the history is read first. With none, Atlas's baseline does the work.
|
|
7117
|
+
* Behind `<version>`, `atlas migrate set` marks every migration up to it as
|
|
7118
|
+
* applied, which is what a baseline means. At or past it, there is nothing to
|
|
7119
|
+
* record, and the command says so instead of claiming it recorded something.
|
|
7120
|
+
*/
|
|
7121
|
+
/**
|
|
7122
|
+
* Atlas's version order for the versions Rebase writes: numeric timestamps,
|
|
7123
|
+
* compared as numbers so a shorter one is not read as later; anything else as
|
|
7124
|
+
* text.
|
|
7125
|
+
*/
|
|
7126
|
+
function compareMigrationVersions(a, b) {
|
|
7127
|
+
if (/^\d+$/.test(a) && /^\d+$/.test(b)) {
|
|
7128
|
+
const x = BigInt(a);
|
|
7129
|
+
const y = BigInt(b);
|
|
7130
|
+
return x === y ? 0 : x < y ? -1 : 1;
|
|
7131
|
+
}
|
|
7132
|
+
return a.localeCompare(b);
|
|
7133
|
+
}
|
|
7134
|
+
/**
|
|
7135
|
+
* The version Atlas records for a migration file: its numeric prefix
|
|
7136
|
+
* (`20260906101530_init.sql` → `20260906101530`), or the name without `.sql`.
|
|
7137
|
+
*/
|
|
7138
|
+
function migrationVersionOf(file) {
|
|
7139
|
+
return /^(\d+)/.exec(file)?.[1] ?? file.replace(/\.sql$/, "");
|
|
7140
|
+
}
|
|
7141
|
+
/** How many versions a refused baseline names, newest last. */
|
|
7142
|
+
var VERSIONS_NAMED = 5;
|
|
7143
|
+
/**
|
|
7144
|
+
* Why `--baseline <version>` cannot run, or `null` when it names a migration
|
|
7145
|
+
* file in `drizzle/migrations`.
|
|
7146
|
+
*
|
|
7147
|
+
* Asked before anything else, the database included. A version no file has
|
|
7148
|
+
* was refused only by Atlas, after the command had said "Marking every
|
|
7149
|
+
* migration up to abc as applied…"; and one older than every file read
|
|
7150
|
+
* "Nothing to record" and migrated on, though it named nothing to baseline.
|
|
7151
|
+
*
|
|
7152
|
+
* @param files the migration files, sorted oldest first.
|
|
7153
|
+
* @returns the refusal, its first line the error and the rest the detail.
|
|
7154
|
+
*/
|
|
7155
|
+
function baselineVersionProblem(version, files) {
|
|
7156
|
+
const versions = files.map(migrationVersionOf);
|
|
7157
|
+
if (versions.length === 0) return `--baseline ${version}: There are no migrations in drizzle/migrations to baseline. Nothing was run.\nRun \`rebase db generate\` to write the first one.`;
|
|
7158
|
+
if (versions.includes(version)) return null;
|
|
7159
|
+
const named = versions.slice(-5).join(", ");
|
|
7160
|
+
return `--baseline ${version} names no migration in drizzle/migrations. Nothing was run.\n${versions.length > VERSIONS_NAMED ? `The newest ${VERSIONS_NAMED} of the ${versions.length} versions there` : "The versions there"}: ${named}. A baseline is one of them: the newest migration the database already holds.`;
|
|
7161
|
+
}
|
|
7162
|
+
/** How to keep `--baseline <version>`'s promise, given the newest recorded version. */
|
|
7163
|
+
function planBaseline(version, latestRecorded) {
|
|
7164
|
+
if (latestRecorded === null) return { kind: "atlas-baseline" };
|
|
7165
|
+
if (compareMigrationVersions(version, latestRecorded) > 0) return {
|
|
7166
|
+
kind: "set",
|
|
7167
|
+
latest: latestRecorded
|
|
7168
|
+
};
|
|
7169
|
+
return {
|
|
7170
|
+
kind: "already-recorded",
|
|
7171
|
+
latest: latestRecorded
|
|
7172
|
+
};
|
|
7173
|
+
}
|
|
7174
|
+
/** What the command says before it migrates, for each plan. */
|
|
7175
|
+
function describeBaselinePlan(version, plan) {
|
|
7176
|
+
switch (plan.kind) {
|
|
7177
|
+
case "atlas-baseline": return `Recording ${version} as already applied, then migrating from the next one.`;
|
|
7178
|
+
case "set": return `This database already records migrations up to ${plan.latest}, and Atlas applies --baseline only to a database with none.\n Marking every migration up to ${version} as applied with \`atlas migrate set\`, then migrating from the next one.`;
|
|
7179
|
+
case "already-recorded": return `Nothing to record: this database already records migrations up to ${plan.latest}, which includes ${version}.\n Migrating from the next one.`;
|
|
7180
|
+
}
|
|
7181
|
+
}
|
|
7182
|
+
/**
|
|
7183
|
+
* The newest version Atlas has recorded on this database, or `null` when it
|
|
7184
|
+
* has recorded none (no revisions table yet included).
|
|
7185
|
+
*
|
|
7186
|
+
* The table is `rebase.atlas_schema_revisions`: the CLI passes
|
|
7187
|
+
* `--revisions-schema rebase` to every `migrate apply`.
|
|
7188
|
+
*/
|
|
7189
|
+
async function latestRecordedMigration(databaseUrl) {
|
|
7190
|
+
return withAppClient(databaseUrl, async (client) => {
|
|
7191
|
+
if (!(await client.query("SELECT to_regclass('rebase.atlas_schema_revisions') IS NOT NULL AS present")).rows[0]?.present) return null;
|
|
7192
|
+
const versions = (await client.query("SELECT version FROM rebase.atlas_schema_revisions WHERE version NOT LIKE '.%'")).rows.map((row) => row.version);
|
|
7193
|
+
if (versions.length === 0) return null;
|
|
7194
|
+
return versions.reduce((latest, version) => compareMigrationVersions(version, latest) > 0 ? version : latest);
|
|
7195
|
+
});
|
|
7196
|
+
}
|
|
7197
|
+
//#endregion
|
|
7198
|
+
export { rlsRuntimeIsCurrent as C, dropLegacyAuthSchema as S, execa as T, parseCommandFlags as _, migrationVersionOf as a, RLS_BOOTSTRAP_SQL as b, isDriverDbSubcommand as c, resolveBranchSwitches as d, unexpectedBranchArgs as f, collectionsPathIn as g, closestWord as h, latestRecordedMigration as i, backupActionOf as l, assertKnownFlags as m, compareMigrationVersions as n, planBaseline as o, RELAYED_FLAGS as p, describeBaselinePlan as r, DRIVER_DB_SUBCOMMANDS as s, baselineVersionProblem as t, assertKnownBranchFlags as u, parseDriverLine as v, rls_bootstrap_sql_exports as w, RLS_BOOTSTRAP_STATEMENTS as x, resolveDriverSwitches as y };
|
|
6974
7199
|
|
|
6975
|
-
//# sourceMappingURL=
|
|
7200
|
+
//# sourceMappingURL=migrate-baseline-B-2Ef4Mv.js.map
|