@rebasepro/server-postgres 0.23.0 → 0.24.1-canary.g56af4a4

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.
Files changed (180) hide show
  1. package/dist/{BranchService-DGPL6G_C.js → BranchService-Bsn2wfaj.js} +36 -18
  2. package/dist/BranchService-Bsn2wfaj.js.map +1 -0
  3. package/dist/PostgresBackendDriver.d.ts +166 -13
  4. package/dist/auth/ensure-tables.d.ts +12 -0
  5. package/dist/auth/services.d.ts +78 -14
  6. package/dist/{auth-users-columns-D2LBFrMH.js → auth-users-columns-C72EMoDJ.js} +17 -1
  7. package/dist/{auth-users-columns-D2LBFrMH.js.map → auth-users-columns-C72EMoDJ.js.map} +1 -1
  8. package/dist/backup/backup-cli.d.ts +14 -0
  9. package/dist/backup/backup-service.d.ts +2 -2
  10. package/dist/backup/pg-binary.d.ts +5 -0
  11. package/dist/{backup-cli-24v4OlSp.js → backup-cli-aUfRv16h.js} +37 -29
  12. package/dist/backup-cli-aUfRv16h.js.map +1 -0
  13. package/dist/{backup-service-HQ9GC4tN.js → backup-service-BTBB7RXn.js} +60 -28
  14. package/dist/backup-service-BTBB7RXn.js.map +1 -0
  15. package/dist/boot-ddl-DVpsFN6r.js +105 -0
  16. package/dist/boot-ddl-DVpsFN6r.js.map +1 -0
  17. package/dist/cli-errors-CaI4ntyD.js +1919 -0
  18. package/dist/cli-errors-CaI4ntyD.js.map +1 -0
  19. package/dist/cli-errors.d.ts +93 -5
  20. package/dist/{cli-flags-BglvpjHv.js → cli-flags-B-Dawocl.js} +5 -2
  21. package/dist/cli-flags-B-Dawocl.js.map +1 -0
  22. package/dist/cli-helpers.d.ts +52 -12
  23. package/dist/cli-output.d.ts +16 -28
  24. package/dist/cli-push.d.ts +87 -0
  25. package/dist/cli.js +625 -190
  26. package/dist/cli.js.map +1 -1
  27. package/dist/{column-plan-helpers-DF-8dTVa.js → column-plan-helpers-drZIsSNf.js} +42 -26
  28. package/dist/column-plan-helpers-drZIsSNf.js.map +1 -0
  29. package/dist/{databasePoolManager-Bj5FbeAs.js → connection-BPoNILnD.js} +19 -110
  30. package/dist/connection-BPoNILnD.js.map +1 -0
  31. package/dist/connection.d.ts +9 -1
  32. package/dist/data-transformer.d.ts +0 -8
  33. package/dist/databasePoolManager-BkEy2w18.js +119 -0
  34. package/dist/databasePoolManager-BkEy2w18.js.map +1 -0
  35. package/dist/deferred-index-build-DP1_SNFo.js +1051 -0
  36. package/dist/deferred-index-build-DP1_SNFo.js.map +1 -0
  37. package/dist/{doctor-Cb2thZ8s.js → doctor-C4WiftHm.js} +279 -87
  38. package/dist/doctor-C4WiftHm.js.map +1 -0
  39. package/dist/ensure-collection-policies-CXpbeNag.js +541 -0
  40. package/dist/ensure-collection-policies-CXpbeNag.js.map +1 -0
  41. package/dist/ensure-collection-tables-BhsU6qUE.js +532 -0
  42. package/dist/ensure-collection-tables-BhsU6qUE.js.map +1 -0
  43. package/dist/{ensure-tables-Dhn9KM3B.js → ensure-tables-CHsgyLqg.js} +178 -75
  44. package/dist/ensure-tables-CHsgyLqg.js.map +1 -0
  45. package/dist/enum-labels-kept-D8fI1MoX.js +56 -0
  46. package/dist/enum-labels-kept-D8fI1MoX.js.map +1 -0
  47. package/dist/generate-drizzle-schema-Bz52jH2h.js +57 -0
  48. package/dist/generate-drizzle-schema-Bz52jH2h.js.map +1 -0
  49. package/dist/{generate-drizzle-schema-logic-BfzK7UQd.js → generate-drizzle-schema-logic-B74WN37S.js} +28 -10
  50. package/dist/generate-drizzle-schema-logic-B74WN37S.js.map +1 -0
  51. package/dist/generate-files-CdEckX6c.js +199 -0
  52. package/dist/generate-files-CdEckX6c.js.map +1 -0
  53. package/dist/generate-postgres-ddl-logic-B64O2oZF.js +152 -0
  54. package/dist/generate-postgres-ddl-logic-B64O2oZF.js.map +1 -0
  55. package/dist/generated-sql.d.ts +34 -0
  56. package/dist/history/HistoryService.d.ts +38 -6
  57. package/dist/history/ensure-history-table.d.ts +42 -4
  58. package/dist/index.es.js +5557 -7612
  59. package/dist/index.es.js.map +1 -1
  60. package/dist/{introspect-db-logic-WMuAfxvw.js → introspect-db-logic-C-Di8dA9.js} +562 -350
  61. package/dist/introspect-db-logic-C-Di8dA9.js.map +1 -0
  62. package/dist/introspect-db-queries-D6kAqReI.js +339 -0
  63. package/dist/introspect-db-queries-D6kAqReI.js.map +1 -0
  64. package/dist/pg-error-utils-vJezlXdI.js +388 -0
  65. package/dist/pg-error-utils-vJezlXdI.js.map +1 -0
  66. package/dist/{plan-schema-C0fxM8dY.js → plan-schema-B1YF_tYq.js} +278 -533
  67. package/dist/plan-schema-B1YF_tYq.js.map +1 -0
  68. package/dist/{policy-drift-DljYdrpW.js → policy-drift-Dm8i-s1J.js} +24 -7
  69. package/dist/policy-drift-Dm8i-s1J.js.map +1 -0
  70. package/dist/push-index-prebuild-Db4AQF4i.js +45 -0
  71. package/dist/push-index-prebuild-Db4AQF4i.js.map +1 -0
  72. package/dist/push-legacy-renames-BK6ilQq2.js +34 -0
  73. package/dist/push-legacy-renames-BK6ilQq2.js.map +1 -0
  74. package/dist/{generate-postgres-ddl-logic-Bt2d2mRH.js → render-ddl-CtC3y9Ol.js} +17 -151
  75. package/dist/render-ddl-CtC3y9Ol.js.map +1 -0
  76. package/dist/{rls-bootstrap-sql-B8EclDyM.js → rls-bootstrap-sql-RQUljnJ1.js} +125 -1046
  77. package/dist/rls-bootstrap-sql-RQUljnJ1.js.map +1 -0
  78. package/dist/{rls-enforcement-C6Xk0lA6.js → rls-enforcement-DvzqlaL1.js} +137 -17
  79. package/dist/rls-enforcement-DvzqlaL1.js.map +1 -0
  80. package/dist/schema/auth-schema.d.ts +172 -2
  81. package/dist/schema/boot-ddl.d.ts +47 -0
  82. package/dist/schema/classify-change.d.ts +29 -1
  83. package/dist/schema/collection-index.d.ts +45 -0
  84. package/dist/schema/column-plan-helpers.d.ts +38 -21
  85. package/dist/schema/deferred-index-build.d.ts +131 -0
  86. package/dist/schema/destructive-sql.d.ts +27 -1
  87. package/dist/schema/doctor-cli.js +110 -6
  88. package/dist/schema/doctor-cli.js.map +1 -1
  89. package/dist/schema/doctor-search-scale.d.ts +45 -0
  90. package/dist/schema/doctor.d.ts +53 -1
  91. package/dist/schema/ensure-collection-policies.d.ts +95 -35
  92. package/dist/schema/ensure-collection-tables.d.ts +56 -3
  93. package/dist/schema/enum-labels-kept.d.ts +26 -0
  94. package/dist/schema/generate-drizzle-schema.js +1 -1
  95. package/dist/schema/generate-files.d.ts +44 -0
  96. package/dist/schema/generate-next-step.d.ts +0 -13
  97. package/dist/schema/generate-postgres-ddl-logic.d.ts +5 -5
  98. package/dist/schema/generate-postgres-ddl.js +10 -81
  99. package/dist/schema/generate-postgres-ddl.js.map +1 -1
  100. package/dist/schema/generate-schema-commit.d.ts +12 -0
  101. package/dist/schema/introspect-db-logic.d.ts +43 -0
  102. package/dist/schema/introspect-db-queries.d.ts +12 -2
  103. package/dist/schema/introspect-db-search.d.ts +22 -0
  104. package/dist/schema/introspect-db-storage.d.ts +83 -0
  105. package/dist/schema/introspect-db-structure.d.ts +10 -0
  106. package/dist/schema/introspect-db.js +17 -6
  107. package/dist/schema/introspect-db.js.map +1 -1
  108. package/dist/schema/migration-post-process.d.ts +34 -0
  109. package/dist/schema/plan/diff-plan.d.ts +127 -1
  110. package/dist/schema/plan/plan-schema.d.ts +16 -8
  111. package/dist/schema/plan/render-ddl.d.ts +6 -0
  112. package/dist/schema/plan/types.d.ts +45 -11
  113. package/dist/schema/push-index-prebuild.d.ts +25 -0
  114. package/dist/schema/push-legacy-renames.d.ts +20 -0
  115. package/dist/schema/rls-bootstrap-sql.d.ts +15 -0
  116. package/dist/search-column-BM-GV6vH.js +442 -0
  117. package/dist/search-column-BM-GV6vH.js.map +1 -0
  118. package/dist/security/policy-drift.d.ts +1 -1
  119. package/dist/security/rls-enforcement.d.ts +39 -4
  120. package/dist/services/BranchService.d.ts +22 -1
  121. package/dist/services/FetchService.d.ts +63 -12
  122. package/dist/services/PersistService.d.ts +15 -0
  123. package/dist/services/RelationService.d.ts +106 -3
  124. package/dist/services/cdc/CdcListener.d.ts +26 -10
  125. package/dist/services/cdc/identity-columns.d.ts +19 -0
  126. package/dist/services/cdc/trigger-cdc.d.ts +180 -18
  127. package/dist/services/channel-bus/PostgresChannelBus.d.ts +12 -7
  128. package/dist/services/channel-history.d.ts +32 -5
  129. package/dist/services/collection-helpers.d.ts +26 -1
  130. package/dist/services/field-viewer.d.ts +15 -1
  131. package/dist/services/pg-notify-listener.d.ts +95 -6
  132. package/dist/services/realtimeService.d.ts +467 -53
  133. package/dist/services/row-pipeline.d.ts +16 -9
  134. package/dist/services/socket-liveness.d.ts +85 -0
  135. package/dist/services/soft-delete.d.ts +12 -0
  136. package/dist/services/sql-script.d.ts +275 -0
  137. package/dist/services/vector-iterative-scan.d.ts +40 -0
  138. package/dist/services/write-depth.d.ts +22 -0
  139. package/dist/services/write-transaction-scope.d.ts +15 -3
  140. package/dist/socket-liveness-D3UD5_BW.js +7570 -0
  141. package/dist/socket-liveness-D3UD5_BW.js.map +1 -0
  142. package/dist/socket-opt-ins.d.ts +64 -0
  143. package/dist/source-DBDbBTL4.js +811 -0
  144. package/dist/source-DBDbBTL4.js.map +1 -0
  145. package/dist/tsx-loader.d.ts +14 -0
  146. package/dist/utils/drizzle-conditions.d.ts +63 -3
  147. package/dist/utils/error-cause.d.ts +7 -0
  148. package/dist/utils/pg-error-utils.d.ts +2 -4
  149. package/dist/utils/result-rows.d.ts +10 -0
  150. package/dist/websocket.d.ts +63 -18
  151. package/package.json +7 -7
  152. package/dist/BranchService-DGPL6G_C.js.map +0 -1
  153. package/dist/backup-cli-24v4OlSp.js.map +0 -1
  154. package/dist/backup-service-HQ9GC4tN.js.map +0 -1
  155. package/dist/cli-errors-B8qHg02P.js +0 -798
  156. package/dist/cli-errors-B8qHg02P.js.map +0 -1
  157. package/dist/cli-flags-BglvpjHv.js.map +0 -1
  158. package/dist/cli-output-CNdMql-L.js +0 -47
  159. package/dist/cli-output-CNdMql-L.js.map +0 -1
  160. package/dist/collection-index-DdnsxiJ_.js +0 -286
  161. package/dist/collection-index-DdnsxiJ_.js.map +0 -1
  162. package/dist/column-plan-helpers-DF-8dTVa.js.map +0 -1
  163. package/dist/databasePoolManager-Bj5FbeAs.js.map +0 -1
  164. package/dist/doctor-Cb2thZ8s.js.map +0 -1
  165. package/dist/ensure-collection-policies-RHUcEp4v.js +0 -105
  166. package/dist/ensure-collection-policies-RHUcEp4v.js.map +0 -1
  167. package/dist/ensure-collection-tables-BEEjn5cn.js +0 -857
  168. package/dist/ensure-collection-tables-BEEjn5cn.js.map +0 -1
  169. package/dist/ensure-tables-Dhn9KM3B.js.map +0 -1
  170. package/dist/generate-drizzle-schema-logic-BfzK7UQd.js.map +0 -1
  171. package/dist/generate-drizzle-schema-yzY_BLhr.js +0 -123
  172. package/dist/generate-drizzle-schema-yzY_BLhr.js.map +0 -1
  173. package/dist/generate-postgres-ddl-logic-Bt2d2mRH.js.map +0 -1
  174. package/dist/introspect-db-logic-WMuAfxvw.js.map +0 -1
  175. package/dist/plan-schema-C0fxM8dY.js.map +0 -1
  176. package/dist/policy-drift-DljYdrpW.js.map +0 -1
  177. package/dist/rls-bootstrap-sql-B8EclDyM.js.map +0 -1
  178. package/dist/rls-enforcement-C6Xk0lA6.js.map +0 -1
  179. package/dist/source-Br7L7GOI.js +0 -410
  180. package/dist/source-Br7L7GOI.js.map +0 -1
