@rebasepro/types 0.6.1 → 0.7.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.
@@ -49,33 +49,42 @@ export interface BaseEntityCollection<M extends Record<string, unknown> = Record
49
49
  */
50
50
  childCollections?: () => EntityCollection<Record<string, unknown>>[];
51
51
  /**
52
- * Which driver handles this collection.
53
- * Use this to route collections to different backends:
54
- * - `"postgres"` - Route to PostgreSQL backend
55
- * - `"firestore"` - Route to Firestore (client-side)
56
- * - `"mongodb"` - Route to MongoDB backend
57
- * - Custom IDs for your own driver implementations
52
+ * The data source this collection belongs to — the routing key shared by
53
+ * the frontend router and the backend driver registry. It points at a
54
+ * {@link DataSourceDefinition} registered on `<Rebase dataSources>` (front)
55
+ * and `initRebase({ dataSources })` (back).
58
56
  *
59
- * If not specified, the default driver `"(default)"` is used.
57
+ * If not specified, the default data source `"(default)"` is used, which
58
+ * for a standard Rebase app is the server-mediated Postgres backend.
60
59
  *
61
60
  * @example
62
- * // Simple - no driver needed for default
61
+ * // Default data source (server-mediated Postgres)
63
62
  * { slug: "products" }
64
63
  *
65
- * // Firestore collection (client-side real-time)
66
- * { slug: "analytics", driver: "firestore" }
64
+ * // A direct-transport Firestore data source registered as "analytics"
65
+ * { slug: "events", dataSource: "analytics" }
66
+ */
67
+ dataSource?: string;
68
+ /**
69
+ * The engine backing this collection (`"postgres"`, `"firestore"`,
70
+ * `"mongodb"`, or a custom id). Drives editor capabilities (relations vs
71
+ * subcollections, RLS, column types).
72
+ *
73
+ * @deprecated Prefer {@link dataSource} for routing. `driver` is retained
74
+ * as an engine hint and for backward compatibility: when `dataSource` is
75
+ * omitted it also acts as the data-source key.
67
76
  *
68
- * // Multiple databases within a driver
69
- * { slug: "orders", driver: "postgres", databaseId: "orders_db" }
77
+ * If not specified, `"postgres"` is assumed.
70
78
  */
71
79
  driver?: string;
72
80
  /**
73
- * Which database within the driver.
81
+ * Which database within the engine.
74
82
  * - For Firestore: The Firestore database ID (e.g., for multi-database projects)
75
83
  * - For PostgreSQL: Schema or database name
76
84
  * - For MongoDB: Database name
77
85
  *
78
- * If not specified, the default database of the driver is used.
86
+ * If not specified, the default database of the engine is used. Resolved
87
+ * from the collection's {@link DataSourceDefinition} when omitted here.
79
88
  */
80
89
  databaseId?: string;
81
90
  /**
@@ -142,6 +151,25 @@ export interface BaseEntityCollection<M extends Record<string, unknown> = Record
142
151
  * When true, this collection is used for user management, login, password hashing, and invitation flows.
143
152
  */
144
153
  auth?: boolean | AuthCollectionConfig;
154
+ /**
155
+ * Opt out of the framework's default Row Level Security policies for
156
+ * authentication collections.
157
+ *
158
+ * When a collection has `auth` enabled, the schema generator automatically
159
+ * injects an admin-only write policy (INSERT/UPDATE/DELETE require the
160
+ * `admin` role, or the trusted server context) for any write operation that
161
+ * the collection does not already cover with an explicit `securityRules`
162
+ * entry. This makes privileged columns such as `roles` safe by default — a
163
+ * non-admin cannot modify the user row through the data API regardless of
164
+ * which code path issues the write.
165
+ *
166
+ * Defining your own write rule for an operation overrides the default for
167
+ * that operation. Set this flag to `true` to remove the default policies
168
+ * entirely and take full responsibility for the collection's RLS.
169
+ *
170
+ * @default false
171
+ */
172
+ disableDefaultAuthPolicies?: boolean;
145
173
  /**
146
174
  * Order in which the properties are displayed.
147
175
  * If you are specifying your collection as code, the order is the same as the
@@ -277,6 +305,12 @@ export interface BaseEntityCollection<M extends Record<string, unknown> = Record
277
305
  * are writing custom code
278
306
  */
279
307
  ownerId?: string;
