@rebasepro/server-postgres 0.19.1 → 0.19.2-canary.g09316f6
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-ByLfM_Tt.js → BranchService-W3DMfcZZ.js} +2 -2
- package/dist/{BranchService-ByLfM_Tt.js.map → BranchService-W3DMfcZZ.js.map} +1 -1
- package/dist/PostgresBackendDriver.d.ts +81 -7
- package/dist/PostgresBootstrapper.d.ts +10 -0
- package/dist/{backup-cli-oM9WQVlV.js → backup-cli-DSpQyqcG.js} +2 -2
- package/dist/{backup-cli-oM9WQVlV.js.map → backup-cli-DSpQyqcG.js.map} +1 -1
- package/dist/{backup-service-Br3tqwsy.js → backup-service-DA7a6SUV.js} +2 -2
- package/dist/{backup-service-Br3tqwsy.js.map → backup-service-DA7a6SUV.js.map} +1 -1
- package/dist/{cli-errors-DxN4yzdH.js → cli-errors-C3g_kHBw.js} +137 -18
- package/dist/cli-errors-C3g_kHBw.js.map +1 -0
- package/dist/cli-errors.d.ts +19 -0
- package/dist/cli-helpers.d.ts +47 -0
- package/dist/cli.js +233 -19
- package/dist/cli.js.map +1 -1
- package/dist/{collection-index-BHgT_TKd.js → collection-index-DdnsxiJ_.js} +14 -4
- package/dist/{collection-index-BHgT_TKd.js.map → collection-index-DdnsxiJ_.js.map} +1 -1
- package/dist/collections/validate-relations.d.ts +7 -0
- package/dist/column-plan-helpers-CpILzHJS.js +145 -0
- package/dist/column-plan-helpers-CpILzHJS.js.map +1 -0
- package/dist/{doctor-D7HWmGzs.js → doctor-D5SrGJ5P.js} +175 -61
- package/dist/doctor-D5SrGJ5P.js.map +1 -0
- package/dist/{ensure-collection-policies-2c2NV8zX.js → ensure-collection-policies-CHO0moXQ.js} +5 -5
- package/dist/{ensure-collection-policies-2c2NV8zX.js.map → ensure-collection-policies-CHO0moXQ.js.map} +1 -1
- package/dist/{ensure-collection-tables-D4wJzM4y.js → ensure-collection-tables-Bkvehxdm.js} +318 -312
- package/dist/ensure-collection-tables-Bkvehxdm.js.map +1 -0
- package/dist/{ensure-tables-CIojK-Rx.js → ensure-tables-CYMtuuOd.js} +2 -2
- package/dist/{ensure-tables-CIojK-Rx.js.map → ensure-tables-CYMtuuOd.js.map} +1 -1
- package/dist/generate-drizzle-schema-logic-Dfyf_MRu.js +228 -0
- package/dist/generate-drizzle-schema-logic-Dfyf_MRu.js.map +1 -0
- package/dist/{generate-drizzle-schema-CwEgVyjO.js → generate-drizzle-schema-vSK-VdYT.js} +3 -3
- package/dist/generate-drizzle-schema-vSK-VdYT.js.map +1 -0
- package/dist/generate-postgres-ddl-logic-CR2xcS7e.js +475 -0
- package/dist/generate-postgres-ddl-logic-CR2xcS7e.js.map +1 -0
- package/dist/{generated-schema-staleness-DQdfJl2A.js → generated-schema-staleness-DRQe2BpC.js} +81 -3
- package/dist/{generated-schema-staleness-DQdfJl2A.js.map → generated-schema-staleness-DRQe2BpC.js.map} +1 -1
- package/dist/history/HistoryService.d.ts +23 -4
- package/dist/index.es.js +1991 -580
- package/dist/index.es.js.map +1 -1
- package/dist/introspect-db-logic-C6LQdTxj.js.map +1 -1
- package/dist/plan-schema-Hgl62S-w.js +1531 -0
- package/dist/plan-schema-Hgl62S-w.js.map +1 -0
- package/dist/{policy-drift-kNJ6X2Uj.js → policy-drift-B0GDRh7_.js} +2 -2
- package/dist/{policy-drift-kNJ6X2Uj.js.map → policy-drift-B0GDRh7_.js.map} +1 -1
- package/dist/{rls-bootstrap-sql-DLDnUjtx.js → rls-bootstrap-sql-BlzsOUtz.js} +111 -8
- package/dist/{rls-bootstrap-sql-DLDnUjtx.js.map → rls-bootstrap-sql-BlzsOUtz.js.map} +1 -1
- package/dist/{rls-enforcement-DeYEjYLt.js → rls-enforcement-BV12vBwQ.js} +2 -1
- package/dist/rls-enforcement-BV12vBwQ.js.map +1 -0
- package/dist/schema/catalogue-schema.d.ts +97 -0
- package/dist/schema/collection-index.d.ts +9 -0
- package/dist/schema/column-plan-helpers.d.ts +125 -0
- package/dist/schema/config-relations.d.ts +32 -0
- package/dist/schema/doctor-cli.js +4 -4
- package/dist/schema/doctor.d.ts +9 -0
- package/dist/schema/dynamic-tables.d.ts +27 -6
- package/dist/schema/ensure-collection-tables.d.ts +31 -268
- package/dist/schema/generate-drizzle-schema-logic.d.ts +26 -8
- package/dist/schema/generate-drizzle-schema.js +1 -1
- package/dist/schema/generate-postgres-ddl-logic.d.ts +84 -168
- package/dist/schema/generate-postgres-ddl.js +8 -2
- package/dist/schema/generate-postgres-ddl.js.map +1 -1
- package/dist/schema/generated-column-conflicts.d.ts +84 -0
- package/dist/schema/generated-schema-diff.d.ts +56 -0
- package/dist/schema/generated-schema-staleness.d.ts +33 -0
- package/dist/schema/introspect-db-logic.d.ts +2 -0
- package/dist/schema/plan/diff-plan.d.ts +220 -0
- package/dist/schema/plan/plan-schema.d.ts +84 -0
- package/dist/schema/plan/render-ddl.d.ts +62 -0
- package/dist/schema/plan/render-drizzle.d.ts +31 -0
- package/dist/schema/plan/types.d.ts +410 -0
- package/dist/schema/plan/updated-at-trigger.d.ts +22 -0
- package/dist/schema/relation-names.d.ts +28 -0
- package/dist/schema/search-column.d.ts +9 -0
- package/dist/security/rls-enforcement.d.ts +17 -0
- package/dist/services/FetchService.d.ts +176 -36
- package/dist/services/PersistService.d.ts +17 -4
- package/dist/services/RelationService.d.ts +11 -3
- package/dist/services/collection-helpers.d.ts +16 -2
- package/dist/services/dataService.d.ts +29 -2
- package/dist/services/field-op-sql.d.ts +16 -0
- package/dist/services/field-viewer.d.ts +19 -0
- package/dist/services/realtimeService.d.ts +35 -1
- package/dist/services/row-pipeline.d.ts +29 -5
- package/dist/services/soft-delete.d.ts +73 -0
- package/dist/utils/pg-error-utils.d.ts +41 -1
- package/dist/{vector-index-DkWxm2de.js → vector-index-CMJKb3C9.js} +3 -14
- package/dist/{vector-index-DkWxm2de.js.map → vector-index-CMJKb3C9.js.map} +1 -1
- package/package.json +18 -10
- package/dist/cli-errors-DxN4yzdH.js.map +0 -1
- package/dist/doctor-D7HWmGzs.js.map +0 -1
- package/dist/ensure-collection-tables-D4wJzM4y.js.map +0 -1
- package/dist/generate-drizzle-schema-CwEgVyjO.js.map +0 -1
- package/dist/generate-drizzle-schema-logic-so2Z_lyC.js +0 -528
- package/dist/generate-drizzle-schema-logic-so2Z_lyC.js.map +0 -1
- package/dist/generate-postgres-ddl-logic-CtnpIBVv.js +0 -1312
- package/dist/generate-postgres-ddl-logic-CtnpIBVv.js.map +0 -1
- package/dist/rls-enforcement-DeYEjYLt.js.map +0 -1
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The additive statements that bring a database up to a {@link SchemaPlan}.
|
|
3
|
+
*
|
|
4
|
+
* ## Why additive-only, forever
|
|
5
|
+
*
|
|
6
|
+
* This runs unattended, at boot, against a database with customers' data in it,
|
|
7
|
+
* with no human reading a diff. So it may only ever do things that cannot lose
|
|
8
|
+
* data: create a missing table, add a missing column, create a missing enum
|
|
9
|
+
* type, add an enum value, create an index.
|
|
10
|
+
*
|
|
11
|
+
* It will **never** drop a table or a column, narrow a type, or alter a
|
|
12
|
+
* constraint at boot. A removed field leaves its column behind; a renamed field
|
|
13
|
+
* looks like an addition and the old column stays. That is the correct trade
|
|
14
|
+
* for an automated path — the alternative is an unattended process that can
|
|
15
|
+
* silently destroy a column. Destructive changes stay a deliberate,
|
|
16
|
+
* human-reviewed migration. Because of that, this is safe to run on every boot,
|
|
17
|
+
* and re-running it is a no-op.
|
|
18
|
+
*
|
|
19
|
+
* ## What changed when the planner arrived
|
|
20
|
+
*
|
|
21
|
+
* This used to read `Property` itself — its own reading of the type, of
|
|
22
|
+
* `validation`, of relations, of enums — and disagreed with `db push` about all
|
|
23
|
+
* of them. The audit found a required `author_id` that was NOT NULL after a
|
|
24
|
+
* push and nullable after a boot, on the one path with no developer in the
|
|
25
|
+
* loop. Now it reads the same {@link ColumnPlan} the DDL renderer does, so a
|
|
26
|
+
* column's type, default, uniqueness and foreign key are decided once. What is
|
|
27
|
+
* left here is the half that is genuinely this path's own: *what the database
|
|
28
|
+
* already has*, and which of the planned constraints are safe to apply to it.
|
|
29
|
+
*/
|
|
30
|
+
import type { SchemaPlan } from "./types.js";
|
|
31
|
+
import { type SkippedVectorIndex } from "../vector-index.js";
|
|
32
|
+
import { type ColumnTypeDrift } from "../column-type-drift.js";
|
|
33
|
+
/**
|
|
34
|
+
* Validation used to run only on the names read back OUT of the catalogue,
|
|
35
|
+
* which is the direction that cannot hurt anyone: those came from Postgres. The
|
|
36
|
+
* names going IN — the schema and table a collection declares — were quoted and
|
|
37
|
+
* concatenated on trust, and quoting is not escaping. A table named
|
|
38
|
+
* `x" (id int); DROP TABLE users; --` closes the quote and the statement, and
|
|
39
|
+
* the whole thing runs on the owner connection, which is the one connection in
|
|
40
|
+
* the system that is exempt from every RLS policy.
|
|
41
|
+
*
|
|
42
|
+
* That is only a config file on a self-hosted project, where the person writing
|
|
43
|
+
* it could run the SQL directly anyway. It is not only a config file where a
|
|
44
|
+
* collection can be defined over the wire — the live-schema and source editors
|
|
45
|
+
* both do that — and there the caller is an admin on the app, not an operator
|
|
46
|
+
* of the database.
|
|
47
|
+
*/
|
|
48
|
+
export declare function assertSafeIdentifier(value: string, what: string): string;
|
|
49
|
+
/** What the database currently has, as the planner needs it. */
|
|
50
|
+
export interface ExistingSchema {
|
|
51
|
+
/** `schema.table` → set of column names. */
|
|
52
|
+
tables: Map<string, Set<string>>;
|
|
53
|
+
/** `schema.typename` of every enum type that already exists. */
|
|
54
|
+
enums: Set<string>;
|
|
55
|
+
/**
|
|
56
|
+
* `schema.table.constraint` of every constraint that already exists.
|
|
57
|
+
*
|
|
58
|
+
* Optional so a caller that only cares about tables can still build one by
|
|
59
|
+
* hand; absent is read as "none known", which at worst re-attempts a
|
|
60
|
+
* constraint that then fails harmlessly as a duplicate.
|
|
61
|
+
*/
|
|
62
|
+
constraints?: Set<string>;
|
|
63
|
+
/**
|
|
64
|
+
* `schema.table.column` → that column's comment, for the columns that have
|
|
65
|
+
* one. This is where a generated search column's fingerprint lives.
|
|
66
|
+
*/
|
|
67
|
+
columnComments?: Map<string, string>;
|
|
68
|
+
/** `schema.typename` → its labels, in `enumsortorder`. */
|
|
69
|
+
enumValues?: Map<string, string[]>;
|
|
70
|
+
/** `schema.table.column` of every NOT NULL column. */
|
|
71
|
+
notNullColumns?: Set<string>;
|
|
72
|
+
/** `schema.table.column` of every column that has a DEFAULT. */
|
|
73
|
+
columnDefaults?: Set<string>;
|
|
74
|
+
/** `schema.table` of every table that holds at least one row. */
|
|
75
|
+
populatedTables?: Set<string>;
|
|
76
|
+
/**
|
|
77
|
+
* `schema.table.column` → the type Postgres reports, as `udt_name` (plus a
|
|
78
|
+
* modifier where one distinguishes two columns of the same family, e.g.
|
|
79
|
+
* `numeric(10,2)`).
|
|
80
|
+
*/
|
|
81
|
+
columnTypes?: Map<string, string>;
|
|
82
|
+
/** `schema.table.trigger` of every trigger that already exists. */
|
|
83
|
+
triggers?: Set<string>;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* How far the planner may go in making the database's constraints match the
|
|
87
|
+
* configuration.
|
|
88
|
+
*
|
|
89
|
+
* - `additive` — the boot default. Columns, tables, indexes and enum values are
|
|
90
|
+
* created; no existing column's constraints are touched. Unattended boots run
|
|
91
|
+
* against customer data with nobody reading a diff, and a database adopted by
|
|
92
|
+
* introspection legitimately carries NOT NULL on columns the generated
|
|
93
|
+
* collection leaves optional (`introspect-db-logic` withholds `required` from
|
|
94
|
+
* a column with a default or a trigger behind it). Converging there would
|
|
95
|
+
* strip real constraints on first boot.
|
|
96
|
+
* - `converge` — the live schema editor. Every statement is planned, shown to
|
|
97
|
+
* the person making the change, and applied only once they confirm it.
|
|
98
|
+
*/
|
|
99
|
+
export type ConstraintPolicy = "additive" | "converge";
|
|
100
|
+
export interface DiffOptions {
|
|
101
|
+
/** Defaults to `additive`. See {@link ConstraintPolicy}. */
|
|
102
|
+
constraints?: ConstraintPolicy;
|
|
103
|
+
}
|
|
104
|
+
export interface EnsureAction {
|
|
105
|
+
kind: "create-enum" | "create-table" | "add-column" | "add-constraint" | "rename-column" | "create-extension" | "create-function" | "create-index" | "comment-column" | "add-enum-value" | "set-not-null" | "drop-not-null" | "set-default" | "create-trigger";
|
|
106
|
+
/** Qualified target, for logging: `public.posts` or `public.posts.title`. */
|
|
107
|
+
target: string;
|
|
108
|
+
sql: string;
|
|
109
|
+
}
|
|
110
|
+
/** A NOT NULL column with no default that no property declares. */
|
|
111
|
+
export interface OrphanedRequiredColumn {
|
|
112
|
+
/** `schema.table`. */
|
|
113
|
+
table: string;
|
|
114
|
+
/** The column left behind. */
|
|
115
|
+
column: string;
|
|
116
|
+
/** The collection that no longer declares it. */
|
|
117
|
+
slug: string;
|
|
118
|
+
}
|
|
119
|
+
/** A constraint the configuration asks for that the planner is not applying. */
|
|
120
|
+
export interface WithheldConstraint {
|
|
121
|
+
/** `schema.table.column`. */
|
|
122
|
+
target: string;
|
|
123
|
+
kind: "not-null";
|
|
124
|
+
/**
|
|
125
|
+
* Why, in a sentence that names the obstacle rather than the rule. The
|
|
126
|
+
* reader is looking at a column that is nullable when they asked for
|
|
127
|
+
* required, and needs to know what to do about it.
|
|
128
|
+
*/
|
|
129
|
+
reason: string;
|
|
130
|
+
/** What would make it applicable. */
|
|
131
|
+
remedy: string;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* A generated search column built from a `search` block that has since changed.
|
|
135
|
+
*
|
|
136
|
+
* Reported instead of applied because the two ways to apply it are both worse
|
|
137
|
+
* than stopping. `ALTER COLUMN … SET EXPRESSION` exists only on PG17+ and
|
|
138
|
+
* rewrites the table either way; `DROP COLUMN` + `ADD COLUMN` rewrites it under
|
|
139
|
+
* an ACCESS EXCLUSIVE lock and rebuilds the GIN index. This module runs
|
|
140
|
+
* unattended against live customer data with nobody reading a diff, so a
|
|
141
|
+
* multi-minute outage is not a decision it may take on its own.
|
|
142
|
+
*
|
|
143
|
+
* Not applying it silently is not an option either: a collection that added a
|
|
144
|
+
* field, flipped `unaccent` or raised a weight kept indexing the *old* set
|
|
145
|
+
* forever, and the only symptom was searches returning nothing for content
|
|
146
|
+
* plainly in the row.
|
|
147
|
+
*/
|
|
148
|
+
export interface SearchColumnDrift {
|
|
149
|
+
/** `schema.table`. */
|
|
150
|
+
table: string;
|
|
151
|
+
column: string;
|
|
152
|
+
/** The fingerprint recorded on the column. */
|
|
153
|
+
found: string;
|
|
154
|
+
/** The fingerprint the current `search` block computes. */
|
|
155
|
+
expected: string;
|
|
156
|
+
/** The statements that would rebuild the column, for the operator to run. */
|
|
157
|
+
rebuild: string[];
|
|
158
|
+
}
|
|
159
|
+
/** A relation column whose old and new spellings both plausibly apply. */
|
|
160
|
+
export interface LegacyForeignKey {
|
|
161
|
+
/** `schema.table`. */
|
|
162
|
+
table: string;
|
|
163
|
+
/** The name the current rule derives, and what this plan would create. */
|
|
164
|
+
expected: string;
|
|
165
|
+
/** The name the old rule derived, which the table already has. */
|
|
166
|
+
legacy: string;
|
|
167
|
+
}
|
|
168
|
+
export interface EnsurePlan {
|
|
169
|
+
actions: EnsureAction[];
|
|
170
|
+
/** Every statement, in dependency order. Empty when the schema is current. */
|
|
171
|
+
statements: string[];
|
|
172
|
+
/**
|
|
173
|
+
* Relation columns this plan is about to create where the table already
|
|
174
|
+
* carries the same column under its pre-singularization name.
|
|
175
|
+
*
|
|
176
|
+
* Reported rather than silently handled: the ensure is additive, so it
|
|
177
|
+
* would add `category_id` beside a populated `categorie_id` and the
|
|
178
|
+
* relation would then read the new, empty one. No statement fails, no table
|
|
179
|
+
* is missing, and the only symptom is relations resolving to nothing.
|
|
180
|
+
*/
|
|
181
|
+
legacyForeignKeys: LegacyForeignKey[];
|
|
182
|
+
/** @see SearchColumnDrift */
|
|
183
|
+
searchDrift: SearchColumnDrift[];
|
|
184
|
+
/**
|
|
185
|
+
* Generated search columns that exist but carry no fingerprint — created
|
|
186
|
+
* before this check existed, or by `search.sql` on an older CLI. The plan
|
|
187
|
+
* stamps them so the *next* change is detectable.
|
|
188
|
+
*/
|
|
189
|
+
searchAdopted: {
|
|
190
|
+
table: string;
|
|
191
|
+
column: string;
|
|
192
|
+
}[];
|
|
193
|
+
/**
|
|
194
|
+
* Vector columns this plan is deliberately leaving unindexed, because
|
|
195
|
+
* pgvector cannot build an ANN index that wide. Reported rather than
|
|
196
|
+
* thrown: the column is valid, storable and searchable.
|
|
197
|
+
*/
|
|
198
|
+
vectorIndexSkipped: SkippedVectorIndex[];
|
|
199
|
+
/**
|
|
200
|
+
* Constraints the configuration asks for that this plan is not applying,
|
|
201
|
+
* and why. Every one of these was previously withheld in silence.
|
|
202
|
+
*/
|
|
203
|
+
withheldConstraints: WithheldConstraint[];
|
|
204
|
+
/**
|
|
205
|
+
* Columns whose type in the database is in a different family from the one
|
|
206
|
+
* the collection declares. Reported and never acted on — this is the one
|
|
207
|
+
* divergence that presents as a *working* deploy.
|
|
208
|
+
*/
|
|
209
|
+
columnTypeDrift: ColumnTypeDrift[];
|
|
210
|
+
/**
|
|
211
|
+
* Columns that are NOT NULL, have no default, and that no property declares
|
|
212
|
+
* any more — so every insert through the API is rejected for a field the
|
|
213
|
+
* author cannot name, because they already deleted it. This is what a
|
|
214
|
+
* **rename** looks like to an additive provisioner. Reported, never acted
|
|
215
|
+
* on: dropping the column is the right fix roughly always and destructive
|
|
216
|
+
* exactly once, which is not a decision to take unattended.
|
|
217
|
+
*/
|
|
218
|
+
orphanedRequiredColumns: OrphanedRequiredColumn[];
|
|
219
|
+
}
|
|
220
|
+
export declare function diffPlanAgainstCatalogue(plan: SchemaPlan, existing: ExistingSchema, options?: DiffOptions): EnsurePlan;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The only place a `Property` is read for schema purposes.
|
|
3
|
+
*
|
|
4
|
+
* Everything that used to `switch (prop.type)` — the Drizzle generator, the DDL
|
|
5
|
+
* generator, the boot-time ensure — now renders the {@link SchemaPlan} this
|
|
6
|
+
* produces. See `./types.ts` for why.
|
|
7
|
+
*
|
|
8
|
+
* Pure and synchronous. It reads collections and nothing else: no database, no
|
|
9
|
+
* filesystem, no process-wide registry. The one fact about the world it needs
|
|
10
|
+
* (which extensions a project's databases gave Rebase leave to install) is
|
|
11
|
+
* passed in, because a plan that depended on whatever module happened to be
|
|
12
|
+
* imported would not be comparable with itself.
|
|
13
|
+
*
|
|
14
|
+
* It **throws** rather than guessing. A configuration no renderer can honour —
|
|
15
|
+
* an empty enum, two `isId` properties, `isId: "cuid"`, an unknown
|
|
16
|
+
* `columnType`, a relation to a collection that is not in the bundle, a
|
|
17
|
+
* `search` block on a collection Postgres does not store — used to fail
|
|
18
|
+
* differently in each of the three emitters, or not at all, and the failure
|
|
19
|
+
* landed at `CREATE TABLE` time on a managed tenant with nobody in the loop.
|
|
20
|
+
* Here it lands once, with the collection and the property named.
|
|
21
|
+
*/
|
|
22
|
+
import { type CollectionConfig, type Property, type SecurityRule } from "@rebasepro/types";
|
|
23
|
+
import { SET_UPDATED_AT_FN } from "./updated-at-trigger.js";
|
|
24
|
+
import type { PgType, PlanOptions, PolicyPlan, SchemaPlan } from "./types.js";
|
|
25
|
+
type ResolveCollection = (slug: string) => CollectionConfig | undefined;
|
|
26
|
+
/**
|
|
27
|
+
* Single-quote escaping for a SQL string literal (PostgreSQL doubles the
|
|
28
|
+
* quote). Enum labels and `defaultValue`s come straight from user-authored
|
|
29
|
+
* collection config, so a value like `it's` closes the literal early and the
|
|
30
|
+
* whole generated file stops parsing at that statement.
|
|
31
|
+
*/
|
|
32
|
+
export declare const quoteSqlLiteral: (value: string) => string;
|
|
33
|
+
/**
|
|
34
|
+
* The `ON DELETE` a foreign key gets when the author did not say.
|
|
35
|
+
*
|
|
36
|
+
* One rule for every property that emits one — `belongsTo` relations and
|
|
37
|
+
* `reference` properties alike. `reference` kept its own `CASCADE` default for
|
|
38
|
+
* a release after this rule was written, which is exactly the split this
|
|
39
|
+
* function exists to prevent: two spellings of the same link, two
|
|
40
|
+
* data-retention behaviours, and only one of them documented.
|
|
41
|
+
*
|
|
42
|
+
* An optional link is `SET NULL`: the column can hold NULL, so dropping the
|
|
43
|
+
* parent leaves the child row with an empty pointer, which is what "optional"
|
|
44
|
+
* already means.
|
|
45
|
+
*
|
|
46
|
+
* A required link is **`RESTRICT`**, not `CASCADE`. `NOT NULL` says the child
|
|
47
|
+
* cannot exist without a parent; it does not say deleting the parent should
|
|
48
|
+
* take the child with it. That second claim is a data-retention decision, and
|
|
49
|
+
* defaulting to it meant `onDelete` — a field nobody has to write — silently
|
|
50
|
+
* turned every `DELETE FROM authors` into a cascade through posts, comments and
|
|
51
|
+
* anything else that hung off them.
|
|
52
|
+
*/
|
|
53
|
+
export declare const defaultBelongsToOnDelete: (required: boolean | undefined) => "RESTRICT" | "SET NULL";
|
|
54
|
+
/**
|
|
55
|
+
* The type a column pointing at this collection's primary key must have — a
|
|
56
|
+
* junction endpoint, a `belongsTo` foreign key, a `reference`.
|
|
57
|
+
*
|
|
58
|
+
* One function because it was three: the ladder was spelled inline in
|
|
59
|
+
* `generatePostgresDdl`, again in `planJunctionTables` and a third time in the
|
|
60
|
+
* Drizzle generator.
|
|
61
|
+
*/
|
|
62
|
+
export declare const primaryKeyPgType: (collection: CollectionConfig) => PgType;
|
|
63
|
+
/**
|
|
64
|
+
* The Postgres type a property's column has.
|
|
65
|
+
*
|
|
66
|
+
* Every member of `DataType` has an arm. A type this does not know is a
|
|
67
|
+
* generator that has not been taught it yet, and it says so — a silent `TEXT`
|
|
68
|
+
* here is how `geopoint` ended up with a database column, no Drizzle key, and
|
|
69
|
+
* every write to it discarded with a 201.
|
|
70
|
+
*/
|
|
71
|
+
export declare const columnPgType: (propName: string, prop: Property, collection: CollectionConfig, resolveCollection: ResolveCollection) => PgType;
|
|
72
|
+
/**
|
|
73
|
+
* One security rule, compiled to the clauses a policy is made of.
|
|
74
|
+
*
|
|
75
|
+
* The desugaring (`access` / `ownerField` / `roles` / structured condition /
|
|
76
|
+
* raw SQL → `PolicyExpression`) and the SQL compilation are `@rebasepro/common`'s,
|
|
77
|
+
* which is what the client-side evaluator uses too — so the UI, the DDL and the
|
|
78
|
+
* database agree about who can read a row. What lives here is only the shape:
|
|
79
|
+
* which operations a rule expands to, which clauses each operation takes, and
|
|
80
|
+
* the deny-all fallback for a clause that compiled to nothing.
|
|
81
|
+
*/
|
|
82
|
+
export declare const compileSecurityRule: (collection: CollectionConfig, rule: SecurityRule, resolveCollection: ResolveCollection, injected: boolean, ruleKey?: string) => PolicyPlan[];
|
|
83
|
+
export declare function planSchema(allCollections: CollectionConfig[], options?: PlanOptions): SchemaPlan;
|
|
84
|
+
export { SET_UPDATED_AT_FN };
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { ColumnPlan, PgType, PolicyPlan, SchemaPlan, TablePlan } from "./types.js";
|
|
2
|
+
/** What `schema.sql` may leave out, because another file owns it. */
|
|
3
|
+
export interface DdlRenderOptions {
|
|
4
|
+
/** RLS policies. `false` puts them in `policies.sql` alone. */
|
|
5
|
+
includePolicies?: boolean;
|
|
6
|
+
/** The search column, its helpers and its index. See `search.sql`. */
|
|
7
|
+
includeSearch?: boolean;
|
|
8
|
+
/** The vector columns and their ANN indexes. See `vector.sql`. */
|
|
9
|
+
includeVector?: boolean;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* A {@link PgType} as Postgres spells it.
|
|
13
|
+
*
|
|
14
|
+
* The one place. `getSqlColumnType` and `getDrizzleColumn` each carried their
|
|
15
|
+
* own ladder and disagreed about `VARCHAR` widths, about `geopoint`, and about
|
|
16
|
+
* whether an `increment` id honours `columnType`.
|
|
17
|
+
*/
|
|
18
|
+
export declare const renderPgType: (type: PgType) => string;
|
|
19
|
+
/**
|
|
20
|
+
* Everything after the column name, in one order for every SQL emitter.
|
|
21
|
+
*
|
|
22
|
+
* `CREATE TABLE` and `ADD COLUMN` used to assemble this separately, which is
|
|
23
|
+
* how a required relation column came out `NOT NULL` after `db push` and
|
|
24
|
+
* nullable after a boot-ensure. `identity` is part of the type rather than a
|
|
25
|
+
* DEFAULT, which is why it is rendered here and not in the DEFAULT slot.
|
|
26
|
+
*/
|
|
27
|
+
export declare const renderColumnDefinition: (column: ColumnPlan) => string;
|
|
28
|
+
/**
|
|
29
|
+
* One policy as its `DROP` / `CREATE` pair — each a complete statement.
|
|
30
|
+
*
|
|
31
|
+
* This is the primitive the boot-time RLS applier runs one statement at a time
|
|
32
|
+
* (the runtime's DB handle speaks the extended query protocol, which forbids
|
|
33
|
+
* multiple commands in one execute), while `db push` writes the joined string.
|
|
34
|
+
*/
|
|
35
|
+
export declare const renderPolicyStatements: (table: Pick<TablePlan, "schema" | "table">, policy: PolicyPlan) => string[];
|
|
36
|
+
/** `ALTER TABLE … ENABLE ROW LEVEL SECURITY;` — every generated table is locked. */
|
|
37
|
+
export declare const renderEnableRls: (table: Pick<TablePlan, "schema" | "table">) => string;
|
|
38
|
+
export declare function renderPostgresDdl(plan: SchemaPlan, options?: DdlRenderOptions): string;
|
|
39
|
+
export declare function renderPoliciesDdl(plan: SchemaPlan): string;
|
|
40
|
+
export declare function renderSearchDdl(plan: SchemaPlan): string;
|
|
41
|
+
/**
|
|
42
|
+
* Glob patterns telling Atlas to leave an object alone.
|
|
43
|
+
*
|
|
44
|
+
* Fully qualified, `schema.table.object`, matching the include list. The
|
|
45
|
+
* two-part form is what Atlas wants when the connection URL scopes it to one
|
|
46
|
+
* schema and is *silently ignored* otherwise: it reads `posts.search_vector` as
|
|
47
|
+
* a table named `search_vector` in a schema named `posts`, matches nothing, and
|
|
48
|
+
* reports no error for the pattern that never fired.
|
|
49
|
+
*/
|
|
50
|
+
export declare const searchExcludePatternsOf: (plan: SchemaPlan) => string[];
|
|
51
|
+
export declare function renderVectorDdl(plan: SchemaPlan): string;
|
|
52
|
+
/** @see searchExcludePatternsOf */
|
|
53
|
+
export declare const vectorExcludePatternsOf: (plan: SchemaPlan) => string[];
|
|
54
|
+
/**
|
|
55
|
+
* `autoValue: "on_update"`, as the file Rebase applies itself.
|
|
56
|
+
*
|
|
57
|
+
* Empty when nothing declares one — the caller writes no file then, and removes
|
|
58
|
+
* a stale one.
|
|
59
|
+
*/
|
|
60
|
+
export declare function renderTriggersDdl(plan: SchemaPlan): string;
|
|
61
|
+
/** @see searchExcludePatternsOf */
|
|
62
|
+
export declare const triggerExcludePatternsOf: (plan: SchemaPlan) => string[];
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `schema.generated.ts`, rendered from a {@link SchemaPlan}.
|
|
3
|
+
*
|
|
4
|
+
* This file is what a developer running drizzle-kit themselves diffs against,
|
|
5
|
+
* and what the runtime's query builder is typed by. It has to *compile*, which
|
|
6
|
+
* nothing in this repo checked until `generated-schema-compiles.test.ts`: six
|
|
7
|
+
* ordinary inputs used to produce a file TypeScript rejects, and the class the
|
|
8
|
+
* bigint incident already taught is that a file which will not build gets
|
|
9
|
+
* hand-patched and then sits stale until a security fix misses production.
|
|
10
|
+
*
|
|
11
|
+
* Two structural rules keep that from coming back:
|
|
12
|
+
*
|
|
13
|
+
* - **The import list is derived from what was emitted.** Every builder is
|
|
14
|
+
* recorded as it is used ({@link BuilderUses}), and the header is written
|
|
15
|
+
* last, from that set. It used to be a fixed roster plus three
|
|
16
|
+
* property-scanning heuristics, so `columnType: "uuid"` on a plain string
|
|
17
|
+
* emitted `uuid(…)` and imported nothing.
|
|
18
|
+
* - **Nothing here reads a `Property`.** Types, defaults, keys and constraints
|
|
19
|
+
* all arrive decided. The Drizzle generator disagreeing with the DDL one is
|
|
20
|
+
* what left `geopoint` with a database column and no Drizzle key.
|
|
21
|
+
*/
|
|
22
|
+
import type { SchemaPlan } from "./types.js";
|
|
23
|
+
/** What the generated file may leave out. */
|
|
24
|
+
export interface DrizzleRenderOptions {
|
|
25
|
+
/**
|
|
26
|
+
* `false` strips the `pgPolicy(...)` calls. RLS is still enabled on every
|
|
27
|
+
* table regardless — a bare table must default-deny, not fail open.
|
|
28
|
+
*/
|
|
29
|
+
policies?: boolean;
|
|
30
|
+
}
|
|
31
|
+
export declare function renderDrizzleSchema(plan: SchemaPlan, options?: DrizzleRenderOptions): string;
|