@rebasepro/client-postgresql 0.0.1-canary.dbf160a → 0.0.1-canary.e17585f

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.
@@ -50,7 +50,12 @@ export declare function createAuth(transport: Transport, options?: CreateAuthOpt
50
50
  accessToken: string;
51
51
  refreshToken: string;
52
52
  }>;
53
- signInWithGoogle: (idToken: string) => Promise<{
53
+ signInWithGoogle: (tokenOrPayload: string | {
54
+ idToken?: string;
55
+ accessToken?: string;
56
+ code?: string;
57
+ redirectUri?: string;
58
+ }) => Promise<{
54
59
  user: RebaseUser;
55
60
  accessToken: string;
56
61
  refreshToken: string;
@@ -1,4 +1,4 @@
1
- import { Transport } from "./transport";
1
+ import { Transport, FindParams } from "./transport";
2
2
  import { RebaseWebSocketClient } from "./websocket";
3
3
  import { CollectionAccessor } from "@rebasepro/types";
4
4
  import { FilterOperator, QueryBuilder } from "./query_builder";
@@ -15,5 +15,6 @@ export interface CollectionClient<M extends Record<string, unknown> = Record<str
15
15
  offset(count: number): QueryBuilder<M>;
16
16
  search(searchString: string): QueryBuilder<M>;
17
17
  include(...relations: string[]): QueryBuilder<M>;
18
+ count(params?: FindParams): Promise<number>;
18
19
  }
19
20
  export declare function createCollectionClient<M extends Record<string, unknown> = Record<string, unknown>>(transport: Transport, slug: string, ws?: RebaseWebSocketClient): CollectionClient<M>;
@@ -0,0 +1,49 @@
1
+ import type { Transport } from "./transport";
2
+ /**
3
+ * Client interface for invoking custom backend functions.
4
+ *
5
+ * Custom functions are Hono route files auto-mounted by the Rebase backend
6
+ * at `/api/functions/{name}`. The `FunctionsClient` wraps the shared
7
+ * transport so callers never need to manually construct URLs or inject
8
+ * auth tokens.
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * const result = await client.functions.invoke<{ job: Job }>('extract-job', {
13
+ * url: 'https://example.com/posting',
14
+ * html: htmlContent,
15
+ * });
16
+ * ```
17
+ */
18
+ export interface FunctionsClient {
19
+ /**
20
+ * Invoke a custom backend function by name.
21
+ *
22
+ * @typeParam T - Expected shape of the response payload.
23
+ * @param name - Function name (the filename without extension, e.g. `"extract-job"`).
24
+ * @param payload - Optional JSON-serialisable body sent as `POST`.
25
+ * @param options - Optional overrides (HTTP method, sub-path, extra headers).
26
+ * @returns The parsed JSON response from the function.
27
+ */
28
+ invoke<T = unknown>(name: string, payload?: unknown, options?: FunctionInvokeOptions): Promise<T>;
29
+ }
30
+ export interface FunctionInvokeOptions {
31
+ /** HTTP method — defaults to `"POST"`. */
32
+ method?: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
33
+ /** Sub-path appended after the function name, e.g. `"status/123"`. */
34
+ path?: string;
35
+ /** Extra headers merged into the request (auth is still injected automatically). */
36
+ headers?: Record<string, string>;
37
+ }
38
+ /**
39
+ * Create a `FunctionsClient` backed by the given transport.
40
+ *
41
+ * The transport already handles:
42
+ * - Base URL resolution
43
+ * - JWT injection via `Authorization: Bearer`
44
+ * - 401 retry / `onUnauthorized` flow
45
+ * - Consistent error throwing via `RebaseApiError`
46
+ *
47
+ * @internal
48
+ */
49
+ export declare function createFunctionsClient(transport: Transport): FunctionsClient;
@@ -3,6 +3,7 @@ import { createAuth, CreateAuthOptions } from "./auth";
3
3
  import { createAdmin, CreateAdminOptions } from "./admin";
4
4
  import { createCron, CreateCronOptions } from "./cron";
5
5
  import { CollectionClient } from "./collection";
6
+ import type { FunctionsClient } from "./functions";
6
7
  export * from "./transport";
7
8
  export * from "./auth";
8
9
  export * from "./admin";
@@ -11,6 +12,7 @@ export * from "./collection";
11
12
  export * from "./websocket";
12
13
  export * from "./storage";
13
14
  export * from "./reviver";
15
+ export * from "./functions";
14
16
  export interface CreateRebaseClientOptions extends RebaseClientConfig {
15
17
  auth?: CreateAuthOptions;
16
18
  admin?: CreateAdminOptions;
@@ -26,6 +28,7 @@ export type RebaseClient<DB = Record<string, unknown>> = BaseRebaseClient<DB> &
26
28
  auth: ReturnType<typeof createAuth>;
27
29
  admin: ReturnType<typeof createAdmin>;
28
30
  cron: ReturnType<typeof createCron>;
31
+ functions: FunctionsClient;
29
32
  ws?: RebaseWebSocketClient;
30
33
  storage?: StorageSource;
31
34
  call: <T = unknown>(endpoint: string, payload?: unknown) => Promise<T>;
@@ -80,8 +80,14 @@ export type AuthController<USER extends User = User, ExtraData = unknown> = {
80
80
  export interface AuthControllerExtended<USER extends User = User, ExtraData = unknown> extends AuthController<USER, ExtraData> {
81
81
  /** Login with email and password */
82
82
  emailPasswordLogin?(email: string, password: string): Promise<void>;
83
- /** Login with a Google ID token or trigger Google popup */
84
- googleLogin?(idToken: string): Promise<void>;
83
+ /** Login with a Google token or authorization code */
84
+ googleLogin?: {
85
+ (token: string, tokenType?: "idToken" | "accessToken"): Promise<void>;
86
+ (payload: {
87
+ code: string;
88
+ redirectUri: string;
89
+ }): Promise<void>;
90
+ };
85
91
  /** Register a new user */
86
92
  register?(email: string, password: string, displayName?: string): Promise<void>;
87
93
  /** Skip login (for anonymous access if enabled) */
@@ -167,4 +167,17 @@ export interface RebaseClient<DB = unknown> {
167
167
  email?: EmailService;
168
168
  /** Admin API for user and role management */
169
169
  admin?: AdminAPI;
170
+ /**
171
+ * The base HTTP URL of the backend server.
172
+ * Exposed by the SDK client (`@rebasepro/client`) and used to auto-derive
173
+ * the `ApiConfigProvider` URL.
174
+ */
175
+ baseUrl?: string;
176
+ /**
177
+ * WebSocket client for realtime subscriptions and admin capabilities.
178
+ * Exposed by the SDK client (`@rebasepro/client`). The shape is intentionally
179
+ * left as `unknown` in the base interface — callers should narrow via feature
180
+ * detection (e.g. `typeof ws.executeSql === "function"`).
181
+ */
182
+ ws?: unknown;
170
183
  }
@@ -36,7 +36,8 @@ export type CollectionRegistryController<DB = Record<string, unknown>, EC extend
36
36
  * Retrieve all the related parent collection ids for a given path
37
37
  * @param path
38
38
  */
39
- getParentCollectionIds: (path: string) => string[];
39
+ getParentCollectionSlugs: (path: string) => string[];
40
+ getParentEntityIds: (path: string) => string[];
40
41
  /**
41
42
  * Resolve paths from a list of ids
42
43
  * @param ids
@@ -144,12 +144,19 @@ export interface DataDriver {
144
144
  path: string;
145
145
  databaseId?: string;
146
146
  collection: EntityCollection;
147
- parentCollectionIds?: string[];
147
+ parentCollectionSlugs?: string[];
148
+ parentEntityIds?: string[];
148
149
  }) => Promise<boolean>;
149
150
  /**
150
151
  * Flag to indicate if the driver has requested the initialization of the text search index
151
152
  */
152
153
  needsInitTextSearch?: boolean;
154
+ /**
155
+ * Optional REST-optimised fetch service. When present, the REST API
156
+ * generator uses these methods instead of the generic `fetchEntity` /
157
+ * `fetchCollection` pipeline, enabling include-aware eager-loading.
158
+ */
159
+ restFetchService?: RestFetchService;
153
160
  /**
154
161
  * Return the admin capabilities of this driver.
155
162
  * @see SQLAdmin
@@ -158,3 +165,31 @@ export interface DataDriver {
158
165
  */
159
166
  admin?: import("../types/backend").DatabaseAdmin;
160
167
  }
168
+ /**
169
+ * REST-optimised fetch service exposed by drivers that support
170
+ * eager-loading of relations via `include`.
171
+ *
172
+ * The methods return flattened rows (`{ id, ...columns }`) rather
173
+ * than the `Entity<M>` wrapper used by the generic DataDriver API.
174
+ *
175
+ * @group DataDriver
176
+ */
177
+ export interface RestFetchService {
178
+ /**
179
+ * Fetch a collection of flattened entities with optional relation includes.
180
+ */
181
+ fetchCollectionForRest(collectionPath: string, options?: {
182
+ filter?: FilterValues<string>;
183
+ orderBy?: string;
184
+ order?: "desc" | "asc";
185
+ limit?: number;
186
+ offset?: number;
187
+ startAfter?: Record<string, unknown>;
188
+ searchString?: string;
189
+ databaseId?: string;
190
+ }, include?: string[]): Promise<Record<string, unknown>[]>;
191
+ /**
192
+ * Fetch a single flattened entity with optional relation includes.
193
+ */
194
+ fetchEntityForRest(collectionPath: string, entityId: string | number, include?: string[], databaseId?: string): Promise<Record<string, unknown> | null>;
195
+ }
@@ -144,17 +144,18 @@ export interface AppView {
144
144
  * It will still be accessible if you reach the specified path
145
145
  */
146
146
  hideFromNavigation?: boolean;
147
+ /**
148
+ * Navigation group for this view.
149
+ * Views sharing the same group name will be visually grouped
150
+ * together in the drawer and home page. If not set, the view
151
+ * falls into the default "Views" group.
152
+ */
153
+ group?: string;
147
154
  /**
148
155
  * Component to be rendered. This can be any React component, and can use
149
156
  * any of the provided hooks
150
157
  */
151
158
  view: React.ReactNode;
152
- /**
153
- * Optional field used to group top level navigation entries under a
154
- * navigation view.
155
- * This prop is ignored for admin views.
156
- */
157
- group?: string;
158
159
  /**
159
160
  * If true, a wildcard route (slug/*) is automatically registered
160
161
  * alongside the base route, enabling nested navigation within this view.
@@ -193,6 +194,17 @@ export interface NavigationGroupMapping {
193
194
  * List of collection ids or view paths that belong to this group.
194
195
  */
195
196
  entries: string[];
197
+ /**
198
+ * Configure which groups start collapsed.
199
+ * Set to `true` to collapse in both drawer and home page,
200
+ * or use an object to control each independently.
201
+ *
202
+ * @defaultValue false (expanded)
203
+ */
204
+ collapsedByDefault?: boolean | {
205
+ drawer?: boolean;
206
+ home?: boolean;
207
+ };
196
208
  }
197
209
  export interface NavigationEntry {
198
210
  id: string;
@@ -3,7 +3,7 @@ import type { EntityCollection } from "../types/collections";
3
3
  import type { EntityCollectionsBuilder } from "../types/builders";
4
4
  import type { EntityCustomView } from "../types/entity_views";
5
5
  import type { EntityAction } from "../types/entity_actions";
6
- import type { AppView } from "./navigation";
6
+ import type { AppView, NavigationGroupMapping } from "./navigation";
7
7
  /**
8
8
  * Options to enable the built-in collection editor.
9
9
  * When provided to `<RebaseCMS>`, the editor is auto-wired as a native feature.
@@ -25,6 +25,14 @@ export interface RebaseCMSConfig<EC extends EntityCollection = any> {
25
25
  entityViews?: EntityCustomView<any>[];
26
26
  entityActions?: EntityAction[];
27
27
  plugins?: any[];
28
+ /**
29
+ * Centralized configuration for how collections and views are grouped
30
+ * in the navigation sidebar and home page.
31
+ * Each mapping defines a named group and the collection/view slugs
32
+ * that belong to it. The array order determines group display order.
33
+ * Entry order within each group determines card order.
34
+ */
35
+ navigationGroupMappings?: NavigationGroupMapping[];
28
36
  /**
29
37
  * Enable the built-in visual collection/schema editor.
30
38
  * Pass `true` for zero-config, or an options object for fine-grained control.
@@ -62,6 +62,13 @@ export interface EntitySidePanelProps<M extends Record<string, unknown> = Record
62
62
  * Allow the user to open the entity fullscreen
63
63
  */
64
64
  allowFullScreen?: boolean;
65
+ /**
66
+ * Pre-populate the form with these values when creating a new entity.
67
+ * Only applied when `entityId` is not set (i.e. the form is in "new" mode).
68
+ * Useful for actions that fetch data from an external source (e.g. a URL)
69
+ * and want to pre-fill the document before the user saves.
70
+ */
71
+ defaultValues?: Partial<M>;
65
72
  }
66
73
  /**
67
74
  * Controller to open the side dialog displaying entity forms
@@ -3,6 +3,7 @@ import type { AuthController } from "./controllers/auth";
3
3
  import type { StorageSource } from "./controllers/storage";
4
4
  import type { UserConfigurationPersistence } from "./controllers/local_config_persistence";
5
5
  import type { DatabaseAdmin } from "./types/backend";
6
+ import type { RebaseClient } from "./controllers/client";
6
7
  import type { RebaseData } from "./controllers/data";
7
8
  import type { User } from "./users";
8
9
  import type { UserManagementDelegate } from "./types/user_management_delegate";
@@ -12,6 +13,22 @@ import type { UserManagementDelegate } from "./types/user_management_delegate";
12
13
  * @group Hooks and utilities
13
14
  */
14
15
  export type RebaseCallContext<USER extends User = User> = {
16
+ /**
17
+ * The Rebase client instance.
18
+ * Available in all entity callbacks (beforeSave, afterSave, afterRead,
19
+ * beforeDelete, afterDelete) and in CollectionActionsProps via context.
20
+ * Use it to call backend functions, access data, storage, etc.
21
+ *
22
+ * @example
23
+ * // In a beforeSave callback:
24
+ * const result = await context.client.functions.invoke('my-function', { ... });
25
+ *
26
+ * @example
27
+ * // In a CollectionAction component:
28
+ * const { client } = props.context;
29
+ * const result = await client.functions.invoke('extract-job', { url });
30
+ */
31
+ client: RebaseClient<any>;
15
32
  /**
16
33
  * Unified data access — `context.data.products.create(...)`.
17
34
  * Access any collection as a dynamic property.
@@ -0,0 +1,354 @@
1
+ /**
2
+ * @module AuthAdapter
3
+ *
4
+ * Pluggable authentication abstraction for Rebase.
5
+ *
6
+ * An `AuthAdapter` decouples authentication from the database layer,
7
+ * allowing users to bring their own auth system (Clerk, Auth0, Firebase Auth,
8
+ * custom JWT, etc.) while keeping the Rebase admin frontend fully functional.
9
+ *
10
+ * @example Built-in auth (default — zero config change)
11
+ * ```ts
12
+ * initializeRebaseBackend({
13
+ * auth: { jwtSecret: "...", google: { clientId: "..." } },
14
+ * database: createPostgresAdapter({ ... }),
15
+ * });
16
+ * ```
17
+ *
18
+ * @example Custom auth
19
+ * ```ts
20
+ * import { createCustomAuthAdapter } from "@rebasepro/server-core";
21
+ *
22
+ * initializeRebaseBackend({
23
+ * auth: createCustomAuthAdapter({
24
+ * verifyRequest: async (req) => { ... },
25
+ * }),
26
+ * database: createPostgresAdapter({ ... }),
27
+ * });
28
+ * ```
29
+ *
30
+ * @group Auth
31
+ */
32
+ import type { Hono } from "hono";
33
+ /**
34
+ * The normalized user object returned by `AuthAdapter.verifyRequest()`.
35
+ *
36
+ * Regardless of the auth provider, every request is resolved to this shape
37
+ * so that downstream middleware (RLS scoping, route guards) can work uniformly.
38
+ *
39
+ * @group Auth
40
+ */
41
+ export interface AuthenticatedUser {
42
+ /** Unique user identifier (provider-specific). */
43
+ uid: string;
44
+ /** Primary email address. */
45
+ email: string;
46
+ /** Human-readable display name. */
47
+ displayName?: string | null;
48
+ /** Avatar URL. */
49
+ photoUrl?: string | null;
50
+ /** Role identifiers the user holds. */
51
+ roles: string[];
52
+ /** Whether the user has admin privileges. */
53
+ isAdmin: boolean;
54
+ /** Raw bearer token from the request (for forwarding). */
55
+ rawToken?: string;
56
+ /** Extra claims/metadata from the auth provider. */
57
+ claims?: Record<string, unknown>;
58
+ }
59
+ /**
60
+ * Feature flags advertised by an auth adapter.
61
+ *
62
+ * The frontend reads these from `GET /api/auth/config` to dynamically
63
+ * show/hide UI elements (login form, registration, password reset, etc.).
64
+ *
65
+ * @group Auth
66
+ */
67
+ export interface AuthAdapterCapabilities {
68
+ /**
69
+ * Whether this adapter mounts its own `/auth/*` routes.
70
+ *
71
+ * - `true` for the built-in Rebase auth (login, register, refresh, etc.)
72
+ * - `false` for external providers like Clerk or Auth0 that handle
73
+ * auth flows outside of the Rebase backend.
74
+ */
75
+ hasBuiltInAuthRoutes: boolean;
76
+ /** Supports email/password login. */
77
+ emailPasswordLogin: boolean;
78
+ /** Supports new user registration. */
79
+ registration: boolean;
80
+ /** Supports password reset flow. */
81
+ passwordReset: boolean;
82
+ /** Supports session listing/revocation. */
83
+ sessionManagement: boolean;
84
+ /** Supports profile updates (display name, photo). */
85
+ profileUpdate: boolean;
86
+ /** Supports email verification. */
87
+ emailVerification: boolean;
88
+ /** List of enabled OAuth provider IDs (e.g. `["google", "github"]`). */
89
+ enabledProviders: string[];
90
+ /**
91
+ * For external auth (Clerk, Auth0, etc.): the URL where the user should
92
+ * be redirected for login. The Rebase frontend will navigate here instead
93
+ * of showing its own login form.
94
+ */
95
+ externalLoginUrl?: string;
96
+ /**
97
+ * True when no users exist yet — first-user bootstrap mode.
98
+ * Only applicable for built-in auth.
99
+ */
100
+ needsSetup?: boolean;
101
+ /** Whether new user registration is enabled (may differ from `registration` capability at runtime). */
102
+ registrationEnabled?: boolean;
103
+ }
104
+ /**
105
+ * Options for paginated user listing.
106
+ * @group Auth
107
+ */
108
+ export interface AuthUserListOptions {
109
+ limit?: number;
110
+ offset?: number;
111
+ search?: string;
112
+ orderBy?: string;
113
+ orderDir?: "asc" | "desc";
114
+ roleId?: string;
115
+ }
116
+ /**
117
+ * Paginated user listing result.
118
+ * @group Auth
119
+ */
120
+ export interface AuthUserListResult {
121
+ users: AuthUserData[];
122
+ total: number;
123
+ limit: number;
124
+ offset: number;
125
+ }
126
+ /**
127
+ * User data exposed by the auth adapter.
128
+ * @group Auth
129
+ */
130
+ export interface AuthUserData {
131
+ id: string;
132
+ email: string;
133
+ displayName?: string | null;
134
+ photoUrl?: string | null;
135
+ emailVerified?: boolean;
136
+ createdAt?: Date;
137
+ updatedAt?: Date;
138
+ }
139
+ /**
140
+ * Data for creating a user.
141
+ * @group Auth
142
+ */
143
+ export interface AuthCreateUserData {
144
+ email: string;
145
+ password?: string;
146
+ displayName?: string;
147
+ photoUrl?: string;
148
+ }
149
+ /**
150
+ * Role data exposed by the auth adapter.
151
+ * @group Auth
152
+ */
153
+ export interface AuthRoleData {
154
+ id: string;
155
+ name: string;
156
+ isAdmin: boolean;
157
+ defaultPermissions?: {
158
+ read?: boolean;
159
+ create?: boolean;
160
+ edit?: boolean;
161
+ delete?: boolean;
162
+ } | null;
163
+ collectionPermissions?: Record<string, {
164
+ read?: boolean;
165
+ create?: boolean;
166
+ edit?: boolean;
167
+ delete?: boolean;
168
+ }> | null;
169
+ config?: Record<string, unknown> | null;
170
+ }
171
+ /**
172
+ * Data for creating a role.
173
+ * @group Auth
174
+ */
175
+ export interface AuthCreateRoleData {
176
+ id: string;
177
+ name: string;
178
+ isAdmin?: boolean;
179
+ defaultPermissions?: AuthRoleData["defaultPermissions"];
180
+ collectionPermissions?: AuthRoleData["collectionPermissions"];
181
+ config?: AuthRoleData["config"];
182
+ }
183
+ /**
184
+ * User management operations for the admin panel.
185
+ *
186
+ * Optional — if not provided by the adapter, the user management UI is hidden.
187
+ *
188
+ * @group Auth
189
+ */
190
+ export interface UserManagementAdapter {
191
+ listUsers(options?: AuthUserListOptions): Promise<AuthUserListResult>;
192
+ getUserById(id: string): Promise<AuthUserData | null>;
193
+ createUser(data: AuthCreateUserData): Promise<AuthUserData>;
194
+ updateUser(id: string, data: Partial<AuthCreateUserData>): Promise<AuthUserData | null>;
195
+ deleteUser(id: string): Promise<void>;
196
+ getUserRoles(userId: string): Promise<AuthRoleData[]>;
197
+ setUserRoles(userId: string, roleIds: string[]): Promise<void>;
198
+ }
199
+ /**
200
+ * Role management operations for the admin panel.
201
+ *
202
+ * Optional — if not provided by the adapter, role management is disabled.
203
+ *
204
+ * @group Auth
205
+ */
206
+ export interface RoleManagementAdapter {
207
+ listRoles(): Promise<AuthRoleData[]>;
208
+ getRoleById(id: string): Promise<AuthRoleData | null>;
209
+ createRole(data: AuthCreateRoleData): Promise<AuthRoleData>;
210
+ updateRole(id: string, data: Partial<AuthRoleData>): Promise<AuthRoleData | null>;
211
+ deleteRole(id: string): Promise<void>;
212
+ }
213
+ /**
214
+ * Pluggable authentication adapter for Rebase.
215
+ *
216
+ * This is the **key interface** that decouples authentication from the
217
+ * database layer. Each auth adapter knows how to:
218
+ *
219
+ * 1. Verify incoming HTTP requests (`verifyRequest`)
220
+ * 2. Optionally manage users and roles (for the admin panel)
221
+ * 3. Optionally mount auth-specific routes (login, register, etc.)
222
+ * 4. Advertise its capabilities so the frontend can adapt
223
+ *
224
+ * The built-in Rebase auth implements this interface internally.
225
+ * External providers (Clerk, Auth0, Firebase Auth) provide their own adapters.
226
+ * Users with custom auth can use `createCustomAuthAdapter()` for a minimal setup.
227
+ *
228
+ * @group Auth
229
+ */
230
+ export interface AuthAdapter {
231
+ /**
232
+ * Unique identifier for this auth adapter.
233
+ *
234
+ * @example "rebase-builtin", "clerk", "auth0", "firebase", "custom"
235
+ */
236
+ readonly id: string;
237
+ /**
238
+ * Verify an incoming request and extract the authenticated user.
239
+ *
240
+ * This replaces the hardcoded JWT verification in server-core's middleware.
241
+ * Each adapter implements its own token verification strategy:
242
+ * - Built-in: verify Rebase JWT
243
+ * - Clerk: call Clerk's `verifyToken()`
244
+ * - Auth0: validate Auth0 JWT with JWKS
245
+ * - Custom: whatever logic the user provides
246
+ *
247
+ * @param request - The raw `Request` object (portable across Hono, Express, Fastify)
248
+ * @returns The authenticated user, or `null` for unauthenticated requests.
249
+ * Throw an error to reject the request with 401.
250
+ */
251
+ verifyRequest(request: Request): Promise<AuthenticatedUser | null>;
252
+ /**
253
+ * Verify a raw bearer token and extract the authenticated user.
254
+ *
255
+ * Used for **WebSocket authentication**, where there is no HTTP `Request`
256
+ * object — only a token string sent over the socket.
257
+ *
258
+ * If not implemented, the default behavior synthesizes a minimal `Request`
259
+ * with an `Authorization: Bearer <token>` header and delegates to
260
+ * `verifyRequest()`. Adapters should override this if their token
261
+ * verification logic doesn't depend on request headers/cookies.
262
+ *
263
+ * @param token - The raw bearer token string.
264
+ * @returns The authenticated user, or `null` if the token is invalid.
265
+ */
266
+ verifyToken?(token: string): Promise<AuthenticatedUser | null>;
267
+ /**
268
+ * User CRUD for the admin panel's user management UI.
269
+ * Optional — if not provided, user management UI is hidden.
270
+ */
271
+ userManagement?: UserManagementAdapter;
272
+ /**
273
+ * Role CRUD for the admin panel.
274
+ * Optional — if not provided, role management is disabled.
275
+ */
276
+ roleManagement?: RoleManagementAdapter;
277
+ /**
278
+ * Mount adapter-specific auth routes (login, register, refresh, etc.).
279
+ *
280
+ * - Built-in adapter: mounts `/auth/login`, `/auth/register`, etc.
281
+ * - External adapter: typically returns `undefined` (auth is handled externally).
282
+ * - Custom adapter: user mounts their own routes.
283
+ *
284
+ * The return type uses `Hono<any, any, any>` because this sub-app will be
285
+ * mounted into a parent app via `.route()`, which accepts any Hono env type.
286
+ * Adapter implementations are free to use their own env (e.g. `Hono<HonoEnv>`).
287
+ *
288
+ * @returns A Hono sub-app with auth routes, or `undefined` to skip route mounting.
289
+ */
290
+ createAuthRoutes?(): Hono<any, any, any> | undefined;
291
+ /**
292
+ * Mount admin routes for user/role management.
293
+ *
294
+ * Same typing rationale as `createAuthRoutes` — the sub-app env is
295
+ * unconstrained to support arbitrary adapter implementations.
296
+ *
297
+ * @returns A Hono sub-app with admin routes, or `undefined` to skip.
298
+ */
299
+ createAdminRoutes?(): Hono<any, any, any> | undefined;
300
+ /**
301
+ * Advertise what this auth adapter supports.
302
+ *
303
+ * The frontend reads this from `GET /api/auth/config` to dynamically
304
+ * show/hide UI elements. This is the bridge between backend capabilities
305
+ * and the frontend's `AuthCapabilities` type.
306
+ */
307
+ getCapabilities(): AuthAdapterCapabilities | Promise<AuthAdapterCapabilities>;
308
+ /**
309
+ * Called during backend initialization.
310
+ * Use for running migrations, creating tables, seeding initial data, etc.
311
+ */
312
+ initialize?(): Promise<void>;
313
+ /**
314
+ * Called during graceful shutdown.
315
+ * Use for closing connections, flushing caches, etc.
316
+ */
317
+ destroy?(): Promise<void>;
318
+ /**
319
+ * A static secret key for server-to-server / script authentication.
320
+ *
321
+ * When set, requests with `Authorization: Bearer <serviceKey>` bypass
322
+ * normal token verification and are granted admin-level access.
323
+ */
324
+ serviceKey?: string;
325
+ }
326
+ /**
327
+ * Options for creating a minimal custom auth adapter via `createCustomAuthAdapter()`.
328
+ *
329
+ * This is the simplest way to plug an existing auth system into Rebase.
330
+ * Only `verifyRequest` is required — everything else is optional.
331
+ *
332
+ * @group Auth
333
+ */
334
+ export interface CustomAuthAdapterOptions {
335
+ /**
336
+ * Verify an incoming request and return the authenticated user.
337
+ * This is the only required method.
338
+ */
339
+ verifyRequest: (request: Request) => Promise<AuthenticatedUser | null>;
340
+ /**
341
+ * Verify a raw bearer token for WebSocket authentication.
342
+ * Optional — if omitted, a synthetic `Request` is constructed and passed
343
+ * to `verifyRequest`.
344
+ */
345
+ verifyToken?: (token: string) => Promise<AuthenticatedUser | null>;
346
+ /** Optional user management for the admin panel. */
347
+ userManagement?: UserManagementAdapter;
348
+ /** Optional role management for the admin panel. */
349
+ roleManagement?: RoleManagementAdapter;
350
+ /** Static service key for server-to-server auth. */
351
+ serviceKey?: string;
352
+ /** Override default capabilities. */
353
+ capabilities?: Partial<AuthAdapterCapabilities>;
354
+ }