308
+ /**
309
+ * Arbitrary key-value metadata for external consumers.
310
+ * Not interpreted by Rebase — passed through serialization unchanged.
311
+ * Used by domain apps to store custom per-collection config.
312
+ */
313
+ metadata?: Record<string, unknown>;
280
314
  /**
281
315
  * Overrides for the entity view, like the data source or the storage source.
282
316
  */
@@ -324,7 +358,7 @@ export interface BaseEntityCollection<M extends Record<string, unknown> = Record
324
358
  * Possible values: "table", "cards", "kanban".
325
359
  * Defaults to all three: ["table", "cards", "kanban"].
326
360
  * Note: "kanban" will only be available if the collection has at least
327
- * one string property with enumValues defined, regardless of this setting.
361
+ * one string property with `enum` defined, regardless of this setting.
328
362
  */
329
363
  enabledViews?: ViewMode[];
330
364
  /**
@@ -519,9 +553,9 @@ export declare function isMongoDBCollection<M extends Record<string, unknown> =
519
553
  export interface KanbanConfig<M extends Record<string, unknown> = Record<string, unknown>> {
520
554
  /**
521
555
  * Property key to use for Kanban board columns.
522
- * Must reference a string property with enumValues defined.
556
+ * Must reference a string property with `enum` values defined.
523
557
  * Entities will be grouped into columns based on this property's value.
524
- * The column order is determined by the order of enumValues in the property.
558
+ * The column order is determined by the order of `enum` values in the property.
525
559
  */
526
560
  columnProperty: Extract<keyof M, string> | (string & {});
527
561
  }
@@ -39,6 +39,82 @@ export interface DataSourceCapabilities {
39
39
  * @group Models
40
40
  */
41
41
  export type DataSourceFeatures = Omit<DataSourceCapabilities, "key" | "label">;
42
+ /**
43
+ * The default data-source key, used when a collection does not name a
44
+ * `dataSource`. Shared by the frontend router and the backend driver
45
+ * registry so both agree on "the default database".
46
+ * @group Models
47
+ */
48
+ export declare const DEFAULT_DATA_SOURCE_KEY = "(default)";
49
+ /**
50
+ * How the *frontend* reaches a data source.
51
+ *
52
+ * - `"server"` — through the Rebase backend (the `RebaseClient`). The backend
53
+ * holds the actual database adapter and routes by data-source key. This is
54
+ * the default and covers Postgres, MongoDB, and any other server-mediated
55
+ * engine.
56
+ * - `"direct"` — straight from the client to the external backend via its own
57
+ * SDK driver (e.g. Firestore). The Rebase backend is not in the data path.
58
+ * - `"custom"` — a developer-supplied {@link DataDriver}, transport unspecified.
59
+ *
60
+ * @group Models
61
+ */
62
+ export type DataSourceTransport = "server" | "direct" | "custom";
63
+ /**
64
+ * Declarative definition of a data source — a named place data lives.
65
+ *
66
+ * Declared once and shared front and back: the frontend uses it to decide
67
+ * transport (client vs direct driver), the backend uses the same `key` to
68
+ * resolve a database adapter, and the editor derives capabilities from
69
+ * `engine`. Collections reference a definition by its `key` via
70
+ * `collection.dataSource`.
71
+ *
72
+ * @group Models
73
+ */
74
+ export interface DataSourceDefinition {
75
+ /**
76
+ * Unique identifier for this data source. Collections point at it via
77
+ * `dataSource`. Defaults to {@link DEFAULT_DATA_SOURCE_KEY}.
78
+ */
79
+ key: string;
80
+ /**
81
+ * The engine backing this data source (e.g. `"postgres"`, `"mongodb"`,
82
+ * `"firestore"`, or a custom id). Determines the
83
+ * {@link DataSourceCapabilities} surfaced in the editor.
84
+ */
85
+ engine: string;
86
+ /**
87
+ * How the frontend reaches this source. Defaults to `"server"`.
88
+ */
89
+ transport: DataSourceTransport;
90
+ /**
91
+ * The physical database/schema/Firestore-database within the engine.
92
+ * Threaded to drivers/adapters as the existing `databaseId` runtime
93
+ * parameter. Defaults to the engine's own default.
94
+ */
95
+ databaseId?: string;
96
+ /** Human-readable label for the UI. */
97
+ label?: string;
98
+ }
99
+ /**
100
+ * The resolved data source for a collection: the single source of truth that
101
+ * the frontend router, backend registry, and editor all derive from.
102
+ * Produced by `resolveDataSource(collection, registry)`.
103
+ *
104
+ * @group Models
105
+ */
106
+ export interface ResolvedDataSource {
107
+ /** Data-source key (routing key, shared front + back). */
108
+ key: string;
109
+ /** Engine backing the source (drives capabilities). */
110
+ engine: string;
111
+ /** Frontend transport. */
112
+ transport: DataSourceTransport;
113
+ /** Within-engine instance, if any (the `databaseId` runtime param). */
114
+ databaseId?: string;
115
+ /** Capabilities derived from {@link engine}. */
116
+ capabilities: DataSourceCapabilities;
117
+ }
42
118
  /** @group Models */
43
119
  export declare const POSTGRES_CAPABILITIES: DataSourceCapabilities;
44
120
  /** @group Models */
@@ -59,7 +59,7 @@ export interface EntityAction<M extends Record<string, unknown> = Record<string,
59
59
  }