@@ -81,7 +81,83 @@ export interface ExistingSchema {
81
81
  columnTypes?: Map<string, string>;
82
82
  /** `schema.table.trigger` of every trigger that already exists. */
83
83
  triggers?: Set<string>;
84
+ /**
85
+ * `schema.name` of every index (any relation of kind `i`/`I`) that already
86
+ * exists. Absent means unknown, and every index is planned as before —
87
+ * `IF NOT EXISTS` makes that correct, just not free.
88
+ */
89
+ indexes?: Set<string>;
90
+ /**
91
+ * `schema.name` of every index whose `pg_index.indisvalid` is false — the
92
+ * husk a `CREATE INDEX CONCURRENTLY` leaves behind when it is cancelled,
93
+ * times out, or loses a race with a peer. Such an index is in
94
+ * {@link indexes} too, maintained on every write and used by no query, and
95
+ * `IF NOT EXISTS` skips it by name forever. Absent means unknown.
96
+ */
97
+ invalidIndexes?: Set<string>;
98
+ /**
99
+ * Names of the extensions installed in the database. `CREATE EXTENSION IF
100
+ * NOT EXISTS` skips by name whatever schema the extension is in, so the name
101
+ * is the whole test. Absent means unknown.
102
+ */
103
+ extensions?: Set<string>;
104
+ /**
105
+ * {@link HELPER_FUNCTIONS} as they are in the catalogue: `schema.name(args)`
106
+ * → {@link describeHelperFunction} of what `CREATE OR REPLACE` would set.
107
+ * Absent means unknown, and every helper is re-created as before.
108
+ */
109
+ functions?: Map<string, string>;
84
110
  }
