@rebasepro/server-postgres 0.19.1 → 0.19.2-canary.g08eed46
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
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Applying a schema plan to a database that is already running.
|
|
3
3
|
*
|
|
4
|
-
* ##
|
|
4
|
+
* ## What this module is
|
|
5
5
|
*
|
|
6
6
|
* A managed runtime boots someone else's compiled project against a database it
|
|
7
7
|
* has never seen. Auth tables are ensured at boot already, but collection tables
|
|
@@ -9,291 +9,49 @@
|
|
|
9
9
|
* request answered 500 on a missing relation. `rebase db push` cannot help — it
|
|
10
10
|
* is an Atlas-driven CLI command, and the runtime image ships no CLI.
|
|
11
11
|
*
|
|
12
|
+
* Two halves, and only one of them is here. *What the collections ask for* is
|
|
13
|
+
* `schema/plan/plan-schema.ts`, shared with `db push` and the generated Drizzle
|
|
14
|
+
* file; *what the database already has, and which of those statements are safe
|
|
15
|
+
* to run against it* is `schema/plan/diff-plan.ts`. This module reads the
|
|
16
|
+
* catalogue, runs the statements, and reports what happened.
|
|
17
|
+
*
|
|
12
18
|
* ## Why additive-only, forever
|
|
13
19
|
*
|
|
14
20
|
* This runs unattended, against a database with customers' data in it, with no
|
|
15
|
-
* human reading a diff. So it may only ever do things that cannot lose data
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* It will **never** drop a table or a column, narrow a type, or alter a
|
|
19
|
-
* constraint. A removed field leaves its column behind; a renamed field looks
|
|
20
|
-
* like an addition and the old column stays. That is the correct trade for an
|
|
21
|
-
* automated path — the alternative is an unattended process that can silently
|
|
22
|
-
* destroy a column, which is precisely the failure `db push` was hardened
|
|
23
|
-
* against. Destructive changes stay a deliberate, human-reviewed migration.
|
|
24
|
-
*
|
|
25
|
-
* Because of that, this is safe to run on every boot, and re-running it is a
|
|
26
|
-
* no-op.
|
|
21
|
+
* human reading a diff. So it may only ever do things that cannot lose data.
|
|
22
|
+
* See `diff-plan.ts` for the whole of that argument.
|
|
27
23
|
*/
|
|
28
24
|
import { type CollectionConfig } from "@rebasepro/types";
|
|
29
|
-
import { type
|
|
30
|
-
|
|
25
|
+
import { type ConstraintPolicy, type DiffOptions, type EnsureAction, type EnsurePlan, type ExistingSchema, type LegacyForeignKey, type OrphanedRequiredColumn, type SearchColumnDrift, type WithheldConstraint } from "./plan/diff-plan.js";
|
|
26
|
+
export type { ConstraintPolicy, EnsureAction, EnsurePlan, ExistingSchema, LegacyForeignKey, OrphanedRequiredColumn, SearchColumnDrift, WithheldConstraint };
|
|
31
27
|
/**
|
|
32
28
|
* The subset of a database handle this needs: run a statement, get rows back.
|
|
33
29
|
*
|
|
34
30
|
* Deliberately parameterless. Everything here is DDL or catalogue reads keyed by
|
|
35
31
|
* schema name, and schema names are identifiers — they cannot be bound as
|
|
36
|
-
* parameters anyway. They are validated
|
|
37
|
-
*
|
|
38
|
-
*
|
|
32
|
+
* parameters anyway. They are validated by `assertSafeIdentifier` before they
|
|
33
|
+
* reach a statement, so a config that somehow carried a quote is refused rather
|
|
34
|
+
* than concatenated.
|
|
39
35
|
*/
|
|
40
36
|
export interface Queryable {
|
|
41
37
|
query<T = unknown>(sql: string): Promise<{
|
|
42
38
|
rows: T[];
|
|
43
39
|
}>;
|
|
44
40
|
}
|
|
45
|
-
|
|
46
|
-
export interface ExistingSchema {
|
|
47
|
-
/** `schema.table` → set of column names. */
|
|
48
|
-
tables: Map<string, Set<string>>;
|
|
49
|
-
/** `schema.typename` of every enum type that already exists. */
|
|
50
|
-
enums: Set<string>;
|
|
51
|
-
/**
|
|
52
|
-
* `schema.table.constraint` of every constraint that already exists.
|
|
53
|
-
*
|
|
54
|
-
* Optional so a caller that only cares about tables can still build one by
|
|
55
|
-
* hand; absent is read as "none known", which at worst re-attempts a
|
|
56
|
-
* constraint that then fails harmlessly as a duplicate.
|
|
57
|
-
*/
|
|
58
|
-
constraints?: Set<string>;
|
|
59
|
-
/**
|
|
60
|
-
* `schema.table.column` → that column's comment, for the columns that have
|
|
61
|
-
* one. This is where a generated search column's fingerprint lives, so it
|
|
62
|
-
* is the only evidence that a `search` block has changed since the column
|
|
63
|
-
* was built. Absent is read as "no column is stamped", which plans a stamp
|
|
64
|
-
* and reports nothing as drifted.
|
|
65
|
-
*/
|
|
66
|
-
columnComments?: Map<string, string>;
|
|
67
|
-
/**
|
|
68
|
-
* `schema.typename` → the values that type currently holds, in order.
|
|
69
|
-
*
|
|
70
|
-
* Without this, an enum type that already exists is skipped whole and a
|
|
71
|
-
* value added to it never reaches the database — the type is there, so
|
|
72
|
-
* nothing plans anything, and the first row using the new value is rejected
|
|
73
|
-
* by a constraint nobody changed. Absent is read as "the values are
|
|
74
|
-
* unknown", which keeps the old skip-by-name behaviour rather than guessing.
|
|
75
|
-
*/
|
|
76
|
-
enumValues?: Map<string, string[]>;
|
|
77
|
-
/** `schema.table.column` for every column the database marks NOT NULL. */
|
|
78
|
-
notNullColumns?: Set<string>;
|
|
79
|
-
/**
|
|
80
|
-
* `schema.table.column` → the column's `udt_name` as the database reports
|
|
81
|
-
* it (`int4`, `jsonb`, `_numeric` for an array of numeric).
|
|
82
|
-
*
|
|
83
|
-
* The only evidence that a column's declared type and its real type have
|
|
84
|
-
* parted company. Absent is read as "unknown", which reports no drift —
|
|
85
|
-
* see `column-type-drift.ts` for why silence is the right unknown here.
|
|
86
|
-
*/
|
|
87
|
-
columnTypes?: Map<string, string>;
|
|
88
|
-
/**
|
|
89
|
-
* Tables known to hold at least one row.
|
|
90
|
-
*
|
|
91
|
-
* The only thing that decides whether a NOT NULL can be added without
|
|
92
|
-
* reading the data: on an empty table the constraint cannot fail, on a
|
|
93
|
-
* populated one it is checked against every existing row. Absent is read as
|
|
94
|
-
* "assume populated", which is the conservative direction — it withholds a
|
|
95
|
-
* constraint rather than attempting one that aborts the boot.
|
|
96
|
-
*/
|
|
97
|
-
populatedTables?: Set<string>;
|
|
98
|
-
/**
|
|
99
|
-
* `schema.table.column` for every column the database gives a DEFAULT.
|
|
100
|
-
*
|
|
101
|
-
* Paired with {@link notNullColumns} to decide whether a column no property
|
|
102
|
-
* declares can still accept a write: NOT NULL with a default can, NOT NULL
|
|
103
|
-
* without one cannot. Absent is read as "unknown", which reports nothing.
|
|
104
|
-
*/
|
|
105
|
-
columnDefaults?: Set<string>;
|
|
106
|
-
}
|
|
107
|
-
/**
|
|
108
|
-
* How far the planner may go in making the database's constraints match the
|
|
109
|
-
* configuration.
|
|
110
|
-
*
|
|
111
|
-
* - `additive` — the boot default. Columns, tables, indexes and enum values are
|
|
112
|
-
* created; no existing column's constraints are touched. Unattended boots run
|
|
113
|
-
* against customer data with nobody reading a diff, and a database adopted by
|
|
114
|
-
* introspection legitimately carries NOT NULL on columns the generated
|
|
115
|
-
* collection leaves optional (`introspect-db-logic` withholds `required` from
|
|
116
|
-
* a column with a default or a trigger behind it). Converging there would
|
|
117
|
-
* strip real constraints on first boot.
|
|
118
|
-
* - `converge` — the live schema editor. Every statement is planned, shown to
|
|
119
|
-
* the person making the change, and applied only once they confirm it. That
|
|
120
|
-
* is the context in which changing an existing column's constraints is a
|
|
121
|
-
* reviewed act rather than a surprise.
|
|
122
|
-
*/
|
|
123
|
-
export type ConstraintPolicy = "additive" | "converge";
|
|
124
|
-
export interface EnsureOptions {
|
|
125
|
-
/** Defaults to `additive`. See {@link ConstraintPolicy}. */
|
|
126
|
-
constraints?: ConstraintPolicy;
|
|
41
|
+
export interface EnsureOptions extends DiffOptions {
|
|
127
42
|
/**
|
|
128
43
|
* Server extensions the project's databases gave Rebase leave to install —
|
|
129
44
|
* `declaredDatabaseExtensions()`. Absent means none, which is a refusal and
|
|
130
45
|
* is the right default for a planner given no configuration at all.
|
|
131
46
|
*
|
|
132
|
-
* Explicit rather than read from the resource registry in here, because
|
|
133
|
-
*
|
|
134
|
-
*
|
|
135
|
-
*
|
|
136
|
-
*
|
|
47
|
+
* Explicit rather than read from the resource registry in here, because the
|
|
48
|
+
* planner is pure and several callers plan against fixtures: reaching for a
|
|
49
|
+
* process-wide registry would make the plan depend on whatever some other
|
|
50
|
+
* module happened to import. `ensureCollectionTables` is the boundary that
|
|
51
|
+
* reads the world.
|
|
137
52
|
*/
|
|
138
53
|
databaseExtensions?: readonly string[];
|
|
139
54
|
}
|
|
140
|
-
export interface EnsureAction {
|
|
141
|
-
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";
|
|
142
|
-
/** Qualified target, for logging: `public.posts` or `public.posts.title`. */
|
|
143
|
-
target: string;
|
|
144
|
-
sql: string;
|
|
145
|
-
}
|
|
146
|
-
export interface EnsurePlan {
|
|
147
|
-
actions: EnsureAction[];
|
|
148
|
-
/** Every statement, in dependency order. Empty when the schema is current. */
|
|
149
|
-
statements: string[];
|
|
150
|
-
/**
|
|
151
|
-
* Relation columns this plan is about to create where the table already
|
|
152
|
-
* carries the same column under its pre-singularization name.
|
|
153
|
-
*
|
|
154
|
-
* The reason this is reported rather than silently handled: the ensure is
|
|
155
|
-
* additive, so it would add `category_id` beside a populated
|
|
156
|
-
* `categorie_id` and the relation would then read the new, empty one. No
|
|
157
|
-
* statement fails, no table is missing, and the only symptom is relations
|
|
158
|
-
* resolving to nothing — which is indistinguishable from having no data.
|
|
159
|
-
*/
|
|
160
|
-
legacyForeignKeys: LegacyForeignKey[];
|
|
161
|
-
/**
|
|
162
|
-
* Generated search columns whose `search` block has changed since they were
|
|
163
|
-
* built. Reported, never planned into `actions` — see
|
|
164
|
-
* {@link SearchColumnDrift} for why applying it is not this path's call.
|
|
165
|
-
*/
|
|
166
|
-
searchDrift: SearchColumnDrift[];
|
|
167
|
-
/**
|
|
168
|
-
* Generated search columns that exist but carry no fingerprint — created
|
|
169
|
-
* before this check existed, or by `search.sql` on an older CLI. The plan
|
|
170
|
-
* stamps them so the *next* change is detectable; whether they match the
|
|
171
|
-
* current block cannot be known, which is what the caller reports.
|
|
172
|
-
*/
|
|
173
|
-
searchAdopted: {
|
|
174
|
-
table: string;
|
|
175
|
-
column: string;
|
|
176
|
-
}[];
|
|
177
|
-
/**
|
|
178
|
-
* Vector columns this plan is deliberately leaving unindexed, because
|
|
179
|
-
* pgvector cannot build an ANN index that wide.
|
|
180
|
-
*
|
|
181
|
-
* Reported rather than thrown: the column is valid, storable and
|
|
182
|
-
* searchable, and refusing the boot over it would make a working
|
|
183
|
-
* configuration unbootable. Reported rather than dropped: an unindexed
|
|
184
|
-
* vector column and an indexed one differ only in latency, so nothing
|
|
185
|
-
* about the running system says which one you got.
|
|
186
|
-
*/
|
|
187
|
-
vectorIndexSkipped: SkippedVectorIndex[];
|
|
188
|
-
/**
|
|
189
|
-
* Constraints the configuration asks for that this plan is not applying,
|
|
190
|
-
* and why.
|
|
191
|
-
*
|
|
192
|
-
* This is the half of the feature that matters most. Every one of these was
|
|
193
|
-
* previously withheld in silence: a required property arrived nullable, and
|
|
194
|
-
* the only evidence was a database that disagreed with its own
|
|
195
|
-
* configuration. Reporting them is what lets boot warn, the live editor
|
|
196
|
-
* refuse, and the doctor explain — three surfaces that until now had nothing
|
|
197
|
-
* to read.
|
|
198
|
-
*/
|
|
199
|
-
withheldConstraints: WithheldConstraint[];
|
|
200
|
-
/**
|
|
201
|
-
* Columns whose type in the database is in a different family from the one
|
|
202
|
-
* the collection declares.
|
|
203
|
-
*
|
|
204
|
-
* Reported and never acted on — see `column-type-drift.ts`. This is the one
|
|
205
|
-
* divergence that presents as a *working* deploy: the statement was never
|
|
206
|
-
* planned, so nothing failed, and the first evidence is a write rejected
|
|
207
|
-
* hours later by whichever end validates first.
|
|
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.
|
|
214
|
-
*
|
|
215
|
-
* This is what a **rename** looks like to an additive provisioner. Rename
|
|
216
|
-
* `title` to `headline` and boot does exactly what it promises: it adds
|
|
217
|
-
* `headline` (nullable, correctly, and says why) and leaves `title` alone,
|
|
218
|
-
* because dropping a column is destructive and this runs unattended. The
|
|
219
|
-
* table is then unwritable:
|
|
220
|
-
*
|
|
221
|
-
* POST /api/data/posts -> 400 PG_23502
|
|
222
|
-
* Missing required field: "title" in "posts" cannot be empty.
|
|
223
|
-
*
|
|
224
|
-
* naming a field that is no longer in the collection at all. On the default
|
|
225
|
-
* first-run path there is no way out inside the product either: the managed
|
|
226
|
-
* database is PGlite, and `db push` — the documented repair — refuses there
|
|
227
|
-
* because Atlas needs a second database to diff against.
|
|
228
|
-
*
|
|
229
|
-
* Reported, never acted on. Dropping the column is the right fix roughly
|
|
230
|
-
* always and destructive exactly once, which is not a decision to take
|
|
231
|
-
* unattended.
|
|
232
|
-
*/
|
|
233
|
-
orphanedRequiredColumns: OrphanedRequiredColumn[];
|
|
234
|
-
}
|
|
235
|
-
/**
|
|
236
|
-
* A NOT NULL column with no default that no property declares.
|
|
237
|
-
* @see EnsurePlan.orphanedRequiredColumns
|
|
238
|
-
*/
|
|
239
|
-
export interface OrphanedRequiredColumn {
|
|
240
|
-
/** `schema.table`. */
|
|
241
|
-
table: string;
|
|
242
|
-
/** The column left behind. */
|
|
243
|
-
column: string;
|
|
244
|
-
/** The collection that no longer declares it. */
|
|
245
|
-
slug: string;
|
|
246
|
-
}
|
|
247
|
-
/** A constraint the configuration asks for that the planner is not applying. */
|
|
248
|
-
export interface WithheldConstraint {
|
|
249
|
-
/** `schema.table.column`. */
|
|
250
|
-
target: string;
|
|
251
|
-
kind: "not-null";
|
|
252
|
-
/**
|
|
253
|
-
* Why, in a sentence that names the obstacle rather than the rule. The
|
|
254
|
-
* reader is looking at a column that is nullable when they asked for
|
|
255
|
-
* required, and needs to know what to do about it.
|
|
256
|
-
*/
|
|
257
|
-
reason: string;
|
|
258
|
-
/** What would make it applicable. */
|
|
259
|
-
remedy: string;
|
|
260
|
-
}
|
|
261
|
-
/**
|
|
262
|
-
* A generated search column built from a `search` block that has since changed.
|
|
263
|
-
*
|
|
264
|
-
* Reported instead of applied because the two ways to apply it are both worse
|
|
265
|
-
* than stopping. `ALTER COLUMN … SET EXPRESSION` exists only on PG17+ and
|
|
266
|
-
* rewrites the table either way; `DROP COLUMN` + `ADD COLUMN` rewrites it under
|
|
267
|
-
* an ACCESS EXCLUSIVE lock and rebuilds the GIN index. This module runs
|
|
268
|
-
* unattended against live customer data with nobody reading a diff — the same
|
|
269
|
-
* reason it withholds `SET NOT NULL` from an adopted table — so a multi-minute
|
|
270
|
-
* outage is not a decision it may take on its own.
|
|
271
|
-
*
|
|
272
|
-
* Not applying it silently is not an option either: that is the bug this
|
|
273
|
-
* detection exists for. A collection that added a field, flipped `unaccent` or
|
|
274
|
-
* raised a weight kept indexing the *old* set forever, and the only symptom was
|
|
275
|
-
* searches returning nothing for content plainly in the row.
|
|
276
|
-
*/
|
|
277
|
-
export interface SearchColumnDrift {
|
|
278
|
-
/** `schema.table`. */
|
|
279
|
-
table: string;
|
|
280
|
-
column: string;
|
|
281
|
-
/** The fingerprint recorded on the column. */
|
|
282
|
-
found: string;
|
|
283
|
-
/** The fingerprint the current `search` block computes. */
|
|
284
|
-
expected: string;
|
|
285
|
-
/** The statements that would rebuild the column, for the operator to run. */
|
|
286
|
-
rebuild: string[];
|
|
287
|
-
}
|
|
288
|
-
/** A relation column whose old and new spellings both plausibly apply. */
|
|
289
|
-
export interface LegacyForeignKey {
|
|
290
|
-
/** `schema.table`. */
|
|
291
|
-
table: string;
|
|
292
|
-
/** The name the current rule derives, and what this plan would create. */
|
|
293
|
-
expected: string;
|
|
294
|
-
/** The name the old rule derived, which the table already has. */
|
|
295
|
-
legacy: string;
|
|
296
|
-
}
|
|
297
55
|
export interface EnsureOutcome extends EnsurePlan {
|
|
298
56
|
/**
|
|
299
57
|
* Actions that could not be applied and are non-fatal by nature.
|
|
@@ -312,11 +70,16 @@ export interface EnsureOutcome extends EnsurePlan {
|
|
|
312
70
|
}[];
|
|
313
71
|
}
|
|
314
72
|
/**
|
|
315
|
-
* Decide what to add. Pure — the caller supplies what exists and runs the
|
|
316
|
-
*
|
|
317
|
-
*
|
|
318
|
-
*
|
|
319
|
-
*
|
|
73
|
+
* Decide what to add. Pure — the caller supplies what exists and runs the
|
|
74
|
+
* result.
|
|
75
|
+
*
|
|
76
|
+
* A plan and a diff: the collections are read once, by `planSchema`, into the
|
|
77
|
+
* same {@link SchemaPlan} `db push` renders `schema.sql` from, and the diff
|
|
78
|
+
* subtracts what the database already has. Before that split this function had
|
|
79
|
+
* its own reading of every `Property`, and the audit found twelve places where
|
|
80
|
+
* it disagreed with the two generators — a required `author_id` that was
|
|
81
|
+
* NOT NULL after a push and nullable after a boot among them, on the one path
|
|
82
|
+
* with no developer in the loop.
|
|
320
83
|
*/
|
|
321
84
|
export declare function planCollectionSchemaEnsure(allCollections: CollectionConfig[], existing: ExistingSchema, options?: EnsureOptions): EnsurePlan;
|
|
322
85
|
/** Read what the database has, for the schemas the collections live in. */
|
|
@@ -1,10 +1,28 @@
|
|
|
1
|
-
import { CollectionConfig, Property } from "@rebasepro/types";
|
|
2
1
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
2
|
+
* `schema.generated.ts`, the Drizzle half of `rebase db generate`.
|
|
3
|
+
*
|
|
4
|
+
* There is no interpretation left in this file. `schema/plan/plan-schema.ts`
|
|
5
|
+
* reads the collections into a {@link SchemaPlan} and
|
|
6
|
+
* `schema/plan/render-drizzle.ts` writes the TypeScript; this is the entry
|
|
7
|
+
* point they are reached through.
|
|
8
|
+
*
|
|
9
|
+
* It used to hold `getDrizzleColumn` — one of three `switch (prop.type)`
|
|
10
|
+
* statements, each with its own reading of relations, enums, search and
|
|
11
|
+
* `validation.unique`, and each disagreeing with the other two about something.
|
|
12
|
+
* See `schema/plan/types.ts`.
|
|
8
13
|
*/
|
|
9
|
-
|
|
10
|
-
|
|
14
|
+
import type { CollectionConfig } from "@rebasepro/types";
|
|
15
|
+
import { type DrizzleRenderOptions } from "./plan/render-drizzle.js";
|
|
16
|
+
/**
|
|
17
|
+
* The generated Drizzle schema for a set of collections.
|
|
18
|
+
*
|
|
19
|
+
* Synchronous, and takes an options object. It was `async` with nothing to
|
|
20
|
+
* await and a positional `stripPolicies` boolean — `generateSchema(c, true)`,
|
|
21
|
+
* which reads as neither "with policies" nor "without".
|
|
22
|
+
*
|
|
23
|
+
* Sorted by slug here rather than in the writer script: the output is
|
|
24
|
+
* order-dependent and `rebase doctor` regenerates it in memory to compare
|
|
25
|
+
* against the file on disk, so with the sort in the writer only, a project
|
|
26
|
+
* whose file order differed from its slug order was reported stale forever.
|
|
27
|
+
*/
|
|
28
|
+
export declare const generateSchema: (allCollections: CollectionConfig[], options?: DrizzleRenderOptions) => string;
|
|
@@ -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-vSK-VdYT.js";
|
|
4
4
|
//#region src/schema/bin/generate-drizzle-schema.ts
|
|
5
5
|
/**
|
|
6
6
|
* The built entry point for `generate-drizzle-schema`.
|