@rebasepro/server-postgres 0.23.0 → 0.24.1-canary.g19596ef
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/README.md +16 -0
- package/dist/{BranchService-DGPL6G_C.js → BranchService-UgKa416x.js} +47 -19
- package/dist/BranchService-UgKa416x.js.map +1 -0
- package/dist/PostgresBackendDriver.d.ts +187 -13
- package/dist/PostgresBootstrapper.d.ts +101 -2
- package/dist/auth/ensure-tables.d.ts +12 -0
- package/dist/auth/services.d.ts +78 -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/backup-cli.d.ts +75 -2
- package/dist/backup/backup-service.d.ts +2 -2
- package/dist/backup/pg-binary.d.ts +5 -0
- package/dist/{backup-cli-24v4OlSp.js → backup-cli-yiKd1GsC.js} +168 -75
- package/dist/backup-cli-yiKd1GsC.js.map +1 -0
- package/dist/{backup-service-HQ9GC4tN.js → backup-service-AZWc2wvI.js} +104 -35
- package/dist/backup-service-AZWc2wvI.js.map +1 -0
- package/dist/boot-ddl-B9ZmBJ75.js +105 -0
- package/dist/boot-ddl-B9ZmBJ75.js.map +1 -0
- package/dist/cli-console-DGee3Zl7.js +225 -0
- package/dist/cli-console-DGee3Zl7.js.map +1 -0
- package/dist/cli-console.d.ts +39 -0
- package/dist/cli-errors-oVUuD8k0.js +2180 -0
- package/dist/cli-errors-oVUuD8k0.js.map +1 -0
- package/dist/cli-errors.d.ts +133 -9
- package/dist/{cli-flags-BglvpjHv.js → cli-flags-DnPHXjRH.js} +56 -6
- package/dist/cli-flags-DnPHXjRH.js.map +1 -0
- package/dist/cli-flags.d.ts +15 -0
- package/dist/cli-helpers.d.ts +88 -34
- package/dist/cli-output.d.ts +16 -28
- package/dist/{arg-Dni7MzLB.js → cli-prompt-egtNKkZl.js} +49 -3
- package/dist/cli-prompt-egtNKkZl.js.map +1 -0
- package/dist/cli-prompt.d.ts +19 -0
- package/dist/cli-push.d.ts +87 -0
- package/dist/cli-scratch-database.d.ts +33 -8
- package/dist/cli.js +826 -230
- package/dist/cli.js.map +1 -1
- package/dist/{column-plan-helpers-DF-8dTVa.js → column-plan-helpers-D_V4oaZh.js} +43 -27
- package/dist/column-plan-helpers-D_V4oaZh.js.map +1 -0
- package/dist/{databasePoolManager-Bj5FbeAs.js → connection-C938nR3E.js} +25 -113
- package/dist/connection-C938nR3E.js.map +1 -0
- package/dist/connection.d.ts +13 -2
- package/dist/data-transformer.d.ts +0 -8
- package/dist/databasePoolManager-DZgnBOgj.js +119 -0
- package/dist/databasePoolManager-DZgnBOgj.js.map +1 -0
- package/dist/deferred-index-build-BqmEHGaD.js +1051 -0
- package/dist/deferred-index-build-BqmEHGaD.js.map +1 -0
- package/dist/{doctor-Cb2thZ8s.js → doctor-CUAAOFZm.js} +281 -89
- package/dist/doctor-CUAAOFZm.js.map +1 -0
- package/dist/ensure-collection-policies-Bb51V2OV.js +541 -0
- package/dist/ensure-collection-policies-Bb51V2OV.js.map +1 -0
- package/dist/ensure-collection-tables-egjGBjhv.js +532 -0
- package/dist/ensure-collection-tables-egjGBjhv.js.map +1 -0
- package/dist/{ensure-tables-Dhn9KM3B.js → ensure-tables-DMPWhJ6R.js} +180 -77
- package/dist/ensure-tables-DMPWhJ6R.js.map +1 -0
- package/dist/enum-labels-kept-Msq5gMcb.js +56 -0
- package/dist/enum-labels-kept-Msq5gMcb.js.map +1 -0
- package/dist/generate-drizzle-schema-DrA-YgXv.js +57 -0
- package/dist/generate-drizzle-schema-DrA-YgXv.js.map +1 -0
- package/dist/{generate-drizzle-schema-logic-BfzK7UQd.js → generate-drizzle-schema-logic-BaT0H7Gq.js} +29 -11
- package/dist/generate-drizzle-schema-logic-BaT0H7Gq.js.map +1 -0
- package/dist/generate-files-OoRJLEdk.js +199 -0
- package/dist/generate-files-OoRJLEdk.js.map +1 -0
- package/dist/generate-postgres-ddl-logic-B4k9djAV.js +152 -0
- package/dist/generate-postgres-ddl-logic-B4k9djAV.js.map +1 -0
- package/dist/{generated-schema-staleness-Di9c4ZxN.js → generated-schema-staleness-BWN_PsMi.js} +2 -2
- package/dist/{generated-schema-staleness-Di9c4ZxN.js.map → generated-schema-staleness-BWN_PsMi.js.map} +1 -1
- package/dist/generated-sql.d.ts +34 -0
- package/dist/history/HistoryService.d.ts +64 -5
- package/dist/history/ensure-history-table.d.ts +63 -4
- package/dist/index.d.ts +1 -0
- package/dist/index.es.js +139 -16738
- package/dist/index.es.js.map +1 -1
- package/dist/{introspect-db-logic-WMuAfxvw.js → introspect-db-logic-BCc1Jym2.js} +654 -353
- package/dist/introspect-db-logic-BCc1Jym2.js.map +1 -0
- package/dist/introspect-db-queries-BhhJg0b8.js +364 -0
- package/dist/introspect-db-queries-BhhJg0b8.js.map +1 -0
- package/dist/open-rebase-CAjWpPjs.js +20895 -0
- package/dist/open-rebase-CAjWpPjs.js.map +1 -0
- package/dist/open-rebase.d.ts +94 -0
- package/dist/pg-error-utils-Bs_Ue4wn.js +395 -0
- package/dist/pg-error-utils-Bs_Ue4wn.js.map +1 -0
- package/dist/{plan-schema-C0fxM8dY.js → plan-schema-CsNgK0qi.js} +279 -534
- package/dist/plan-schema-CsNgK0qi.js.map +1 -0
- package/dist/{policy-drift-DljYdrpW.js → policy-drift-BKC50y2p.js} +33 -9
- package/dist/policy-drift-BKC50y2p.js.map +1 -0
- package/dist/push-index-prebuild-C_qhyoJa.js +45 -0
- package/dist/push-index-prebuild-C_qhyoJa.js.map +1 -0
- package/dist/push-legacy-renames-5g9h3HOa.js +34 -0
- package/dist/push-legacy-renames-5g9h3HOa.js.map +1 -0
- package/dist/{generate-postgres-ddl-logic-Bt2d2mRH.js → render-ddl-CrfEe__B.js} +24 -157
- package/dist/render-ddl-CrfEe__B.js.map +1 -0
- package/dist/{rls-bootstrap-sql-B8EclDyM.js → rls-bootstrap-sql-Bd-hJk08.js} +125 -1101
- package/dist/rls-bootstrap-sql-Bd-hJk08.js.map +1 -0
- package/dist/{rls-enforcement-C6Xk0lA6.js → rls-enforcement-D7P4-ZYX.js} +138 -18
- package/dist/rls-enforcement-D7P4-ZYX.js.map +1 -0
- package/dist/{__vite-browser-external-BnuHet1e.js → rolldown-runtime-V7rFbMRe.js} +1 -8
- package/dist/schema/atlas-exclude.d.ts +42 -0
- package/dist/schema/auth-schema.d.ts +172 -2
- package/dist/schema/boot-ddl.d.ts +47 -0
- package/dist/schema/carved-out-migration.d.ts +5 -4
- package/dist/schema/classify-change.d.ts +29 -1
- package/dist/schema/collection-index.d.ts +45 -0
- package/dist/schema/column-plan-helpers.d.ts +38 -21
- package/dist/schema/deferred-index-build.d.ts +131 -0
- package/dist/schema/destructive-sql.d.ts +50 -2
- package/dist/schema/doctor-cli.js +110 -6
- package/dist/schema/doctor-cli.js.map +1 -1
- package/dist/schema/doctor-search-scale.d.ts +45 -0
- package/dist/schema/doctor.d.ts +53 -1
- package/dist/schema/ensure-collection-policies.d.ts +95 -35
- package/dist/schema/ensure-collection-tables.d.ts +56 -3
- package/dist/schema/enum-labels-kept.d.ts +26 -0
- package/dist/schema/generate-drizzle-schema.js +1 -1
- package/dist/schema/generate-files.d.ts +44 -0
- package/dist/schema/generate-next-step.d.ts +0 -13
- package/dist/schema/generate-postgres-ddl-logic.d.ts +5 -5
- package/dist/schema/generate-postgres-ddl.js +10 -81
- package/dist/schema/generate-postgres-ddl.js.map +1 -1
- package/dist/schema/generate-schema-commit.d.ts +12 -0
- package/dist/schema/generated-schema-diff.d.ts +7 -0
- package/dist/schema/introspect-db-logic.d.ts +63 -0
- package/dist/schema/introspect-db-queries.d.ts +21 -2
- 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-structure.d.ts +10 -0
- package/dist/schema/introspect-db.js +29 -21
- package/dist/schema/introspect-db.js.map +1 -1
- package/dist/schema/migrate-baseline.d.ts +33 -0
- package/dist/schema/migration-post-process.d.ts +34 -0
- package/dist/schema/plan/diff-plan.d.ts +127 -1
- package/dist/schema/plan/plan-schema.d.ts +16 -8
- package/dist/schema/plan/render-ddl.d.ts +8 -1
- package/dist/schema/plan/types.d.ts +45 -11
- package/dist/schema/push-index-prebuild.d.ts +25 -0
- package/dist/schema/push-legacy-renames.d.ts +20 -0
- package/dist/schema/rls-bootstrap-sql.d.ts +15 -0
- package/dist/schema/undeclarable-constraints.d.ts +59 -0
- 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 +39 -4
- package/dist/services/BranchService.d.ts +29 -1
- package/dist/services/FetchService.d.ts +63 -12
- package/dist/services/PersistService.d.ts +15 -0
- package/dist/services/RelationService.d.ts +106 -3
- package/dist/services/cdc/CdcListener.d.ts +26 -10
- package/dist/services/cdc/identity-columns.d.ts +19 -0
- package/dist/services/cdc/trigger-cdc.d.ts +180 -18
- package/dist/services/channel-bus/PostgresChannelBus.d.ts +12 -7
- package/dist/services/channel-bus/index.d.ts +1 -1
- package/dist/services/channel-history.d.ts +32 -5
- package/dist/services/collection-helpers.d.ts +26 -1
- package/dist/services/field-viewer.d.ts +15 -1
- package/dist/services/pg-notify-listener.d.ts +95 -6
- package/dist/services/realtimeService.d.ts +467 -53
- package/dist/services/row-pipeline.d.ts +16 -9
- package/dist/services/socket-liveness.d.ts +85 -0
- package/dist/services/soft-delete.d.ts +12 -0
- package/dist/services/sql-script.d.ts +275 -0
- package/dist/services/vector-iterative-scan.d.ts +40 -0
- package/dist/services/write-depth.d.ts +22 -0
- package/dist/services/write-transaction-scope.d.ts +15 -3
- package/dist/socket-opt-ins.d.ts +64 -0
- package/dist/source-DB6xJv3p.js +873 -0
- package/dist/source-DB6xJv3p.js.map +1 -0
- package/dist/tsx-loader.d.ts +14 -0
- package/dist/utils/connection-string.d.ts +31 -0
- package/dist/utils/drizzle-conditions.d.ts +63 -3
- package/dist/utils/error-cause.d.ts +7 -0
- package/dist/utils/pg-error-utils.d.ts +2 -4
- package/dist/utils/result-rows.d.ts +10 -0
- package/dist/{vector-index-CMJKb3C9.js → vector-index-BFhyEaiz.js} +2 -2
- package/dist/{vector-index-CMJKb3C9.js.map → vector-index-BFhyEaiz.js.map} +1 -1
- package/dist/websocket-DUiiwQd2.js +1632 -0
- package/dist/websocket-DUiiwQd2.js.map +1 -0
- package/dist/websocket.d.ts +63 -18
- package/package.json +7 -7
- package/dist/BranchService-DGPL6G_C.js.map +0 -1
- package/dist/__vite-browser-external-BnuHet1e.js.map +0 -1
- package/dist/arg-Dni7MzLB.js.map +0 -1
- package/dist/backup-cli-24v4OlSp.js.map +0 -1
- package/dist/backup-service-HQ9GC4tN.js.map +0 -1
- package/dist/cli-errors-B8qHg02P.js +0 -798
- package/dist/cli-errors-B8qHg02P.js.map +0 -1
- package/dist/cli-flags-BglvpjHv.js.map +0 -1
- package/dist/cli-output-CNdMql-L.js +0 -47
- package/dist/cli-output-CNdMql-L.js.map +0 -1
- package/dist/collection-index-DdnsxiJ_.js +0 -286
- package/dist/collection-index-DdnsxiJ_.js.map +0 -1
- package/dist/column-plan-helpers-DF-8dTVa.js.map +0 -1
- package/dist/databasePoolManager-Bj5FbeAs.js.map +0 -1
- package/dist/doctor-Cb2thZ8s.js.map +0 -1
- package/dist/ensure-collection-policies-RHUcEp4v.js +0 -105
- package/dist/ensure-collection-policies-RHUcEp4v.js.map +0 -1
- package/dist/ensure-collection-tables-BEEjn5cn.js +0 -857
- 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-drizzle-schema-yzY_BLhr.js +0 -123
- package/dist/generate-drizzle-schema-yzY_BLhr.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/source-Br7L7GOI.js +0 -410
- package/dist/source-Br7L7GOI.js.map +0 -1
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import { createRequire as __createRequire } from "module";
|
|
2
2
|
__createRequire(import.meta.url);
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { r as
|
|
7
|
-
import "@rebasepro/types";
|
|
8
|
-
import "@rebasepro/common";
|
|
3
|
+
import { c as searchColumnDefinition, f as searchExtensionStatements, g as searchStampGuards, h as searchIndexStatements, m as searchIndexNames, o as fuzzyColumnDefinition, p as searchHelperFunctions, u as searchColumnStamps } from "./search-column-BM-GV6vH.js";
|
|
4
|
+
import { a as vectorDimensionGuard, c as vectorExtensionStatement, d as vectorIndexStatements, i as vectorColumnDefinition, l as vectorIndexNames, o as vectorExtensionDeclared, t as VECTOR_EXTENSION_OPT_IN } from "./vector-index-BFhyEaiz.js";
|
|
5
|
+
import { o as atlasExcludePattern, u as collectionIndexStatements } from "./source-DB6xJv3p.js";
|
|
6
|
+
import { a as triggerStatements, r as quoteSqlLiteral } from "./plan-schema-CsNgK0qi.js";
|
|
9
7
|
//#region src/schema/plan/render-ddl.ts
|
|
10
8
|
/**
|
|
11
9
|
* The SQL files, rendered from a {@link SchemaPlan}.
|
|
@@ -86,6 +84,12 @@ var renderColumnDefinition = (column) => {
|
|
|
86
84
|
if (!column.nullable && !column.primaryKey) definition += " NOT NULL";
|
|
87
85
|
return definition;
|
|
88
86
|
};
|
|
87
|
+
/**
|
|
88
|
+
* `PRIMARY KEY ("a", "b")`, the clause a composite key takes inside a
|
|
89
|
+
* `CREATE TABLE`. Shared by `schema.sql` and boot-ensure's `CREATE TABLE`, so
|
|
90
|
+
* the two cannot list the columns differently.
|
|
91
|
+
*/
|
|
92
|
+
var renderPrimaryKeyConstraint = (table) => `PRIMARY KEY (${table.primaryKey.map((c) => `"${c}"`).join(", ")})`;
|
|
89
93
|
/** `"col" TYPE …`, as it appears inside a `CREATE TABLE`. */
|
|
90
94
|
var renderColumn = (column) => `"${column.column}" ${renderColumnDefinition(column)}`;
|
|
91
95
|
/**
|
|
@@ -100,7 +104,11 @@ var renderPolicyStatements = (table, policy) => {
|
|
|
100
104
|
let create = `CREATE POLICY "${policy.name}" ON ${target} AS ${policy.mode.toUpperCase()} FOR ${policy.operation.toUpperCase()} TO ${policy.roles.map((r) => `"${r}"`).join(", ")}`;
|
|
101
105
|
if (policy.using) create += ` USING (${policy.using})`;
|
|
102
106
|
if (policy.withCheck) create += ` WITH CHECK (${policy.withCheck})`;
|
|
103
|
-
return [
|
|
107
|
+
return [
|
|
108
|
+
...(policy.supersedes ?? []).map((name) => `DROP POLICY IF EXISTS "${name}" ON ${target};`),
|
|
109
|
+
`DROP POLICY IF EXISTS "${policy.name}" ON ${target};`,
|
|
110
|
+
`${create};`
|
|
111
|
+
];
|
|
104
112
|
};
|
|
105
113
|
/** `ALTER TABLE … ENABLE ROW LEVEL SECURITY;` — every generated table is locked. */
|
|
106
114
|
var renderEnableRls = (table) => `ALTER TABLE "${table.schema}"."${table.table}" ENABLE ROW LEVEL SECURITY;`;
|
|
@@ -146,7 +154,7 @@ function renderPostgresDdl(plan, options = {}) {
|
|
|
146
154
|
});
|
|
147
155
|
ddl += `CREATE TABLE "${table.schema}"."${table.table}" (\n`;
|
|
148
156
|
const lines = emitted.map((column) => ` ${renderColumn(column)}`);
|
|
149
|
-
if (table.
|
|
157
|
+
if (table.primaryKey.length > 1) lines.push(` ${renderPrimaryKeyConstraint(table)}`);
|
|
150
158
|
ddl += lines.join(",\n");
|
|
151
159
|
ddl += "\n);\n\n";
|
|
152
160
|
for (const column of table.columns) if (column.foreignKey) fkStatements.push(`${column.foreignKey.sql};`);
|
|
@@ -250,7 +258,8 @@ function renderSearchDdl(plan) {
|
|
|
250
258
|
* two-part form is what Atlas wants when the connection URL scopes it to one
|
|
251
259
|
* schema and is *silently ignored* otherwise: it reads `posts.search_vector` as
|
|
252
260
|
* a table named `search_vector` in a schema named `posts`, matches nothing, and
|
|
253
|
-
* reports no error for the pattern that never fired.
|
|
261
|
+
* reports no error for the pattern that never fired. Each name is spelled by
|
|
262
|
+
* `atlasExcludePattern`, so one holding a `.` or glob syntax still matches.
|
|
254
263
|
*/
|
|
255
264
|
var searchExcludePatternsOf = (plan) => {
|
|
256
265
|
const patterns = [];
|
|
@@ -258,9 +267,9 @@ var searchExcludePatternsOf = (plan) => {
|
|
|
258
267
|
if (!table.search) continue;
|
|
259
268
|
for (const column of table.columns) {
|
|
260
269
|
if (column.source.kind !== "search") continue;
|
|
261
|
-
patterns.push(
|
|
270
|
+
patterns.push(atlasExcludePattern(table.schema, table.table, column.column));
|
|
262
271
|
}
|
|
263
|
-
for (const index of searchIndexNames(table.search)) patterns.push(
|
|
272
|
+
for (const index of searchIndexNames(table.search)) patterns.push(atlasExcludePattern(table.schema, table.table, index));
|
|
264
273
|
}
|
|
265
274
|
return patterns;
|
|
266
275
|
};
|
|
@@ -297,7 +306,7 @@ var vectorExcludePatternsOf = (plan) => {
|
|
|
297
306
|
const patterns = [];
|
|
298
307
|
for (const table of plan.tables) {
|
|
299
308
|
const names = [...table.vectorColumns.map((spec) => spec.column), ...table.vector ? vectorIndexNames(table.vector) : []];
|
|
300
|
-
for (const name of names) patterns.push(
|
|
309
|
+
for (const name of names) patterns.push(atlasExcludePattern(table.schema, table.table, name));
|
|
301
310
|
}
|
|
302
311
|
return patterns;
|
|
303
312
|
};
|
|
@@ -326,150 +335,8 @@ function renderTriggersDdl(plan) {
|
|
|
326
335
|
}
|
|
327
336
|
var isTriggerFunction = (statement) => statement.includes("RETURNS trigger");
|
|
328
337
|
/** @see searchExcludePatternsOf */
|
|
329
|
-
var triggerExcludePatternsOf = (plan) => plan.tables.flatMap((table) => table.triggers.map((t) =>
|
|
330
|
-
//#endregion
|
|
331
|
-
//#region src/schema/generate-postgres-ddl-logic.ts
|
|
332
|
-
var generate_postgres_ddl_logic_exports = /* @__PURE__ */ __exportAll({
|
|
333
|
-
generatePostgresDdl: () => generatePostgresDdl,
|
|
334
|
-
generatePostgresPoliciesDdl: () => generatePostgresPoliciesDdl,
|
|
335
|
-
generatePostgresSearchDdl: () => generatePostgresSearchDdl,
|
|
336
|
-
generatePostgresTriggersDdl: () => generatePostgresTriggersDdl,
|
|
337
|
-
generatePostgresVectorDdl: () => generatePostgresVectorDdl,
|
|
338
|
-
planCollectionPolicies: () => planCollectionPolicies,
|
|
339
|
-
planJunctionTables: () => planJunctionTables,
|
|
340
|
-
searchColumnDependencies: () => searchColumnDependencies,
|
|
341
|
-
searchExcludePatterns: () => searchExcludePatterns,
|
|
342
|
-
triggerExcludePatterns: () => triggerExcludePatterns,
|
|
343
|
-
vectorExcludePatterns: () => vectorExcludePatterns
|
|
344
|
-
});
|
|
345
|
-
/**
|
|
346
|
-
* `drizzle/schema.sql` — the desired state Atlas diffs the database against.
|
|
347
|
-
*
|
|
348
|
-
* Synchronous. It was `async` with nothing to await, which made every caller
|
|
349
|
-
* (the writer script, the doctor, the live editor, two gates) carry a promise
|
|
350
|
-
* for no reason and made the one place that forgot to await it silently compare
|
|
351
|
-
* `[object Promise]`.
|
|
352
|
-
*/
|
|
353
|
-
var generatePostgresDdl = (allCollections, options = {}) => renderPostgresDdl(planSchema(allCollections), options);
|
|
354
|
-
/** `drizzle/policies.sql` — the RLS policies. Atlas has no model for a policy. */
|
|
355
|
-
var generatePostgresPoliciesDdl = (allCollections) => renderPoliciesDdl(planSchema(allCollections));
|
|
356
|
-
/**
|
|
357
|
-
* `drizzle/search.sql` — everything a `search` block needs, as a file Rebase
|
|
358
|
-
* applies itself.
|
|
359
|
-
*
|
|
360
|
-
* Search is one of the parts of the schema Atlas does not own, for two
|
|
361
|
-
* independent reasons and either alone would be enough:
|
|
362
|
-
*
|
|
363
|
-
* 1. Its free tier refuses to *parse* a desired-state file that so much as
|
|
364
|
-
* contains a function — "functions and procedures are available to
|
|
365
|
-
* logged-in users only". A generated `tsvector` column cannot avoid one:
|
|
366
|
-
* `unaccent` is STABLE and jsonb flattening needs a set-returning function,
|
|
367
|
-
* so both have to be wrapped in an IMMUTABLE helper to be legal in a
|
|
368
|
-
* generated column at all.
|
|
369
|
-
* 2. Even with the file accepted, Atlas *wipes* the dev database it diffs
|
|
370
|
-
* against, so a helper seeded there beforehand is gone by the time the plan
|
|
371
|
-
* is analysed. There is no hook to reinstate it.
|
|
372
|
-
*
|
|
373
|
-
* Empty when nothing opted in — the caller writes no file then.
|
|
374
|
-
*/
|
|
375
|
-
var generatePostgresSearchDdl = (allCollections) => renderSearchDdl(planSchema(allCollections));
|
|
376
|
-
/**
|
|
377
|
-
* Glob patterns telling Atlas to leave the search column and its index alone.
|
|
378
|
-
*
|
|
379
|
-
* Without these, a desired state that omits search reads to Atlas as an
|
|
380
|
-
* instruction to drop the column — taking the index and the whole search
|
|
381
|
-
* feature with it on the next push.
|
|
382
|
-
*/
|
|
383
|
-
var searchExcludePatterns = (allCollections) => searchExcludePatternsOf(planSchema(allCollections));
|
|
384
|
-
/**
|
|
385
|
-
* `drizzle/vector.sql` — the `vector` columns, their ANN indexes and, when a
|
|
386
|
-
* database declared it, the extension.
|
|
387
|
-
*
|
|
388
|
-
* Vector is out of Atlas's hands for a narrower reason than search: not that
|
|
389
|
-
* Atlas refuses to parse the file, but that it cannot *execute* it. To compute
|
|
390
|
-
* a desired state Atlas materialises `schema.sql` in a dev database, that
|
|
391
|
-
* database is created empty, and Atlas empties it again at the start of every
|
|
392
|
-
* run — so `VECTOR(384)` resolves against a database that structurally cannot
|
|
393
|
-
* have pgvector, and every push dies with `type "vector" does not exist`.
|
|
394
|
-
*/
|
|
395
|
-
var generatePostgresVectorDdl = (allCollections, options = {}) => renderVectorDdl(planSchema(allCollections, { databaseExtensions: options.extensions }));
|
|
396
|
-
/** @see searchExcludePatterns */
|
|
397
|
-
var vectorExcludePatterns = (allCollections) => vectorExcludePatternsOf(planSchema(allCollections));
|
|
398
|
-
/**
|
|
399
|
-
* `drizzle/triggers.sql` — the `BEFORE UPDATE` triggers behind
|
|
400
|
-
* `autoValue: "on_update"`, and the one function they share.
|
|
401
|
-
*
|
|
402
|
-
* A trigger is a function plus a binding, so it is carved out of Atlas's view
|
|
403
|
-
* for the first of the two reasons search is. Empty when no property declares
|
|
404
|
-
* `on_update` — the caller writes no file then, and removes a stale one.
|
|
405
|
-
*/
|
|
406
|
-
var generatePostgresTriggersDdl = (allCollections) => renderTriggersDdl(planSchema(allCollections));
|
|
407
|
-
/** @see searchExcludePatterns */
|
|
408
|
-
var triggerExcludePatterns = (allCollections) => triggerExcludePatternsOf(planSchema(allCollections));
|
|
409
|
-
var planOf = (collections) => planSchema(collections);
|
|
410
|
-
/**
|
|
411
|
-
* The junction tables a bundle's many-to-many relations imply.
|
|
412
|
-
*
|
|
413
|
-
* Derived from the same plan the derived RLS comes from, so a table created
|
|
414
|
-
* here always has policies planned for it — a junction with row-level security
|
|
415
|
-
* left off is readable and writable by every signed-in user.
|
|
416
|
-
*/
|
|
417
|
-
var planJunctionTables = (allCollections) => planOf(allCollections).tables.filter((table) => table.kind === "junction").map((table) => ({
|
|
418
|
-
schema: table.schema,
|
|
419
|
-
table: table.table,
|
|
420
|
-
columns: table.columns.map((c) => ({
|
|
421
|
-
name: c.column,
|
|
422
|
-
type: renderPgType(c.type),
|
|
423
|
-
legacyName: c.legacyColumn
|
|
424
|
-
})),
|
|
425
|
-
createTable: `CREATE TABLE IF NOT EXISTS "${table.schema}"."${table.table}" (` + table.columns.map((c) => `"${c.column}" ${renderPgType(c.type)} NOT NULL`).join(", ") + `, PRIMARY KEY (${table.primaryKey.map((c) => `"${c}"`).join(", ")}));`,
|
|
426
|
-
foreignKeys: table.columns.map((c) => c.foreignKey).filter((fk) => fk !== void 0)
|
|
427
|
-
}));
|
|
428
|
-
/**
|
|
429
|
-
* The per-table RLS plan for the declared collections and their junctions, as
|
|
430
|
-
* executable statements — what the managed runtime applies at boot so a freshly
|
|
431
|
-
* provisioned tenant database serves data instead of 401ing every read.
|
|
432
|
-
*
|
|
433
|
-
* The same policies `policies.sql` carries, from the same plan, so boot and
|
|
434
|
-
* `db push` produce identical RLS from identical collections.
|
|
435
|
-
*/
|
|
436
|
-
var planCollectionPolicies = (allCollections) => {
|
|
437
|
-
const plan = planOf(allCollections);
|
|
438
|
-
return [...plan.tables.filter((t) => t.kind === "collection"), ...plan.tables.filter((t) => t.kind === "junction")].map((table) => ({
|
|
439
|
-
schema: table.schema,
|
|
440
|
-
table: table.table,
|
|
441
|
-
qualified: table.qualified,
|
|
442
|
-
enableRls: `ALTER TABLE "${table.schema}"."${table.table}" ENABLE ROW LEVEL SECURITY;`,
|
|
443
|
-
policyStatements: table.policies.flatMap((policy) => renderPolicyStatements(table, policy))
|
|
444
|
-
}));
|
|
445
|
-
};
|
|
446
|
-
/**
|
|
447
|
-
* The `generated column → column it reads` edges a project's `search` blocks
|
|
448
|
-
* imply, derived from the collections alone.
|
|
449
|
-
*
|
|
450
|
-
* The same edges `queryGeneratedColumnDependencies` reads out of `pg_depend`,
|
|
451
|
-
* but available where no database is: `rebase db generate` writes a migration
|
|
452
|
-
* that will run somewhere else, later, against a database it cannot inspect.
|
|
453
|
-
* A spec's `fields[].column` is the physical column each search field starts
|
|
454
|
-
* at, which is exactly what the generated expression depends on.
|
|
455
|
-
*/
|
|
456
|
-
var searchColumnDependencies = (allCollections) => {
|
|
457
|
-
const dependencies = [];
|
|
458
|
-
for (const table of planOf(allCollections).tables) {
|
|
459
|
-
const spec = table.search;
|
|
460
|
-
if (!spec) continue;
|
|
461
|
-
const generated = [spec.column, ...spec.fuzzy ? [spec.fuzzy.column] : []];
|
|
462
|
-
const sources = new Set(spec.fields.map((field) => field.column));
|
|
463
|
-
for (const column of generated) for (const dependsOn of sources) dependencies.push({
|
|
464
|
-
schema: table.schema,
|
|
465
|
-
table: table.table,
|
|
466
|
-
column,
|
|
467
|
-
dependsOn
|
|
468
|
-
});
|
|
469
|
-
}
|
|
470
|
-
return dependencies;
|
|
471
|
-
};
|
|
338
|
+
var triggerExcludePatternsOf = (plan) => plan.tables.flatMap((table) => table.triggers.map((t) => atlasExcludePattern(table.schema, table.table, t.name)));
|
|
472
339
|
//#endregion
|
|
473
|
-
export {
|
|
340
|
+
export { renderPolicyStatements as a, renderSearchDdl as c, searchExcludePatternsOf as d, triggerExcludePatternsOf as f, renderPoliciesDdl as i, renderTriggersDdl as l, renderEnableRls as n, renderPostgresDdl as o, vectorExcludePatternsOf as p, renderPgType as r, renderPrimaryKeyConstraint as s, renderColumnDefinition as t, renderVectorDdl as u };
|
|
474
341
|
|
|
475
|
-
//# sourceMappingURL=
|
|
342
|
+
//# sourceMappingURL=render-ddl-CrfEe__B.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-ddl-CrfEe__B.js","names":[],"sources":["../src/schema/plan/render-ddl.ts"],"sourcesContent":["/**\n * The SQL files, rendered from a {@link SchemaPlan}.\n *\n * Four files, because Atlas owns exactly one of them:\n *\n * - `schema.sql` — the desired state Atlas diffs the database against.\n * - `policies.sql` — the RLS policies. Atlas has no model for a policy.\n * - `search.sql` — the generated `tsvector` column, its GIN index and the\n * IMMUTABLE helpers its expression calls. Atlas's free tier refuses to\n * *parse* a file containing a function, and it wipes the dev database it\n * diffs against, so a helper seeded there is gone by the time the plan runs.\n * - `vector.sql` — the `vector` columns and their ANN indexes. Atlas cannot\n * *execute* these: it materialises `schema.sql` in a dev database that is\n * created empty and emptied again on every run, so `VECTOR(384)` resolves\n * against a database that structurally cannot have pgvector.\n * - `triggers.sql` — `autoValue: \"on_update\"`, which is a function plus a\n * binding, so it is out for the same reason search is.\n *\n * Everything not in `schema.sql` is excluded from Atlas's view by pattern\n * (`…ExcludePatterns` below) and applied by Rebase — at push time by the CLI,\n * at boot by the schema ensure. Without the excludes a desired state that omits\n * an object reads to Atlas as an instruction to drop it.\n */\nimport {\n fuzzyColumnDefinition,\n searchColumnDefinition,\n searchColumnStamps,\n searchExtensionStatements,\n searchHelperFunctions,\n searchIndexNames,\n searchIndexStatements,\n searchStampGuards\n} from \"../search-column\";\nimport {\n VECTOR_EXTENSION_OPT_IN,\n vectorColumnDefinition,\n vectorDimensionGuard,\n vectorExtensionDeclared,\n vectorExtensionStatement,\n vectorIndexNames,\n vectorIndexStatements\n} from \"../vector-index\";\nimport { atlasExcludePattern } from \"../atlas-exclude\";\nimport { collectionIndexStatements } from \"../collection-index\";\nimport { quoteSqlLiteral } from \"./plan-schema\";\nimport { triggerStatements } from \"./updated-at-trigger\";\nimport type { ColumnPlan, PgType, PolicyPlan, SchemaPlan, TablePlan } from \"./types\";\n\n/** What `schema.sql` may leave out, because another file owns it. */\nexport interface DdlRenderOptions {\n /** RLS policies. `false` puts them in `policies.sql` alone. */\n includePolicies?: boolean;\n /** The search column, its helpers and its index. See `search.sql`. */\n includeSearch?: boolean;\n /** The vector columns and their ANN indexes. See `vector.sql`. */\n includeVector?: boolean;\n}\n\n/**\n * A {@link PgType} as Postgres spells it.\n *\n * The one place. `getSqlColumnType` and `getDrizzleColumn` each carried their\n * own ladder and disagreed about `VARCHAR` widths, about `geopoint`, and about\n * whether an `increment` id honours `columnType`.\n */\nexport const renderPgType = (type: PgType): string => {\n switch (type.kind) {\n case \"text\": return \"TEXT\";\n case \"varchar\": return `VARCHAR(${type.length})`;\n case \"char\": return `CHAR(${type.length})`;\n case \"uuid\": return \"UUID\";\n case \"enum\": return `\"${type.schema}\".\"${type.name}\"`;\n case \"smallint\": return \"SMALLINT\";\n case \"integer\": return \"INTEGER\";\n case \"bigint\": return \"BIGINT\";\n case \"smallserial\": return \"SMALLSERIAL\";\n case \"serial\": return \"SERIAL\";\n case \"bigserial\": return \"BIGSERIAL\";\n case \"real\": return \"REAL\";\n case \"doublePrecision\": return \"DOUBLE PRECISION\";\n case \"numeric\":\n if (type.precision === undefined) return \"NUMERIC\";\n return type.scale === undefined\n ? `NUMERIC(${type.precision})`\n : `NUMERIC(${type.precision}, ${type.scale})`;\n case \"boolean\": return \"BOOLEAN\";\n case \"timestamptz\": return \"TIMESTAMP WITH TIME ZONE\";\n case \"date\": return \"DATE\";\n case \"time\": return \"TIME\";\n case \"json\": return \"JSON\";\n case \"jsonb\": return \"JSONB\";\n case \"vector\": return `VECTOR(${type.dimensions})`;\n case \"bytea\": return \"BYTEA\";\n case \"tsvector\": return \"tsvector\";\n case \"array\": return `${renderPgType(type.of)}[]`;\n }\n};\n\n/**\n * Everything after the column name, in one order for every SQL emitter.\n *\n * `CREATE TABLE` and `ADD COLUMN` used to assemble this separately, which is\n * how a required relation column came out `NOT NULL` after `db push` and\n * nullable after a boot-ensure. `identity` is part of the type rather than a\n * DEFAULT, which is why it is rendered here and not in the DEFAULT slot.\n */\nexport const renderColumnDefinition = (column: ColumnPlan): string => {\n // `auth-users-columns` is the single description of what an auth user\n // table's columns must be, and it hands over a rendered definition.\n if (column.sqlDefinition) return column.sqlDefinition;\n\n if (column.generated) {\n return `${renderPgType(column.type)} GENERATED ALWAYS AS (${column.generated.expression}) STORED`;\n }\n\n let definition = renderPgType(column.type);\n if (column.default?.kind === \"identity\") definition += \" GENERATED BY DEFAULT AS IDENTITY\";\n if (column.primaryKey) definition += \" PRIMARY KEY\";\n if (column.unique) definition += \" UNIQUE\";\n if (column.default && column.default.kind !== \"identity\") {\n definition += ` DEFAULT ${column.default.kind === \"sql\" ? column.default.expression : column.default.sql}`;\n }\n if (!column.nullable && !column.primaryKey) definition += \" NOT NULL\";\n return definition;\n};\n\n/**\n * `PRIMARY KEY (\"a\", \"b\")`, the clause a composite key takes inside a\n * `CREATE TABLE`. Shared by `schema.sql` and boot-ensure's `CREATE TABLE`, so\n * the two cannot list the columns differently.\n */\nexport const renderPrimaryKeyConstraint = (table: Pick<TablePlan, \"primaryKey\">): string =>\n `PRIMARY KEY (${table.primaryKey.map(c => `\"${c}\"`).join(\", \")})`;\n\n/** `\"col\" TYPE …`, as it appears inside a `CREATE TABLE`. */\nconst renderColumn = (column: ColumnPlan): string =>\n `\"${column.column}\" ${renderColumnDefinition(column)}`;\n\n// ── Policies ─────────────────────────────────────────────────────────────────\n\n/**\n * One policy as its `DROP` / `CREATE` pair — each a complete statement.\n *\n * This is the primitive the boot-time RLS applier runs one statement at a time\n * (the runtime's DB handle speaks the extended query protocol, which forbids\n * multiple commands in one execute), while `db push` writes the joined string.\n */\nexport const renderPolicyStatements = (\n table: Pick<TablePlan, \"schema\" | \"table\">,\n policy: PolicyPlan\n): string[] => {\n const target = `\"${table.schema}\".\"${table.table}\"`;\n let create = `CREATE POLICY \"${policy.name}\" ON ${target} AS ${policy.mode.toUpperCase()} ` +\n `FOR ${policy.operation.toUpperCase()} TO ${policy.roles.map(r => `\"${r}\"`).join(\", \")}`;\n if (policy.using) create += ` USING (${policy.using})`;\n if (policy.withCheck) create += ` WITH CHECK (${policy.withCheck})`;\n // The one policy an older naming stored this rule's operations under —\n // see `PolicyPlan.supersedes`. In the same per-table transaction, so a\n // request sees the old policy or the new ones, never neither.\n const superseded = (policy.supersedes ?? []).map(name => `DROP POLICY IF EXISTS \"${name}\" ON ${target};`);\n return [...superseded, `DROP POLICY IF EXISTS \"${policy.name}\" ON ${target};`, `${create};`];\n};\n\n/** `ALTER TABLE … ENABLE ROW LEVEL SECURITY;` — every generated table is locked. */\nexport const renderEnableRls = (table: Pick<TablePlan, \"schema\" | \"table\">): string =>\n `ALTER TABLE \"${table.schema}\".\"${table.table}\" ENABLE ROW LEVEL SECURITY;`;\n\nconst statementsToDdl = (statements: string[]): string => statements.map(s => `${s}\\n`).join(\"\");\n\n// ── schema.sql ───────────────────────────────────────────────────────────────\n\nexport function renderPostgresDdl(plan: SchemaPlan, options: DdlRenderOptions = {}): string {\n const includePolicies = options.includePolicies !== false;\n const includeSearch = options.includeSearch !== false;\n const includeVector = options.includeVector !== false;\n\n let ddl = \"-- This file is auto-generated by the Rebase DDL generator. Do not edit manually.\\n\\n\";\n\n // 1. Custom schemas.\n //\n // `rebase` is unconditional and load-bearing. The RLS helper functions live\n // in it, so the migration preamble creates it — which puts it in Atlas's\n // replayed state, and anything in that state but absent from this desired\n // schema gets a `DROP SCHEMA … CASCADE` planned against it. That would take\n // the auth tables.\n plan.schemas.forEach(schema => { ddl += `CREATE SCHEMA IF NOT EXISTS \"${schema}\";\\n`; });\n if (plan.schemas.length > 0) ddl += \"\\n\";\n\n // 1b. Search support, for collections that opted in.\n //\n // Extensions and helper functions come before every CREATE TABLE because a\n // generated column's expression is resolved at creation time: a table whose\n // search column calls `rebase_search_text` cannot be created before that\n // function exists. Both are `IF NOT EXISTS` / `OR REPLACE`, so a file\n // replayed against a live database is a no-op here.\n const searchTables = plan.tables.filter(t => t.search);\n if (searchTables.length > 0) {\n if (!includeSearch) {\n ddl += \"-- Full-text search support lives in `search.sql`, applied separately.\\n\\n\";\n } else {\n const extensions = Array.from(new Set(searchTables.flatMap(t => searchExtensionStatements(t.search!))));\n const helpers = Array.from(new Set(searchTables.flatMap(t => searchHelperFunctions(t.search!))));\n ddl += \"-- Full-text search support (collections declaring a `search` block)\\n\";\n extensions.forEach(s => { ddl += `${s}\\n`; });\n if (extensions.length > 0) ddl += \"\\n\";\n helpers.forEach(s => { ddl += `${s}\\n\\n`; });\n }\n }\n\n // 1c. Vector support. Only ever a note, never a statement — unlike 1b.\n // `CREATE EXTENSION vector` is the one thing this file must never carry\n // whichever way the flag goes: Atlas rejects an extension in a desired\n // state as a paid feature.\n if (!includeVector && plan.tables.some(t => t.vectorColumns.length > 0)) {\n ddl += \"-- Vector columns and their ANN indexes live in `vector.sql`, applied separately.\\n\\n\";\n }\n\n // 1d. `autoValue: \"on_update\"`. A trigger is a function plus a binding, so\n // it is out of Atlas's sight for the reason search is — and out\n // unconditionally, because `schema.sql` has no flag that would make Atlas\n // able to read one.\n if (plan.tables.some(t => t.triggers.length > 0)) {\n ddl += \"-- `autoValue: \\\"on_update\\\"` triggers live in `triggers.sql`, applied separately.\\n\\n\";\n }\n\n // 2. Enum types.\n plan.enums.forEach(enumPlan => {\n ddl += `CREATE TYPE \"${enumPlan.schema}\".\"${enumPlan.name}\" AS ENUM (${enumPlan.labels.map(quoteSqlLiteral).join(\", \")});\\n`;\n });\n if (ddl.endsWith(\";\\n\")) ddl += \"\\n\";\n\n // 3. Tables, in the plan's order — each collection, then any junction its\n // relations imply.\n const fkStatements: string[] = [];\n // Indexes follow the tables for the same reason the FK constraints do: the\n // table has to exist first.\n const indexStatements: string[] = [];\n // Policies are emitted after every CREATE TABLE, like the FK constraints: a\n // policy may reference other tables (a junction's derived policies always\n // reference both endpoints; `policy.existsIn` references a join table), and\n // CREATE POLICY validates those relations at creation time.\n const policyStatements: string[] = [];\n\n for (const table of plan.tables) {\n const emitted = table.columns.filter(column => {\n // A vector column is not Atlas's — `vector.sql` adds it. Filtered\n // here rather than upstream so the column keeps its place in the\n // generator's order when it *is* included, which is what the\n // derived-names contract renders.\n if (!includeVector && column.type.kind === \"vector\") return false;\n if (!includeSearch && column.source.kind === \"search\") return false;\n // A declared property already emits this column (an explicit\n // `postId` beside the `belongsTo` that uses it); the relation\n // contributes only the constraint.\n if (column.columnOwnedByProperty) return false;\n return true;\n });\n\n ddl += `CREATE TABLE \"${table.schema}\".\"${table.table}\" (\\n`;\n const lines = emitted.map(column => ` ${renderColumn(column)}`);\n // A key over several columns — a junction's two endpoints, or a\n // collection with several `isId` properties — is one table constraint;\n // a single-column key is already inline on its column.\n if (table.primaryKey.length > 1) {\n lines.push(` ${renderPrimaryKeyConstraint(table)}`);\n }\n ddl += lines.join(\",\\n\");\n ddl += \"\\n);\\n\\n\";\n\n for (const column of table.columns) {\n if (column.foreignKey) fkStatements.push(`${column.foreignKey.sql};`);\n }\n\n if (includeSearch && table.search) {\n indexStatements.push(...searchIndexStatements(table.search));\n }\n // ANN indexes are emitted with the other indexes rather than inline,\n // because `CREATE INDEX` is a statement and a column definition is not\n // — and because a column too wide for pgvector to index still needs its\n // column. Absent alongside their column when vector is carved out.\n if (includeVector && table.vector) {\n indexStatements.push(...vectorIndexStatements(table.vector));\n for (const skip of table.vector.skipped) {\n indexStatements.push(`-- No ANN index on \"${skip.schema}\".\"${skip.table}\".\"${skip.column}\": ${skip.reason}`);\n }\n }\n // The collection's own `indexes:` block. Last of the three index\n // producers, and the only one the developer wrote deliberately rather\n // than getting as a side effect of another feature.\n indexStatements.push(...collectionIndexStatements(table.indexes));\n\n if (includePolicies) {\n // No FORCE: authenticated requests run as the non-owner\n // `rebase_user` role, which plain ENABLE already binds. The owner\n // (server context) must bypass — it is the trusted plane.\n ddl += `${renderEnableRls(table)}\\n`;\n ddl += \"\\n\";\n for (const policy of table.policies) {\n policyStatements.push(statementsToDdl(renderPolicyStatements(table, policy)));\n }\n }\n }\n\n // Indexes before foreign keys. Today every FK targets a primary key created\n // inline, so the order is safe by accident; the moment a declared\n // `unique: true` index can back an FK target, a constraint emitted first\n // would reference an index that does not exist yet.\n if (indexStatements.length > 0) {\n ddl += \"-- Indexes\\n\";\n ddl += indexStatements.join(\"\\n\") + \"\\n\\n\";\n }\n\n if (fkStatements.length > 0) {\n ddl += \"-- Foreign Key Constraints\\n\";\n ddl += fkStatements.join(\"\\n\") + \"\\n\\n\";\n }\n\n if (policyStatements.length > 0) {\n ddl += \"-- Row Level Security Policies\\n\";\n ddl += policyStatements.join(\"\");\n ddl += \"\\n\";\n }\n\n return ddl;\n}\n\n// ── policies.sql ─────────────────────────────────────────────────────────────\n\nexport function renderPoliciesDdl(plan: SchemaPlan): string {\n let ddl = \"-- This file contains RLS policies generated by Rebase. Applied separately from migrations.\\n\\n\";\n\n // Collections first, then the junctions no collection declares — the order\n // the boot-time applier plans them in.\n for (const table of plan.tables.filter(t => t.kind === \"collection\")) {\n ddl += `${renderEnableRls(table)}\\n`;\n ddl += \"\\n\";\n if (table.policies.length === 0) continue;\n let announced: string | undefined;\n for (const policy of table.policies) {\n // Say which policies the author did not write. They are permissive,\n // so they OR with the declared rules and widen the final ACL beyond\n // what `securityRules` reads like — and re-appear after any manual\n // DROP, because a push asserts the declared state. Once per *rule*:\n // one rule with four operations is one thing the author did not\n // write, not four.\n if (policy.injected && policy.ruleKey !== announced) {\n ddl += \"-- Injected by Rebase (not from this collection's securityRules).\\n\";\n ddl += `-- Set \\`disableDefaultPolicies: true\\` on \"${table.slug}\" to drop these and own its RLS outright.\\n`;\n }\n announced = policy.ruleKey;\n ddl += statementsToDdl(renderPolicyStatements(table, policy));\n }\n ddl += \"\\n\";\n }\n\n for (const table of plan.tables.filter(t => t.kind === \"junction\")) {\n ddl += `${renderEnableRls(table)}\\n`;\n ddl += \"\\n\";\n if (table.policies.length === 0) continue;\n const declaringSlugs = (table.declaringSlugs ?? []).join('\", \"');\n ddl += `-- Derived by Rebase for the junction \"${table.table}\" (no collection declares it).\\n`;\n ddl += \"-- Reads require both endpoint rows to be visible; writes follow the update\\n\";\n ddl += `-- rules of \"${declaringSlugs}\". Set \\`disableDefaultPolicies: true\\` on the\\n`;\n ddl += \"-- declaring collection(s) to drop these and police the junction yourself.\\n\";\n for (const policy of table.policies) {\n ddl += statementsToDdl(renderPolicyStatements(table, policy));\n }\n ddl += \"\\n\";\n }\n\n return ddl;\n}\n\n// ── search.sql ───────────────────────────────────────────────────────────────\n\nexport function renderSearchDdl(plan: SchemaPlan): string {\n const tables = plan.tables.filter(t => t.search);\n if (tables.length === 0) return \"\";\n\n const extensions = Array.from(new Set(tables.flatMap(t => searchExtensionStatements(t.search!))));\n const helpers = Array.from(new Set(tables.flatMap(t => searchHelperFunctions(t.search!))));\n\n let ddl = \"-- This file is auto-generated by the Rebase DDL generator. Do not edit manually.\\n\";\n ddl += \"--\\n\";\n ddl += \"-- Full-text search for the collections declaring a `search` block.\\n\";\n ddl += \"-- Applied by Rebase, not by Atlas — see generatePostgresSearchDdl.\\n\\n\";\n\n extensions.forEach(s => { ddl += `${s}\\n`; });\n if (extensions.length > 0) ddl += \"\\n\";\n helpers.forEach(s => { ddl += `${s}\\n\\n`; });\n\n for (const table of tables) {\n const spec = table.search!;\n const target = `\"${table.schema}\".\"${table.table}\"`;\n // ADD COLUMN IF NOT EXISTS rather than the inline definition the\n // CREATE TABLE would use: by the time this runs the table exists,\n // whether Atlas just created it or it has been live for a year. The\n // guard first, because `ADD COLUMN IF NOT EXISTS` is a no-op against an\n // existing column — without it the file would report success, leave the\n // old expression in place, and then stamp it as current.\n searchStampGuards(spec).forEach(s => { ddl += `${s}\\n`; });\n ddl += `ALTER TABLE ${target} ADD COLUMN IF NOT EXISTS ${searchColumnDefinition(spec)};\\n`;\n const fuzzy = fuzzyColumnDefinition(spec);\n if (fuzzy) ddl += `ALTER TABLE ${target} ADD COLUMN IF NOT EXISTS ${fuzzy};\\n`;\n searchColumnStamps(spec).forEach(s => { ddl += `${s.sql}\\n`; });\n searchIndexStatements(spec).forEach(s => { ddl += `${s}\\n`; });\n ddl += \"\\n\";\n }\n\n return ddl;\n}\n\n/**\n * Glob patterns telling Atlas to leave an object alone.\n *\n * Fully qualified, `schema.table.object`, matching the include list. The\n * two-part form is what Atlas wants when the connection URL scopes it to one\n * schema and is *silently ignored* otherwise: it reads `posts.search_vector` as\n * a table named `search_vector` in a schema named `posts`, matches nothing, and\n * reports no error for the pattern that never fired. Each name is spelled by\n * `atlasExcludePattern`, so one holding a `.` or glob syntax still matches.\n */\nexport const searchExcludePatternsOf = (plan: SchemaPlan): string[] => {\n const patterns: string[] = [];\n for (const table of plan.tables) {\n if (!table.search) continue;\n for (const column of table.columns) {\n if (column.source.kind !== \"search\") continue;\n patterns.push(atlasExcludePattern(table.schema, table.table, column.column));\n }\n for (const index of searchIndexNames(table.search)) {\n patterns.push(atlasExcludePattern(table.schema, table.table, index));\n }\n }\n return patterns;\n};\n\n// ── vector.sql ───────────────────────────────────────────────────────────────\n\nexport function renderVectorDdl(plan: SchemaPlan): string {\n const tables = plan.tables.filter(t => t.vectorColumns.length > 0);\n if (tables.length === 0) return \"\";\n\n let ddl = \"-- This file is auto-generated by the Rebase DDL generator. Do not edit manually.\\n\";\n ddl += \"--\\n\";\n ddl += \"-- Vector columns and their ANN indexes, for the collections declaring a\\n\";\n ddl += \"-- `vector` property. Applied by Rebase, not by Atlas — see\\n\";\n ddl += \"-- generatePostgresVectorDdl.\\n\\n\";\n // The note is not decoration. Someone reading this file after a failed push\n // is looking for the reason the type does not exist, and \"no CREATE\n // EXTENSION here\" is invisible unless it is written down.\n ddl += vectorExtensionDeclared(plan.options.databaseExtensions)\n ? `${vectorExtensionStatement()}\\n\\n`\n : \"-- pgvector is not installed from here: no database declared it. To let Rebase\\n\" +\n `-- install it, add ${VECTOR_EXTENSION_OPT_IN} in config/resources.ts.\\n` +\n \"-- Otherwise install it once by hand; the column below needs the type either way.\\n\\n\";\n\n for (const table of tables) {\n const target = `\"${table.schema}\".\"${table.table}\"`;\n for (const spec of table.vectorColumns) {\n // Guard before the ADD, so a changed `dimensions` is reported\n // rather than skipped over — see `vectorDimensionGuard`.\n ddl += `${vectorDimensionGuard(spec)}\\n`;\n ddl += `ALTER TABLE ${target} ADD COLUMN IF NOT EXISTS ${vectorColumnDefinition(spec)};\\n`;\n }\n if (table.vector) {\n vectorIndexStatements(table.vector).forEach(s => { ddl += `${s}\\n`; });\n for (const skip of table.vector.skipped) {\n ddl += `-- No ANN index on \"${skip.schema}\".\"${skip.table}\".\"${skip.column}\": ${skip.reason}\\n`;\n }\n }\n ddl += \"\\n\";\n }\n\n return ddl;\n}\n\n/** @see searchExcludePatternsOf */\nexport const vectorExcludePatternsOf = (plan: SchemaPlan): string[] => {\n const patterns: string[] = [];\n for (const table of plan.tables) {\n const names = [\n ...table.vectorColumns.map(spec => spec.column),\n ...(table.vector ? vectorIndexNames(table.vector) : [])\n ];\n for (const name of names) patterns.push(atlasExcludePattern(table.schema, table.table, name));\n }\n return patterns;\n};\n\n// ── triggers.sql ─────────────────────────────────────────────────────────────\n\n/**\n * `autoValue: \"on_update\"`, as the file Rebase applies itself.\n *\n * Empty when nothing declares one — the caller writes no file then, and removes\n * a stale one.\n */\nexport function renderTriggersDdl(plan: SchemaPlan): string {\n const tables = plan.tables.filter(t => t.triggers.length > 0);\n if (tables.length === 0) return \"\";\n\n let ddl = \"-- This file is auto-generated by the Rebase DDL generator. Do not edit manually.\\n\";\n ddl += \"--\\n\";\n ddl += \"-- `updated_at` triggers, for the properties declaring `autoValue: \\\"on_update\\\"`.\\n\";\n ddl += \"-- Applied by Rebase, not by Atlas — a trigger is a function plus a binding,\\n\";\n ddl += \"-- and Atlas's free tier refuses to parse a desired state containing one.\\n\\n\";\n\n for (const statement of plan.functions.filter(isTriggerFunction)) {\n ddl += `${statement}\\n\\n`;\n }\n for (const table of tables) {\n for (const trigger of table.triggers) {\n triggerStatements(trigger).forEach(s => { ddl += `${s}\\n`; });\n }\n ddl += \"\\n\";\n }\n return ddl;\n}\n\nconst isTriggerFunction = (statement: string): boolean => statement.includes(\"RETURNS trigger\");\n\n/** @see searchExcludePatternsOf */\nexport const triggerExcludePatternsOf = (plan: SchemaPlan): string[] =>\n plan.tables.flatMap(table => table.triggers.map(t => atlasExcludePattern(table.schema, table.table, t.name)));\n"],"mappings":"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"}
|