111
+ /**
112
+ * The functions the plan creates with `CREATE OR REPLACE`, which the catalogue
113
+ * reader looks up so a boot that finds them unchanged plans nothing.
114
+ *
115
+ * A helper missing from this list is not wrong, only re-created on every boot,
116
+ * which is what all of them were before.
117
+ */
118
+ export declare const HELPER_FUNCTIONS: readonly string[];
119
+ /**
120
+ * Everything `CREATE OR REPLACE FUNCTION` sets on a function, as one string.
121
+ *
122
+ * Built from the catalogue by the reader and from the statement by
123
+ * {@link parseHelperFunction}, so the two meet in one shape. It covers every
124
+ * attribute a `CREATE OR REPLACE` resets — body, language, volatility,
125
+ * strictness, parallel safety, security, leakproofness, cost and `SET` options —
126
+ * so a function someone altered by hand (`ALTER FUNCTION … VOLATILE`) still
127
+ * compares unequal and is re-created, exactly as the unconditional statement
128
+ * used to re-create it.
129
+ */
130
+ export interface HelperFunctionFacts {
131
+ returns: string;
132
+ language: string;
133
+ /** `provolatile`: `i`mmutable, `s`table, `v`olatile. */
134
+ volatility: string;
135
+ strict: boolean;
136
+ /** `proparallel`: `s`afe, `r`estricted, `u`nsafe. */
137
+ parallel: string;
138
+ securityDefiner: boolean;
139
+ leakproof: boolean;
140
+ cost: number;
141
+ /** Whether the function carries any `SET` options (`proconfig`). */
142
+ hasConfig: boolean;
143
+ /** `prosrc`: the text between the dollar quotes, exactly. */
144
+ body: string;
145
+ }
146
+ export declare const helperFunctionKey: (schema: string, name: string, args: string) => string;
147
+ export declare const describeHelperFunction: (facts: HelperFunctionFacts) => string;
148
+ /**
149
+ * What a helper's `CREATE OR REPLACE FUNCTION` statement would leave in the
150
+ * catalogue, or `undefined` for a statement this does not recognise — which is
151
+ * then planned unconditionally, as every statement was before.
152
+ *
153
+ * Only ever given statements this package renders (`searchHelperFunctions`,
154
+ * `setUpdatedAtFunction`), so a strict pattern is the right tool: anything it
155
+ * does not match exactly falls back to the safe behaviour.
156
+ */
157
+ export declare function parseHelperFunction(statement: string): {
158
+ key: string;
159
+ definition: string;
160
+ } | undefined;
85
161
  /**
86
162
  * How far the planner may go in making the database's constraints match the
87
163
  * configuration.
@@ -100,9 +176,21 @@ export type ConstraintPolicy = "additive" | "converge";
100
176
  export interface DiffOptions {
101
177
  /** Defaults to `additive`. See {@link ConstraintPolicy}. */
