@rebasepro/server-postgres 0.22.0 → 0.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{BranchService-CucnFcSE.js → BranchService-BRt78gfa.js} +35 -18
- package/dist/BranchService-BRt78gfa.js.map +1 -0
- package/dist/PostgresBackendDriver.d.ts +116 -4
- package/dist/auth/services.d.ts +99 -22
- 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 +22 -0
- package/dist/{backup-cli-DqBakiMO.js → backup-cli-DW5p9_zv.js} +17 -14
- package/dist/backup-cli-DW5p9_zv.js.map +1 -0
- package/dist/{backup-service-CaMOS76G.js → backup-service-EwcDVG-8.js} +7 -9
- package/dist/{backup-service-CaMOS76G.js.map → backup-service-EwcDVG-8.js.map} +1 -1
- package/dist/{cli-errors-Dka89exj.js → cli-errors-DsA-K9uP.js} +101 -1
- package/dist/cli-errors-DsA-K9uP.js.map +1 -0
- package/dist/cli-errors.d.ts +42 -0
- package/dist/cli-flags-BglvpjHv.js +138 -0
- package/dist/cli-flags-BglvpjHv.js.map +1 -0
- package/dist/cli-flags.d.ts +28 -0
- package/dist/cli-helpers.d.ts +18 -12
- package/dist/cli-scratch-database.d.ts +34 -0
- package/dist/cli.js +177 -287
- package/dist/cli.js.map +1 -1
- package/dist/{column-plan-helpers-CpILzHJS.js → column-plan-helpers-1-LQD0yI.js} +44 -38
- package/dist/column-plan-helpers-1-LQD0yI.js.map +1 -0
- package/dist/data-transformer.d.ts +0 -8
- package/dist/{doctor-CU9IogdL.js → doctor-C-sYWbmt.js} +228 -46
- package/dist/doctor-C-sYWbmt.js.map +1 -0
- package/dist/{ensure-collection-policies-Dzd-2S81.js → ensure-collection-policies-B1ureSIV.js} +73 -18
- package/dist/ensure-collection-policies-B1ureSIV.js.map +1 -0
- package/dist/{ensure-collection-tables-CpAgy51F.js → ensure-collection-tables-kkkHk8oo.js} +124 -37
- package/dist/ensure-collection-tables-kkkHk8oo.js.map +1 -0
- package/dist/{ensure-tables-Cr5B4UmH.js → ensure-tables-BmI_tRxc.js} +10 -3
- package/dist/ensure-tables-BmI_tRxc.js.map +1 -0
- package/dist/{generate-drizzle-schema-B537GIvz.js → generate-drizzle-schema-93M0lUxK.js} +2 -2
- package/dist/{generate-drizzle-schema-B537GIvz.js.map → generate-drizzle-schema-93M0lUxK.js.map} +1 -1
- package/dist/{generate-drizzle-schema-logic-BcMl7VSy.js → generate-drizzle-schema-logic-sSFDp6LR.js} +26 -8
- package/dist/generate-drizzle-schema-logic-sSFDp6LR.js.map +1 -0
- package/dist/generate-postgres-ddl-logic-BJsLaVNX.js +152 -0
- package/dist/generate-postgres-ddl-logic-BJsLaVNX.js.map +1 -0
- package/dist/generated-sql.d.ts +28 -0
- package/dist/index.es.js +4768 -1117
- package/dist/index.es.js.map +1 -1
- package/dist/{introspect-db-logic-C6LQdTxj.js → introspect-db-logic-kCETE8TY.js} +532 -39
- package/dist/introspect-db-logic-kCETE8TY.js.map +1 -0
- package/dist/introspect-db-queries-C_Q5VgQw.js +317 -0
- package/dist/introspect-db-queries-C_Q5VgQw.js.map +1 -0
- package/dist/{plan-schema-CboAIwLN.js → plan-schema-DU9exq6C.js} +291 -529
- package/dist/plan-schema-DU9exq6C.js.map +1 -0
- package/dist/{policy-drift-xJfy9xG7.js → policy-drift-B-J2hhm0.js} +3 -3
- package/dist/policy-drift-B-J2hhm0.js.map +1 -0
- package/dist/{generate-postgres-ddl-logic-D7imhYV8.js → render-ddl-Ds2t_d9V.js} +11 -149
- package/dist/render-ddl-Ds2t_d9V.js.map +1 -0
- package/dist/{rls-bootstrap-sql-H3rCFi3F.js → rls-bootstrap-sql-_KNnjanK.js} +562 -35
- package/dist/rls-bootstrap-sql-_KNnjanK.js.map +1 -0
- package/dist/{rls-enforcement-C6Xk0lA6.js → rls-enforcement-CfXOJJaW.js} +10 -2
- package/dist/rls-enforcement-CfXOJJaW.js.map +1 -0
- package/dist/schema/atlas-argv.d.ts +15 -0
- package/dist/schema/auth-schema.d.ts +170 -0
- package/dist/schema/classify-change.d.ts +29 -1
- package/dist/schema/column-plan-helpers.d.ts +51 -20
- package/dist/schema/destructive-sql.d.ts +71 -1
- package/dist/schema/doctor-cli.js +4 -4
- package/dist/schema/doctor.d.ts +34 -1
- package/dist/schema/ensure-collection-policies.d.ts +22 -0
- package/dist/schema/generate-drizzle-schema.js +1 -1
- package/dist/schema/generate-postgres-ddl-logic.d.ts +5 -5
- package/dist/schema/generate-postgres-ddl.js +1 -1
- package/dist/schema/generate-schema-commit.d.ts +12 -0
- package/dist/schema/introspect-db-logic.d.ts +31 -0
- package/dist/schema/introspect-db-queries.d.ts +1 -1
- package/dist/schema/introspect-db-search.d.ts +22 -0
- package/dist/schema/introspect-db-storage.d.ts +83 -0
- package/dist/schema/introspect-db.js +15 -314
- package/dist/schema/introspect-db.js.map +1 -1
- package/dist/schema/plan/diff-plan.d.ts +4 -3
- package/dist/schema/plan/plan-schema.d.ts +26 -11
- package/dist/schema/plan/render-ddl.d.ts +6 -0
- package/dist/schema/plan/types.d.ts +43 -12
- package/dist/search-column-BM-GV6vH.js +442 -0
- package/dist/search-column-BM-GV6vH.js.map +1 -0
- package/dist/security/policy-drift.d.ts +1 -1
- package/dist/security/rls-enforcement.d.ts +7 -0
- package/dist/services/BranchService.d.ts +22 -1
- package/dist/services/FetchService.d.ts +102 -32
- package/dist/services/PersistService.d.ts +41 -5
- package/dist/services/RelationService.d.ts +29 -0
- package/dist/services/RelationWriteService.d.ts +6 -0
- package/dist/services/cdc/CdcListener.d.ts +15 -5
- package/dist/services/cdc/identity-columns.d.ts +19 -0
- package/dist/services/cdc/trigger-cdc.d.ts +45 -7
- package/dist/services/channel-bus/PostgresChannelBus.d.ts +12 -7
- package/dist/services/channel-history.d.ts +17 -1
- package/dist/services/collection-helpers.d.ts +21 -0
- package/dist/services/dataService.d.ts +3 -20
- package/dist/services/field-op-sql.d.ts +71 -0
- package/dist/services/junction-writes.d.ts +19 -3
- package/dist/services/pg-notify-listener.d.ts +95 -6
- package/dist/services/read-field-access.d.ts +19 -0
- package/dist/services/realtimeService.d.ts +232 -44
- package/dist/services/row-pipeline.d.ts +5 -0
- package/dist/services/socket-liveness.d.ts +45 -0
- package/dist/services/soft-delete.d.ts +12 -2
- package/dist/services/sql-script.d.ts +71 -0
- package/dist/services/write-depth.d.ts +16 -0
- package/dist/services/write-transaction-scope.d.ts +42 -0
- package/dist/utils/drizzle-conditions.d.ts +49 -4
- package/dist/utils/sql-redaction.d.ts +21 -0
- package/dist/websocket.d.ts +57 -18
- package/package.json +9 -9
- package/dist/BranchService-CucnFcSE.js.map +0 -1
- package/dist/backup-cli-DqBakiMO.js.map +0 -1
- package/dist/cli-errors-Dka89exj.js.map +0 -1
- package/dist/column-plan-helpers-CpILzHJS.js.map +0 -1
- package/dist/doctor-CU9IogdL.js.map +0 -1
- package/dist/ensure-collection-policies-Dzd-2S81.js.map +0 -1
- package/dist/ensure-collection-tables-CpAgy51F.js.map +0 -1
- package/dist/ensure-tables-Cr5B4UmH.js.map +0 -1
- package/dist/generate-drizzle-schema-logic-BcMl7VSy.js.map +0 -1
- package/dist/generate-postgres-ddl-logic-D7imhYV8.js.map +0 -1
- package/dist/introspect-db-logic-C6LQdTxj.js.map +0 -1
- package/dist/plan-schema-CboAIwLN.js.map +0 -1
- package/dist/policy-drift-xJfy9xG7.js.map +0 -1
- package/dist/rls-bootstrap-sql-H3rCFi3F.js.map +0 -1
- package/dist/rls-enforcement-C6Xk0lA6.js.map +0 -1
package/dist/schema/doctor.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { CollectionConfig, Property } from "@rebasepro/types";
|
|
2
|
+
import type { PgType, TablePlan } from "./plan/types.js";
|
|
2
3
|
export type IssueSeverity = "error" | "warning" | "info";
|
|
3
4
|
export interface DoctorIssue {
|
|
4
5
|
severity: IssueSeverity;
|
|
5
|
-
category: "missing_table" | "missing_column" | "type_mismatch" | "missing_constraint" | "schema_stale" | "missing_enum" | "enum_value_mismatch" | "missing_foreign_key" | "sdk_stale" | "sdk_not_generated" | "sdk_ungeneratable";
|
|
6
|
+
category: "missing_table" | "missing_column" | "type_mismatch" | "missing_constraint" | "primary_key_mismatch" | "schema_stale" | "missing_enum" | "enum_value_mismatch" | "missing_foreign_key" | "orphaned_junction" | "sdk_stale" | "sdk_not_generated" | "sdk_ungeneratable";
|
|
6
7
|
table?: string;
|
|
7
8
|
column?: string;
|
|
8
9
|
expected?: string;
|
|
@@ -84,6 +85,14 @@ export declare function getExpectedColumnType(prop: Property): string | null;
|
|
|
84
85
|
export declare function loadCollections(collectionsPath: string): Promise<CollectionConfig[]>;
|
|
85
86
|
export declare function checkCollectionsVsSchema(collections: CollectionConfig[], schemaFilePath: string): Promise<DoctorPhase>;
|
|
86
87
|
export declare function checkCollectionsVsSdk(collections: CollectionConfig[], sdkFilePath: string): Promise<DoctorPhase>;
|
|
88
|
+
interface DbColumn {
|
|
89
|
+
table_schema: string;
|
|
90
|
+
table_name: string;
|
|
91
|
+
column_name: string;
|
|
92
|
+
data_type: string;
|
|
93
|
+
is_nullable: string;
|
|
94
|
+
udt_name: string;
|
|
95
|
+
}
|
|
87
96
|
/**
|
|
88
97
|
* Extensions the collections need, that the database does not have installed.
|
|
89
98
|
*
|
|
@@ -115,6 +124,29 @@ export declare function schemaStampIssues(pool: {
|
|
|
115
124
|
rows: T[];
|
|
116
125
|
}>;
|
|
117
126
|
}, collections: CollectionConfig[]): Promise<DoctorIssue[]>;
|
|
127
|
+
/**
|
|
128
|
+
* What to do about a column whose type is not the one the collection plans.
|
|
129
|
+
*
|
|
130
|
+
* Both ways out, because the doctor cannot know which side is right: the
|
|
131
|
+
* property moved, or the database did. Putting the property back always clears
|
|
132
|
+
* the finding; converting the column clears it when every value converts.
|
|
133
|
+
*/
|
|
134
|
+
export declare function typeMismatchFix(schema: string, table: string, column: string, actual: string, planned: PgType | undefined): string;
|
|
135
|
+
/**
|
|
136
|
+
* The table's primary key against the one the collection reads it by.
|
|
137
|
+
*
|
|
138
|
+
* Rebase addresses a row by the key the plan names — the `isId` property, or
|
|
139
|
+
* the implicit `id` — so a table keyed on other columns, or on none, serves
|
|
140
|
+
* reads and writes against a key that does not hold. An error, because that is
|
|
141
|
+
* what it is at runtime.
|
|
142
|
+
*/
|
|
143
|
+
export declare function primaryKeyIssues(tablePlan: TablePlan, dbPk: string[], displayName: string): DoctorIssue[];
|
|
144
|
+
/**
|
|
145
|
+
* A junction's two key columns: present, typed like the keys they point at,
|
|
146
|
+
* and the table keyed on the pair. Order is not compared — boot and `db push`
|
|
147
|
+
* have built the key in both orders, and either one serves the same rows.
|
|
148
|
+
*/
|
|
149
|
+
export declare function junctionKeyIssues(junctionPlan: TablePlan, dbColumns: DbColumn[], dbPk: string[], displayName: string): DoctorIssue[];
|
|
118
150
|
export declare function checkCollectionsVsDatabase(collections: CollectionConfig[], databaseUrl: string): Promise<DoctorPhase>;
|
|
119
151
|
export declare function renderReport(report: DoctorReport): void;
|
|
120
152
|
export declare function runDoctor(options: {
|
|
@@ -123,3 +155,4 @@ export declare function runDoctor(options: {
|
|
|
123
155
|
sdkPath: string;
|
|
124
156
|
databaseUrl?: string;
|
|
125
157
|
}): Promise<DoctorReport>;
|
|
158
|
+
export {};
|
|
@@ -81,4 +81,26 @@ export interface PolicyEnsureResult {
|
|
|
81
81
|
*/
|
|
82
82
|
orphansDropped: number;
|
|
83
83
|
}
|
|
84
|
+
export interface TableLockResult {
|
|
85
|
+
/** Tables RLS is now on for. */
|
|
86
|
+
locked: number;
|
|
87
|
+
/** Tables it could not be switched on for. See {@link PolicyEnsureResult.unsecured}. */
|
|
88
|
+
unsecured: PolicyEnsureResult["unsecured"];
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Switch RLS on for every table the collections declare — each collection's
|
|
92
|
+
* and each junction's — and do nothing else.
|
|
93
|
+
*
|
|
94
|
+
* The first thing `rebase db push` does once Atlas has committed. Atlas cannot
|
|
95
|
+
* carry `ENABLE ROW LEVEL SECURITY` (its free tier neither plans nor reads it),
|
|
96
|
+
* so a table it creates arrives with RLS off — while the user role already
|
|
97
|
+
* holds DML on it through the schema's default privileges. Everything push runs
|
|
98
|
+
* after Atlas can refuse: the vector, search and trigger DDL, the policies
|
|
99
|
+
* themselves. Locking first means none of those failures can leave a table
|
|
100
|
+
* open: RLS with no policy denies, which is a state a failed push may leave.
|
|
101
|
+
*
|
|
102
|
+
* A declared table that is not in the database is skipped — nothing can reach
|
|
103
|
+
* a table that does not exist, and the step that creates it locks it.
|
|
104
|
+
*/
|
|
105
|
+
export declare function lockCollectionTables(client: Queryable, collections: CollectionConfig[]): Promise<TableLockResult>;
|
|
84
106
|
export declare function ensureCollectionPolicies(client: Queryable, collections: CollectionConfig[], log?: (message: string) => void): Promise<PolicyEnsureResult>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createRequire as __createRequire } from "module";
|
|
2
2
|
__createRequire(import.meta.url);
|
|
3
|
-
import { t as main } from "../generate-drizzle-schema-
|
|
3
|
+
import { t as main } from "../generate-drizzle-schema-93M0lUxK.js";
|
|
4
4
|
//#region src/schema/bin/generate-drizzle-schema.ts
|
|
5
5
|
/**
|
|
6
6
|
* The built entry point for `generate-drizzle-schema`.
|
|
@@ -31,7 +31,7 @@ type ResolveCollection = (slug: string) => CollectionConfig | undefined;
|
|
|
31
31
|
*/
|
|
32
32
|
export declare const generatePolicyStatements: (collection: CollectionConfig, rule: SecurityRule, resolveCollection: ResolveCollection) => string[];
|
|
33
33
|
/**
|
|
34
|
-
*
|
|
34
|
+
* `.rebase/sql/schema.sql` — the desired state Atlas diffs the database against.
|
|
35
35
|
*
|
|
36
36
|
* Synchronous. It was `async` with nothing to await, which made every caller
|
|
37
37
|
* (the writer script, the doctor, the live editor, two gates) carry a promise
|
|
@@ -39,10 +39,10 @@ export declare const generatePolicyStatements: (collection: CollectionConfig, ru
|
|
|
39
39
|
* `[object Promise]`.
|
|
40
40
|
*/
|
|
41
41
|
export declare const generatePostgresDdl: (allCollections: CollectionConfig[], options?: DdlRenderOptions) => string;
|
|
42
|
-
/**
|
|
42
|
+
/** `.rebase/sql/policies.sql` — the RLS policies. Atlas has no model for a policy. */
|
|
43
43
|
export declare const generatePostgresPoliciesDdl: (allCollections: CollectionConfig[]) => string;
|
|
44
44
|
/**
|
|
45
|
-
*
|
|
45
|
+
* `.rebase/sql/search.sql` — everything a `search` block needs, as a file Rebase
|
|
46
46
|
* applies itself.
|
|
47
47
|
*
|
|
48
48
|
* Search is one of the parts of the schema Atlas does not own, for two
|
|
@@ -70,7 +70,7 @@ export declare const generatePostgresSearchDdl: (allCollections: CollectionConfi
|
|
|
70
70
|
*/
|
|
71
71
|
export declare const searchExcludePatterns: (allCollections: CollectionConfig[]) => string[];
|
|
72
72
|
/**
|
|
73
|
-
*
|
|
73
|
+
* `.rebase/sql/vector.sql` — the `vector` columns, their ANN indexes and, when a
|
|
74
74
|
* database declared it, the extension.
|
|
75
75
|
*
|
|
76
76
|
* Vector is out of Atlas's hands for a narrower reason than search: not that
|
|
@@ -86,7 +86,7 @@ export declare const generatePostgresVectorDdl: (allCollections: CollectionConfi
|
|
|
86
86
|
/** @see searchExcludePatterns */
|
|
87
87
|
export declare const vectorExcludePatterns: (allCollections: CollectionConfig[]) => string[];
|
|
88
88
|
/**
|
|
89
|
-
*
|
|
89
|
+
* `.rebase/sql/triggers.sql` — the `BEFORE UPDATE` triggers behind
|
|
90
90
|
* `autoValue: "on_update"`, and the one function they share.
|
|
91
91
|
*
|
|
92
92
|
* A trigger is a function plus a binding, so it is carved out of Atlas's view
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createRequire as __createRequire } from "module";
|
|
2
2
|
__createRequire(import.meta.url);
|
|
3
|
-
import { a as generatePostgresVectorDdl, i as generatePostgresTriggersDdl, n as generatePostgresPoliciesDdl, r as generatePostgresSearchDdl, t as generatePostgresDdl } from "../generate-postgres-ddl-logic-
|
|
3
|
+
import { a as generatePostgresVectorDdl, i as generatePostgresTriggersDdl, n as generatePostgresPoliciesDdl, r as generatePostgresSearchDdl, t as generatePostgresDdl } from "../generate-postgres-ddl-logic-BJsLaVNX.js";
|
|
4
4
|
import { n as outError, t as out } from "../cli-output-CNdMql-L.js";
|
|
5
5
|
import { loadCollectionsFromDirectory } from "@rebasepro/server";
|
|
6
6
|
import { declaredDatabaseExtensions } from "@rebasepro/types";
|
|
@@ -72,6 +72,12 @@ export interface SchemaCommitInput {
|
|
|
72
72
|
* a statement that applies and one that is rejected.
|
|
73
73
|
*/
|
|
74
74
|
existing?: ExistingSchema;
|
|
75
|
+
/**
|
|
76
|
+
* Plan a commit of the source alone — "Edit source only". An unapplicable
|
|
77
|
+
* change is not refused: it is committed with no statements, under a
|
|
78
|
+
* message that names what the database keeps.
|
|
79
|
+
*/
|
|
80
|
+
sourceOnly?: boolean;
|
|
75
81
|
}
|
|
76
82
|
export interface SchemaCommit {
|
|
77
83
|
/** Every file the commit writes, source and generated alike. */
|
|
@@ -123,6 +129,12 @@ export declare class SchemaCommitError extends Error {
|
|
|
123
129
|
* where there is no database to describe.
|
|
124
130
|
*/
|
|
125
131
|
export declare function additiveStatements(before: CollectionConfig[], after: CollectionConfig[], existing?: ExistingSchema, options?: EnsureOptions): string[];
|
|
132
|
+
/**
|
|
133
|
+
* The commit of an "Edit source only": what changed in the source, and what
|
|
134
|
+
* the database keeps — `chore(schema): remove sku from products (source only —
|
|
135
|
+
* column products.sku kept)`. The body lists what each change leaves behind.
|
|
136
|
+
*/
|
|
137
|
+
export declare function sourceOnlyCommitMessage(classified: ClassifiedChanges): string;
|
|
126
138
|
/** A commit message that says what changed rather than that something did. */
|
|
127
139
|
export declare function commitMessage(classified: ClassifiedChanges): string;
|
|
128
140
|
/**
|
|
@@ -91,6 +91,24 @@ export interface SchemaMetadata {
|
|
|
91
91
|
*/
|
|
92
92
|
rowCounts: Record<string, number>;
|
|
93
93
|
}
|
|
94
|
+
/**
|
|
95
|
+
* Why a table keyed on several columns is not generated as a collection, or
|
|
96
|
+
* `undefined` when it is.
|
|
97
|
+
*
|
|
98
|
+
* Several `isId` properties are one composite key, and the planner builds that
|
|
99
|
+
* table under the same `PRIMARY KEY (a, b)` — so such a table round-trips when
|
|
100
|
+
* two things hold:
|
|
101
|
+
*
|
|
102
|
+
* - **Every key column can carry `isId`,** which exists on string and number
|
|
103
|
+
* properties only. Read from the column's SQL type, not a data sample: a
|
|
104
|
+
* `line_no` holding only 1s is not a boolean. A key with a column of another
|
|
105
|
+
* type — pagila's `payment` is keyed on a timestamp too — can be marked on
|
|
106
|
+
* some of its columns only, and those would be read as the whole key.
|
|
107
|
+
* - **Nothing points at it.** A foreign key into it, or a junction, is a link
|
|
108
|
+
* into a composite key, which the planner refuses: the relation has one
|
|
109
|
+
* column to point with.
|
|
110
|
+
*/
|
|
111
|
+
export declare function compositeKeySkipReason(meta: TableMeta, allFks: ForeignKeyRow[]): string | undefined;
|
|
94
112
|
export interface TableMeta {
|
|
95
113
|
name: string;
|
|
96
114
|
columns: TableColumn[];
|
|
@@ -232,6 +250,19 @@ export interface GenerationContext {
|
|
|
232
250
|
* from the target project and passes it. See `detectCollectionBuilder`.
|
|
233
251
|
*/
|
|
234
252
|
builder?: CollectionBuilder;
|
|
253
|
+
/**
|
|
254
|
+
* Collects one line per column the planner will not reproduce exactly —
|
|
255
|
+
* what `rebase db push` would do to it, and how to avoid that when there is
|
|
256
|
+
* a way. The CLI prints them; the same lines are written at the top of the
|
|
257
|
+
* generated file.
|
|
258
|
+
*/
|
|
259
|
+
notes?: string[];
|
|
260
|
+
/**
|
|
261
|
+
* Tables this run does not generate a collection for, so nothing may point
|
|
262
|
+
* at them: a relation whose target file does not exist is an import that
|
|
263
|
+
* does not resolve.
|
|
264
|
+
*/
|
|
265
|
+
skippedTables?: ReadonlySet<string>;
|
|
235
266
|
}
|
|
236
267
|
/**
|
|
237
268
|
* Generate the full TypeScript file content for a single collection.
|
|
@@ -71,7 +71,7 @@ export declare const TABLES_QUERY = "\n SELECT c.relname AS table_name,\n
|
|
|
71
71
|
* errors. `character_maximum_length` is the declared `varchar(n)` bound —
|
|
72
72
|
* already enforced by the database, and free to surface as validation.
|
|
73
73
|
*/
|
|
74
|
-
export declare const COLUMNS_QUERY = "\n SELECT\n c.table_name,\n c.column_name,\n c.data_type,\n c.udt_name,\n c.is_nullable,\n c.column_default,\n c.ordinal_position,\n c.is_generated,\n c.is_identity,\n c.identity_generation,\n c.character_maximum_length,\n c.numeric_precision,\n c.numeric_scale,\n (SELECT a.atttypmod FROM pg_attribute a\n JOIN pg_class pc ON a.attrelid = pc.oid\n WHERE pc.relname = c.table_name\n AND a.attname = c.column_name\n AND pc.relnamespace = (SELECT oid FROM pg_namespace WHERE nspname = c.table_schema)) as atttypmod\n FROM information_schema.columns c\n WHERE c.table_schema = $1\n ORDER BY c.table_name, c.ordinal_position\n";
|
|
74
|
+
export declare const COLUMNS_QUERY = "\n SELECT\n c.table_name,\n c.column_name,\n c.data_type,\n c.udt_name,\n c.is_nullable,\n c.column_default,\n c.ordinal_position,\n c.is_generated,\n c.generation_expression,\n c.is_identity,\n c.identity_generation,\n c.character_maximum_length,\n c.numeric_precision,\n c.numeric_scale,\n (SELECT a.atttypmod FROM pg_attribute a\n JOIN pg_class pc ON a.attrelid = pc.oid\n WHERE pc.relname = c.table_name\n AND a.attname = c.column_name\n AND pc.relnamespace = (SELECT oid FROM pg_namespace WHERE nspname = c.table_schema)) as atttypmod\n FROM information_schema.columns c\n WHERE c.table_schema = $1\n ORDER BY c.table_name, c.ordinal_position\n";
|
|
75
75
|
export declare const ENUMS_QUERY = "\n SELECT t.typname AS enum_name,\n e.enumlabel AS enum_value,\n e.enumsortorder AS sort_order\n FROM pg_type t\n JOIN pg_enum e ON t.oid = e.enumtypid\n JOIN pg_namespace n ON t.typnamespace = n.oid\n WHERE n.nspname = $1\n ORDER BY t.typname, e.enumsortorder\n";
|
|
76
76
|
/**
|
|
77
77
|
* Primary key columns, in key order.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { TableColumn } from "./introspect-db-logic.js";
|
|
2
|
+
/** What introspection makes of a table's search columns. */
|
|
3
|
+
export interface ReconstructedSearch {
|
|
4
|
+
/** The generated columns that belong to the search block — never emitted as properties. */
|
|
5
|
+
columns: Set<string>;
|
|
6
|
+
/** The `search: { … }` source, when the stamp confirmed it. */
|
|
7
|
+
block?: string;
|
|
8
|
+
note?: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* The search block a table's stamped generated columns were built from, or a
|
|
12
|
+
* note saying why it could not be read back.
|
|
13
|
+
*/
|
|
14
|
+
export declare function reconstructSearchBlock(input: {
|
|
15
|
+
schema: string;
|
|
16
|
+
table: string;
|
|
17
|
+
columns: TableColumn[];
|
|
18
|
+
/** column → `COMMENT ON COLUMN`. */
|
|
19
|
+
comments: Map<string, string>;
|
|
20
|
+
/** column → the property key it is generated under. */
|
|
21
|
+
keyByColumn: Map<string, string>;
|
|
22
|
+
}): ReconstructedSearch;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The property keys a column needs for the planner to build that same column.
|
|
3
|
+
*
|
|
4
|
+
* Introspection writes collections, and `rebase db push` plans them back into
|
|
5
|
+
* DDL. The two used to read a column differently: introspection wrote
|
|
6
|
+
* `type: "number"` for an `integer`, and the planner reads an unqualified
|
|
7
|
+
* number as `NUMERIC`; `validation.max: 40` for a `varchar(40)`, and the
|
|
8
|
+
* planner reads an unqualified string as `TEXT`; a `time` as a plain `date`,
|
|
9
|
+
* which the planner makes a `timestamptz` — a change Postgres refuses to cast.
|
|
10
|
+
* So adopting a database — introspect, then push, the documented path — planned
|
|
11
|
+
* a type change on nearly every column, and some it could not even dry-run.
|
|
12
|
+
*
|
|
13
|
+
* Each function here answers one question about one column: what to write so
|
|
14
|
+
* that `planSchema` produces exactly what the catalogue holds. Where no
|
|
15
|
+
* property can say it, the answer is a note naming the column and what a push
|
|
16
|
+
* would do to it, so the reader decides before anything runs.
|
|
17
|
+
*
|
|
18
|
+
* Pure: catalogue rows in, keys and notes out.
|
|
19
|
+
*/
|
|
20
|
+
import type { ForeignKeyRow, TableColumn } from "./introspect-db-logic.js";
|
|
21
|
+
/** Keys to write on a property, as `key: value` source fragments, plus what could not be said. */
|
|
22
|
+
export interface ColumnStorage {
|
|
23
|
+
/** e.g. `columnType: "varchar"`, `precision: 10`. */
|
|
24
|
+
keys: string[];
|
|
25
|
+
/** Why the planner will not reproduce this column exactly, when it will not. */
|
|
26
|
+
note?: string;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* The name Postgres gives a `SERIAL` column's sequence — `ChooseRelationName`
|
|
30
|
+
* with the `seq` label: `<table>_<column>_seq`, and when that is over 63 bytes
|
|
31
|
+
* the longer of the two names is shortened, one character at a time, until it
|
|
32
|
+
* fits.
|
|
33
|
+
*/
|
|
34
|
+
export declare function serialSequenceName(table: string, column: string): string;
|
|
35
|
+
/**
|
|
36
|
+
* The `isId` (and `columnType`) a single-column primary key needs.
|
|
37
|
+
*
|
|
38
|
+
* `isId: "increment"` is an identity column, and only an INTEGER one. A serial
|
|
39
|
+
* key — an integer with a `nextval` default — is `SERIAL`/`BIGSERIAL`, declared
|
|
40
|
+
* through `columnType` beside `isId: "manual"`. A uuid key is `"uuid"` only when
|
|
41
|
+
* the database generates it; a key with no default is `"manual"`, which keeps
|
|
42
|
+
* the planner from inventing one.
|
|
43
|
+
*/
|
|
44
|
+
export declare function primaryKeyStorage(col: TableColumn, propType: string): ColumnStorage;
|
|
45
|
+
/**
|
|
46
|
+
* The keys a non-key column needs, for the property type introspection chose.
|
|
47
|
+
*
|
|
48
|
+
* `enumTypeName` is the type the planner would name for this column
|
|
49
|
+
* (`<table>_<column>`, cut to 63 bytes); an enum column whose type is called
|
|
50
|
+
* anything else cannot be declared, and the note says how to rename it.
|
|
51
|
+
*/
|
|
52
|
+
export declare function columnStorage(col: TableColumn, propType: string, context: {
|
|
53
|
+
isEnumColumn: boolean;
|
|
54
|
+
enumTypeName: string;
|
|
55
|
+
enumTypeShared: boolean;
|
|
56
|
+
}): ColumnStorage;
|
|
57
|
+
/**
|
|
58
|
+
* The `columnType` an array column needs, or a note when its element type is
|
|
59
|
+
* not one the planner stores natively.
|
|
60
|
+
*
|
|
61
|
+
* Only `text[]`, `integer[]`, `boolean[]` and `numeric[]` are. Reading
|
|
62
|
+
* `bigint[]` as `integer[]` — what this used to do — planned a narrowing.
|
|
63
|
+
*/
|
|
64
|
+
export declare function arrayStorage(col: TableColumn): {
|
|
65
|
+
columnType?: string;
|
|
66
|
+
innerType: string;
|
|
67
|
+
note?: string;
|
|
68
|
+
};
|
|
69
|
+
/**
|
|
70
|
+
* A column default as a `defaultValue`, when it is a literal a property can carry.
|
|
71
|
+
*
|
|
72
|
+
* `undefined` when there is no default to carry, or when the default is one the
|
|
73
|
+
* generator expresses another way (`now()` is `autoValue`, a key's default is
|
|
74
|
+
* its `isId`). `{ note }` when there is a default and no property can say it —
|
|
75
|
+
* a push would plan dropping it.
|
|
76
|
+
*/
|
|
77
|
+
export declare function literalDefaultOf(col: TableColumn, propType: string): {
|
|
78
|
+
source: string;
|
|
79
|
+
} | {
|
|
80
|
+
note: string;
|
|
81
|
+
} | undefined;
|
|
82
|
+
/** `ON DELETE` as the relation's `onDelete`, when it is not the default the planner would choose. */
|
|
83
|
+
export declare function onDeleteOf(fk: ForeignKeyRow, required: boolean): string | undefined;
|