60
60
  export type EntityActionClickProps<M extends Record<string, unknown>, USER extends User = User> = {
61
61
  entity?: Entity<M>;
62
- context: RebaseContext<USER>;
62
+ context?: RebaseContext<USER>;
63
63
  path?: string;
64
64
  collection?: EntityCollection<M>;
65
65
  /**
@@ -78,7 +78,7 @@ export type EntityActionClickProps<M extends Record<string, unknown>, USER exten
78
78
  /**
79
79
  * If the action is rendered in the form, is it open in a side panel or full screen?
80
80
  */
81
- openEntityMode: "side_panel" | "full_screen" | "split" | "dialog";
81
+ openEntityMode?: "side_panel" | "full_screen" | "split" | "dialog";
82
82
  /**
83
83
  * Optional selection controller, present if the action is being called from a collection view
84
84
  */
@@ -43,7 +43,7 @@ export interface FormContext<M extends Record<string, unknown> = Record<string,
43
43
  status: "new" | "existing" | "copy";
44
44
  entity?: Entity<M>;
45
45
  savingError?: Error;
46
- openEntityMode: "side_panel" | "full_screen" | "split" | "dialog";
46
+ openEntityMode?: "side_panel" | "full_screen" | "split" | "dialog";
47
47
  /**
48
48
  * The underlying formex controller that powers the form.
49
49
  */
@@ -28,3 +28,4 @@ export * from "./auth_adapter";
28
28
  export * from "./database_adapter";
29
29
  export * from "./breadcrumbs";
30
30
  export * from "./component_overrides";
31
+ export * from "./api_keys";
@@ -245,7 +245,7 @@ export interface PluginFormActionProps<USER extends User = User, EC extends Enti
245
245
  disabled: boolean;
246
246
  formContext?: FormContext;
247
247
  context: RebaseContext<USER>;
248
- openEntityMode: "side_panel" | "full_screen" | "split" | "dialog";
248
+ openEntityMode?: "side_panel" | "full_screen" | "split" | "dialog";
249
249
  }
250
250
  /**
251
251
  * Parameters passed to the field builder wrap function.
@@ -167,6 +167,13 @@ export interface BaseProperty<CustomProps = unknown> {
167
167
  * Callbacks/Hooks for this property field to transform and sanitize data during its lifecycle.
168
168
  */
169
169
  callbacks?: PropertyCallbacks;
170
+ /**
171
+ * Arbitrary key-value metadata for external consumers.
172
+ * Not interpreted by Rebase — passed through serialization unchanged.
173
+ * Used by domain apps to store custom per-property config
174
+ * (e.g. CRM visibility flags, display hints).
175
+ */
176
+ metadata?: Record<string, unknown>;
170
177
  }
171
178
  /**
172
179
  * @group Entity properties
@@ -39,6 +39,12 @@ export interface RebaseTranslations {
39
39
  unsaved_changes_body: string;
40
40
  discard_changes: string;
41
41
  keep_editing: string;
42
+ /** Dialog title when clearing a new/copy form */
43
+ clear_form?: string;
44
+ /** Confirmation body when discarding changes on an existing entity */
45
+ discard_changes_confirmation?: string;
46
+ /** Confirmation body when clearing a new/copy form */
47
+ clear_form_confirmation?: string;
42
48
  search: string;
43
49
  find_by_id: string;
44
50
  find_entity_by_id: string;