102
178
  constraints?: ConstraintPolicy;
179
+ /**
180
+ * Plan every index a table that already exists needs — declared, search
181
+ * and vector, missing or left INVALID under its name — as a
182
+ * {@link DeferredIndexBuild} rather than an action, as the derived
183
+ * foreign-key indexes always are. `ensureCollectionTables` sets it: it
184
+ * hands them to `buildDeferredIndexes`, which builds them on a connection
185
+ * of its own with no `statement_timeout`, and drops and rebuilds a husk.
186
+ *
187
+ * Absent — the live schema editor, which applies `statements` as text —
188
+ * they stay `CREATE INDEX CONCURRENTLY IF NOT EXISTS` actions, as before.
189
+ */
190
+ deferLiveIndexes?: boolean;
103
191
  }
104
192
  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";
193
+ kind: "create-enum" | "create-table" | "enable-rls" | "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
194
  /** Qualified target, for logging: `public.posts` or `public.posts.title`. */
107
195
  target: string;
108
196
  sql: string;
@@ -166,6 +254,42 @@ export interface LegacyForeignKey {
166
254
  /** The name the old rule derived, which the table already has. */
167
255
  legacy: string;
168
256
  }
257
+ /**
258
+ * An index a table that already exists is missing, or holds INVALID — a
259
+ * derived foreign-key index always, and under
260
+ * {@link DiffOptions.deferLiveIndexes} a declared, search or vector one too.
261
+ *
262
+ * Not an {@link EnsureAction}, because it must not hold the boot: on a table
263
+ * with millions of rows `CREATE INDEX CONCURRENTLY` takes minutes, and every
264
+ * minute of it would be a minute the deployment is not serving. The caller
265
+ * builds these after the fact — boot in the background once it serves, every
266
+ * other caller inline after the actions — through `buildDeferredIndexes`. A
267
+ * {@link unique} one is the exception: it is built before the ensure returns.
268
+ *
269
+ * Kept out of {@link EnsurePlan.statements} for the same reason: a caller that
270
+ * applies statements as text (the live schema editor) may run them inside a
271
+ * transaction, which `CONCURRENTLY` refuses.
272
+ */
273
+ export interface DeferredIndexBuild {
274
+ schema: string;
275
+ /** Bare table name. */
276
+ table: string;
277
+ indexName: string;
278
+ /** `CREATE [UNIQUE] INDEX CONCURRENTLY IF NOT EXISTS …;` */
279
+ sql: string;
280
+ /**
281
+ * The catalogue already holds an INVALID index under this name, which has
282
+ * to be dropped before the build — `IF NOT EXISTS` would skip it.
283
+ */
284
+ invalid: boolean;
285
+ /**
286
+ * A declared `unique: true` index. Not an optimization but the collection
287
+ * promising two rows cannot share a value, so `ensureCollectionTables`
288
+ * builds it before it returns — never after the server is serving — and
289
+ * fails when it cannot, as it did when this was an action. Absent is false.
290
+ */
291
+ unique?: boolean;
292
+ }
169
293
  export interface EnsurePlan {
170
294
  actions: EnsureAction[];
171
295
  /** Every statement, in dependency order. Empty when the schema is current. */
@@ -217,5 +341,7 @@ export interface EnsurePlan {
217
341
  * exactly once, which is not a decision to take unattended.
218
342
  */
219
343
  orphanedRequiredColumns: OrphanedRequiredColumn[];
344
+ /** @see DeferredIndexBuild */
345
+ deferredIndexes: DeferredIndexBuild[];
220
346
  }
221
347
  export declare function diffPlanAgainstCatalogue(plan: SchemaPlan, existing: ExistingSchema, options?: DiffOptions): EnsurePlan;
@@ -12,7 +12,7 @@
12
12
  * imported would not be comparable with itself.
13
13
  *
14
14
  * It **throws** rather than guessing. A configuration no renderer can honour —
15
- * an empty enum, two `isId` properties, `isId: "cuid"`, an unknown
15
+ * an empty enum, `isId: "cuid"`, a foreign key into a composite key, an unknown
16
16
  * `columnType`, a relation to a collection that is not in the bundle, a
17
17
  * `search` block on a collection Postgres does not store — used to fail
18
18
  * differently in each of the three emitters, or not at all, and the failure
@@ -65,8 +65,17 @@ export declare const defaultBelongsToOnDelete: (required: boolean | undefined) =
65
65
  * One exception: a `serial` key owns a sequence, and a column pointing at it is
66
66
  * the plain integer of the same width — `SERIAL` there would give every
67
67
  * referencing column a sequence of its own.
68
+ *
69
+ * @param via the link asking, named if the collection's key is composite and so
70
+ * cannot be pointed at — see `getPrimaryKeyProp`.
71
+ */
72
+ export declare const primaryKeyPgType: (collection: CollectionConfig, via: string) => PgType;
73
+ /**
74
+ * The DEFAULT of the implicit `id TEXT PRIMARY KEY` a collection that declares
75
+ * no key gets: a uuid, as text. The same generator `isId: "uuid"` uses, cast to
76
+ * the column the key has always been.
68
77
  */
69
- export declare const primaryKeyPgType: (collection: CollectionConfig) => PgType;
78
+ export declare const IMPLICIT_ID_DEFAULT = "gen_random_uuid()::text";
70
79
  /**
71
80
  * The Postgres type a property's column has.
72
81
  *
@@ -79,12 +88,11 @@ export declare const columnPgType: (propName: string, prop: Property, collection
79
88
  /**
80
89
  * One security rule, compiled to the clauses a policy is made of.
81
90
  *
82
- * The desugaring (`access` / `ownerField` / `roles` / structured condition /
83
- * raw SQL → `PolicyExpression`) and the SQL compilation are `@rebasepro/common`'s,
84
- * which is what the client-side evaluator uses too — so the UI, the DDL and the
85
- * database agree about who can read a row. What lives here is only the shape:
86
- * which operations a rule expands to, which clauses each operation takes, and
87
- * the deny-all fallback for a clause that compiled to nothing.
91
+ * The compilation is `compileRulePolicies` in `@rebasepro/common`, which the
92
+ * Studio's RLS editor also compares the live database against — so the UI, the
93
+ * DDL and the database agree about who can read a row. What this adds is only
94
+ * the planner's bookkeeping: which rule a policy came from, and whether Rebase
95
+ * injected it.
88
96
  */
89
97
  export declare const compileSecurityRule: (collection: CollectionConfig, rule: SecurityRule, resolveCollection: ResolveCollection, injected: boolean, ruleKey?: string) => PolicyPlan[];
90
98
  export declare function planSchema(allCollections: CollectionConfig[], options?: PlanOptions): SchemaPlan;
@@ -25,6 +25,12 @@ export declare const renderPgType: (type: PgType) => string;
25
25
  * DEFAULT, which is why it is rendered here and not in the DEFAULT slot.
26
26
  */
27
27
  export declare const renderColumnDefinition: (column: ColumnPlan) => string;
28
+ /**
29
+ * `PRIMARY KEY ("a", "b")`, the clause a composite key takes inside a
30
+ * `CREATE TABLE`. Shared by `schema.sql` and boot-ensure's `CREATE TABLE`, so
31
+ * the two cannot list the columns differently.
32
+ */
33
+ export declare const renderPrimaryKeyConstraint: (table: Pick<TablePlan, "primaryKey">) => string;
28
34
  /**
29
35
  * One policy as its `DROP` / `CREATE` pair — each a complete statement.
30
36
  *
@@ -200,6 +200,13 @@ export interface ColumnPlan {
200
200
  column: string;
201
201
  type: PgType;
202
202
  nullable: boolean;
203
+ /**
204
+ * This column alone is the table's primary key, declared inline on it.
205
+ *
206
+ * `false` for a column of a composite key: several inline `PRIMARY KEY`
207
+ * clauses would be several primary keys, so a composite key is one table
208
+ * constraint over {@link TablePlan.primaryKey} instead.
209
+ */
203
210
  primaryKey: boolean;
204
211
  unique: boolean;
205
212
  default?: ColumnDefault;
@@ -273,6 +280,14 @@ export interface PolicyPlan {
273
280
  * what `securityRules` reads like — `policies.sql` says so in a comment.
274
281
  */
275
282
  injected: boolean;
283
+ /**
284
+ * Policy names, as Postgres stored them, that this policy replaces — set
285
+ * only on the first policy of a rule whose per-operation names used to
286
+ * collide at 63 bytes (see `getPolicySupersededNames`). Rendered as a
287
+ * `DROP POLICY IF EXISTS` ahead of the policy, so a boot or push swaps the
288
+ * one truncated survivor for a policy per operation. Absent otherwise.
289
+ */
290
+ supersedes?: string[];
276
291
  }
277
292
  /** A `BEFORE UPDATE` trigger stamping `now()` onto an `on_update` column. */
278
293
  export interface TriggerPlan {
@@ -326,7 +341,13 @@ export interface TablePlan {
326
341
  */
327
342
  declaringSlugs?: string[];
328
343
  columns: ColumnPlan[];
329
- /** Column names, in order. One entry for a collection, two for a junction. */
344
+ /**
345
+ * The primary key's column names, in key order.
346
+ *
347
+ * One entry is a key declared inline on its column ({@link ColumnPlan.primaryKey}).
348
+ * Several — a junction's two endpoints, or a collection marking several
349
+ * properties `isId` — are rendered as one `PRIMARY KEY (a, b)` constraint.
350
+ */
330
351
  primaryKey: string[];
331
352
  /** The declared `indexes:` block, with its frozen names. */
332
353
  indexes: CollectionIndexSpec[];
@@ -355,23 +376,35 @@ export interface TablePlan {
355
376
  * pair them; the rule that derives it is `sharedRelationName`, which both sides
356
377
  * compute independently from the table that owns the column.
357
378
  */
358
- export interface RelationPlan {
379
+ export type RelationPlan = OneRelationPlan | ManyRelationPlan;
380
+ interface RelationPlanBase {
359
381
  /** The Drizzle table variable this entry belongs to. */
360
382
  tableVar: string;
361
383
  /** The key in the relations object. */
362
384
  key: string;
363
- kind: "one" | "many";
364
385
  targetVar: string;
365
- /**
366
- * Absent only for a `hasOne` inverse, which is the documented FK-less form:
367
- * `one(target)` with no config. `one(target, { relationName })` is not a
368
- * `RelationConfig` (TS2345) and throws at runtime besides.
369
- */
370
- relationName?: string;
386
+ relationName: string;
387
+ }
388
+ /**
389
+ * A `one()`. Every one names its join — Drizzle has no `one()` paired by
390
+ * `relationName` alone, and one paired by table is ambiguous as soon as two
391
+ * links join the same pair of tables.
392
+ */
393
+ export interface OneRelationPlan extends RelationPlanBase {
394
+ kind: "one";
371
395
  /** Property keys on this table. */
372
- fields?: string[];
396
+ fields: string[];
373
397
  /** Property keys on the target table. */
374
- references?: string[];
398
+ references: string[];
399
+ /**
400
+ * Set on a `hasOne`, whose `fields` are this table's own key: the target
401
+ * row may not exist although every column in `fields` is NOT NULL, which
402
+ * is what Drizzle reads a `one()`'s nullability from.
403
+ */
404
+ nullable?: true;
405
+ }
406
+ export interface ManyRelationPlan extends RelationPlanBase {
407
+ kind: "many";
375
408
  }
376
409
  export interface PlanOptions {
377
410
  /**
@@ -413,3 +446,4 @@ export interface SchemaPlan {
413
446
  collections: CollectionConfig[];
414
447
  options: PlanOptions;
415
448
  }
449
+ export {};
@@ -0,0 +1,25 @@
1
+ /**
2
+ * The foreign-key indexes `rebase db push` builds before Atlas plans.
3
+ *
4
+ * Rebase derives a btree for every `belongsTo` key and every junction's target
5
+ * column (15b00afcd). On a table that already exists — every table of a
6
+ * project upgraded across that release — the index is missing, and a push left
7
+ * it to Atlas, which builds it inside the push's one transaction: a plain
8
+ * `CREATE INDEX`, holding writes to the table for the whole build, about 0.4 s
9
+ * at a million rows and 6 s at ten million. Atlas's own concurrent mode would
10
+ * run the entire apply outside a transaction, which the push relies on.
11
+ *
12
+ * So the push builds those first, `CONCURRENTLY`, with the builder the boot
13
+ * uses for the same indexes (`deferred-index-build.ts`: one at a time, a lock
14
+ * budget for getting the table, an INVALID leftover dropped and rebuilt, a
15
+ * claim shared with booting instances). Atlas then finds them and plans
16
+ * nothing for them. One it could not build is still Atlas's, as before.
17
+ *
18
+ * Only an index whose columns are already there: a column this push adds is
19
+ * created by Atlas, and its index with it, on a column that holds no values.
20
+ */
21
+ import { type CollectionConfig } from "@rebasepro/types";
22
+ import { type DeferredIndexBuild } from "./plan/diff-plan.js";
23
+ import { type Queryable } from "./ensure-collection-tables.js";
24
+ /** The derived foreign-key indexes a live table lacks (or holds INVALID) whose columns it already has. */
25
+ export declare function missingForeignKeyIndexes(client: Queryable, collections: CollectionConfig[]): Promise<DeferredIndexBuild[]>;
@@ -0,0 +1,20 @@
1
+ /**
2
+ * The relation columns an aged database still holds under the name Rebase
3
+ * derived before 0.13 (`categorie_id`, `people_id`), for `db push` to rename
4
+ * before Atlas plans.
5
+ *
6
+ * Boot renames them losslessly (`diff-plan.ts`, `renameLegacyColumn`). Push
7
+ * runs Atlas, which sees only "drop `categorie_id`, add `category_id` NOT
8
+ * NULL": it listed the links as destructive changes to approve, and with
9
+ * `--allow-destructive` dropped them. A pipeline that runs only `db push`
10
+ * could not upgrade an aged database at all. Renaming first — the same
11
+ * metadata-only statement boot runs — leaves Atlas nothing to plan.
12
+ */
13
+ import { type CollectionConfig } from "@rebasepro/types";
14
+ import { type LegacyForeignKey } from "./plan/diff-plan.js";
15
+ import { type Queryable } from "./ensure-collection-tables.js";
16
+ export interface LegacyRename extends LegacyForeignKey {
17
+ /** `ALTER TABLE … RENAME COLUMN …;` */
18
+ sql: string;
19
+ }
20
+ export declare function legacyForeignKeyRenames(client: Queryable, collections: CollectionConfig[]): Promise<LegacyRename[]>;
@@ -45,6 +45,21 @@
45
45
  * a parser for a problem that does not need one.
46
46
  */
47
47
  export declare const RLS_BOOTSTRAP_STATEMENTS: readonly string[];
48
+ /**
49
+ * Whether the `rebase` schema and every RLS helper function are exactly what
50
+ * {@link RLS_BOOTSTRAP_STATEMENTS} would make them — one catalogue read.
51
+ *
52
+ * The boot ran those statements unconditionally, on every boot and on every
53
+ * source: four `CREATE OR REPLACE FUNCTION`s in a transaction under an
54
+ * advisory lock. Replacing a function rewrites its `pg_proc` row even when
55
+ * nothing changed, and every cached plan that inlined it — every plan of every
56
+ * statement a policy applies to, on every connection — is invalidated by it.
57
+ * A function that differs in anything `CREATE OR REPLACE` sets (body,
58
+ * language, volatility, strictness, parallel safety, security, leakproofness,
59
+ * cost, `SET` options), or is missing, answers `false`, and the statements run
60
+ * as before.
61
+ */
62
+ export declare function rlsRuntimeIsCurrent(run: (sql: string) => Promise<Record<string, unknown>[]>): Promise<boolean>;
48
63
  /** The same statements as one script, for migration files and raw clients. */
49
64
  export declare const RLS_BOOTSTRAP_SQL: string;
50
65
  /**