@rebasepro/server-postgresql 0.4.0 → 0.6.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.
Files changed (168) hide show
  1. package/README.md +69 -89
  2. package/dist/{server-postgresql/src/PostgresAdapter.d.ts → PostgresAdapter.d.ts} +1 -1
  3. package/dist/{server-postgresql/src/PostgresBackendDriver.d.ts → PostgresBackendDriver.d.ts} +2 -2
  4. package/dist/{server-postgresql/src/PostgresBootstrapper.d.ts → PostgresBootstrapper.d.ts} +11 -1
  5. package/dist/{server-postgresql/src/auth → auth}/services.d.ts +11 -11
  6. package/dist/{server-postgresql/src/collections → collections}/PostgresCollectionRegistry.d.ts +4 -0
  7. package/dist/{server-postgresql/src/data-transformer.d.ts → data-transformer.d.ts} +0 -3
  8. package/dist/{server-postgresql/src/databasePoolManager.d.ts → databasePoolManager.d.ts} +1 -1
  9. package/dist/index.es.js +10174 -11184
  10. package/dist/index.es.js.map +1 -1
  11. package/dist/index.umd.js +10735 -11462
  12. package/dist/index.umd.js.map +1 -1
  13. package/dist/{server-postgresql/src/services → services}/EntityPersistService.d.ts +0 -14
  14. package/dist/types.d.ts +3 -0
  15. package/dist/utils/pg-error-utils.d.ts +55 -0
  16. package/dist/{server-postgresql/src/websocket.d.ts → websocket.d.ts} +8 -3
  17. package/package.json +24 -21
  18. package/src/PostgresAdapter.ts +9 -10
  19. package/src/PostgresBackendDriver.ts +135 -122
  20. package/src/PostgresBootstrapper.ts +90 -16
  21. package/src/auth/ensure-tables.ts +28 -5
  22. package/src/auth/services.ts +56 -45
  23. package/src/cli.ts +140 -110
  24. package/src/collections/PostgresCollectionRegistry.ts +7 -0
  25. package/src/connection.ts +11 -6
  26. package/src/data-transformer.ts +73 -109
  27. package/src/databasePoolManager.ts +5 -3
  28. package/src/history/HistoryService.ts +3 -2
  29. package/src/history/ensure-history-table.ts +5 -4
  30. package/src/schema/auth-schema.ts +1 -2
  31. package/src/schema/doctor-cli.ts +2 -1
  32. package/src/schema/doctor.ts +40 -37
  33. package/src/schema/generate-drizzle-schema-logic.ts +56 -18
  34. package/src/schema/generate-drizzle-schema.ts +11 -11
  35. package/src/schema/introspect-db-inference.ts +25 -25
  36. package/src/schema/introspect-db-logic.ts +38 -38
  37. package/src/schema/introspect-db.ts +28 -27
  38. package/src/services/BranchService.ts +14 -0
  39. package/src/services/EntityFetchService.ts +28 -25
  40. package/src/services/EntityPersistService.ts +11 -124
  41. package/src/services/RelationService.ts +57 -37
  42. package/src/services/entity-helpers.ts +6 -2
  43. package/src/services/realtimeService.ts +45 -32
  44. package/src/types.ts +4 -0
  45. package/src/utils/drizzle-conditions.ts +31 -15
  46. package/src/utils/pg-error-utils.ts +211 -0
  47. package/src/websocket.ts +51 -33
  48. package/test/auth-services.test.ts +36 -19
  49. package/test/batch-many-to-many-regression.test.ts +119 -39
  50. package/test/data-transformer-hardening.test.ts +67 -33
  51. package/test/data-transformer.test.ts +4 -2
  52. package/test/doctor.test.ts +10 -5
  53. package/test/drizzle-conditions.test.ts +59 -6
  54. package/test/generate-drizzle-schema.test.ts +65 -40
  55. package/test/introspect-db-generation.test.ts +179 -81
  56. package/test/introspect-db-utils.test.ts +92 -37
  57. package/test/mocks/chalk.cjs +7 -0
  58. package/test/pg-error-utils.test.ts +221 -0
  59. package/test/postgresDataDriver.test.ts +14 -5
  60. package/test/property-ordering.test.ts +126 -79
  61. package/test/realtimeService.test.ts +6 -2
  62. package/test/relation-pipeline-gaps.test.ts +84 -36
  63. package/test/relations.test.ts +247 -0
  64. package/test/unmapped-tables-safety.test.ts +14 -6
  65. package/test/websocket.test.ts +1 -1
  66. package/tsconfig.json +5 -0
  67. package/tsconfig.prod.json +3 -0
  68. package/vite.config.ts +5 -5
  69. package/dist/common/src/collections/CollectionRegistry.d.ts +0 -56
  70. package/dist/common/src/collections/default-collections.d.ts +0 -9
  71. package/dist/common/src/collections/index.d.ts +0 -2
  72. package/dist/common/src/data/buildRebaseData.d.ts +0 -14
  73. package/dist/common/src/data/query_builder.d.ts +0 -55
  74. package/dist/common/src/index.d.ts +0 -4
  75. package/dist/common/src/util/builders.d.ts +0 -57
  76. package/dist/common/src/util/callbacks.d.ts +0 -6
  77. package/dist/common/src/util/collections.d.ts +0 -11
  78. package/dist/common/src/util/common.d.ts +0 -2
  79. package/dist/common/src/util/conditions.d.ts +0 -26
  80. package/dist/common/src/util/entities.d.ts +0 -58
  81. package/dist/common/src/util/enums.d.ts +0 -3
  82. package/dist/common/src/util/index.d.ts +0 -16
  83. package/dist/common/src/util/navigation_from_path.d.ts +0 -34
  84. package/dist/common/src/util/navigation_utils.d.ts +0 -20
  85. package/dist/common/src/util/parent_references_from_path.d.ts +0 -6
  86. package/dist/common/src/util/paths.d.ts +0 -14
  87. package/dist/common/src/util/permissions.d.ts +0 -6
  88. package/dist/common/src/util/references.d.ts +0 -2
  89. package/dist/common/src/util/relations.d.ts +0 -22
  90. package/dist/common/src/util/resolutions.d.ts +0 -72
  91. package/dist/common/src/util/storage.d.ts +0 -24
  92. package/dist/types/src/controllers/analytics_controller.d.ts +0 -7
  93. package/dist/types/src/controllers/auth.d.ts +0 -104
  94. package/dist/types/src/controllers/client.d.ts +0 -168
  95. package/dist/types/src/controllers/collection_registry.d.ts +0 -46
  96. package/dist/types/src/controllers/customization_controller.d.ts +0 -60
  97. package/dist/types/src/controllers/data.d.ts +0 -207
  98. package/dist/types/src/controllers/data_driver.d.ts +0 -218
  99. package/dist/types/src/controllers/database_admin.d.ts +0 -11
  100. package/dist/types/src/controllers/dialogs_controller.d.ts +0 -36
  101. package/dist/types/src/controllers/effective_role.d.ts +0 -4
  102. package/dist/types/src/controllers/email.d.ts +0 -36
  103. package/dist/types/src/controllers/index.d.ts +0 -18
  104. package/dist/types/src/controllers/local_config_persistence.d.ts +0 -20
  105. package/dist/types/src/controllers/navigation.d.ts +0 -225
  106. package/dist/types/src/controllers/registry.d.ts +0 -63
  107. package/dist/types/src/controllers/side_dialogs_controller.d.ts +0 -67
  108. package/dist/types/src/controllers/side_entity_controller.d.ts +0 -97
  109. package/dist/types/src/controllers/snackbar.d.ts +0 -24
  110. package/dist/types/src/controllers/storage.d.ts +0 -171
  111. package/dist/types/src/index.d.ts +0 -4
  112. package/dist/types/src/rebase_context.d.ts +0 -122
  113. package/dist/types/src/types/auth_adapter.d.ts +0 -301
  114. package/dist/types/src/types/backend.d.ts +0 -536
  115. package/dist/types/src/types/backend_hooks.d.ts +0 -172
  116. package/dist/types/src/types/builders.d.ts +0 -15
  117. package/dist/types/src/types/chips.d.ts +0 -5
  118. package/dist/types/src/types/collections.d.ts +0 -941
  119. package/dist/types/src/types/component_ref.d.ts +0 -47
  120. package/dist/types/src/types/cron.d.ts +0 -102
  121. package/dist/types/src/types/data_source.d.ts +0 -64
  122. package/dist/types/src/types/database_adapter.d.ts +0 -94
  123. package/dist/types/src/types/entities.d.ts +0 -145
  124. package/dist/types/src/types/entity_actions.d.ts +0 -104
  125. package/dist/types/src/types/entity_callbacks.d.ts +0 -173
  126. package/dist/types/src/types/entity_link_builder.d.ts +0 -7
  127. package/dist/types/src/types/entity_overrides.d.ts +0 -10
  128. package/dist/types/src/types/entity_views.d.ts +0 -87
  129. package/dist/types/src/types/export_import.d.ts +0 -21
  130. package/dist/types/src/types/formex.d.ts +0 -40
  131. package/dist/types/src/types/index.d.ts +0 -28
  132. package/dist/types/src/types/locales.d.ts +0 -4
  133. package/dist/types/src/types/modify_collections.d.ts +0 -5
  134. package/dist/types/src/types/plugins.d.ts +0 -282
  135. package/dist/types/src/types/properties.d.ts +0 -1181
  136. package/dist/types/src/types/property_config.d.ts +0 -74
  137. package/dist/types/src/types/relations.d.ts +0 -336
  138. package/dist/types/src/types/slots.d.ts +0 -262
  139. package/dist/types/src/types/translations.d.ts +0 -900
  140. package/dist/types/src/types/user_management_delegate.d.ts +0 -86
  141. package/dist/types/src/types/websockets.d.ts +0 -78
  142. package/dist/types/src/users/index.d.ts +0 -1
  143. package/dist/types/src/users/user.d.ts +0 -50
  144. package/drizzle.test.config.ts +0 -10
  145. /package/dist/{server-postgresql/src/auth → auth}/ensure-tables.d.ts +0 -0
  146. /package/dist/{server-postgresql/src/cli.d.ts → cli.d.ts} +0 -0
  147. /package/dist/{server-postgresql/src/connection.d.ts → connection.d.ts} +0 -0
  148. /package/dist/{server-postgresql/src/history → history}/HistoryService.d.ts +0 -0
  149. /package/dist/{server-postgresql/src/history → history}/ensure-history-table.d.ts +0 -0
  150. /package/dist/{server-postgresql/src/index.d.ts → index.d.ts} +0 -0
  151. /package/dist/{server-postgresql/src/interfaces.d.ts → interfaces.d.ts} +0 -0
  152. /package/dist/{server-postgresql/src/schema → schema}/auth-schema.d.ts +0 -0
  153. /package/dist/{server-postgresql/src/schema → schema}/doctor-cli.d.ts +0 -0
  154. /package/dist/{server-postgresql/src/schema → schema}/doctor.d.ts +0 -0
  155. /package/dist/{server-postgresql/src/schema → schema}/generate-drizzle-schema-logic.d.ts +0 -0
  156. /package/dist/{server-postgresql/src/schema → schema}/generate-drizzle-schema.d.ts +0 -0
  157. /package/dist/{server-postgresql/src/schema → schema}/introspect-db-inference.d.ts +0 -0
  158. /package/dist/{server-postgresql/src/schema → schema}/introspect-db-logic.d.ts +0 -0
  159. /package/dist/{server-postgresql/src/schema → schema}/introspect-db.d.ts +0 -0
  160. /package/dist/{server-postgresql/src/schema → schema}/test-schema.d.ts +0 -0
  161. /package/dist/{server-postgresql/src/services → services}/BranchService.d.ts +0 -0
  162. /package/dist/{server-postgresql/src/services → services}/EntityFetchService.d.ts +0 -0
  163. /package/dist/{server-postgresql/src/services → services}/RelationService.d.ts +0 -0
  164. /package/dist/{server-postgresql/src/services → services}/entity-helpers.d.ts +0 -0
  165. /package/dist/{server-postgresql/src/services → services}/entityService.d.ts +0 -0
  166. /package/dist/{server-postgresql/src/services → services}/index.d.ts +0 -0
  167. /package/dist/{server-postgresql/src/services → services}/realtimeService.d.ts +0 -0
  168. /package/dist/{server-postgresql/src/utils → utils}/drizzle-conditions.d.ts +0 -0