@@ -153,6 +159,8 @@ export interface RebaseTranslations {
153
159
  form_modified: string;
154
160
  /** Tooltip when the form is in sync with the database */
155
161
  form_in_sync: string;
162
+ /** Tooltip/alert shown when form has validation errors */
163
+ fix_errors_before_saving?: string;
156
164
  admin: string;
157
165
  home: string;
158
166
  this_form_has_errors: string;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@rebasepro/types",
3
3
  "type": "module",
4
- "version": "0.6.1",
4
+ "version": "0.7.0",
5
5
  "description": "Rebase type definitions — shared interfaces and controller types",
6
6
  "funding": {
7
7
  "url": "https://github.com/sponsors/rebaseco"
@@ -3,6 +3,8 @@ import type { RebaseData } from "./data";
3
3
  import type { EmailService } from "./email";
4
4
  import type { StorageSource } from "./storage";
5
5
  import type { CronJobStatus, CronJobLogEntry } from "../types/cron";
6
+ import type { ApiKeysAPI } from "../types/api_keys";
7
+
6
8
 
7
9
  /**
8
10
  * Event type for authentication state changes
@@ -86,6 +88,8 @@ export interface AdminAPI {
86
88
  createUser(data: { email: string; displayName?: string; password?: string; roles?: string[]; metadata?: Record<string, any> }): Promise<{ user: AdminUser }>;
87
89
  updateUser(userId: string, data: { email?: string; displayName?: string; password?: string; roles?: string[]; metadata?: Record<string, any> }): Promise<{ user: AdminUser }>;
88
90
  deleteUser(userId: string): Promise<{ success: boolean }>;
91
+ resetPassword(userId: string, options?: { password?: string }): Promise<{ user: AdminUser; temporaryPassword?: string; invitationSent?: boolean }>;
92
+ listRoles(): Promise<{ roles: Array<{ id: string; name: string }> }>;
89
93
  bootstrap(): Promise<{ success: boolean; message: string; user: { uid: string; roles: string[] } }>;
90
94
  }
91
95
 
@@ -171,6 +175,10 @@ export interface RebaseClient<DB = unknown> {
171
175
  /** Custom backend functions API */
172
176
  functions?: FunctionsAPI;
173
177
 
178
+ /** Service API keys management API */
179
+ apiKeys?: ApiKeysAPI;
180
+
181
+
174
182
  /** Base HTTP URL of the backend server */
175
183
  baseUrl?: string;
176
184
 
@@ -1,7 +1,7 @@
1
1
  import React from "react";
2
2
  import type { EntityReference } from "../types/entities";
3
3
  import type { EntityCollection } from "../types/collections";
4
- import type { RebasePlugin } from "../types/plugins";
4
+
5
5
 
6
6
  /**
7
7
  * Controller that handles URL path building and resolution.
@@ -104,17 +104,12 @@ export type NavigationStateController = {
104
104
  /**
105
105
  * Was there an error while loading the navigation data
106
106
  */
107
- navigationLoadingError?: unknown;
107
+ navigationLoadingError?: Error;
108
108
 
109
109
  /**
110
110
  * Call this method to recalculate the navigation
111
111
  */
112
112
  refreshNavigation: () => void;
113
-
114
- /**
115
- * Plugin system allowing to extend the CMS functionality.
116
- */
117
- plugins?: RebasePlugin[];
118
113
  };
119
114
 
120
115
  export interface NavigateOptions {
@@ -126,13 +121,7 @@ export interface NavigateOptions {
126
121
  viewTransition?: boolean;
127
122
  }
128
123
 
129
- // currently not used, in favor of a single blocker in `RebaseRoute`
130
- export type NavigationBlocker = {
131
- updateBlockListener: (path: string, block: boolean, basePath?: string) => () => void;
132
- isBlocked: (path: string) => boolean;
133
- proceed?: () => void;
134
- reset?: () => void;
135
- };
124
+
136
125
 
137
126
  /**
138
127
  * Custom additional views created by the developer, added to the main
@@ -181,9 +170,13 @@ export interface AppView {
181
170
 
182
171
  /**
183
172
  * Component to be rendered. This can be any React component, and can use
184
- * any of the provided hooks
173
+ * any of the provided hooks.
174
+ *
175
+ * Pass a `ComponentType` to enable lazy rendering — the component will
176
+ * only be instantiated when the route is visited. This is recommended
177
+ * for dynamic views generated from database data.
185
178
  */
186
- view: React.ReactNode;
179
+ view: React.ReactNode | React.ComponentType;
187
180
 
188
181
  /**
189
182
  * If true, a wildcard route (slug/*) is automatically registered
@@ -191,6 +184,14 @@ export interface AppView {
191
184
  */
192
185
  nestedRoutes?: boolean;
193
186
 
187
+ /**
188
+ * Restrict this view to users with at least one of the listed roles.
189
+ * When omitted or empty, the view is visible to all authenticated users.
190
+ * Applied during view resolution — the view is filtered out entirely
191
+ * (not just hidden from nav) if the user lacks a matching role.
192
+ */
193
+ roles?: string[];
194
+
194
195
  }
195
196
 
196
197
  /**
@@ -1,6 +1,6 @@
1
1
  import { ReactNode } from "react";
2
2
  import type { EntityCollection } from "../types/collections";
3
- import type { EntityCollectionsBuilder } from "../types/builders";
3
+ import type { EntityCollectionsBuilder, AppViewsBuilder } from "../types/builders";
4
4
  import type { EntityCustomView } from "../types/entity_views";
5
5
  import type { EntityAction } from "../types/entity_actions";
6
6
  import type { AppView, NavigationGroupMapping } from "./navigation";
@@ -24,6 +24,14 @@ export interface CollectionEditorOptions {
24
24
 
25
25
  export interface RebaseCMSConfig<EC extends EntityCollection = EntityCollection> {
26
26
  collections?: EC[] | EntityCollectionsBuilder<EC>;
27
+
28
+ /**
29
+ * Custom top-level views added to the main navigation.
30
+ * Accepts a static array of views or an async builder function
31
+ * that receives the current user/auth context for role-based views.
32
+ */
33
+ views?: AppView[] | AppViewsBuilder;
34
+
27
35
  homePage?: ReactNode;
28
36
  entityViews?: EntityCustomView[];
29
37
  entityActions?: EntityAction[];
@@ -48,7 +56,7 @@ export interface RebaseCMSConfig<EC extends EntityCollection = EntityCollection>
48
56
  }