@@ -1,536 +0,0 @@
1
- import type { Entity } from "./entities";
2
- import type { EntityCollection, FilterValues, WhereFilterOp } from "./collections";
3
- /**
4
- * Abstract database connection interface.
5
- * Represents a connection to any database system.
6
- */
7
- export interface DatabaseConnection {
8
- /**
9
- * Type identifier for this database (e.g., 'postgres', 'mongodb', 'mysql')
10
- */
11
- readonly type: string;
12
- /**
13
- * Whether the connection is currently active
14
- */
15
- readonly isConnected?: boolean;
16
- /**
17
- * Close the database connection and release resources.
18
- */
19
- close?(): Promise<void>;
20
- }
21
- /**
22
- * A single filter condition for database queries
23
- */
24
- export interface QueryFilter {
25
- field: string;
26
- operator: WhereFilterOp;
27
- value: unknown;
28
- }
29
- /**
30
- * Options for fetching a collection of entities
31
- */
32
- export interface FetchCollectionOptions<M extends Record<string, unknown> = Record<string, unknown>> {
33
- filter?: FilterValues<Extract<keyof M, string>>;
34
- orderBy?: string;
35
- order?: "desc" | "asc";
36
- limit?: number;
37
- offset?: number;
38
- startAfter?: unknown;
39
- searchString?: string;
40
- databaseId?: string;
41
- collection?: EntityCollection;
42
- }
43
- /**
44
- * Options for searching entities
45
- */
46
- export interface SearchOptions<M extends Record<string, unknown> = Record<string, unknown>> {
47
- filter?: FilterValues<Extract<keyof M, string>>;
48
- orderBy?: string;
49
- order?: "desc" | "asc";
50
- limit?: number;
51
- databaseId?: string;
52
- collection?: EntityCollection;
53
- }
54
- /**
55
- * Options for counting entities
56
- */
57
- export interface CountOptions<M extends Record<string, unknown> = Record<string, unknown>> {
58
- filter?: FilterValues<Extract<keyof M, string>>;
59
- searchString?: string;
60
- databaseId?: string;
61
- }
62
- /**
63
- * Abstract condition builder interface.
64
- * Implementations translate Rebase filter conditions to database-specific queries.
65
- *
66
- * Note: This interface can be implemented as instance methods or as a class with static methods.
67
- * For static implementations (like DrizzleConditionBuilder), use the ConditionBuilderStatic type.
68
- *
69
- * @template T The type of condition returned by the builder (e.g., SQL for PostgreSQL, Filter<Document> for MongoDB)
70
- */
71
- export interface ConditionBuilder<T = unknown> {
72
- /**
73
- * Build filter conditions from Rebase FilterValues
74
- */
75
- buildFilterConditions<M extends Record<string, unknown>>(filter: FilterValues<Extract<keyof M, string>>, collectionPath: string, ...args: unknown[]): T[];
76
- /**
77
- * Build search conditions for text search
78
- */
79
- buildSearchConditions(searchString: string, properties: Record<string, unknown>, ...args: unknown[]): T[];
80
- /**
81
- * Combine multiple conditions with AND operator
82
- */
83
- combineConditionsWithAnd(conditions: T[]): T | undefined;
84
- /**
85
- * Combine multiple conditions with OR operator
86
- */
87
- combineConditionsWithOr(conditions: T[]): T | undefined;
88
- }
89
- /**
90
- * Static condition builder type for implementations using static methods.
91
- * Use this type when the class provides static methods rather than instance methods.
92
- *
93
- * @example
94
- * // DrizzleConditionBuilder satisfies this type
95
- * const builder: ConditionBuilderStatic<SQL> = DrizzleConditionBuilder;
96
- */
97
- export type ConditionBuilderStatic<T = unknown> = {
98
- buildFilterConditions<M extends Record<string, unknown>>(filter: FilterValues<Extract<keyof M, string>>, ...args: unknown[]): T[];
99
- buildSearchConditions(searchString: string, properties: Record<string, unknown>, ...args: unknown[]): T[];
100
- combineConditionsWithAnd(conditions: T[]): T | undefined;
101
- combineConditionsWithOr(conditions: T[]): T | undefined;
102
- };
103
- /**
104
- * Abstract entity repository interface.
105
- * Handles all CRUD operations for entities in the database.
106
- *
107
- * Implementations should handle:
108
- * - Entity serialization/deserialization
109
- * - Relation resolution
110
- * - ID generation and conversion
111
- */
112
- export interface EntityRepository {
113
- /**
114
- * Fetch a single entity by ID
115
- */
116
- fetchEntity<M extends Record<string, unknown>>(collectionPath: string, entityId: string | number, databaseId?: string): Promise<Entity<M> | undefined>;
117
- /**
118
- * Fetch a collection of entities with optional filtering, ordering, and pagination
119
- */
120
- fetchCollection<M extends Record<string, unknown>>(collectionPath: string, options?: FetchCollectionOptions<M>): Promise<Entity<M>[]>;
121
- /**
122
- * Search entities by text
123
- */
124
- searchEntities<M extends Record<string, unknown>>(collectionPath: string, searchString: string, options?: SearchOptions<M>): Promise<Entity<M>[]>;
125
- /**
126
- * Count entities in a collection
127
- */
128
- countEntities<M extends Record<string, unknown>>(collectionPath: string, options?: CountOptions<M>): Promise<number>;
129
- /**
130
- * Save an entity (create or update)
131
- */
132
- saveEntity<M extends Record<string, unknown>>(collectionPath: string, values: Partial<M>, entityId?: string | number, databaseId?: string): Promise<Entity<M>>;
133
- /**
134
- * Delete an entity by ID
135
- */
136
- deleteEntity(collectionPath: string, entityId: string | number, databaseId?: string): Promise<void>;
137
- /**
138
- * Check if a field value is unique in a collection
139
- */
140
- checkUniqueField(collectionPath: string, fieldName: string, value: unknown, excludeEntityId?: string, databaseId?: string): Promise<boolean>;
141
- }
142
- /**
143
- * Configuration for subscribing to a collection
144
- */
145
- export interface CollectionSubscriptionConfig {
146
- clientId: string;
147
- path: string;
148
- filter?: unknown;
149
- orderBy?: string;
150
- order?: "desc" | "asc";
151
- limit?: number;
152
- startAfter?: unknown;
153
- databaseId?: string;
154
- searchString?: string;
155
- }
156
- /**
157
- * Configuration for subscribing to a single entity
158
- */
159
- export interface EntitySubscriptionConfig {
160
- clientId: string;
161
- path: string;
162
- entityId: string | number;
163
- }
164
- /**
165
- * Abstract realtime provider interface.
166
- * Handles real-time subscriptions and notifications for entity changes.
167
- */
168
- export interface RealtimeProvider {
169
- /**
170
- * Subscribe to collection changes
171
- */
172
- subscribeToCollection(subscriptionId: string, config: CollectionSubscriptionConfig, callback?: (entities: Entity[]) => void): void;
173
- /**
174
- * Subscribe to single entity changes
175
- */
176
- subscribeToEntity(subscriptionId: string, config: EntitySubscriptionConfig, callback?: (entity: Entity | null) => void): void;
177
- /**
178
- * Unsubscribe from a subscription
179
- */
180
- unsubscribe(subscriptionId: string): void;
181
- /**
182
- * Notify all relevant subscribers of an entity update
183
- */
184
- notifyEntityUpdate(path: string, entityId: string, entity: Entity | null, databaseId?: string): Promise<void>;
185
- }
186
- /**
187
- * Abstract collection registry interface.
188
- * Manages registration and lookup of entity collections.
189
- */
190
- export interface CollectionRegistryInterface {
191
- /**
192
- * Register a collection
193
- */
194
- register(collection: EntityCollection): void;
195
- /**
196
- * Get a collection by its path
197
- */
198
- getCollectionByPath(path: string): EntityCollection | undefined;
199
- /**
200
- * Get all registered collections
201
- */
202
- getCollections(): EntityCollection[];
203
- }
204
- /**
205
- * Abstract data transformer interface.
206
- * Handles serialization/deserialization between frontend and database formats.
207
- */
208
- export interface DataTransformer {
209
- /**
210
- * Transform entity data for storage in the database
211
- */
212
- serializeToDatabase<M extends Record<string, unknown>>(entity: M, collection: EntityCollection): Record<string, unknown>;
213
- /**
214
- * Transform database data back to entity format
215
- */
216
- deserializeFromDatabase<M extends Record<string, unknown>>(data: Record<string, unknown>, collection: EntityCollection): Promise<M>;
217
- }
218
- /**
219
- * Administrative operations for SQL-based databases (PostgreSQL, MySQL, etc.).
220
- * Used by the SQL Editor, RLS Editor, and schema browser.
221
- *
222
- * @group Admin
223
- */
224
- export interface SQLAdmin {
225
- /**
226
- * Execute raw SQL against the database.
227
- */
228
- executeSql(sql: string, options?: {
229
- database?: string;
230
- role?: string;
231
- }): Promise<Record<string, unknown>[]>;
232
- /**
233
- * Fetch the available databases on the server.
234
- */
235
- fetchAvailableDatabases?(): Promise<string[]>;
236
- /**
237
- * Fetch the available database roles.
238
- */
239
- fetchAvailableRoles?(): Promise<string[]>;
240
- /**
241
- * Fetch the current database name.
242
- */
243
- fetchCurrentDatabase?(): Promise<string | undefined>;
244
- }
245
- /**
246
- * Administrative operations for document-based databases (MongoDB, Firestore, etc.).
247
- * Used by future document administration tools.
248
- *
249
- * @group Admin
250
- */
251
- export interface DocumentAdmin {
252
- /**
253
- * Execute an aggregation pipeline or equivalent query.
254
- */
255
- executeAggregate?(pipeline: Record<string, unknown>[]): Promise<Record<string, unknown>[]>;
256
- /**
257
- * Fetch statistics for a collection (document count, size, etc.).
258
- */
259
- fetchCollectionStats?(collectionName: string): Promise<{
260
- count: number;
261
- sizeBytes?: number;
262
- }>;
263
- }
264
- /**
265
- * Administrative operations for schema management.
266
- * Shared across SQL and document databases.
267
- *
268
- * @group Admin
269
- */
270
- export interface SchemaAdmin {
271
- /**
272
- * Fetch database tables/collections not yet mapped to a Rebase collection.
273
- */
274
- fetchUnmappedTables?(mappedPaths?: string[]): Promise<string[]>;
275
- /**
276
- * Fetch column/field metadata for a single table/collection.
277
- * The return type is generic — SQL backends return TableMetadata,
278
- * document backends may return a different shape.
279
- */
280
- fetchTableMetadata?(tableName: string): Promise<unknown>;
281
- }
282
- /**
283
- * Metadata for a database branch.
284
- * @group Admin
285
- */
286
- export interface BranchInfo {
287
- /** Branch name (without prefix). */
288
- name: string;
289
- /** The database this branch was created from. */
290
- parentDatabase: string;
291
- /** When the branch was created. */
292
- createdAt: Date;
293
- /** Size in bytes, if available from the server. */
294
- sizeBytes?: number;
295
- }
296
- /**
297
- * Administrative operations for database branching.
298
- * Allows creating isolated database copies for development/preview workflows.
299
- *
300
- * @group Admin
301
- */
302
- export interface BranchAdmin {
303
- /** Create a new branch (database copy) from the current or specified source database. */
304
- createBranch(name: string, options?: {
305
- source?: string;
306
- }): Promise<BranchInfo>;
307
- /** Delete a branch database. Cannot delete the main/default database. */
308
- deleteBranch(name: string): Promise<void>;
309
- /** List all branches (databases that were created via branching). */
310
- listBranches(): Promise<BranchInfo[]>;
311
- /** Get info about a specific branch. */
312
- getBranchInfo(name: string): Promise<BranchInfo | undefined>;
313
- }
314
- /**
315
- * Union type for all admin capabilities.
316
- * A backend may implement any combination of these interfaces.
317
- *
318
- * Use type guards (`isSQLAdmin`, `isDocumentAdmin`, `isSchemaAdmin`, `isBranchAdmin`)
319
- * to safely narrow the type before calling methods.
320
- *
321
- * @group Admin
322
- */
323
- export type DatabaseAdmin = Partial<SQLAdmin> & Partial<DocumentAdmin> & Partial<SchemaAdmin> & Partial<BranchAdmin>;
324
- /**
325
- * Type guard: does this admin support SQL operations?
326
- * @group Admin
327
- */
328
- export declare function isSQLAdmin(admin: DatabaseAdmin | undefined): admin is SQLAdmin;
329
- /**
330
- * Type guard: does this admin support document operations?
331
- * @group Admin
332
- */
333
- export declare function isDocumentAdmin(admin: DatabaseAdmin | undefined): admin is DocumentAdmin;
334
- /**
335
- * Type guard: does this admin support schema management?
336
- * @group Admin
337
- */
338
- export declare function isSchemaAdmin(admin: DatabaseAdmin | undefined): admin is SchemaAdmin;
339
- /**
340
- * Type guard: does this admin support database branching?
341
- * @group Admin
342
- */
343
- export declare function isBranchAdmin(admin: DatabaseAdmin | undefined): admin is BranchAdmin;
344
- /**
345
- * Health check result returned by `healthCheck()`.
346
- * @group Lifecycle
347
- */
348
- export interface HealthCheckResult {
349
- /** Whether the backend is healthy and able to serve requests. */
350
- healthy: boolean;
351
- /** Round-trip latency to the database in milliseconds. */
352
- latencyMs: number;
353
- /** Optional details (e.g., pool stats, replication lag). */
354
- details?: Record<string, unknown>;
355
- }
356
- /**
357
- * Lifecycle contract for backend components that hold resources
358
- * (database connections, WebSocket pools, timers, etc.).
359
- *
360
- * All methods are optional — simple backends (e.g., in-memory) can skip them.
361
- * @group Lifecycle
362
- */
363
- export interface BackendLifecycle {
364
- /**
365
- * Initialize the backend: open connections, run migrations, seed data.
366
- * Called once during startup. Idempotent.
367
- */
368
- initialize?(): Promise<void>;
369
- /**
370
- * Check whether the backend is healthy and reachable.
371
- * Should be fast (< 1 s) and safe to call frequently.
372
- */
373
- healthCheck?(): Promise<HealthCheckResult>;
374
- /**
375
- * Gracefully shut down: close connections, flush buffers, cancel timers.
376
- * After calling `destroy()`, no other methods should be called.
377
- */
378
- destroy?(): Promise<void>;
379
- }
380
- /**
381
- * Configuration for creating a database backend
382
- */
383
- export interface BackendConfig {
384
- /**
385
- * Type of database backend
386
- */
387
- type: string;
388
- /**
389
- * Database connection (implementation-specific)
390
- */
391
- connection: unknown;
392
- /**
393
- * Schema definition (implementation-specific, e.g., Drizzle schema for PostgreSQL)
394
- */
395
- schema?: unknown;
396
- }
397
- /**
398
- * A complete backend instance with all required services.
399
- *
400
- * Now includes optional lifecycle management and admin capabilities.
401
- */
402
- export interface BackendInstance extends BackendLifecycle {
403
- /**
404
- * Entity repository for CRUD operations
405
- */
406
- entityRepository: EntityRepository;
407
- /**
408
- * Realtime provider for subscriptions
409
- */
410
- realtimeProvider: RealtimeProvider;
411
- /**
412
- * Collection registry
413
- */
414
- collectionRegistry: CollectionRegistryInterface;
415
- /**
416
- * The underlying database connection
417
- */
418
- connection: DatabaseConnection;
419
- /**
420
- * Administrative operations (SQL, schema, documents).
421
- * What's available depends on the backend type — use type guards
422
- * (`isSQLAdmin`, `isSchemaAdmin`, etc.) to narrow.
423
- */
424
- admin?: DatabaseAdmin;
425
- }
426
- /**
427
- * Factory function type for creating backend instances
428
- */
429
- export type BackendFactory<TConfig extends BackendConfig = BackendConfig> = (config: TConfig) => BackendInstance;
430
- /**
431
- * A `BackendBootstrapper` encapsulates all driver-specific initialization logic.
432
- *
433
- * Instead of hard-coding Postgres setup into `initializeRebaseBackend()`,
434
- * each database backend provides its own bootstrapper that knows how to:
435
- * - Create the DataDriver from a config object
436
- * - Optionally initialize auth tables
437
- * - Optionally create a realtime service
438
- * - Mount driver-specific API routes
439
- *
440
- * The main `initializeRebaseBackend()` becomes a **coordinator** that iterates
441
- * registered bootstrappers, calls their hooks, and wires the results together.
442
- *
443
- * @group Backend
444
- *
445
- * @example
446
- * ```typescript
447
- * // Third-party MySQL bootstrapper
448
- * const mysqlBootstrapper: BackendBootstrapper = {
449
- * type: "mysql",
450
- * initializeDriver: async (config) => new MySQLDataDriver(config.connection),
451
- * initializeRealtime: async (config) => new MySQLChangeStreamRealtime(config.connection),
452
- * };
453
- *
454
- * initializeRebaseBackend({
455
- * ...config,
456
- * bootstrappers: [postgresBootstrapper, mysqlBootstrapper]
457
- * });
458
- * ```
459
- */
460
- export interface BackendBootstrapper {
461
- /**
462
- * Which driver type this bootstrapper handles.
463
- * Must match the `type` field on the driver config object
464
- * (e.g., `"postgres"`, `"mongodb"`, `"mysql"`).
465
- */
466
- type: string;
467
- /**
468
- * Create a DataDriver from the given config.
469
- * This is the only **required** method.
470
- */
471
- initializeDriver(config: unknown): Promise<InitializedDriver>;
472
- /**
473
- * Initialize auth tables / services if this driver supports them.
474
- * Return undefined if auth is not supported by this backend.
475
- */
476
- initializeAuth?(config: unknown, driverResult: InitializedDriver): Promise<BootstrappedAuth | undefined>;
477
- /**
478
- * Initialize history tables / services if this driver supports them.
479
- * Return undefined if history is not supported by this backend.
480
- */
481
- initializeHistory?(config: unknown, driverResult: InitializedDriver): Promise<{
482
- historyService: unknown;
483
- } | undefined>;
484
- /**
485
- * Create a realtime provider for this driver.
486
- * Return undefined if the driver does not support realtime.
487
- */
488
- initializeRealtime?(config: unknown, driverResult: InitializedDriver): Promise<RealtimeProvider | undefined>;
489
- /**
490
- * Mount any driver-specific HTTP routes (e.g., custom admin endpoints).
491
- * Called after all drivers are initialized.
492
- */
493
- mountRoutes?(app: unknown, basePath: string, driverResult: InitializedDriver): void;
494
- /**
495
- * Return admin capabilities for this driver.
496
- */
497
- getAdmin?(driverResult: InitializedDriver): DatabaseAdmin | undefined;
498
- /**
499
- * Initialize WebSocket server for realtime operations.
500
- */
501
- initializeWebsockets?(server: unknown, realtimeService: RealtimeProvider, driver: import("../controllers/data_driver").DataDriver, config?: unknown): Promise<void> | void;
502
- }
503
- /**
504
- * Result of `BackendBootstrapper.initializeDriver()`.
505
- * @group Backend
506
- */
507
- export interface InitializedDriver {
508
- /** The DataDriver instance, ready for use. */
509
- driver: import("../controllers/data_driver").DataDriver;
510
- /** The realtime service, if the driver created one during init. */
511
- realtimeProvider?: RealtimeProvider;
512
- /** A collection registry to register schema / tables into. */
513
- collectionRegistry?: CollectionRegistryInterface;
514
- /** The underlying database connection (for lifecycle management). */
515
- connection?: DatabaseConnection;
516
- /**
517
- * Opaque handle that the bootstrapper can use in subsequent hooks
518
- * (e.g., `initializeAuth`, `mountRoutes`) to access driver internals.
519
- * Not used by the coordinator.
520
- */
521
- internals?: unknown;
522
- }
523
- /**
524
- * Result of `BackendBootstrapper.initializeAuth()`.
525
- * @group Backend
526
- */
527
- export interface BootstrappedAuth {
528
- /** User management service. */
529
- userService: unknown;
530
- /** Role management service (optional, roles are now simple strings). */
531
- roleService?: unknown;
532
- /** Email service (optional). */
533
- emailService?: unknown;
534
- /** Combined Auth Repository for unified token and user management. */
535
- authRepository?: unknown;
536
- }
@@ -1,172 +0,0 @@
1
- import type { AdminUser } from "../controllers/client";
2
- /**
3
- * Context passed to every backend hook.
4
- * Provides information about the request that triggered the hook.
5
- * @group Backend Hooks
6
- */
7
- export interface BackendHookContext {
8
- /** The currently authenticated user making the request (if any) */
9
- requestUser?: {
10
- userId: string;
11
- roles: string[];
12
- };
13
- /** The HTTP method of the request */
14
- method: "GET" | "POST" | "PUT" | "DELETE";
15
- }
16
- /**
17
- * Hooks for intercepting Admin User data at the API boundary.
18
- *
19
- * These hooks run on the server after the database operation completes
20
- * but before the response is sent to the client.
21
- *
22
- * @group Backend Hooks
23
- */
24
- export interface UserHooks {
25
- /**
26
- * Transform a user record after it's read from the database,
27
- * before it's returned to the client.
28
- *
29
- * Return the modified user, or `null` to filter it out entirely
30
- * (the user won't appear in listings or individual fetches).
31
- */
32
- afterRead?(user: AdminUser, context: BackendHookContext): AdminUser | null | Promise<AdminUser | null>;
33
- /**
34
- * Transform user data before it's written to the database.
35
- * Runs on POST (create) and PUT (update).
36
- *
37
- * Return the (possibly modified) data to proceed with the save.
38
- * Throw an error to abort the operation.
39
- */
40
- beforeSave?(data: {
41
- email?: string;
42
- displayName?: string;
43
- roles?: string[];
44
- }, context: BackendHookContext): {
45
- email?: string;
46
- displayName?: string;
47
- roles?: string[];
48
- } | Promise<{
49
- email?: string;
50
- displayName?: string;
51
- roles?: string[];
52
- }>;
53
- /**
54
- * Called after a user is successfully created or updated.
55
- * Useful for side-effects like sending notifications.
56
- */
57
- afterSave?(user: AdminUser, context: BackendHookContext): void | Promise<void>;
58
- /**
59
- * Called before a user is deleted. Throw to prevent deletion.
60
- */
61
- beforeDelete?(userId: string, context: BackendHookContext): void | Promise<void>;
62
- /**
63
- * Called after a user is successfully deleted.
64
- */
65
- afterDelete?(userId: string, context: BackendHookContext): void | Promise<void>;
66
- }
67
- /**
68
- * Hooks for intercepting collection entity data at the REST API boundary.
69
- *
70
- * These run **after** per-collection `EntityCallbacks` (which execute inside
71
- * the DataDriver) and provide a single cross-cutting interception point for
72
- * ALL collections flowing through the REST API.
73
- *
74
- * Every callback receives the collection `slug` so you can target specific
75
- * collections or apply logic globally.
76
- *
77
- * @group Backend Hooks
78
- */
79
- export interface DataHooks {
80
- /**
81
- * Transform an entity after it's read from the database,
82
- * before it's returned to the client.
83
- *
84
- * Runs for both list (GET /:slug) and single (GET /:slug/:id) fetches.
85
- * Return the modified entity, or `null` to filter it out.
86
- *
87
- * @param slug - The collection slug (e.g. "orders", "products")
88
- * @param entity - The flattened entity object (id + values merged)
89
- * @param context - Request context (authenticated user, HTTP method)
90
- */
91
- afterRead?(slug: string, entity: Record<string, unknown>, context: BackendHookContext): Record<string, unknown> | null | Promise<Record<string, unknown> | null>;
92
- /**
93
- * Transform entity values before they are written to the database.
94
- * Runs on POST (create) and PUT (update).
95
- *
96
- * Return the (possibly modified) values. Throw to abort the save.
97
- *
98
- * @param slug - The collection slug
99
- * @param values - The raw request body values
100
- * @param entityId - The entity ID (only present on updates)
101
- * @param context - Request context
102
- */
103
- beforeSave?(slug: string, values: Record<string, unknown>, entityId: string | undefined, context: BackendHookContext): Record<string, unknown> | Promise<Record<string, unknown>>;
104
- /**
105
- * Called after an entity is successfully saved (created or updated).
106
- * Useful for side-effects like syncing to external systems.
107
- *
108
- * @param slug - The collection slug
109
- * @param entity - The saved entity (flattened)
110
- * @param context - Request context
111
- */
112
- afterSave?(slug: string, entity: Record<string, unknown>, context: BackendHookContext): void | Promise<void>;
113
- /**
114
- * Called before an entity is deleted. Throw to prevent deletion.
115
- *
116
- * @param slug - The collection slug
117
- * @param entityId - The entity ID being deleted
118
- * @param context - Request context
119
- */
120
- beforeDelete?(slug: string, entityId: string, context: BackendHookContext): void | Promise<void>;
121
- /**
122
- * Called after an entity is successfully deleted.
123
- *
124
- * @param slug - The collection slug
125
- * @param entityId - The deleted entity ID
126
- * @param context - Request context
127
- */
128
- afterDelete?(slug: string, entityId: string, context: BackendHookContext): void | Promise<void>;
129
- }
130
- /**
131
- * Backend-level hooks for intercepting data at the API boundary.
132
- *
133
- * These hooks run server-side after database operations complete and before
134
- * API responses are sent.
135
- *
136
- * - `users` — intercept admin user management endpoints
137
- * - `data` — intercept ALL collection entity data flowing through the REST API
138
- *
139
- * `data` hooks complement per-collection `EntityCallbacks`. Entity callbacks
140
- * run inside the DataDriver (close to the DB); data hooks run at the HTTP
141
- * boundary (close to the client). Use data hooks for cross-cutting concerns
142
- * like audit logging, response enrichment, or field masking.
143
- *
144
- * @example
145
- * ```typescript
146
- * const hooks: BackendHooks = {
147
- * data: {
148
- * afterRead(slug, entity, ctx) {
149
- * // Mask PII for non-admin users across all collections
150
- * if (!ctx.requestUser?.roles.includes("admin") && entity.email) {
151
- * return { ...entity, email: "***" };
152
- * }
153
- * return entity;
154
- * }
155
- * },
156
- * users: {
157
- * afterRead(user, ctx) {
158
- * if (user.email.endsWith("@system.internal")) return null;
159
- * return user;
160
- * }
161
- * }
162
- * };
163
- * ```
164
- *
165
- * @group Backend Hooks
166
- */
167
- export interface BackendHooks {
168
- /** Hooks for intercepting user management data */
169
- users?: UserHooks;
170
- /** Hooks for intercepting ALL collection entity data via the REST API */
171
- data?: DataHooks;
172
- }