49
57
 
50
58
  export interface RebaseStudioConfig {
51
- tools?: ("sql" | "js" | "rls" | "schema" | "storage" | "cron" | "schema-visualizer" | "branches" | "api" | "logs")[];
59
+ tools?: ("sql" | "js" | "rls" | "schema" | "storage" | "cron" | "schema-visualizer" | "branches" | "api" | "logs" | "api-keys")[];
52
60
  homePage?: ReactNode;
53
61
  devViews?: AppView[];
54
62
  }
@@ -0,0 +1,52 @@
1
+ /** A single permission entry scoping an API key to a collection and its allowed operations. */
2
+ export interface ApiKeyPermission {
3
+ collection: string;
4
+ operations: ("read" | "write" | "delete")[];
5
+ }
6
+
7
+ /** An API key with the secret portion masked (returned by list / get / update). */
8
+ export interface ApiKeyMasked {
9
+ id: string;
10
+ name: string;
11
+ key_prefix: string;
12
+ permissions: ApiKeyPermission[];
13
+ admin: boolean;
14
+ rate_limit: number | null;
15
+ created_by: string;
16
+ created_at: string;
17
+ updated_at: string;
18
+ last_used_at: string | null;
19
+ expires_at: string | null;
20
+ revoked_at: string | null;
21
+ }
22
+
23
+ /** An API key including the full secret (returned only on creation). */
24
+ export interface ApiKeyWithSecret extends ApiKeyMasked {
25
+ key: string;
26
+ }
27
+
28
+ /** Payload for creating a new API key. */
29
+ export interface CreateApiKeyRequest {
30
+ name: string;
31
+ permissions: ApiKeyPermission[];
32
+ admin?: boolean;
33
+ rate_limit?: number | null;
34
+ expires_at?: string | null;
35
+ }
36
+
37
+ /** Payload for updating an existing API key. */
38
+ export interface UpdateApiKeyRequest {
39
+ name?: string;
40
+ permissions?: ApiKeyPermission[];
41
+ admin?: boolean;
42
+ rate_limit?: number | null;
43
+ expires_at?: string | null;
44
+ }
45
+
46
+ export interface ApiKeysAPI {
47
+ listKeys(): Promise<{ keys: ApiKeyMasked[] }>;
48
+ getKey(id: string): Promise<{ key: ApiKeyMasked }>;
49
+ createKey(data: CreateApiKeyRequest): Promise<{ key: ApiKeyWithSecret }>;
50
+ updateKey(id: string, data: UpdateApiKeyRequest): Promise<{ key: ApiKeyMasked }>;
51
+ revokeKey(id: string): Promise<{ success: boolean }>;
52
+ }
@@ -93,6 +93,8 @@ export interface AuthAdapterCapabilities {
93
93
  profileUpdate: boolean;
94
94
  /** Supports email verification. */
95
95
  emailVerification: boolean;
96
+ /** Supports passwordless magic link login. */
97
+ magicLink: boolean;
96
98
  /** List of enabled OAuth provider IDs (e.g. `["google", "github"]`). */
97
99
  enabledProviders: string[];
98
100
 
@@ -218,6 +220,49 @@ export interface UserCreationFinalizeResult {
218
220
  invitationSent: boolean;
219
221
  }
220
222
 
223
+ // ─── Auth Response Transform ─────────────────────────────────────────────────
224
+
225
+ /**
226
+ * The auth response payload shape that flows through `transformAuthResponse`.
227
+ *
228
+ * For login, register, OAuth, anonymous, and magic-link flows the payload
229
+ * contains both `user` and `tokens`. For refresh and MFA flows the payload
230
+ * contains only `tokens` (no `user`).
231
+ *
232
+ * @group Auth
233
+ */
234
+ export interface AuthResponsePayload {
235
+ user?: {
236
+ uid: string;
237
+ email: string;
238
+ displayName: string | null;
239
+ photoURL: string | null;
240
+ roles: string[];
241
+ metadata: Record<string, unknown>;
242
+ };
243
+ tokens: {
244
+ accessToken: string;
245
+ refreshToken: string;
246
+ accessTokenExpiresAt: number;
247
+ /** Additional tokens injected by `transformAuthResponse`. */
248
+ [key: string]: unknown;
249
+ };
250
+ }
251
+
252
+ /**
253
+ * Context passed to the `transformAuthResponse` hook.
254
+ *
255
+ * @group Auth
256
+ */
257
+ export interface TransformAuthResponseContext {
258
+ /** The authenticated user's ID. */
259
+ userId: string;
260
+ /** The auth method that triggered this response. */
261
+ method: "login" | "register" | "oauth" | "refresh" | "anonymous" | "magic-link" | "mfa";
262
+ /** The raw HTTP request (for reading headers, IP, etc.). */
263
+ request: Request;
264
+ }
265
+
221
266
  // ─── Auth Adapter ────────────────────────────────────────────────────────────
222
267
 
223
268
  /**
@@ -379,6 +424,28 @@ export interface AuthAdapter {
379
424
  * normal token verification and are granted admin-level access.
380
425
  */
381
426
  serviceKey?: string;
427
+
428
+ // ── Response Transform ───────────────────────────────────────────────
429
+
430
+ /**
431
+ * Transform the auth response before sending it to the client.
432
+ *
433
+ * Called after successful login, register, refresh, OAuth, anonymous,
434
+ * magic-link, and MFA flows. The hook receives the fully-formed
435
+ * response and returns a (potentially enriched) response.
436
+ *
437
+ * Use cases:
438
+ * - Inject tokens from external auth systems (Firebase Custom Tokens, etc.)
439
+ * - Add project-specific metadata to the response
440
+ * - Enrich the user object with data from external sources
441
+ *
442
+ * The hook runs in the request path — keep it fast.
443
+ * Heavy work should be offloaded to `onAuthenticated` (fire-and-forget).
444
+ */
445
+ transformAuthResponse?(
446
+ response: AuthResponsePayload,
447
+ context: TransformAuthResponseContext
448
+ ): Promise<AuthResponsePayload>;
382
449
  }
383
450
 
384
451
  // ─── Custom Auth Adapter Options ─────────────────────────────────────────────
@@ -413,4 +480,13 @@ export interface CustomAuthAdapterOptions {
413
480
 
414
481
  /** Override default capabilities. */
415
482
  capabilities?: Partial<AuthAdapterCapabilities>;
483
+
484
+ /**
485
+ * Transform the auth response before sending it to the client.
486
+ * Same semantics as `AuthAdapter.transformAuthResponse`.
487
+ */
488
+ transformAuthResponse?: (
489
+ response: AuthResponsePayload,
490
+ context: TransformAuthResponseContext
491
+ ) => Promise<AuthResponsePayload>;
416
492
  }
@@ -367,7 +367,7 @@ export interface SQLAdmin {
367
367
  /**
368
368
  * Execute raw SQL against the database.
369
369
  */
370
- executeSql(sql: string, options?: { database?: string; role?: string }): Promise<Record<string, unknown>[]>;
370
+ executeSql(sql: string, options?: { database?: string; role?: string; params?: unknown[] }): Promise<Record<string, unknown>[]>;
371
371
 
372
372
  /**
373
373
  * Fetch the available databases on the server.