@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.
- package/dist/controllers/client.d.ts +16 -0
- package/dist/controllers/navigation.d.ts +14 -14
- package/dist/controllers/registry.d.ts +8 -2
- package/dist/index.es.js +8 -1
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +8 -0
- package/dist/index.umd.js.map +1 -1
- package/dist/types/api_keys.d.ts +57 -0
- package/dist/types/auth_adapter.d.ts +62 -0
- package/dist/types/backend.d.ts +1 -0
- package/dist/types/collections.d.ts +51 -17
- package/dist/types/data_source.d.ts +76 -0
- package/dist/types/entity_actions.d.ts +2 -2
- package/dist/types/entity_views.d.ts +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/plugins.d.ts +1 -1
- package/dist/types/properties.d.ts +7 -0
- package/dist/types/translations.d.ts +8 -0
- package/package.json +1 -1
- package/src/controllers/client.ts +8 -0
- package/src/controllers/navigation.ts +17 -16
- package/src/controllers/registry.ts +10 -2
- package/src/types/api_keys.ts +52 -0
- package/src/types/auth_adapter.ts +76 -0
- package/src/types/backend.ts +1 -1
- package/src/types/collections.ts +54 -17
- package/src/types/data_source.ts +84 -0
- package/src/types/entity_actions.tsx +2 -2
- package/src/types/entity_views.tsx +1 -1
- package/src/types/index.ts +2 -0
- package/src/types/plugins.tsx +1 -1
- package/src/types/properties.ts +9 -1
- package/src/types/translations.ts +8 -0
|
@@ -3,6 +3,7 @@ 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";
|
|
6
7
|
/**
|
|
7
8
|
* Event type for authentication state changes
|
|
8
9
|
*/
|
|
@@ -102,6 +103,19 @@ export interface AdminAPI {
|
|
|
102
103
|
deleteUser(userId: string): Promise<{
|
|
103
104
|
success: boolean;
|
|
104
105
|
}>;
|
|
106
|
+
resetPassword(userId: string, options?: {
|
|
107
|
+
password?: string;
|
|
108
|
+
}): Promise<{
|
|
109
|
+
user: AdminUser;
|
|
110
|
+
temporaryPassword?: string;
|
|
111
|
+
invitationSent?: boolean;
|
|
112
|
+
}>;
|
|
113
|
+
listRoles(): Promise<{
|
|
114
|
+
roles: Array<{
|
|
115
|
+
id: string;
|
|
116
|
+
name: string;
|
|
117
|
+
}>;
|
|
118
|
+
}>;
|
|
105
119
|
bootstrap(): Promise<{
|
|
106
120
|
success: boolean;
|
|
107
121
|
message: string;
|
|
@@ -190,6 +204,8 @@ export interface RebaseClient<DB = unknown> {
|
|
|
190
204
|
cron?: CronAPI;
|
|
191
205
|
/** Custom backend functions API */
|
|
192
206
|
functions?: FunctionsAPI;
|
|
207
|
+
/** Service API keys management API */
|
|
208
|
+
apiKeys?: ApiKeysAPI;
|
|
193
209
|
/** Base HTTP URL of the backend server */
|
|
194
210
|
baseUrl?: string;
|
|
195
211
|
/** WebSocket client for realtime subscriptions */
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import type { EntityCollection } from "../types/collections";
|
|
3
|
-
import type { RebasePlugin } from "../types/plugins";
|
|
4
3
|
/**
|
|
5
4
|
* Controller that handles URL path building and resolution.
|
|
6
5
|
* @group Models
|
|
@@ -89,15 +88,11 @@ export type NavigationStateController = {
|
|
|
89
88
|
/**
|
|
90
89
|
* Was there an error while loading the navigation data
|
|
91
90
|
*/
|
|
92
|
-
navigationLoadingError?:
|
|
91
|
+
navigationLoadingError?: Error;
|
|
93
92
|
/**
|
|
94
93
|
* Call this method to recalculate the navigation
|
|
95
94
|
*/
|
|
96
95
|
refreshNavigation: () => void;
|
|
97
|
-
/**
|
|
98
|
-
* Plugin system allowing to extend the CMS functionality.
|
|
99
|
-
*/
|
|
100
|
-
plugins?: RebasePlugin[];
|
|
101
96
|
};
|
|
102
97
|
export interface NavigateOptions {
|
|
103
98
|
replace?: boolean;
|
|
@@ -107,12 +102,6 @@ export interface NavigateOptions {
|
|
|
107
102
|
flushSync?: boolean;
|
|
108
103
|
viewTransition?: boolean;
|
|
109
104
|
}
|
|
110
|
-
export type NavigationBlocker = {
|
|
111
|
-
updateBlockListener: (path: string, block: boolean, basePath?: string) => () => void;
|
|
112
|
-
isBlocked: (path: string) => boolean;
|
|
113
|
-
proceed?: () => void;
|
|
114
|
-
reset?: () => void;
|
|
115
|
-
};
|
|
116
105
|
/**
|
|
117
106
|
* Custom additional views created by the developer, added to the main
|
|
118
107
|
* navigation.
|
|
@@ -153,14 +142,25 @@ export interface AppView {
|
|
|
153
142
|
group?: string;
|
|
154
143
|
/**
|
|
155
144
|
* Component to be rendered. This can be any React component, and can use
|
|
156
|
-
* any of the provided hooks
|
|
145
|
+
* any of the provided hooks.
|
|
146
|
+
*
|
|
147
|
+
* Pass a `ComponentType` to enable lazy rendering — the component will
|
|
148
|
+
* only be instantiated when the route is visited. This is recommended
|
|
149
|
+
* for dynamic views generated from database data.
|
|
157
150
|
*/
|
|
158
|
-
view: React.ReactNode;
|
|
151
|
+
view: React.ReactNode | React.ComponentType;
|
|
159
152
|
/**
|
|
160
153
|
* If true, a wildcard route (slug/*) is automatically registered
|
|
161
154
|
* alongside the base route, enabling nested navigation within this view.
|
|
162
155
|
*/
|
|
163
156
|
nestedRoutes?: boolean;
|
|
157
|
+
/**
|
|
158
|
+
* Restrict this view to users with at least one of the listed roles.
|
|
159
|
+
* When omitted or empty, the view is visible to all authenticated users.
|
|
160
|
+
* Applied during view resolution — the view is filtered out entirely
|
|
161
|
+
* (not just hidden from nav) if the user lacks a matching role.
|
|
162
|
+
*/
|
|
163
|
+
roles?: string[];
|
|
164
164
|
}
|
|
165
165
|
/**
|
|
166
166
|
* A composable section that can be rendered on the home page.
|
|
@@ -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";
|
|
@@ -22,6 +22,12 @@ export interface CollectionEditorOptions {
|
|
|
22
22
|
}
|
|
23
23
|
export interface RebaseCMSConfig<EC extends EntityCollection = EntityCollection> {
|
|
24
24
|
collections?: EC[] | EntityCollectionsBuilder<EC>;
|
|
25
|
+
/**
|
|
26
|
+
* Custom top-level views added to the main navigation.
|
|
27
|
+
* Accepts a static array of views or an async builder function
|
|
28
|
+
* that receives the current user/auth context for role-based views.
|
|
29
|
+
*/
|
|
30
|
+
views?: AppView[] | AppViewsBuilder;
|
|
25
31
|
homePage?: ReactNode;
|
|
26
32
|
entityViews?: EntityCustomView[];
|
|
27
33
|
entityActions?: EntityAction[];
|
|
@@ -43,7 +49,7 @@ export interface RebaseCMSConfig<EC extends EntityCollection = EntityCollection>
|
|
|
43
49
|
collectionEditor?: boolean | CollectionEditorOptions;
|
|
44
50
|
}
|
|
45
51
|
export interface RebaseStudioConfig {
|
|
46
|
-
tools?: ("sql" | "js" | "rls" | "schema" | "storage" | "cron" | "schema-visualizer" | "branches" | "api" | "logs")[];
|
|
52
|
+
tools?: ("sql" | "js" | "rls" | "schema" | "storage" | "cron" | "schema-visualizer" | "branches" | "api" | "logs" | "api-keys")[];
|
|
47
53
|
homePage?: ReactNode;
|
|
48
54
|
devViews?: AppView[];
|
|
49
55
|
}
|
package/dist/index.es.js
CHANGED
|
@@ -177,6 +177,13 @@ function isBranchAdmin(admin) {
|
|
|
177
177
|
}
|
|
178
178
|
//#endregion
|
|
179
179
|
//#region src/types/data_source.ts
|
|
180
|
+
/**
|
|
181
|
+
* The default data-source key, used when a collection does not name a
|
|
182
|
+
* `dataSource`. Shared by the frontend router and the backend driver
|
|
183
|
+
* registry so both agree on "the default database".
|
|
184
|
+
* @group Models
|
|
185
|
+
*/
|
|
186
|
+
var DEFAULT_DATA_SOURCE_KEY = "(default)";
|
|
180
187
|
/** @group Models */
|
|
181
188
|
var POSTGRES_CAPABILITIES = {
|
|
182
189
|
key: "postgres",
|
|
@@ -269,6 +276,6 @@ function isLazyComponentRef(ref) {
|
|
|
269
276
|
return typeof ref === "object" && ref !== null && "__rebaseLazy" in ref && ref.__rebaseLazy === true;
|
|
270
277
|
}
|
|
271
278
|
//#endregion
|
|
272
|
-
export { DEFAULT_CAPABILITIES, EntityReference, EntityRelation, FIREBASE_CAPABILITIES, GeoPoint, MONGODB_CAPABILITIES, POSTGRES_CAPABILITIES, Vector, getDataSourceCapabilities, isBranchAdmin, isDocumentAdmin, isFirebaseCollection, isLazyComponentRef, isMongoDBCollection, isPostgresCollection, isSQLAdmin, isSchemaAdmin, registerDataSourceCapabilities };
|
|
279
|
+
export { DEFAULT_CAPABILITIES, DEFAULT_DATA_SOURCE_KEY, EntityReference, EntityRelation, FIREBASE_CAPABILITIES, GeoPoint, MONGODB_CAPABILITIES, POSTGRES_CAPABILITIES, Vector, getDataSourceCapabilities, isBranchAdmin, isDocumentAdmin, isFirebaseCollection, isLazyComponentRef, isMongoDBCollection, isPostgresCollection, isSQLAdmin, isSchemaAdmin, registerDataSourceCapabilities };
|
|
273
280
|
|
|
274
281
|
//# sourceMappingURL=index.es.js.map
|
package/dist/index.es.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.es.js","names":[],"sources":["../src/types/entities.ts","../src/types/collections.ts","../src/types/backend.ts","../src/types/data_source.ts","../src/types/component_ref.ts"],"sourcesContent":["/**\n * New or existing status\n * @group Models\n */\nexport type EntityStatus = \"new\" | \"existing\" | \"copy\";\n\n/**\n * Representation of an entity fetched from the driver\n * @group Models\n */\nexport interface Entity<M extends Record<string, unknown> = Record<string, unknown>> {\n\n /**\n * ID of the entity\n */\n id: string | number;\n\n /**\n * A string representing the path of the referenced document (relative\n * to the root of the database).\n */\n path: string;\n\n /**\n * Current values\n */\n values: EntityValues<M>;\n\n /**\n * Which driver this entity belongs to (e.g., 'postgres', 'firestore').\n * If not specified, the default driver is assumed.\n */\n driver?: string;\n\n /**\n * Which database within the driver (e.g., for Firestore multi-database).\n * If not specified, the default database of the driver is used.\n */\n databaseId?: string;\n}\n\n/**\n * This type represents a record of key value pairs as described in an\n * entity collection.\n * @group Models\n */\nexport type EntityValues<M extends Record<string, unknown>> = M;\n\n/**\n * Props for creating an EntityReference\n */\nexport interface EntityReferenceProps {\n /** ID of the entity */\n id: string;\n /** Path of the collection (relative to the root of the database) */\n path: string;\n /** Which driver (e.g., 'postgres', 'firestore'). Defaults to \"(default)\" */\n driver?: string;\n /** Which database within the driver. Defaults to \"(default)\" */\n databaseId?: string;\n}\n\n/**\n * Class used to create a reference to an entity in a different path.\n *\n * @example\n * // Simple reference (most common case - single driver, single db)\n * new EntityReference({ id: \"123\", path: \"users\" })\n *\n * // Reference to a different driver (e.g., Firestore)\n * new EntityReference({ id: \"123\", path: \"analytics\", driver: \"firestore\" })\n *\n * // Reference to a specific database within a driver\n * new EntityReference({ id: \"123\", path: \"orders\", driver: \"postgres\", databaseId: \"orders_db\" })\n */\nexport class EntityReference {\n\n readonly __type = \"reference\";\n /**\n * ID of the entity\n */\n readonly id: string;\n /**\n * A string representing the path of the referenced document (relative\n * to the root of the database).\n */\n readonly path: string;\n\n /**\n * Which driver (e.g., 'postgres', 'firestore').\n * Defaults to \"(default)\" if not specified.\n */\n readonly driver?: string;\n\n /**\n * Which database within the driver.\n * Defaults to \"(default)\" if not specified.\n */\n readonly databaseId?: string;\n\n /**\n * Create a reference to an entity.\n *\n * @example\n * // Simple reference (most common case)\n * new EntityReference({ id: \"123\", path: \"users\" })\n *\n * // With driver\n * new EntityReference({ id: \"123\", path: \"analytics\", driver: \"firestore\" })\n */\n constructor(props: EntityReferenceProps) {\n this.id = props.id;\n this.path = props.path;\n this.driver = props.driver;\n this.databaseId = props.databaseId;\n }\n\n get pathWithId() {\n return `${this.path}/${this.id}`;\n }\n\n /**\n * Get the full path including driver and database prefixes if specified.\n * For the common case (single driver, single db), this just returns pathWithId.\n */\n get fullPath() {\n const parts: string[] = [];\n\n // Add driver prefix if not default\n if (this.driver && this.driver !== \"(default)\") {\n parts.push(this.driver);\n }\n\n // Add database prefix if specified\n if (this.databaseId && this.databaseId !== \"(default)\") {\n parts.push(this.databaseId);\n }\n\n if (parts.length > 0) {\n return `${parts.join(\":\")}:::${this.path}/${this.id}`;\n }\n return this.pathWithId;\n }\n\n isEntityReference() {\n return true;\n }\n}\n\n/**\n * Class used to create a reference to an entity in a different path\n */\nexport class EntityRelation {\n\n readonly __type = \"relation\";\n /**\n * ID of the entity\n */\n readonly id: string | number;\n /**\n * A string representing the path of the referenced document (relative\n * to the root of the database).\n */\n readonly path: string;\n\n /**\n * Pre-fetched data payload to eliminate N+1 queries.\n * When present, clients can use this directly instead of fetching.\n */\n readonly data?: Entity;\n\n constructor(id: string | number, path: string, data?: Entity) {\n this.id = id;\n this.path = path;\n this.data = data;\n }\n\n get pathWithId() {\n return `${this.path}/${this.id}`;\n }\n\n isEntityReference() {\n return false;\n }\n\n isEntityRelation() {\n return true;\n }\n}\n\nexport class GeoPoint {\n\n /**\n * The latitude of this GeoPoint instance.\n */\n readonly latitude: number;\n /**\n * The longitude of this GeoPoint instance.\n */\n readonly longitude: number;\n\n constructor(latitude: number, longitude: number) {\n this.latitude = latitude;\n this.longitude = longitude;\n }\n}\n\nexport class Vector {\n readonly value: number[];\n\n constructor(value: number[]) {\n this.value = value;\n }\n}\n","import React, { Dispatch, SetStateAction } from \"react\";\nimport type { Entity, EntityStatus, EntityValues } from \"./entities\";\nimport type { EntityCallbacks } from \"./entity_callbacks\";\n\nimport type { EnumValues, Properties } from \"./properties\";\nimport type { ExportConfig } from \"./export_import\";\nimport type { EntityOverrides } from \"./entity_overrides\";\nimport type { User } from \"../users\";\nimport type { RebaseContext } from \"../rebase_context\";\nimport type { Relation } from \"./relations\";\nimport type { EntityCustomView, FormViewConfig } from \"./entity_views\";\nimport type { EntityAction } from \"./entity_actions\";\nimport type { ComponentRef } from \"./component_ref\";\nimport type { CollectionComponentOverrideMap } from \"./component_overrides\";\n\n/**\n * Base interface containing all driver-agnostic collection properties.\n * Use {@link PostgresCollection} or {@link FirebaseCollection} for\n * driver-specific type safety, or {@link EntityCollection} when you\n * need to handle any collection regardless of backend.\n *\n * @group Models\n */\nexport interface BaseEntityCollection<M extends Record<string, unknown> = Record<string, unknown>, USER extends User = User> {\n\n /**\n * You can set an alias that will be used internally instead of the collection name.\n * The `slug` value will be used to determine the URL of the collection.\n * Note that you can use this value in reference properties too.\n */\n slug: string;\n\n /**\n * Name of the collection, typically plural.\n * E.g. `Products`, `Blog`\n */\n name: string;\n\n /**\n * Singular name of an entry in this collection\n * E.g. `Product`, `Blog entry`\n */\n singularName?: string;\n\n /**\n * Optional description of this view. You can use Markdown.\n */\n description?: string;\n\n /**\n * Child collections nested under entities of this collection.\n * Populated automatically during normalization from driver-specific fields\n * (e.g. Firebase `subcollections`, Postgres `relations` with many-cardinality).\n *\n * Custom drivers can set this directly to expose child collections to the UI.\n */\n childCollections?: () => EntityCollection<Record<string, unknown>>[];\n\n\n /**\n * Which driver handles this collection.\n * Use this to route collections to different backends:\n * - `\"postgres\"` - Route to PostgreSQL backend\n * - `\"firestore\"` - Route to Firestore (client-side)\n * - `\"mongodb\"` - Route to MongoDB backend\n * - Custom IDs for your own driver implementations\n *\n * If not specified, the default driver `\"(default)\"` is used.\n *\n * @example\n * // Simple - no driver needed for default\n * { slug: \"products\" }\n *\n * // Firestore collection (client-side real-time)\n * { slug: \"analytics\", driver: \"firestore\" }\n *\n * // Multiple databases within a driver\n * { slug: \"orders\", driver: \"postgres\", databaseId: \"orders_db\" }\n */\n driver?: string;\n\n /**\n * Which database within the driver.\n * - For Firestore: The Firestore database ID (e.g., for multi-database projects)\n * - For PostgreSQL: Schema or database name\n * - For MongoDB: Database name\n *\n * If not specified, the default database of the driver is used.\n */\n databaseId?: string;\n\n /**\n * Set of properties that compose an entity\n */\n properties: Properties;\n\n /**\n * Icon for the navigation sidebar or cards.\n */\n icon?: string | React.ReactNode;\n\n /**\n * Navigation group for this collection.\n * Collections sharing the same group name will be visually grouped\n * together in the drawer and home page. If not set, the collection\n * falls into the default \"Views\" group.\n */\n group?: string;\n\n /**\n * Array of entity views that this collection has.\n * Can be an array of `EntityCustomView` or a string representing the key of a global `EntityCustomView`.\n */\n entityViews?: (string | EntityCustomView<Record<string, unknown>>)[];\n\n /**\n * Default preview properties displayed when this collection is referenced to.\n */\n previewProperties?: string[];\n\n /**\n * Properties to display as columns in the list view.\n * If not specified, the list view uses a smart default (Title, Status, Date).\n */\n listProperties?: string[];\n\n /**\n * Title property of the entity. This is the property that will be used\n * as the title in entity related views and references.\n * If not specified, the first property simple text property will be used.\n */\n readonly titleProperty?: Extract<keyof M, string> | (string & {});\n\n /**\n * When editing an entity, you can choose to open the entity in a side dialog\n * or in a full screen dialog. Defaults to `full_screen`.\n */\n openEntityMode?: \"side_panel\" | \"full_screen\" | \"split\" | \"dialog\";\n\n /**\n * Controls what happens when a user clicks on an entity in the collection view.\n * - `\"edit\"` (default): Opens the entity in the edit form.\n * - `\"view\"`: Opens a read-only detail view with an \"Edit\" button.\n */\n defaultEntityAction?: \"view\" | \"edit\";\n\n /**\n * Replace the default entity form with a custom component.\n * The Builder receives the same props as entity view tabs\n * (entity, formContext, collection, etc.) and has full control over the UI.\n *\n * Works in both edit mode and read-only mode (when `defaultEntityAction`\n * is `\"view\"`). In read-only mode, `formContext.readOnly` will be `true`.\n */\n formView?: FormViewConfig;\n\n /**\n * Prevent default actions from being displayed or executed on this collection.\n */\n disableDefaultActions?: (\"edit\" | \"copy\" | \"delete\")[];\n\n /**\n * Mark this collection as an authentication collection.\n * When true, this collection is used for user management, login, password hashing, and invitation flows.\n */\n auth?: boolean | AuthCollectionConfig;\n\n\n /**\n * Order in which the properties are displayed.\n * If you are specifying your collection as code, the order is the same as the\n * one you define in `properties`. Additional columns are added at the\n * end of the list, if the order is not specified.\n * You can use this prop to hide some properties from the table view.\n * Note that if you set this prop, other ways to hide fields, like\n * `hidden` in the property definition, will be ignored.\n * `propertiesOrder` has precedence over `hidden`.\n * - For properties use the property key.\n * - For additional fields use the field key.\n * - If you have subcollections, you get a column for each subcollection,\n * with the path (or alias) as the subcollection, prefixed with\n * `subcollection:`. e.g. `subcollection:orders`.\n * You can use this prop to hide some properties from the table view.\n * Note that if you set this prop, other ways to hide fields, like\n * `hidden` in the property definition,will be ignored.\n * `propertiesOrder` has precedence over `hidden`.\n */\n propertiesOrder?: (Extract<keyof M, string> | (string & {}) | string | `subcollection:${string}`)[];\n\n /**\n * If enabled, content is loaded in batches. If `false` all entities in the\n * collection are loaded. This means that when reaching the end of the\n * collection, the CMS will load more entities.\n * You can specify a number to specify the pagination size (50 by default)\n * Defaults to `true`\n */\n pagination?: boolean | number;\n\n\n selectionEnabled?: boolean;\n\n /**\n * This interface defines all the callbacks that can be used when an entity\n * is being created, updated or deleted.\n * Useful for adding your own logic or blocking the execution of the operation.\n */\n readonly callbacks?: EntityCallbacks<M, USER>;\n\n /**\n * Pass your own selection controller if you want to control selected\n * entities externally.\n * @see useSelectionController\n */\n selectionController?: SelectionController<M>;\n\n /**\n * Force a filter in this view. If applied, the rest of the filters will\n * be disabled. Filters applied with this prop cannot be changed.\n * e.g. `fixedFilter: { age: [\">\", 18] }`\n * e.g. `fixedFilter: { related_user: [\"==\", new EntityReference(\"sdc43dsw2\", \"users\")] }`\n */\n readonly fixedFilter?: FilterValues<Extract<keyof M, string> | (string & {})>;\n\n /**\n * Initial filters applied to the collection this collection is related to.\n * Defaults to none. Filters applied with this prop can be changed.\n * e.g. `defaultFilter: { age: [\">\", 18] }`\n * e.g. `defaultFilter: { related_user: [\"==\", new EntityReference(\"sdc43dsw2\", \"users\")] }`\n */\n readonly defaultFilter?: FilterValues<Extract<keyof M, string> | (string & {})>; // setting FilterValues<M> can break defining collections by code\n\n /**\n * Pre-defined filter presets that appear as quick-access options in the\n * collection toolbar. Each preset applies a set of filters (and\n * optionally a sort order) with a single click.\n *\n * ```ts\n * filterPresets: [\n * {\n * label: \"Shipped this month\",\n * filterValues: {\n * status: [\"==\", \"shipped\"],\n * order_date: [\">=\", new Date(Date.now() - 30 * 86400000)]\n * }\n * }\n * ]\n * ```\n */\n readonly filterPresets?: FilterPreset<Extract<keyof M, string> | (string & {})>[];\n\n /**\n * Default sort applied to this collection.\n * When setting this prop, entities will have a default order\n * applied in the collection.\n * e.g. `sort: [\"order\", \"asc\"]`\n */\n readonly sort?: [Extract<keyof M, string> | (string & {}), \"asc\" | \"desc\"];\n\n /**\n * You can add additional fields to the collection view by implementing\n * an additional field delegate.\n */\n readonly additionalFields?: AdditionalFieldDelegate<M, USER>[];\n\n /**\n * Default size of the rendered collection\n */\n defaultSize?: CollectionSize;\n\n /**\n * Can the elements in this collection be edited inline in the collection\n * view. If this flag is set to false but `permissions.edit` is `true`, entities\n * can still be edited in the side panel\n */\n inlineEditing?: boolean;\n\n /**\n * Should this collection be hidden from the main navigation panel, if\n * it is at the root level, or in the entity side panel if it's a\n * subcollection.\n * It will still be accessible if you reach the specified path.\n * You can also use this collection as a reference target.\n */\n hideFromNavigation?: boolean;\n\n /**\n * If you want to open custom views or subcollections by default when opening the edit\n * view of an entity, you can specify the path to the view here.\n * The path is relative to the current collection. For example if you have a collection\n * that has a custom view as well as a subcollection that refers to another entity, you can\n * either specify the path to the custom view or the path to the subcollection.\n */\n defaultSelectedView?: string | DefaultSelectedViewBuilder;\n\n /**\n * Should the ID of this collection be hidden from the form view.\n */\n hideIdFromForm?: boolean;\n\n /**\n * Should the ID of this collection be hidden from the grid view.\n */\n hideIdFromCollection?: boolean;\n\n /**\n * If set to true, the form will be auto-saved when the user changes\n * the value of a field.\n * Defaults to false.\n * When a new entity is created, this property can be updated to generated a new ID\n */\n formAutoSave?: boolean;\n\n /**\n *\n */\n exportable?: boolean | ExportConfig<USER>;\n\n /**\n * User id of the owner of this collection. This is used only by plugins, or if you\n * are writing custom code\n */\n ownerId?: string;\n\n /**\n * Overrides for the entity view, like the data source or the storage source.\n */\n overrides?: EntityOverrides;\n\n /**\n * Width of the side dialog (in pixels) when opening an entity in this collection.\n */\n sideDialogWidth?: number | string;\n\n /**\n * If set to true, the default values of the properties will be applied\n * to the entity every time the entity is updated (not only when created).\n * Defaults to false.\n */\n alwaysApplyDefaultValues?: boolean;\n\n /**\n * If set to true, a tab including the JSON representation of the entity will be included.\n */\n includeJsonView?: boolean;\n\n /**\n * If set to true, changes to the entity will be saved in a subcollection.\n * This prop has no effect if the history plugin is not enabled\n */\n history?: boolean;\n\n /**\n * Should local changes be backed up in local storage, to prevent data loss on\n * accidental navigations.\n * - `manual_apply`: When the user navigates back to an entity with local changes,\n * they will be prompted to restore the changes.\n * - `auto_apply`: When the user navigates back to an entity with local changes,\n * the changes will be automatically applied.\n * - `false`: Local changes will not be backed up.\n * Defaults to `manual_apply`.\n */\n localChangesBackup?: \"manual_apply\" | \"auto_apply\" | false;\n\n /**\n * Default view mode for displaying this collection.\n * - \"table\": Display entities in a table with inline editing (default)\n * - \"cards\": Display entities as a grid of cards with thumbnails\n * - \"kanban\": Display entities in a Kanban board grouped by a property\n * Defaults to \"table\".\n */\n defaultViewMode?: ViewMode;\n\n /**\n * Which view modes are available for this collection.\n * Possible values: \"table\", \"cards\", \"kanban\".\n * Defaults to all three: [\"table\", \"cards\", \"kanban\"].\n * Note: \"kanban\" will only be available if the collection has at least\n * one string property with enumValues defined, regardless of this setting.\n */\n enabledViews?: ViewMode[];\n\n /**\n * Configuration for Kanban board view mode.\n * When set, the Kanban view mode becomes available.\n */\n kanban?: KanbanConfig<M>;\n\n /**\n * Property key to use for ordering items.\n * Must reference a string/text property. When items are reordered,\n * this property will be updated with lexicographic sort keys\n * (e.g. \"a0\", \"a1\", \"a0V\") using string-based fractional indexing.\n * Used by Kanban view for ordering within columns\n * and can be used for general ordering purposes.\n */\n readonly orderProperty?: Extract<keyof M, string> | (string & {});\n\n /**\n * Actions that can be performed on the entities in this collection.\n */\n entityActions?: EntityAction<M, USER>[];\n\n /**\n * Builder for the collection actions rendered in the toolbar\n */\n Actions?: ComponentRef<CollectionActionsProps>[];\n\n /**\n * The database table name for this collection.\n * Automatically set for PostgreSQL collections.\n * For non-SQL backends, this may be undefined.\n */\n table?: string;\n\n /**\n * Relations defined for this collection.\n * Populated at normalization time from inline relation properties\n * or explicit relation definitions.\n */\n relations?: Relation[];\n\n /**\n * Security rules for this collection (Row Level Security).\n * When defined, the backend enforces access control policies.\n */\n securityRules?: SecurityRule[];\n\n /**\n * Collection-scoped component overrides. These take precedence over\n * global overrides set on `<Rebase>`, but only within this collection's\n * views (entity form, detail view, table, empty state, etc.).\n *\n * Only collection-scoped components (like `Entity.Form`, `Collection.EmptyState`,\n * `Collection.Card`, etc.) can be overridden here. App-level components\n * (like `Shell.AppBar`, `HomePage`) can only be overridden at the `<Rebase>` level.\n *\n * @example\n * ```tsx\n * const productsCollection: PostgresCollection = {\n * name: \"Products\",\n * slug: \"products\",\n * table: \"products\",\n * components: {\n * \"Entity.Form\": { Component: ProductCustomForm },\n * \"Collection.Card\": { Component: ProductCard },\n * },\n * properties: { ... }\n * };\n * ```\n */\n components?: CollectionComponentOverrideMap;\n}\n\n// ── Driver-specific collection types ──────────────────────────────────\n\n/**\n * A collection backed by PostgreSQL (or any SQL database).\n * Adds support for SQL-style relations (JOINs) and Row Level Security.\n *\n * Use this type instead of {@link EntityCollection} when you want\n * compile-time safety that only SQL-relevant fields appear.\n *\n * @group Models\n */\nexport interface PostgresCollection<M extends Record<string, unknown> = Record<string, unknown>, USER extends User = User>\n extends BaseEntityCollection<M, USER> {\n properties: Properties;\n\n /**\n * The driver for this collection. For Postgres collections this\n * can be omitted (Postgres is the default) or set to `\"postgres\"`.\n */\n driver?: \"postgres\" | undefined;\n\n /**\n * The PostgreSQL table name for this collection.\n */\n table: string;\n\n /**\n * The PostgreSQL schema name for this table.\n * E.g. \"public\", \"rebase\", \"auth\".\n * If not specified, \"public\" is used (or the default search path).\n */\n schema?: string;\n\n /**\n * For SQL databases, you can define the relations between collections here.\n * Relations describe JOINs, foreign keys, and junction tables.\n */\n relations?: Relation[];\n\n /**\n * Security rules for this collection (Supabase-style Row Level Security).\n * When defined, the schema generator will enable RLS on the table and\n * create the corresponding PostgreSQL policies.\n *\n * Supports three levels of expressiveness:\n * 1. **Convenience shortcuts** — `ownerField`, `access`, `roles`\n * 2. **Raw SQL** — `using` and `withCheck` for full PostgreSQL power\n * 3. **Combined** — mix shortcuts with `roles` for common patterns\n *\n * The authenticated user context is available in raw SQL via:\n * - `auth.uid()` — the current user's ID\n * - `auth.roles()` — comma-separated app role IDs\n * - `auth.jwt()` — full JWT claims as JSONB\n */\n securityRules?: SecurityRule[];\n}\n\n/**\n * A collection backed by Firebase / Firestore.\n * Adds support for subcollections (nested document collections).\n *\n * Use this type instead of {@link EntityCollection} when you want\n * compile-time safety that only Firestore-relevant fields appear.\n *\n * @group Models\n */\nexport interface FirebaseCollection<M extends Record<string, unknown> = Record<string, unknown>, USER extends User = User>\n extends BaseEntityCollection<M, USER> {\n /**\n * The driver for this collection. Must be set to `\"firestore\"`.\n */\n driver: \"firestore\";\n\n /**\n * You can add subcollections to your entity in the same way you define the root\n * collections. The collections added here will be displayed when opening\n * the side dialog of an entity.\n */\n subcollections?: () => EntityCollection<Record<string, unknown>>[];\n}\n\n/**\n * A collection backed by MongoDB.\n *\n * Use this type instead of {@link EntityCollection} when you want\n * compile-time safety that only MongoDB-relevant fields appear.\n *\n * @group Models\n */\nexport interface MongoDBCollection<M extends Record<string, unknown> = Record<string, unknown>, USER extends User = User>\n extends BaseEntityCollection<M, USER> {\n\n /**\n * The driver for this collection. Must be set to `\"mongodb\"`.\n */\n driver: \"mongodb\";\n}\n\n/**\n * A collection backed by any data source.\n * This is a discriminated union — use {@link PostgresCollection},\n * {@link FirebaseCollection}, or {@link MongoDBCollection} for\n * driver-specific type safety.\n *\n * @group Models\n */\nexport type EntityCollection<M extends Record<string, unknown> = Record<string, unknown>, USER extends User = User> =\n | PostgresCollection<M, USER>\n | FirebaseCollection<M, USER>\n | MongoDBCollection<M, USER>;\n\n// ── Capability intersection types ─────────────────────────────────────\n// Use these after a `getDataSourceCapabilities()` guard to safely access\n// driver-specific fields without coupling to a concrete driver type.\n\n/**\n * An EntityCollection that supports SQL-style relations (e.g. Postgres).\n * @deprecated Use `EntityCollection` directly — `table`, `relations`, and `securityRules` are now on `BaseEntityCollection`.\n */\nexport type CollectionWithRelations<M extends Record<string, unknown> = Record<string, unknown>> =\n EntityCollection<M> & { table?: string; relations?: Relation[]; securityRules?: SecurityRule[] };\n\n/** An EntityCollection that supports subcollections (e.g. Firestore). */\nexport type CollectionWithSubcollections<M extends Record<string, unknown> = Record<string, unknown>> =\n EntityCollection<M> & { subcollections?: () => EntityCollection<Record<string, unknown>>[] };\n\n\n// ── Type guards ───────────────────────────────────────────────────────\n\n/**\n * Type guard for PostgreSQL collections.\n * Returns true if the collection uses the Postgres driver (or the default driver).\n * @group Models\n */\nexport function isPostgresCollection<M extends Record<string, unknown> = Record<string, unknown>, USER extends User = User>(\n collection: EntityCollection<M, USER>\n): collection is PostgresCollection<M, USER> {\n return !collection.driver || collection.driver === \"postgres\";\n}\n\n/**\n * Type guard for Firebase / Firestore collections.\n * @group Models\n */\nexport function isFirebaseCollection<M extends Record<string, unknown> = Record<string, unknown>, USER extends User = User>(\n collection: EntityCollection<M, USER>\n): collection is FirebaseCollection<M, USER> {\n return collection.driver === \"firestore\";\n}\n\n/**\n * Type guard for MongoDB collections.\n * @group Models\n */\nexport function isMongoDBCollection<M extends Record<string, unknown> = Record<string, unknown>, USER extends User = User>(\n collection: EntityCollection<M, USER>\n): collection is MongoDBCollection<M, USER> {\n return collection.driver === \"mongodb\";\n}\n\n\n/**\n * Configuration for Kanban board view mode.\n * @group Collections\n */\nexport interface KanbanConfig<M extends Record<string, unknown> = Record<string, unknown>> {\n /**\n * Property key to use for Kanban board columns.\n * Must reference a string property with enumValues defined.\n * Entities will be grouped into columns based on this property's value.\n * The column order is determined by the order of enumValues in the property.\n */\n columnProperty: Extract<keyof M, string> | (string & {});\n}\n\n/**\n * View mode for displaying a collection.\n * - \"list\": Simple, clean list view — the classic CMS default\n * - \"table\": Table with inline editing\n * - \"cards\": Grid of visual cards with thumbnails\n * - \"kanban\": Board view grouped by a property\n * @group Collections\n */\nexport type ViewMode = \"list\" | \"table\" | \"cards\" | \"kanban\";\n\n/**\n * Parameter passed to the `Actions` prop in the collection configuration.\n * The component will receive this prop when it is rendered in the collection\n * toolbar.\n *\n * @group Models\n */\nexport interface CollectionActionsProps<M extends Record<string, unknown> = Record<string, unknown>, USER extends User = User, EC extends EntityCollection<M> = EntityCollection<M>> {\n /**\n * Full collection path of this entity. This is the full path, like\n * `users/1234/addresses`\n */\n path: string;\n\n /**\n * Path of the last collection, like `addresses`\n */\n relativePath: string;\n\n /**\n * Array of the parent path segments like `['users']`\n */\n parentCollectionSlugs: string[];\n parentEntityIds: string[];\n\n /**\n * The collection configuration\n */\n collection: EC;\n\n /**\n * Use this controller to get the selected entities and to update the\n * selected entities state.\n */\n selectionController: SelectionController<M>;\n\n /**\n * Use this controller to get the table controller and to update the\n * table controller state.\n */\n tableController: EntityTableController<M>;\n\n /**\n * Context of the app status\n */\n context: RebaseContext<USER>;\n\n /**\n * Count of the entities in this collection.\n * undefined means the count is still loading.\n */\n collectionEntitiesCount?: number;\n\n /**\n * Programmatically open the new-document form for this collection,\n * optionally pre-populating it with initial field values.\n * The form opens in the same mode configured for the collection\n * (side panel, full screen, or split).\n *\n * This is the primary hook for workflows that need to create a document\n * from external data — e.g. fetching content from a URL, importing from\n * a third-party API, or duplicating from another system.\n *\n * @example\n * // Inside a custom CollectionAction component:\n * openNewDocument({ title: \"Fetched title\", body: \"...\" });\n */\n openNewDocument: (defaultValues?: Record<string, unknown>) => void;\n\n}\n\n/**\n * Use this controller to retrieve the selected entities or modify them in\n * an {@link EntityCollection}\n * @group Models\n */\nexport interface SelectionController<M extends Record<string, unknown> = Record<string, unknown>> {\n selectedEntities: Entity<M>[];\n setSelectedEntities(entities: Entity<M>[]): void;\n setSelectedEntities(action: (prev: Entity<M>[]) => Entity<M>[]): void;\n isEntitySelected(entity: Entity<M>): boolean;\n toggleEntitySelection(entity: Entity<M>, newSelectedState?: boolean): void;\n}\n\n/**\n * Filter conditions in a `Query.where()` clause are specified using the\n * strings `<`, `<=`, `==`, `>=`, `>`, `array-contains`, `in`, and `array-contains-any`.\n * @group Models\n */\nexport type WhereFilterOp =\n | \"<\"\n | \"<=\"\n | \"==\"\n | \"!=\"\n | \">=\"\n | \">\"\n | \"array-contains\"\n | \"in\"\n | \"not-in\"\n | \"array-contains-any\";\n\n/**\n * Used to define filters applied in collections\n *\n * e.g. `{ age: [\">=\", 18] }`\n *\n * @group Models\n */\nexport type FilterValues<Key extends string> =\n Partial<Record<Key, [WhereFilterOp, unknown] | [WhereFilterOp, unknown][]>>;\n\n/**\n * A pre-defined filter preset for quick access in the collection toolbar.\n * Users can select a preset to instantly apply a set of filters and\n * optionally a sort order.\n *\n * @group Models\n */\nexport interface FilterPreset<Key extends string = string> {\n /**\n * Display label shown in the preset menu.\n * If omitted, a summary is auto-generated from the filter keys.\n */\n label?: string;\n\n /**\n * The filter values to apply when this preset is selected.\n */\n filterValues: FilterValues<Key>;\n\n /**\n * Optional sort override to apply alongside the filter values.\n */\n sort?: [Key, \"asc\" | \"desc\"];\n}\n\n\n/**\n * Used to indicate valid filter combinations (e.g. created in Firestore)\n * If the user selects a specific filter/sort combination, the CMS checks if it's\n * valid, otherwise it reverts to the simpler valid case\n * @group Models\n */\nexport type FilterCombination<Key extends string> = Partial<Record<Key, \"asc\" | \"desc\">>;\n\n/**\n * Sizes in which a collection can be rendered\n * @group Models\n */\nexport type CollectionSize = \"xs\" | \"s\" | \"m\" | \"l\" | \"xl\";\n\nexport type AdditionalFieldDelegateProps<M extends Record<string, unknown> = Record<string, unknown>, USER extends User = User> = {\n entity: Entity<M>,\n context: RebaseContext<USER>\n};\n\n/**\n * Use this interface for adding additional fields to entity collection views and forms.\n * @group Models\n */\nexport interface AdditionalFieldDelegate<M extends Record<string, unknown> = Record<string, unknown>,\n USER extends User = User> {\n\n /**\n * ID of this column. You can use this id in the `properties` field of the\n * collection in any order you want\n */\n key: string;\n\n /**\n * Header of this column\n */\n name: string;\n\n /**\n * Width of the generated column in pixels\n */\n width?: number;\n\n /**\n * Builder for the custom field\n */\n Builder?(props: { entity: Entity<M>, context: RebaseContext<USER> }): React.ReactNode;\n\n\n /**\n * If this column needs to update dynamically based on other properties,\n * you can define an array of keys as strings with the\n * `dependencies` prop.\n * e.g. [\"name\", \"surname\"]\n * This is a performance optimization, if you don't define dependencies\n * it will be updated in every render.\n */\n dependencies?: NoInfer<Extract<keyof M, string>> | NoInfer<Extract<keyof M, string>>[] | (string & {}) | (string & {})[];\n\n /**\n * Use this prop to define the value of the column as a string or number.\n * This is the value that will be used for exporting the collection.\n * If `Builder` is defined, this prop will be ignored in the collection\n * view.\n * @param entity\n */\n value?(props: {\n entity: Entity<M>,\n context: RebaseContext\n }): string | number | Promise<string | number> | undefined;\n}\n\n\nexport type InferCollectionType<S extends EntityCollection> = S extends EntityCollection<infer M> ? M : never;\n\n/**\n * Used in the {@link EntityCollection#defaultSelectedView} to define the default\n * @group Models\n */\nexport type DefaultSelectedViewBuilder = (params: DefaultSelectedViewParams) => string | undefined;\n\n/**\n * Used in the {@link EntityCollection#defaultSelectedView} to define the default\n * @group Models\n */\nexport type DefaultSelectedViewParams = {\n status?: EntityStatus;\n entityId?: string | number;\n};\n/**\n * You can use this controller to control the table view of a collection.\n */\nexport type EntityTableController<M extends Record<string, unknown> = Record<string, unknown>> = {\n data: Entity<M>[];\n dataLoading: boolean;\n noMoreToLoad: boolean;\n dataLoadingError?: Error;\n filterValues?: FilterValues<Extract<keyof M, string> | (string & {})>;\n setFilterValues?: (filterValues: FilterValues<Extract<keyof M, string> | (string & {})>) => void;\n sortBy?: [Extract<keyof M, string> | (string & {}), \"asc\" | \"desc\"];\n setSortBy?: (sortBy?: [Extract<keyof M, string> | (string & {}), \"asc\" | \"desc\"]) => void;\n searchString?: string;\n setSearchString?: (searchString?: string) => void;\n clearFilter?: () => void;\n itemCount?: number;\n setItemCount?: (itemCount: number) => void;\n initialScroll?: number;\n onScroll?: (props: {\n scrollDirection: \"forward\" | \"backward\",\n scrollOffset: number,\n scrollUpdateWasRequested: boolean\n }) => void;\n paginationEnabled?: boolean;\n pageSize?: number;\n checkFilterCombination?: (filterValues: FilterValues<string>,\n sortBy?: [string, \"asc\" | \"desc\"]) => boolean;\n popupCell?: SelectedCellProps<M>;\n setPopupCell?: (popupCell?: SelectedCellProps<M>) => void;\n\n onAddColumn?: (column: string) => void;\n}\n\nexport type SelectedCellProps<M extends Record<string, unknown> = Record<string, unknown>> = {\n propertyKey: Extract<keyof M, string> | (string & {});\n cellRect: DOMRect;\n width: number;\n height: number;\n entityPath: string;\n entityId: string | number;\n};\n\n/**\n * SQL operation that a policy applies to.\n * @group Models\n */\nexport type SecurityOperation = \"select\" | \"insert\" | \"update\" | \"delete\" | \"all\";\n\n/**\n * Flexible Row Level Security rule for a collection.\n *\n * Inspired by Supabase's approach to PostgreSQL RLS. Rules can range from\n * simple convenience shortcuts to fully custom SQL expressions, giving you the\n * full power of PostgreSQL Row Level Security.\n *\n * The authenticated user's identity is available in raw SQL via:\n * - `auth.uid()` — the user's ID\n * - `auth.roles()` — comma-separated app role IDs\n * - `auth.jwt()` — full JWT claims as JSONB\n *\n * These are set automatically per-transaction by the backend.\n *\n * **How rules combine:** PostgreSQL evaluates all matching policies for an\n * operation. Permissive rules are OR'd together (any one passing is enough).\n * Restrictive rules are AND'd (all must pass). This mirrors Supabase behavior.\n *\n * **Mutual exclusivity:** `ownerField`, `access`, and raw SQL (`using`/`withCheck`)\n * cannot be combined. The type system enforces this — attempting to set\n * conflicting fields will produce a compile-time error.\n *\n * @group Models\n */\nexport type SecurityRule = OwnerSecurityRule | PublicSecurityRule | RawSQLSecurityRule | RolesOnlySecurityRule;\n\n/**\n * Shared fields for all SecurityRule variants.\n * @group Models\n */\nexport interface SecurityRuleBase {\n /**\n * Optional human-readable name for the policy.\n * If not provided, one will be auto-generated from the table name and operation.\n * Must be unique per table.\n *\n * When using `operations` (array), each generated policy will have the\n * operation name appended, e.g. `\"owner_access_select\"`, `\"owner_access_update\"`.\n */\n name?: string;\n\n /**\n * Which SQL operation this policy applies to.\n * Use this when the policy targets a single operation or all operations.\n *\n * For multiple specific operations, use `operations` (array) instead.\n * If neither is specified, defaults to `\"all\"`.\n *\n * @default \"all\"\n */\n operation?: SecurityOperation;\n\n /**\n * Array of SQL operations this policy applies to.\n * The compiler will generate one PostgreSQL policy per operation, sharing\n * the same configuration.\n *\n * This reduces boilerplate when the same rule applies to multiple (but not all)\n * operations.\n *\n * Takes precedence over `operation` (singular) if both are specified.\n *\n * @example\n * // Same rule for select and update\n * { operations: [\"select\", \"update\"], ownerField: \"user_id\" }\n *\n * @example\n * // Equivalent to operation: \"all\"\n * { operations: [\"all\"], ownerField: \"user_id\" }\n */\n operations?: SecurityOperation[];\n\n /**\n * Whether this policy is `\"permissive\"` (default) or `\"restrictive\"`.\n *\n * - **permissive**: Multiple permissive policies for the same operation are\n * OR'd together — if *any* passes, access is granted.\n * - **restrictive**: Restrictive policies are AND'd with all permissive\n * policies — they act as additional gates that *must* also pass.\n *\n * This is the same model as PostgreSQL / Supabase.\n *\n * @default \"permissive\"\n */\n mode?: \"permissive\" | \"restrictive\";\n\n /**\n * **Shortcut.** Restrict this rule to users that have one of these\n * application-level roles.\n *\n * **Important:** These are NOT native PostgreSQL database roles. They are\n * application roles managed by Rebase, stored in the `rebase.user_roles`\n * table, and injected into each transaction via `auth.roles()`.\n *\n * Generates a condition like:\n * `auth.roles() ~ '<role1>|<role2>'`\n *\n * Can be combined with `ownerField`, `access`, or raw `using`/`withCheck`.\n * When combined, the role check is AND'd with the other condition.\n *\n * @example\n * // Only admins can delete\n * { operation: \"delete\", roles: [\"admin\"] }\n *\n * @example\n * // Admins have unfiltered read access to all rows\n * { operation: \"select\", roles: [\"admin\"], using: \"true\" }\n */\n roles?: string[];\n\n // ── Advanced: native PostgreSQL role targeting ───────────────────────\n\n /**\n * **Advanced.** Native PostgreSQL database roles the policy applies to.\n *\n * By default, all generated policies target the `public` role (i.e.\n * every database connection). This is correct for most setups where\n * a single database role is used for all connections.\n *\n * **Important:** These are NOT the same as the application-level `roles`\n * (admin, editor, viewer, etc.) — those are enforced in the USING/WITH\n * CHECK clauses via `auth.roles()`. This field controls the PostgreSQL\n * `TO` clause in `CREATE POLICY ... TO role_name`.\n *\n * Use this if you have dedicated PostgreSQL roles (e.g. `app_read`,\n * `app_write`) and want policies to target specific ones.\n *\n * @default [\"public\"]\n *\n * @example\n * // Only apply this policy when connected as `app_role`\n * { operation: \"select\", access: \"public\", pgRoles: [\"app_role\"] }\n */\n pgRoles?: string[];\n}\n\n/**\n * Security rule that grants access based on row ownership.\n * Generates a USING/WITH CHECK clause like: `<column> = auth.uid()`\n *\n * Cannot be combined with `using`, `withCheck`, or `access`.\n *\n * @example\n * { operation: \"all\", ownerField: \"user_id\" }\n *\n * @group Models\n */\nexport interface OwnerSecurityRule extends SecurityRuleBase {\n /** The property (column) that stores the owner's user ID. */\n ownerField: string;\n access?: never;\n using?: never;\n withCheck?: never;\n}\n\n/**\n * Security rule that grants unrestricted row access (no row filtering).\n * Generates `USING (true)`.\n *\n * This means \"no row-level filter\", NOT \"anonymous/unauthenticated access\".\n * Authentication is still enforced at the API layer — this only controls which\n * *rows* authenticated users can see.\n *\n * Cannot be combined with `using`, `withCheck`, or `ownerField`.\n *\n * @example\n * // Public read (any authenticated user sees all rows)\n * { operation: \"select\", access: \"public\" }\n *\n * @group Models\n */\nexport interface PublicSecurityRule extends SecurityRuleBase {\n /** Grant unrestricted row access for this operation. */\n access: \"public\";\n ownerField?: never;\n using?: never;\n withCheck?: never;\n}\n\n/**\n * Security rule using raw SQL expressions for full PostgreSQL RLS power.\n *\n * Cannot be combined with `ownerField` or `access`.\n *\n * You can reference columns via `{column_name}` which will be resolved to\n * `table.column_name` in the generated Drizzle code.\n *\n * @example\n * // Rows published in the last 30 days are visible\n * { operation: \"select\", using: \"{published_at} > now() - interval '30 days'\" }\n *\n * @example\n * // Only the owner, or users with 'moderator' role\n * {\n * operation: \"select\",\n * using: \"{user_id} = auth.uid() OR auth.roles() ~ 'moderator'\"\n * }\n *\n * @group Models\n */\nexport interface RawSQLSecurityRule extends SecurityRuleBase {\n /**\n * Raw SQL expression for the `USING` clause.\n * This controls which *existing* rows are visible / can be modified / deleted.\n * Applied to SELECT, UPDATE, and DELETE.\n */\n using: string;\n\n /**\n * Raw SQL expression for the `WITH CHECK` clause.\n * This controls which *new/updated* row values are allowed.\n * Applied to INSERT and UPDATE.\n *\n * If not provided on INSERT/UPDATE policies, falls back to `using`\n * (which matches PostgreSQL's own default behavior).\n */\n withCheck?: string;\n\n ownerField?: never;\n access?: never;\n}\n\n/**\n * Security rule that only filters by application roles, without any\n * row-level condition (USING/WITH CHECK).\n *\n * Useful for simple \"only admins can access this table\" rules where\n * no per-row filtering is needed.\n *\n * @example\n * // Only admins can delete\n * { operation: \"delete\", roles: [\"admin\"] }\n *\n * @group Models\n */\nexport interface RolesOnlySecurityRule extends SecurityRuleBase {\n ownerField?: never;\n access?: never;\n using?: never;\n withCheck?: never;\n}\n\n/**\n * Configuration for authentication collections.\n *\n * Controls what happens when admins create users, reset passwords,\n * and which entity actions are auto-injected.\n *\n * Use `auth: true` as sugar for `{ enabled: true }` with all defaults.\n *\n * @example Override user creation\n * ```ts\n * auth: {\n * enabled: true,\n * onCreateUser: async (values, ctx) => {\n * const hash = await ctx.hashPassword(\"welcome123\");\n * return {\n * values: { ...values, passwordHash: hash, emailVerified: true },\n * temporaryPassword: \"welcome123\",\n * };\n * },\n * }\n * ```\n *\n * @example Disable the reset-password entity action\n * ```ts\n * auth: {\n * enabled: true,\n * actions: { resetPassword: false },\n * }\n * ```\n *\n * @group Models\n */\nexport interface AuthCollectionConfig {\n /** Set to true to mark this collection as the authentication collection. */\n enabled: boolean;\n\n /**\n * Called when an admin creates a user via the collection REST API.\n *\n * Default: generate password → hash → normalize email → save →\n * send invitation email (or return temp password if no email configured).\n *\n * Override to implement custom invitation flows, LDAP sync, etc.\n */\n onCreateUser?: (\n values: Record<string, unknown>,\n ctx: AuthCollectionContext\n ) => Promise<AuthCollectionCreateResult>;\n\n /**\n * Called when an admin resets a user's password via the admin panel.\n *\n * Default: generate reset token → send email (or generate + return temp password).\n * Override for custom reset flows.\n */\n onResetPassword?: (\n userId: string,\n ctx: AuthCollectionContext\n ) => Promise<AuthCollectionResetResult>;\n\n /**\n * Control which auth-specific entity actions are auto-injected.\n *\n * Default: `{ resetPassword: true }` — the framework auto-injects\n * the built-in `resetPasswordAction` into the collection's entity actions.\n *\n * Set to `false` to disable, or pass a custom `EntityAction` to replace the UI.\n */\n actions?: {\n resetPassword?: boolean | EntityAction;\n };\n}\n\n/**\n * Context provided to collection-level auth hooks.\n *\n * This is a simplified facade over the server internals —\n * it exposes only what's needed for custom auth flows without\n * coupling collection config to internal interfaces.\n *\n * @group Models\n */\nexport interface AuthCollectionContext {\n /** Hash a password using the configured algorithm (scrypt by default). */\n hashPassword: (password: string) => Promise<string>;\n /** Send an email. Only available when email service is configured. */\n sendEmail?: (options: { to: string; subject: string; html: string; text?: string }) => Promise<void>;\n /** Whether the email service is configured and available. */\n emailConfigured: boolean;\n /** The app name from email config (for templates). */\n appName: string;\n /** The base URL for password reset links. */\n resetPasswordUrl: string;\n}\n\n/**\n * Result of a collection-level `onCreateUser` hook.\n * @group Models\n */\nexport interface AuthCollectionCreateResult {\n /** Processed values to persist (must include passwordHash, NOT raw password). */\n values: Record<string, unknown>;\n /** If set, shown to the admin in the creation result dialog. */\n temporaryPassword?: string;\n /** Whether an invitation email was sent. */\n invitationSent?: boolean;\n}\n\n/**\n * Result of a collection-level `onResetPassword` hook.\n * @group Models\n */\nexport interface AuthCollectionResetResult {\n /** If set, shown to the admin. */\n temporaryPassword?: string;\n /** Whether a reset email was sent. */\n invitationSent?: boolean;\n}\n","import type { Entity } from \"./entities\";\nimport type { EntityCollection, FilterValues, WhereFilterOp } from \"./collections\";\nimport type { AuthAdapter } from \"./auth_adapter\";\n\n// =============================================================================\n// DATABASE CONNECTION INTERFACES\n// =============================================================================\n\n/**\n * Abstract database connection interface.\n * Represents a connection to any database system.\n */\nexport interface DatabaseConnection {\n /**\n * Type identifier for this database (e.g., 'postgres', 'mongodb', 'mysql')\n */\n readonly type: string;\n\n /**\n * Whether the connection is currently active\n */\n readonly isConnected?: boolean;\n\n /**\n * Close the database connection and release resources.\n */\n close?(): Promise<void>;\n}\n\n// =============================================================================\n// QUERY BUILDING INTERFACES\n// =============================================================================\n\n/**\n * A single filter condition for database queries\n */\nexport interface QueryFilter {\n field: string;\n operator: WhereFilterOp;\n value: unknown;\n}\n\n/**\n * Options for fetching a collection of entities\n */\nexport interface FetchCollectionOptions<M extends Record<string, unknown> = Record<string, unknown>> {\n filter?: FilterValues<Extract<keyof M, string>>;\n orderBy?: string;\n order?: \"desc\" | \"asc\";\n limit?: number;\n offset?: number;\n startAfter?: unknown;\n searchString?: string;\n databaseId?: string;\n collection?: EntityCollection;\n}\n\n/**\n * Options for searching entities\n */\nexport interface SearchOptions<M extends Record<string, unknown> = Record<string, unknown>> {\n filter?: FilterValues<Extract<keyof M, string>>;\n orderBy?: string;\n order?: \"desc\" | \"asc\";\n limit?: number;\n databaseId?: string;\n collection?: EntityCollection;\n}\n\n/**\n * Options for counting entities\n */\nexport interface CountOptions<M extends Record<string, unknown> = Record<string, unknown>> {\n filter?: FilterValues<Extract<keyof M, string>>;\n searchString?: string;\n databaseId?: string;\n}\n\n/**\n * Abstract condition builder interface.\n * Implementations translate Rebase filter conditions to database-specific queries.\n *\n * Note: This interface can be implemented as instance methods or as a class with static methods.\n * For static implementations (like DrizzleConditionBuilder), use the ConditionBuilderStatic type.\n *\n * @template T The type of condition returned by the builder (e.g., SQL for PostgreSQL, Filter<Document> for MongoDB)\n */\nexport interface ConditionBuilder<T = unknown> {\n /**\n * Build filter conditions from Rebase FilterValues\n */\n buildFilterConditions<M extends Record<string, unknown>>(\n filter: FilterValues<Extract<keyof M, string>>,\n collectionPath: string,\n ...args: unknown[]\n ): T[];\n\n /**\n * Build search conditions for text search\n */\n buildSearchConditions(\n searchString: string,\n properties: Record<string, unknown>,\n ...args: unknown[]\n ): T[];\n\n /**\n * Combine multiple conditions with AND operator\n */\n combineConditionsWithAnd(conditions: T[]): T | undefined;\n\n /**\n * Combine multiple conditions with OR operator\n */\n combineConditionsWithOr(conditions: T[]): T | undefined;\n}\n\n/**\n * Static condition builder type for implementations using static methods.\n * Use this type when the class provides static methods rather than instance methods.\n *\n * @example\n * // DrizzleConditionBuilder satisfies this type\n * const builder: ConditionBuilderStatic<SQL> = DrizzleConditionBuilder;\n */\nexport type ConditionBuilderStatic<T = unknown> = {\n buildFilterConditions<M extends Record<string, unknown>>(\n filter: FilterValues<Extract<keyof M, string>>,\n ...args: unknown[]\n ): T[];\n buildSearchConditions(\n searchString: string,\n properties: Record<string, unknown>,\n ...args: unknown[]\n ): T[];\n combineConditionsWithAnd(conditions: T[]): T | undefined;\n combineConditionsWithOr(conditions: T[]): T | undefined;\n};\n\n// =============================================================================\n// ENTITY REPOSITORY INTERFACES\n// =============================================================================\n\n/**\n * Abstract entity repository interface.\n * Handles all CRUD operations for entities in the database.\n *\n * Implementations should handle:\n * - Entity serialization/deserialization\n * - Relation resolution\n * - ID generation and conversion\n */\nexport interface EntityRepository {\n /**\n * Fetch a single entity by ID\n */\n fetchEntity<M extends Record<string, unknown>>(\n collectionPath: string,\n entityId: string | number,\n databaseId?: string\n ): Promise<Entity<M> | undefined>;\n\n /**\n * Fetch a collection of entities with optional filtering, ordering, and pagination\n */\n fetchCollection<M extends Record<string, unknown>>(\n collectionPath: string,\n options?: FetchCollectionOptions<M>\n ): Promise<Entity<M>[]>;\n\n /**\n * Search entities by text\n */\n searchEntities<M extends Record<string, unknown>>(\n collectionPath: string,\n searchString: string,\n options?: SearchOptions<M>\n ): Promise<Entity<M>[]>;\n\n /**\n * Count entities in a collection\n */\n countEntities<M extends Record<string, unknown>>(\n collectionPath: string,\n options?: CountOptions<M>\n ): Promise<number>;\n\n /**\n * Save an entity (create or update)\n */\n saveEntity<M extends Record<string, unknown>>(\n collectionPath: string,\n values: Partial<M>,\n entityId?: string | number,\n databaseId?: string\n ): Promise<Entity<M>>;\n\n /**\n * Delete an entity by ID\n */\n deleteEntity(\n collectionPath: string,\n entityId: string | number,\n databaseId?: string\n ): Promise<void>;\n\n /**\n * Check if a field value is unique in a collection\n */\n checkUniqueField(\n collectionPath: string,\n fieldName: string,\n value: unknown,\n excludeEntityId?: string,\n databaseId?: string\n ): Promise<boolean>;\n\n}\n\n// =============================================================================\n// REALTIME INTERFACES\n// =============================================================================\n\n/**\n * Configuration for subscribing to a collection\n */\nexport interface CollectionSubscriptionConfig {\n clientId: string;\n path: string;\n filter?: unknown;\n orderBy?: string;\n order?: \"desc\" | \"asc\";\n limit?: number;\n startAfter?: unknown;\n databaseId?: string;\n searchString?: string;\n}\n\n/**\n * Configuration for subscribing to a single entity\n */\nexport interface EntitySubscriptionConfig {\n clientId: string;\n path: string;\n entityId: string | number;\n}\n\n/**\n * Abstract realtime provider interface.\n * Handles real-time subscriptions and notifications for entity changes.\n */\nexport interface RealtimeProvider {\n /**\n * Subscribe to collection changes\n */\n subscribeToCollection(\n subscriptionId: string,\n config: CollectionSubscriptionConfig,\n callback?: (entities: Entity[]) => void\n ): void;\n\n /**\n * Subscribe to single entity changes\n */\n subscribeToEntity(\n subscriptionId: string,\n config: EntitySubscriptionConfig,\n callback?: (entity: Entity | null) => void\n ): void;\n\n /**\n * Unsubscribe from a subscription\n */\n unsubscribe(subscriptionId: string): void;\n\n /**\n * Notify all relevant subscribers of an entity update\n */\n notifyEntityUpdate(\n path: string,\n entityId: string,\n entity: Entity | null,\n databaseId?: string\n ): Promise<void>;\n\n /**\n * Called when the HTTP server is ready and listening.\n * Useful for providers that need the server address for callbacks.\n */\n onServerReady?(serverInfo: { port: number; hostname?: string }): void;\n\n /**\n * Gracefully shut down the realtime provider.\n * Called during server shutdown to clean up resources.\n */\n destroy?(): Promise<void>;\n\n /**\n * Stop the internal LISTEN client (e.g., PostgreSQL LISTEN/NOTIFY).\n * Called during graceful shutdown before closing database connections.\n */\n stopListening?(): Promise<void>;\n}\n\n// =============================================================================\n// COLLECTION REGISTRY INTERFACES\n// =============================================================================\n\n/**\n * Abstract collection registry interface.\n * Manages registration and lookup of entity collections.\n */\nexport interface CollectionRegistryInterface {\n /**\n * Register a collection\n */\n register(collection: EntityCollection): void;\n\n /**\n * Get a collection by its path\n */\n getCollectionByPath(path: string): EntityCollection | undefined;\n\n /**\n * Get all registered collections\n */\n getCollections(): EntityCollection[];\n}\n\n// =============================================================================\n// DATA TRANSFORMER INTERFACES\n// =============================================================================\n\n/**\n * Abstract data transformer interface.\n * Handles serialization/deserialization between frontend and database formats.\n */\nexport interface DataTransformer {\n /**\n * Transform entity data for storage in the database\n */\n serializeToDatabase<M extends Record<string, unknown>>(\n entity: M,\n collection: EntityCollection\n ): Record<string, unknown>;\n\n /**\n * Transform database data back to entity format\n */\n deserializeFromDatabase<M extends Record<string, unknown>>(\n data: Record<string, unknown>,\n collection: EntityCollection\n ): Promise<M>;\n}\n\n// =============================================================================\n// DATABASE ADMIN — CAPABILITY-SPECIFIC INTERFACES (1.3)\n// =============================================================================\n\n/**\n * Administrative operations for SQL-based databases (PostgreSQL, MySQL, etc.).\n * Used by the SQL Editor, RLS Editor, and schema browser.\n *\n * @group Admin\n */\nexport interface SQLAdmin {\n /**\n * Execute raw SQL against the database.\n */\n executeSql(sql: string, options?: { database?: string; role?: string }): Promise<Record<string, unknown>[]>;\n\n /**\n * Fetch the available databases on the server.\n */\n fetchAvailableDatabases?(): Promise<string[]>;\n\n /**\n * Fetch the available database roles.\n */\n fetchAvailableRoles?(): Promise<string[]>;\n\n /**\n * Fetch the current database name.\n */\n fetchCurrentDatabase?(): Promise<string | undefined>;\n}\n\n/**\n * Administrative operations for document-based databases (MongoDB, Firestore, etc.).\n * Used by future document administration tools.\n *\n * @group Admin\n */\nexport interface DocumentAdmin {\n /**\n * Execute an aggregation pipeline or equivalent query.\n */\n executeAggregate?(pipeline: Record<string, unknown>[]): Promise<Record<string, unknown>[]>;\n\n /**\n * Fetch statistics for a collection (document count, size, etc.).\n */\n fetchCollectionStats?(collectionName: string): Promise<{ count: number; sizeBytes?: number }>;\n}\n\n/**\n * Administrative operations for schema management.\n * Shared across SQL and document databases.\n *\n * @group Admin\n */\nexport interface SchemaAdmin {\n /**\n * Fetch database tables/collections not yet mapped to a Rebase collection.\n */\n fetchUnmappedTables?(mappedPaths?: string[]): Promise<string[]>;\n\n /**\n * Fetch column/field metadata for a single table/collection.\n * The return type is generic — SQL backends return TableMetadata,\n * document backends may return a different shape.\n */\n fetchTableMetadata?(tableName: string): Promise<unknown>;\n}\n\n/**\n * Metadata for a database branch.\n * @group Admin\n */\nexport interface BranchInfo {\n /** Branch name (without prefix). */\n name: string;\n /** The database this branch was created from. */\n parentDatabase: string;\n /** When the branch was created. */\n createdAt: Date;\n /** Size in bytes, if available from the server. */\n sizeBytes?: number;\n}\n\n/**\n * Administrative operations for database branching.\n * Allows creating isolated database copies for development/preview workflows.\n *\n * @group Admin\n */\nexport interface BranchAdmin {\n /** Create a new branch (database copy) from the current or specified source database. */\n createBranch(name: string, options?: { source?: string }): Promise<BranchInfo>;\n\n /** Delete a branch database. Cannot delete the main/default database. */\n deleteBranch(name: string): Promise<void>;\n\n /** List all branches (databases that were created via branching). */\n listBranches(): Promise<BranchInfo[]>;\n\n /** Get info about a specific branch. */\n getBranchInfo(name: string): Promise<BranchInfo | undefined>;\n}\n\n/**\n * Union type for all admin capabilities.\n * A backend may implement any combination of these interfaces.\n *\n * Use type guards (`isSQLAdmin`, `isDocumentAdmin`, `isSchemaAdmin`, `isBranchAdmin`)\n * to safely narrow the type before calling methods.\n *\n * @group Admin\n */\nexport type DatabaseAdmin = Partial<SQLAdmin> & Partial<DocumentAdmin> & Partial<SchemaAdmin> & Partial<BranchAdmin>;\n\n/**\n * Type guard: does this admin support SQL operations?\n * @group Admin\n */\nexport function isSQLAdmin(admin: DatabaseAdmin | undefined): admin is SQLAdmin {\n return !!admin && typeof (admin as SQLAdmin).executeSql === \"function\";\n}\n\n/**\n * Type guard: does this admin support document operations?\n * @group Admin\n */\nexport function isDocumentAdmin(admin: DatabaseAdmin | undefined): admin is DocumentAdmin {\n return !!admin && (\n typeof (admin as DocumentAdmin).executeAggregate === \"function\" ||\n typeof (admin as DocumentAdmin).fetchCollectionStats === \"function\"\n );\n}\n\n/**\n * Type guard: does this admin support schema management?\n * @group Admin\n */\nexport function isSchemaAdmin(admin: DatabaseAdmin | undefined): admin is SchemaAdmin {\n return !!admin && (\n typeof (admin as SchemaAdmin).fetchUnmappedTables === \"function\" ||\n typeof (admin as SchemaAdmin).fetchTableMetadata === \"function\"\n );\n}\n\n/**\n * Type guard: does this admin support database branching?\n * @group Admin\n */\nexport function isBranchAdmin(admin: DatabaseAdmin | undefined): admin is BranchAdmin {\n return !!admin && typeof (admin as BranchAdmin).createBranch === \"function\";\n}\n\n// =============================================================================\n// LIFECYCLE INTERFACES (1.4)\n// =============================================================================\n\n/**\n * Health check result returned by `healthCheck()`.\n * @group Lifecycle\n */\nexport interface HealthCheckResult {\n /** Whether the backend is healthy and able to serve requests. */\n healthy: boolean;\n /** Round-trip latency to the database in milliseconds. */\n latencyMs: number;\n /** Optional details (e.g., pool stats, replication lag). */\n details?: Record<string, unknown>;\n}\n\n/**\n * Lifecycle contract for backend components that hold resources\n * (database connections, WebSocket pools, timers, etc.).\n *\n * All methods are optional — simple backends (e.g., in-memory) can skip them.\n * @group Lifecycle\n */\nexport interface BackendLifecycle {\n /**\n * Initialize the backend: open connections, run migrations, seed data.\n * Called once during startup. Idempotent.\n */\n initialize?(): Promise<void>;\n\n /**\n * Check whether the backend is healthy and reachable.\n * Should be fast (< 1 s) and safe to call frequently.\n */\n healthCheck?(): Promise<HealthCheckResult>;\n\n /**\n * Gracefully shut down: close connections, flush buffers, cancel timers.\n * After calling `destroy()`, no other methods should be called.\n */\n destroy?(): Promise<void>;\n}\n\n// =============================================================================\n// BACKEND FACTORY INTERFACES\n// =============================================================================\n\n/**\n * Configuration for creating a database backend\n */\nexport interface BackendConfig {\n /**\n * Type of database backend\n */\n type: string;\n\n /**\n * Database connection (implementation-specific)\n */\n connection: unknown;\n\n /**\n * Schema definition (implementation-specific, e.g., Drizzle schema for PostgreSQL)\n */\n schema?: unknown;\n}\n\n/**\n * A complete backend instance with all required services.\n *\n * Now includes optional lifecycle management and admin capabilities.\n */\nexport interface BackendInstance extends BackendLifecycle {\n /**\n * Entity repository for CRUD operations\n */\n entityRepository: EntityRepository;\n\n /**\n * Realtime provider for subscriptions\n */\n realtimeProvider: RealtimeProvider;\n\n /**\n * Collection registry\n */\n collectionRegistry: CollectionRegistryInterface;\n\n /**\n * The underlying database connection\n */\n connection: DatabaseConnection;\n\n /**\n * Administrative operations (SQL, schema, documents).\n * What's available depends on the backend type — use type guards\n * (`isSQLAdmin`, `isSchemaAdmin`, etc.) to narrow.\n */\n admin?: DatabaseAdmin;\n}\n\n/**\n * Factory function type for creating backend instances\n */\nexport type BackendFactory<TConfig extends BackendConfig = BackendConfig> =\n (config: TConfig) => BackendInstance;\n\n// =============================================================================\n// BACKEND BOOTSTRAPPER (1.2)\n// =============================================================================\n\n/**\n * A `BackendBootstrapper` encapsulates all driver-specific initialization logic.\n *\n * Instead of hard-coding Postgres setup into `initializeRebaseBackend()`,\n * each database backend provides its own bootstrapper that knows how to:\n * - Create the DataDriver from a config object\n * - Optionally initialize auth tables\n * - Optionally create a realtime service\n * - Mount driver-specific API routes\n *\n * The main `initializeRebaseBackend()` becomes a **coordinator** that iterates\n * registered bootstrappers, calls their hooks, and wires the results together.\n *\n * @group Backend\n *\n * @example\n * ```typescript\n * // Third-party MySQL bootstrapper\n * const mysqlBootstrapper: BackendBootstrapper = {\n * type: \"mysql\",\n * initializeDriver: async (config) => new MySQLDataDriver(config.connection),\n * initializeRealtime: async (config) => new MySQLChangeStreamRealtime(config.connection),\n * };\n *\n * initializeRebaseBackend({\n * ...config,\n * bootstrappers: [postgresBootstrapper, mysqlBootstrapper]\n * });\n * ```\n */\nexport interface BackendBootstrapper {\n /**\n * Which driver type this bootstrapper handles.\n * Must match the `type` field on the driver config object\n * (e.g., `\"postgres\"`, `\"mongodb\"`, `\"mysql\"`).\n */\n type: string;\n\n /**\n * Unique identifier for this bootstrapper instance.\n * Used to register the driver in the driver registry.\n * Defaults to `type` if not set.\n */\n id?: string;\n\n /**\n * Whether this bootstrapper provides the default driver.\n * When true, the coordinator uses this driver as the primary one.\n */\n isDefault?: boolean;\n\n /**\n * Run database migrations for this driver.\n * Called by the coordinator after all drivers are initialized.\n */\n runMigrations?(config: unknown, driverResult: InitializedDriver): Promise<void>;\n\n /**\n * Create a DataDriver from the given config.\n * This is the only **required** method.\n */\n initializeDriver(config: unknown): Promise<InitializedDriver>;\n\n /**\n * Initialize auth tables / services if this driver supports them.\n * Return undefined if auth is not supported by this backend.\n */\n initializeAuth?(config: unknown, driverResult: InitializedDriver): Promise<BootstrappedAuth | undefined>;\n\n /**\n * Initialize history tables / services if this driver supports them.\n * Return undefined if history is not supported by this backend.\n */\n initializeHistory?(config: unknown, driverResult: InitializedDriver): Promise<{ historyService: unknown } | undefined>;\n\n /**\n * Create a realtime provider for this driver.\n * Return undefined if the driver does not support realtime.\n */\n initializeRealtime?(config: unknown, driverResult: InitializedDriver): Promise<RealtimeProvider | undefined>;\n\n /**\n * Mount any driver-specific HTTP routes (e.g., custom admin endpoints).\n * Called after all drivers are initialized.\n */\n mountRoutes?(app: unknown, basePath: string, driverResult: InitializedDriver): void;\n\n /**\n * Return admin capabilities for this driver.\n */\n getAdmin?(driverResult: InitializedDriver): DatabaseAdmin | undefined;\n\n /**\n * Initialize WebSocket server for realtime operations.\n */\n initializeWebsockets?(server: unknown, realtimeService: RealtimeProvider, driver: import(\"../controllers/data_driver\").DataDriver, config?: unknown, authAdapter?: AuthAdapter): Promise<void> | void;\n}\n\n/**\n * Result of `BackendBootstrapper.initializeDriver()`.\n * @group Backend\n */\nexport interface InitializedDriver {\n /** The DataDriver instance, ready for use. */\n driver: import(\"../controllers/data_driver\").DataDriver;\n\n /** The realtime service, if the driver created one during init. */\n realtimeProvider?: RealtimeProvider;\n\n /** A collection registry to register schema / tables into. */\n collectionRegistry?: CollectionRegistryInterface;\n\n /** The underlying database connection (for lifecycle management). */\n connection?: DatabaseConnection;\n\n /**\n * Opaque handle that the bootstrapper can use in subsequent hooks\n * (e.g., `initializeAuth`, `mountRoutes`) to access driver internals.\n * Not used by the coordinator.\n */\n internals?: unknown;\n}\n\n/**\n * Result of `BackendBootstrapper.initializeAuth()`.\n * @group Backend\n */\nexport interface BootstrappedAuth {\n /** User management service. */\n userService: unknown;\n /** Role management service (optional, roles are now simple strings). */\n roleService?: unknown;\n /** Email service (optional). */\n emailService?: unknown;\n /** Combined Auth Repository for unified token and user management. */\n authRepository?: unknown;\n}\n","/**\n * Describes the capabilities and features supported by a data source (driver).\n *\n * Each driver (Postgres, Firebase, MongoDB, etc.) declares which features it\n * supports. The CMS uses this descriptor to:\n * - Show/hide editor tabs (e.g. Relations for SQL, Subcollections for Firebase)\n * - Filter the property type picker (e.g. `relation` for SQL, `reference` for Firebase)\n * - Toggle driver-specific form controls (e.g. `columnType` for SQL)\n *\n * @group Models\n */\nexport interface DataSourceCapabilities {\n /** Unique driver key (e.g. \"postgres\", \"firestore\", \"mongodb\") */\n key: string;\n\n /** Human-readable label for the UI (e.g. \"PostgreSQL\", \"Firebase / Firestore\") */\n label: string;\n\n // ── Feature flags ─────────────────────────────────────────────────\n /** Does this source support SQL-style relations (JOINs)? */\n supportsRelations: boolean;\n\n /** Does this source support nested subcollections? */\n supportsSubcollections: boolean;\n\n /** Does this source support Row Level Security policies? */\n supportsRLS: boolean;\n\n /** Does this source support document references (Firebase-style)? */\n supportsReferences: boolean;\n\n /** Does this source support SQL column type annotations? */\n supportsColumnTypes: boolean;\n\n /** Does this source support real-time listeners? */\n supportsRealtime: boolean;\n\n // ── Admin capability flags ───────────────────────────────────────\n /** Does this source support SQL admin operations (SQL editor, EXPLAIN, etc.)? */\n supportsSQLAdmin: boolean;\n\n /** Does this source support document admin operations (aggregation, stats)? */\n supportsDocumentAdmin: boolean;\n\n /** Does this source support schema admin (unmapped tables, table metadata)? */\n supportsSchemaAdmin: boolean;\n}\n\n/**\n * Subset of DataSourceCapabilities containing only feature flags.\n * Useful when you only need to check capabilities without UI metadata.\n * @group Models\n */\nexport type DataSourceFeatures = Omit<DataSourceCapabilities, \"key\" | \"label\">;\n\n// ── Built-in driver capabilities ─────────────────────────────────────\n\n/** @group Models */\nexport const POSTGRES_CAPABILITIES: DataSourceCapabilities = {\n key: \"postgres\",\n label: \"PostgreSQL\",\n supportsRelations: true,\n supportsSubcollections: false,\n supportsRLS: true,\n supportsReferences: false,\n supportsColumnTypes: true,\n supportsRealtime: true,\n supportsSQLAdmin: true,\n supportsDocumentAdmin: false,\n supportsSchemaAdmin: true\n};\n\n/** @group Models */\nexport const FIREBASE_CAPABILITIES: DataSourceCapabilities = {\n key: \"firestore\",\n label: \"Firebase / Firestore\",\n supportsRelations: false,\n supportsSubcollections: true,\n supportsRLS: false,\n supportsReferences: true,\n supportsColumnTypes: false,\n supportsRealtime: true,\n supportsSQLAdmin: false,\n supportsDocumentAdmin: false,\n supportsSchemaAdmin: false\n};\n\n/** @group Models */\nexport const MONGODB_CAPABILITIES: DataSourceCapabilities = {\n key: \"mongodb\",\n label: \"MongoDB\",\n supportsRelations: false,\n supportsSubcollections: true,\n supportsRLS: false,\n supportsReferences: true,\n supportsColumnTypes: false,\n supportsRealtime: false,\n supportsSQLAdmin: false,\n supportsDocumentAdmin: true,\n supportsSchemaAdmin: true\n};\n\n/**\n * Fallback capabilities when the driver is unknown.\n * Enables everything so nothing is hidden unexpectedly.\n * @group Models\n */\nexport const DEFAULT_CAPABILITIES: DataSourceCapabilities = {\n key: \"(default)\",\n label: \"Default\",\n supportsRelations: true,\n supportsSubcollections: true,\n supportsRLS: true,\n supportsReferences: true,\n supportsColumnTypes: true,\n supportsRealtime: true,\n supportsSQLAdmin: true,\n supportsDocumentAdmin: true,\n supportsSchemaAdmin: true\n};\n\nconst CAPABILITIES_REGISTRY: Record<string, DataSourceCapabilities> = {\n postgres: POSTGRES_CAPABILITIES,\n firestore: FIREBASE_CAPABILITIES,\n mongodb: MONGODB_CAPABILITIES,\n \"(default)\": DEFAULT_CAPABILITIES\n};\n\n/**\n * Look up capabilities for a given driver key.\n * If `driver` is undefined or not found, returns `DEFAULT_CAPABILITIES`.\n * @group Models\n */\nexport function getDataSourceCapabilities(driver?: string): DataSourceCapabilities {\n if (!driver) return POSTGRES_CAPABILITIES; // postgres is the default driver\n return CAPABILITIES_REGISTRY[driver] ?? DEFAULT_CAPABILITIES;\n}\n\n/**\n * Register custom capabilities for a third-party driver.\n * @group Models\n */\nexport function registerDataSourceCapabilities(capabilities: DataSourceCapabilities): void {\n CAPABILITIES_REGISTRY[capabilities.key] = capabilities;\n}\n","import type React from \"react\";\n\n/**\n * Internal marker for a lazily-loaded component reference.\n * Created by the Vite transform plugin when converting string paths\n * to deferred `import()` calls. Users should NOT create these manually.\n *\n * @internal\n */\nexport interface LazyComponentRef<P = unknown> {\n readonly __rebaseLazy: true;\n readonly load: () => Promise<{ default: React.ComponentType<P> }>;\n}\n\n/**\n * A reference to a React component that can be provided in three forms:\n *\n * 1. **String path** (recommended for collection configs):\n * ```ts\n * Field: \"../../frontend/src/components/MyField\"\n * ```\n * The Vite plugin transforms this into a `LazyComponentRef` at build time.\n * On the backend, the string stays inert and is never evaluated.\n *\n * 2. **Lazy import function**:\n * ```ts\n * Field: () => import(\"../../frontend/src/components/MyField\")\n * ```\n * Standard ES dynamic import. Backend never calls the function.\n *\n * 3. **Direct component reference** (use only in frontend-only code):\n * ```ts\n * Field: MyFieldComponent\n * ```\n * Importing a component at the top level will pull React into the\n * backend runtime — only safe in code that the backend never imports.\n *\n * @group Types\n */\nexport type ComponentRef<P = any> =\n | React.ComponentType<P>\n | LazyComponentRef<P>\n | (() => Promise<{ default: React.ComponentType<P> }>)\n | string;\n\n/**\n * Type guard: checks if a value is a `LazyComponentRef` produced by the\n * Vite transform plugin.\n */\nexport function isLazyComponentRef<P = unknown>(ref: unknown): ref is LazyComponentRef<P> {\n return (\n typeof ref === \"object\" &&\n ref !== null &&\n \"__rebaseLazy\" in ref &&\n (ref as Record<string, unknown>).__rebaseLazy === true\n );\n}\n"],"mappings":";;;;;;;;;;;;;;AA2EA,IAAa,kBAAb,MAA6B;CAEzB,SAAkB;;;;CAIlB;;;;;CAKA;;;;;CAMA;;;;;CAMA;;;;;;;;;;;CAYA,YAAY,OAA6B;EACrC,KAAK,KAAK,MAAM;EAChB,KAAK,OAAO,MAAM;EAClB,KAAK,SAAS,MAAM;EACpB,KAAK,aAAa,MAAM;CAC5B;CAEA,IAAI,aAAa;EACb,OAAO,GAAG,KAAK,KAAK,GAAG,KAAK;CAChC;;;;;CAMA,IAAI,WAAW;EACX,MAAM,QAAkB,CAAC;EAGzB,IAAI,KAAK,UAAU,KAAK,WAAW,aAC/B,MAAM,KAAK,KAAK,MAAM;EAI1B,IAAI,KAAK,cAAc,KAAK,eAAe,aACvC,MAAM,KAAK,KAAK,UAAU;EAG9B,IAAI,MAAM,SAAS,GACf,OAAO,GAAG,MAAM,KAAK,GAAG,EAAE,KAAK,KAAK,KAAK,GAAG,KAAK;EAErD,OAAO,KAAK;CAChB;CAEA,oBAAoB;EAChB,OAAO;CACX;AACJ;;;;AAKA,IAAa,iBAAb,MAA4B;CAExB,SAAkB;;;;CAIlB;;;;;CAKA;;;;;CAMA;CAEA,YAAY,IAAqB,MAAc,MAAe;EAC1D,KAAK,KAAK;EACV,KAAK,OAAO;EACZ,KAAK,OAAO;CAChB;CAEA,IAAI,aAAa;EACb,OAAO,GAAG,KAAK,KAAK,GAAG,KAAK;CAChC;CAEA,oBAAoB;EAChB,OAAO;CACX;CAEA,mBAAmB;EACf,OAAO;CACX;AACJ;AAEA,IAAa,WAAb,MAAsB;;;;CAKlB;;;;CAIA;CAEA,YAAY,UAAkB,WAAmB;EAC7C,KAAK,WAAW;EAChB,KAAK,YAAY;CACrB;AACJ;AAEA,IAAa,SAAb,MAAoB;CAChB;CAEA,YAAY,OAAiB;EACzB,KAAK,QAAQ;CACjB;AACJ;;;;;;;;ACsXA,SAAgB,qBACZ,YACyC;CACzC,OAAO,CAAC,WAAW,UAAU,WAAW,WAAW;AACvD;;;;;AAMA,SAAgB,qBACZ,YACyC;CACzC,OAAO,WAAW,WAAW;AACjC;;;;;AAMA,SAAgB,oBACZ,YACwC;CACxC,OAAO,WAAW,WAAW;AACjC;;;;;;;ACxIA,SAAgB,WAAW,OAAqD;CAC5E,OAAO,CAAC,CAAC,SAAS,OAAQ,MAAmB,eAAe;AAChE;;;;;AAMA,SAAgB,gBAAgB,OAA0D;CACtF,OAAO,CAAC,CAAC,UACL,OAAQ,MAAwB,qBAAqB,cACrD,OAAQ,MAAwB,yBAAyB;AAEjE;;;;;AAMA,SAAgB,cAAc,OAAwD;CAClF,OAAO,CAAC,CAAC,UACL,OAAQ,MAAsB,wBAAwB,cACtD,OAAQ,MAAsB,uBAAuB;AAE7D;;;;;AAMA,SAAgB,cAAc,OAAwD;CAClF,OAAO,CAAC,CAAC,SAAS,OAAQ,MAAsB,iBAAiB;AACrE;;;;ACjcA,IAAa,wBAAgD;CACzD,KAAK;CACL,OAAO;CACP,mBAAmB;CACnB,wBAAwB;CACxB,aAAa;CACb,oBAAoB;CACpB,qBAAqB;CACrB,kBAAkB;CAClB,kBAAkB;CAClB,uBAAuB;CACvB,qBAAqB;AACzB;;AAGA,IAAa,wBAAgD;CACzD,KAAK;CACL,OAAO;CACP,mBAAmB;CACnB,wBAAwB;CACxB,aAAa;CACb,oBAAoB;CACpB,qBAAqB;CACrB,kBAAkB;CAClB,kBAAkB;CAClB,uBAAuB;CACvB,qBAAqB;AACzB;;AAGA,IAAa,uBAA+C;CACxD,KAAK;CACL,OAAO;CACP,mBAAmB;CACnB,wBAAwB;CACxB,aAAa;CACb,oBAAoB;CACpB,qBAAqB;CACrB,kBAAkB;CAClB,kBAAkB;CAClB,uBAAuB;CACvB,qBAAqB;AACzB;;;;;;AAOA,IAAa,uBAA+C;CACxD,KAAK;CACL,OAAO;CACP,mBAAmB;CACnB,wBAAwB;CACxB,aAAa;CACb,oBAAoB;CACpB,qBAAqB;CACrB,kBAAkB;CAClB,kBAAkB;CAClB,uBAAuB;CACvB,qBAAqB;AACzB;AAEA,IAAM,wBAAgE;CAClE,UAAU;CACV,WAAW;CACX,SAAS;CACT,aAAa;AACjB;;;;;;AAOA,SAAgB,0BAA0B,QAAyC;CAC/E,IAAI,CAAC,QAAQ,OAAO;CACpB,OAAO,sBAAsB,WAAW;AAC5C;;;;;AAMA,SAAgB,+BAA+B,cAA4C;CACvF,sBAAsB,aAAa,OAAO;AAC9C;;;;;;;AC/FA,SAAgB,mBAAgC,KAA0C;CACtF,OACI,OAAO,QAAQ,YACf,QAAQ,QACR,kBAAkB,OACjB,IAAgC,iBAAiB;AAE1D"}
|
|
1
|
+
{"version":3,"file":"index.es.js","names":[],"sources":["../src/types/entities.ts","../src/types/collections.ts","../src/types/backend.ts","../src/types/data_source.ts","../src/types/component_ref.ts"],"sourcesContent":["/**\n * New or existing status\n * @group Models\n */\nexport type EntityStatus = \"new\" | \"existing\" | \"copy\";\n\n/**\n * Representation of an entity fetched from the driver\n * @group Models\n */\nexport interface Entity<M extends Record<string, unknown> = Record<string, unknown>> {\n\n /**\n * ID of the entity\n */\n id: string | number;\n\n /**\n * A string representing the path of the referenced document (relative\n * to the root of the database).\n */\n path: string;\n\n /**\n * Current values\n */\n values: EntityValues<M>;\n\n /**\n * Which driver this entity belongs to (e.g., 'postgres', 'firestore').\n * If not specified, the default driver is assumed.\n */\n driver?: string;\n\n /**\n * Which database within the driver (e.g., for Firestore multi-database).\n * If not specified, the default database of the driver is used.\n */\n databaseId?: string;\n}\n\n/**\n * This type represents a record of key value pairs as described in an\n * entity collection.\n * @group Models\n */\nexport type EntityValues<M extends Record<string, unknown>> = M;\n\n/**\n * Props for creating an EntityReference\n */\nexport interface EntityReferenceProps {\n /** ID of the entity */\n id: string;\n /** Path of the collection (relative to the root of the database) */\n path: string;\n /** Which driver (e.g., 'postgres', 'firestore'). Defaults to \"(default)\" */\n driver?: string;\n /** Which database within the driver. Defaults to \"(default)\" */\n databaseId?: string;\n}\n\n/**\n * Class used to create a reference to an entity in a different path.\n *\n * @example\n * // Simple reference (most common case - single driver, single db)\n * new EntityReference({ id: \"123\", path: \"users\" })\n *\n * // Reference to a different driver (e.g., Firestore)\n * new EntityReference({ id: \"123\", path: \"analytics\", driver: \"firestore\" })\n *\n * // Reference to a specific database within a driver\n * new EntityReference({ id: \"123\", path: \"orders\", driver: \"postgres\", databaseId: \"orders_db\" })\n */\nexport class EntityReference {\n\n readonly __type = \"reference\";\n /**\n * ID of the entity\n */\n readonly id: string;\n /**\n * A string representing the path of the referenced document (relative\n * to the root of the database).\n */\n readonly path: string;\n\n /**\n * Which driver (e.g., 'postgres', 'firestore').\n * Defaults to \"(default)\" if not specified.\n */\n readonly driver?: string;\n\n /**\n * Which database within the driver.\n * Defaults to \"(default)\" if not specified.\n */\n readonly databaseId?: string;\n\n /**\n * Create a reference to an entity.\n *\n * @example\n * // Simple reference (most common case)\n * new EntityReference({ id: \"123\", path: \"users\" })\n *\n * // With driver\n * new EntityReference({ id: \"123\", path: \"analytics\", driver: \"firestore\" })\n */\n constructor(props: EntityReferenceProps) {\n this.id = props.id;\n this.path = props.path;\n this.driver = props.driver;\n this.databaseId = props.databaseId;\n }\n\n get pathWithId() {\n return `${this.path}/${this.id}`;\n }\n\n /**\n * Get the full path including driver and database prefixes if specified.\n * For the common case (single driver, single db), this just returns pathWithId.\n */\n get fullPath() {\n const parts: string[] = [];\n\n // Add driver prefix if not default\n if (this.driver && this.driver !== \"(default)\") {\n parts.push(this.driver);\n }\n\n // Add database prefix if specified\n if (this.databaseId && this.databaseId !== \"(default)\") {\n parts.push(this.databaseId);\n }\n\n if (parts.length > 0) {\n return `${parts.join(\":\")}:::${this.path}/${this.id}`;\n }\n return this.pathWithId;\n }\n\n isEntityReference() {\n return true;\n }\n}\n\n/**\n * Class used to create a reference to an entity in a different path\n */\nexport class EntityRelation {\n\n readonly __type = \"relation\";\n /**\n * ID of the entity\n */\n readonly id: string | number;\n /**\n * A string representing the path of the referenced document (relative\n * to the root of the database).\n */\n readonly path: string;\n\n /**\n * Pre-fetched data payload to eliminate N+1 queries.\n * When present, clients can use this directly instead of fetching.\n */\n readonly data?: Entity;\n\n constructor(id: string | number, path: string, data?: Entity) {\n this.id = id;\n this.path = path;\n this.data = data;\n }\n\n get pathWithId() {\n return `${this.path}/${this.id}`;\n }\n\n isEntityReference() {\n return false;\n }\n\n isEntityRelation() {\n return true;\n }\n}\n\nexport class GeoPoint {\n\n /**\n * The latitude of this GeoPoint instance.\n */\n readonly latitude: number;\n /**\n * The longitude of this GeoPoint instance.\n */\n readonly longitude: number;\n\n constructor(latitude: number, longitude: number) {\n this.latitude = latitude;\n this.longitude = longitude;\n }\n}\n\nexport class Vector {\n readonly value: number[];\n\n constructor(value: number[]) {\n this.value = value;\n }\n}\n","import React, { Dispatch, SetStateAction } from \"react\";\nimport type { Entity, EntityStatus, EntityValues } from \"./entities\";\nimport type { EntityCallbacks } from \"./entity_callbacks\";\n\nimport type { EnumValues, Properties } from \"./properties\";\nimport type { ExportConfig } from \"./export_import\";\nimport type { EntityOverrides } from \"./entity_overrides\";\nimport type { User } from \"../users\";\nimport type { RebaseContext } from \"../rebase_context\";\nimport type { Relation } from \"./relations\";\nimport type { EntityCustomView, FormViewConfig } from \"./entity_views\";\nimport type { EntityAction } from \"./entity_actions\";\nimport type { ComponentRef } from \"./component_ref\";\nimport type { CollectionComponentOverrideMap } from \"./component_overrides\";\n\n/**\n * Base interface containing all driver-agnostic collection properties.\n * Use {@link PostgresCollection} or {@link FirebaseCollection} for\n * driver-specific type safety, or {@link EntityCollection} when you\n * need to handle any collection regardless of backend.\n *\n * @group Models\n */\nexport interface BaseEntityCollection<M extends Record<string, unknown> = Record<string, unknown>, USER extends User = User> {\n\n /**\n * You can set an alias that will be used internally instead of the collection name.\n * The `slug` value will be used to determine the URL of the collection.\n * Note that you can use this value in reference properties too.\n */\n slug: string;\n\n /**\n * Name of the collection, typically plural.\n * E.g. `Products`, `Blog`\n */\n name: string;\n\n /**\n * Singular name of an entry in this collection\n * E.g. `Product`, `Blog entry`\n */\n singularName?: string;\n\n /**\n * Optional description of this view. You can use Markdown.\n */\n description?: string;\n\n /**\n * Child collections nested under entities of this collection.\n * Populated automatically during normalization from driver-specific fields\n * (e.g. Firebase `subcollections`, Postgres `relations` with many-cardinality).\n *\n * Custom drivers can set this directly to expose child collections to the UI.\n */\n childCollections?: () => EntityCollection<Record<string, unknown>>[];\n\n\n /**\n * The data source this collection belongs to — the routing key shared by\n * the frontend router and the backend driver registry. It points at a\n * {@link DataSourceDefinition} registered on `<Rebase dataSources>` (front)\n * and `initRebase({ dataSources })` (back).\n *\n * If not specified, the default data source `\"(default)\"` is used, which\n * for a standard Rebase app is the server-mediated Postgres backend.\n *\n * @example\n * // Default data source (server-mediated Postgres)\n * { slug: \"products\" }\n *\n * // A direct-transport Firestore data source registered as \"analytics\"\n * { slug: \"events\", dataSource: \"analytics\" }\n */\n dataSource?: string;\n\n /**\n * The engine backing this collection (`\"postgres\"`, `\"firestore\"`,\n * `\"mongodb\"`, or a custom id). Drives editor capabilities (relations vs\n * subcollections, RLS, column types).\n *\n * @deprecated Prefer {@link dataSource} for routing. `driver` is retained\n * as an engine hint and for backward compatibility: when `dataSource` is\n * omitted it also acts as the data-source key.\n *\n * If not specified, `\"postgres\"` is assumed.\n */\n driver?: string;\n\n /**\n * Which database within the engine.\n * - For Firestore: The Firestore database ID (e.g., for multi-database projects)\n * - For PostgreSQL: Schema or database name\n * - For MongoDB: Database name\n *\n * If not specified, the default database of the engine is used. Resolved\n * from the collection's {@link DataSourceDefinition} when omitted here.\n */\n databaseId?: string;\n\n /**\n * Set of properties that compose an entity\n */\n properties: Properties;\n\n /**\n * Icon for the navigation sidebar or cards.\n */\n icon?: string | React.ReactNode;\n\n /**\n * Navigation group for this collection.\n * Collections sharing the same group name will be visually grouped\n * together in the drawer and home page. If not set, the collection\n * falls into the default \"Views\" group.\n */\n group?: string;\n\n /**\n * Array of entity views that this collection has.\n * Can be an array of `EntityCustomView` or a string representing the key of a global `EntityCustomView`.\n */\n entityViews?: (string | EntityCustomView<Record<string, unknown>>)[];\n\n /**\n * Default preview properties displayed when this collection is referenced to.\n */\n previewProperties?: string[];\n\n /**\n * Properties to display as columns in the list view.\n * If not specified, the list view uses a smart default (Title, Status, Date).\n */\n listProperties?: string[];\n\n /**\n * Title property of the entity. This is the property that will be used\n * as the title in entity related views and references.\n * If not specified, the first property simple text property will be used.\n */\n readonly titleProperty?: Extract<keyof M, string> | (string & {});\n\n /**\n * When editing an entity, you can choose to open the entity in a side dialog\n * or in a full screen dialog. Defaults to `full_screen`.\n */\n openEntityMode?: \"side_panel\" | \"full_screen\" | \"split\" | \"dialog\";\n\n /**\n * Controls what happens when a user clicks on an entity in the collection view.\n * - `\"edit\"` (default): Opens the entity in the edit form.\n * - `\"view\"`: Opens a read-only detail view with an \"Edit\" button.\n */\n defaultEntityAction?: \"view\" | \"edit\";\n\n /**\n * Replace the default entity form with a custom component.\n * The Builder receives the same props as entity view tabs\n * (entity, formContext, collection, etc.) and has full control over the UI.\n *\n * Works in both edit mode and read-only mode (when `defaultEntityAction`\n * is `\"view\"`). In read-only mode, `formContext.readOnly` will be `true`.\n */\n formView?: FormViewConfig;\n\n /**\n * Prevent default actions from being displayed or executed on this collection.\n */\n disableDefaultActions?: (\"edit\" | \"copy\" | \"delete\")[];\n\n /**\n * Mark this collection as an authentication collection.\n * When true, this collection is used for user management, login, password hashing, and invitation flows.\n */\n auth?: boolean | AuthCollectionConfig;\n\n /**\n * Opt out of the framework's default Row Level Security policies for\n * authentication collections.\n *\n * When a collection has `auth` enabled, the schema generator automatically\n * injects an admin-only write policy (INSERT/UPDATE/DELETE require the\n * `admin` role, or the trusted server context) for any write operation that\n * the collection does not already cover with an explicit `securityRules`\n * entry. This makes privileged columns such as `roles` safe by default — a\n * non-admin cannot modify the user row through the data API regardless of\n * which code path issues the write.\n *\n * Defining your own write rule for an operation overrides the default for\n * that operation. Set this flag to `true` to remove the default policies\n * entirely and take full responsibility for the collection's RLS.\n *\n * @default false\n */\n disableDefaultAuthPolicies?: boolean;\n\n\n /**\n * Order in which the properties are displayed.\n * If you are specifying your collection as code, the order is the same as the\n * one you define in `properties`. Additional columns are added at the\n * end of the list, if the order is not specified.\n * You can use this prop to hide some properties from the table view.\n * Note that if you set this prop, other ways to hide fields, like\n * `hidden` in the property definition, will be ignored.\n * `propertiesOrder` has precedence over `hidden`.\n * - For properties use the property key.\n * - For additional fields use the field key.\n * - If you have subcollections, you get a column for each subcollection,\n * with the path (or alias) as the subcollection, prefixed with\n * `subcollection:`. e.g. `subcollection:orders`.\n * You can use this prop to hide some properties from the table view.\n * Note that if you set this prop, other ways to hide fields, like\n * `hidden` in the property definition,will be ignored.\n * `propertiesOrder` has precedence over `hidden`.\n */\n propertiesOrder?: (Extract<keyof M, string> | (string & {}) | string | `subcollection:${string}`)[];\n\n /**\n * If enabled, content is loaded in batches. If `false` all entities in the\n * collection are loaded. This means that when reaching the end of the\n * collection, the CMS will load more entities.\n * You can specify a number to specify the pagination size (50 by default)\n * Defaults to `true`\n */\n pagination?: boolean | number;\n\n\n selectionEnabled?: boolean;\n\n /**\n * This interface defines all the callbacks that can be used when an entity\n * is being created, updated or deleted.\n * Useful for adding your own logic or blocking the execution of the operation.\n */\n readonly callbacks?: EntityCallbacks<M, USER>;\n\n /**\n * Pass your own selection controller if you want to control selected\n * entities externally.\n * @see useSelectionController\n */\n selectionController?: SelectionController<M>;\n\n /**\n * Force a filter in this view. If applied, the rest of the filters will\n * be disabled. Filters applied with this prop cannot be changed.\n * e.g. `fixedFilter: { age: [\">\", 18] }`\n * e.g. `fixedFilter: { related_user: [\"==\", new EntityReference(\"sdc43dsw2\", \"users\")] }`\n */\n readonly fixedFilter?: FilterValues<Extract<keyof M, string> | (string & {})>;\n\n /**\n * Initial filters applied to the collection this collection is related to.\n * Defaults to none. Filters applied with this prop can be changed.\n * e.g. `defaultFilter: { age: [\">\", 18] }`\n * e.g. `defaultFilter: { related_user: [\"==\", new EntityReference(\"sdc43dsw2\", \"users\")] }`\n */\n readonly defaultFilter?: FilterValues<Extract<keyof M, string> | (string & {})>; // setting FilterValues<M> can break defining collections by code\n\n /**\n * Pre-defined filter presets that appear as quick-access options in the\n * collection toolbar. Each preset applies a set of filters (and\n * optionally a sort order) with a single click.\n *\n * ```ts\n * filterPresets: [\n * {\n * label: \"Shipped this month\",\n * filterValues: {\n * status: [\"==\", \"shipped\"],\n * order_date: [\">=\", new Date(Date.now() - 30 * 86400000)]\n * }\n * }\n * ]\n * ```\n */\n readonly filterPresets?: FilterPreset<Extract<keyof M, string> | (string & {})>[];\n\n /**\n * Default sort applied to this collection.\n * When setting this prop, entities will have a default order\n * applied in the collection.\n * e.g. `sort: [\"order\", \"asc\"]`\n */\n readonly sort?: [Extract<keyof M, string> | (string & {}), \"asc\" | \"desc\"];\n\n /**\n * You can add additional fields to the collection view by implementing\n * an additional field delegate.\n */\n readonly additionalFields?: AdditionalFieldDelegate<M, USER>[];\n\n /**\n * Default size of the rendered collection\n */\n defaultSize?: CollectionSize;\n\n /**\n * Can the elements in this collection be edited inline in the collection\n * view. If this flag is set to false but `permissions.edit` is `true`, entities\n * can still be edited in the side panel\n */\n inlineEditing?: boolean;\n\n /**\n * Should this collection be hidden from the main navigation panel, if\n * it is at the root level, or in the entity side panel if it's a\n * subcollection.\n * It will still be accessible if you reach the specified path.\n * You can also use this collection as a reference target.\n */\n hideFromNavigation?: boolean;\n\n /**\n * If you want to open custom views or subcollections by default when opening the edit\n * view of an entity, you can specify the path to the view here.\n * The path is relative to the current collection. For example if you have a collection\n * that has a custom view as well as a subcollection that refers to another entity, you can\n * either specify the path to the custom view or the path to the subcollection.\n */\n defaultSelectedView?: string | DefaultSelectedViewBuilder;\n\n /**\n * Should the ID of this collection be hidden from the form view.\n */\n hideIdFromForm?: boolean;\n\n /**\n * Should the ID of this collection be hidden from the grid view.\n */\n hideIdFromCollection?: boolean;\n\n /**\n * If set to true, the form will be auto-saved when the user changes\n * the value of a field.\n * Defaults to false.\n * When a new entity is created, this property can be updated to generated a new ID\n */\n formAutoSave?: boolean;\n\n /**\n *\n */\n exportable?: boolean | ExportConfig<USER>;\n\n /**\n * User id of the owner of this collection. This is used only by plugins, or if you\n * are writing custom code\n */\n ownerId?: string;\n\n /**\n * Arbitrary key-value metadata for external consumers.\n * Not interpreted by Rebase — passed through serialization unchanged.\n * Used by domain apps to store custom per-collection config.\n */\n metadata?: Record<string, unknown>;\n\n /**\n * Overrides for the entity view, like the data source or the storage source.\n */\n overrides?: EntityOverrides;\n\n /**\n * Width of the side dialog (in pixels) when opening an entity in this collection.\n */\n sideDialogWidth?: number | string;\n\n /**\n * If set to true, the default values of the properties will be applied\n * to the entity every time the entity is updated (not only when created).\n * Defaults to false.\n */\n alwaysApplyDefaultValues?: boolean;\n\n /**\n * If set to true, a tab including the JSON representation of the entity will be included.\n */\n includeJsonView?: boolean;\n\n /**\n * If set to true, changes to the entity will be saved in a subcollection.\n * This prop has no effect if the history plugin is not enabled\n */\n history?: boolean;\n\n /**\n * Should local changes be backed up in local storage, to prevent data loss on\n * accidental navigations.\n * - `manual_apply`: When the user navigates back to an entity with local changes,\n * they will be prompted to restore the changes.\n * - `auto_apply`: When the user navigates back to an entity with local changes,\n * the changes will be automatically applied.\n * - `false`: Local changes will not be backed up.\n * Defaults to `manual_apply`.\n */\n localChangesBackup?: \"manual_apply\" | \"auto_apply\" | false;\n\n /**\n * Default view mode for displaying this collection.\n * - \"table\": Display entities in a table with inline editing (default)\n * - \"cards\": Display entities as a grid of cards with thumbnails\n * - \"kanban\": Display entities in a Kanban board grouped by a property\n * Defaults to \"table\".\n */\n defaultViewMode?: ViewMode;\n\n /**\n * Which view modes are available for this collection.\n * Possible values: \"table\", \"cards\", \"kanban\".\n * Defaults to all three: [\"table\", \"cards\", \"kanban\"].\n * Note: \"kanban\" will only be available if the collection has at least\n * one string property with `enum` defined, regardless of this setting.\n */\n enabledViews?: ViewMode[];\n\n /**\n * Configuration for Kanban board view mode.\n * When set, the Kanban view mode becomes available.\n */\n kanban?: KanbanConfig<M>;\n\n /**\n * Property key to use for ordering items.\n * Must reference a string/text property. When items are reordered,\n * this property will be updated with lexicographic sort keys\n * (e.g. \"a0\", \"a1\", \"a0V\") using string-based fractional indexing.\n * Used by Kanban view for ordering within columns\n * and can be used for general ordering purposes.\n */\n readonly orderProperty?: Extract<keyof M, string> | (string & {});\n\n /**\n * Actions that can be performed on the entities in this collection.\n */\n entityActions?: EntityAction<M, USER>[];\n\n /**\n * Builder for the collection actions rendered in the toolbar\n */\n Actions?: ComponentRef<CollectionActionsProps>[];\n\n /**\n * The database table name for this collection.\n * Automatically set for PostgreSQL collections.\n * For non-SQL backends, this may be undefined.\n */\n table?: string;\n\n /**\n * Relations defined for this collection.\n * Populated at normalization time from inline relation properties\n * or explicit relation definitions.\n */\n relations?: Relation[];\n\n /**\n * Security rules for this collection (Row Level Security).\n * When defined, the backend enforces access control policies.\n */\n securityRules?: SecurityRule[];\n\n /**\n * Collection-scoped component overrides. These take precedence over\n * global overrides set on `<Rebase>`, but only within this collection's\n * views (entity form, detail view, table, empty state, etc.).\n *\n * Only collection-scoped components (like `Entity.Form`, `Collection.EmptyState`,\n * `Collection.Card`, etc.) can be overridden here. App-level components\n * (like `Shell.AppBar`, `HomePage`) can only be overridden at the `<Rebase>` level.\n *\n * @example\n * ```tsx\n * const productsCollection: PostgresCollection = {\n * name: \"Products\",\n * slug: \"products\",\n * table: \"products\",\n * components: {\n * \"Entity.Form\": { Component: ProductCustomForm },\n * \"Collection.Card\": { Component: ProductCard },\n * },\n * properties: { ... }\n * };\n * ```\n */\n components?: CollectionComponentOverrideMap;\n}\n\n// ── Driver-specific collection types ──────────────────────────────────\n\n/**\n * A collection backed by PostgreSQL (or any SQL database).\n * Adds support for SQL-style relations (JOINs) and Row Level Security.\n *\n * Use this type instead of {@link EntityCollection} when you want\n * compile-time safety that only SQL-relevant fields appear.\n *\n * @group Models\n */\nexport interface PostgresCollection<M extends Record<string, unknown> = Record<string, unknown>, USER extends User = User>\n extends BaseEntityCollection<M, USER> {\n properties: Properties;\n\n /**\n * The driver for this collection. For Postgres collections this\n * can be omitted (Postgres is the default) or set to `\"postgres\"`.\n */\n driver?: \"postgres\" | undefined;\n\n /**\n * The PostgreSQL table name for this collection.\n */\n table: string;\n\n /**\n * The PostgreSQL schema name for this table.\n * E.g. \"public\", \"rebase\", \"auth\".\n * If not specified, \"public\" is used (or the default search path).\n */\n schema?: string;\n\n /**\n * For SQL databases, you can define the relations between collections here.\n * Relations describe JOINs, foreign keys, and junction tables.\n */\n relations?: Relation[];\n\n /**\n * Security rules for this collection (Supabase-style Row Level Security).\n * When defined, the schema generator will enable RLS on the table and\n * create the corresponding PostgreSQL policies.\n *\n * Supports three levels of expressiveness:\n * 1. **Convenience shortcuts** — `ownerField`, `access`, `roles`\n * 2. **Raw SQL** — `using` and `withCheck` for full PostgreSQL power\n * 3. **Combined** — mix shortcuts with `roles` for common patterns\n *\n * The authenticated user context is available in raw SQL via:\n * - `auth.uid()` — the current user's ID\n * - `auth.roles()` — comma-separated app role IDs\n * - `auth.jwt()` — full JWT claims as JSONB\n */\n securityRules?: SecurityRule[];\n}\n\n/**\n * A collection backed by Firebase / Firestore.\n * Adds support for subcollections (nested document collections).\n *\n * Use this type instead of {@link EntityCollection} when you want\n * compile-time safety that only Firestore-relevant fields appear.\n *\n * @group Models\n */\nexport interface FirebaseCollection<M extends Record<string, unknown> = Record<string, unknown>, USER extends User = User>\n extends BaseEntityCollection<M, USER> {\n /**\n * The driver for this collection. Must be set to `\"firestore\"`.\n */\n driver: \"firestore\";\n\n /**\n * You can add subcollections to your entity in the same way you define the root\n * collections. The collections added here will be displayed when opening\n * the side dialog of an entity.\n */\n subcollections?: () => EntityCollection<Record<string, unknown>>[];\n}\n\n/**\n * A collection backed by MongoDB.\n *\n * Use this type instead of {@link EntityCollection} when you want\n * compile-time safety that only MongoDB-relevant fields appear.\n *\n * @group Models\n */\nexport interface MongoDBCollection<M extends Record<string, unknown> = Record<string, unknown>, USER extends User = User>\n extends BaseEntityCollection<M, USER> {\n\n /**\n * The driver for this collection. Must be set to `\"mongodb\"`.\n */\n driver: \"mongodb\";\n}\n\n/**\n * A collection backed by any data source.\n * This is a discriminated union — use {@link PostgresCollection},\n * {@link FirebaseCollection}, or {@link MongoDBCollection} for\n * driver-specific type safety.\n *\n * @group Models\n */\nexport type EntityCollection<M extends Record<string, unknown> = Record<string, unknown>, USER extends User = User> =\n | PostgresCollection<M, USER>\n | FirebaseCollection<M, USER>\n | MongoDBCollection<M, USER>;\n\n// ── Capability intersection types ─────────────────────────────────────\n// Use these after a `getDataSourceCapabilities()` guard to safely access\n// driver-specific fields without coupling to a concrete driver type.\n\n/**\n * An EntityCollection that supports SQL-style relations (e.g. Postgres).\n * @deprecated Use `EntityCollection` directly — `table`, `relations`, and `securityRules` are now on `BaseEntityCollection`.\n */\nexport type CollectionWithRelations<M extends Record<string, unknown> = Record<string, unknown>> =\n EntityCollection<M> & { table?: string; relations?: Relation[]; securityRules?: SecurityRule[] };\n\n/** An EntityCollection that supports subcollections (e.g. Firestore). */\nexport type CollectionWithSubcollections<M extends Record<string, unknown> = Record<string, unknown>> =\n EntityCollection<M> & { subcollections?: () => EntityCollection<Record<string, unknown>>[] };\n\n\n// ── Type guards ───────────────────────────────────────────────────────\n\n/**\n * Type guard for PostgreSQL collections.\n * Returns true if the collection uses the Postgres driver (or the default driver).\n * @group Models\n */\nexport function isPostgresCollection<M extends Record<string, unknown> = Record<string, unknown>, USER extends User = User>(\n collection: EntityCollection<M, USER>\n): collection is PostgresCollection<M, USER> {\n return !collection.driver || collection.driver === \"postgres\";\n}\n\n/**\n * Type guard for Firebase / Firestore collections.\n * @group Models\n */\nexport function isFirebaseCollection<M extends Record<string, unknown> = Record<string, unknown>, USER extends User = User>(\n collection: EntityCollection<M, USER>\n): collection is FirebaseCollection<M, USER> {\n return collection.driver === \"firestore\";\n}\n\n/**\n * Type guard for MongoDB collections.\n * @group Models\n */\nexport function isMongoDBCollection<M extends Record<string, unknown> = Record<string, unknown>, USER extends User = User>(\n collection: EntityCollection<M, USER>\n): collection is MongoDBCollection<M, USER> {\n return collection.driver === \"mongodb\";\n}\n\n\n/**\n * Configuration for Kanban board view mode.\n * @group Collections\n */\nexport interface KanbanConfig<M extends Record<string, unknown> = Record<string, unknown>> {\n /**\n * Property key to use for Kanban board columns.\n * Must reference a string property with `enum` values defined.\n * Entities will be grouped into columns based on this property's value.\n * The column order is determined by the order of `enum` values in the property.\n */\n columnProperty: Extract<keyof M, string> | (string & {});\n}\n\n/**\n * View mode for displaying a collection.\n * - \"list\": Simple, clean list view — the classic CMS default\n * - \"table\": Table with inline editing\n * - \"cards\": Grid of visual cards with thumbnails\n * - \"kanban\": Board view grouped by a property\n * @group Collections\n */\nexport type ViewMode = \"list\" | \"table\" | \"cards\" | \"kanban\";\n\n/**\n * Parameter passed to the `Actions` prop in the collection configuration.\n * The component will receive this prop when it is rendered in the collection\n * toolbar.\n *\n * @group Models\n */\nexport interface CollectionActionsProps<M extends Record<string, unknown> = Record<string, unknown>, USER extends User = User, EC extends EntityCollection<M> = EntityCollection<M>> {\n /**\n * Full collection path of this entity. This is the full path, like\n * `users/1234/addresses`\n */\n path: string;\n\n /**\n * Path of the last collection, like `addresses`\n */\n relativePath: string;\n\n /**\n * Array of the parent path segments like `['users']`\n */\n parentCollectionSlugs: string[];\n parentEntityIds: string[];\n\n /**\n * The collection configuration\n */\n collection: EC;\n\n /**\n * Use this controller to get the selected entities and to update the\n * selected entities state.\n */\n selectionController: SelectionController<M>;\n\n /**\n * Use this controller to get the table controller and to update the\n * table controller state.\n */\n tableController: EntityTableController<M>;\n\n /**\n * Context of the app status\n */\n context: RebaseContext<USER>;\n\n /**\n * Count of the entities in this collection.\n * undefined means the count is still loading.\n */\n collectionEntitiesCount?: number;\n\n /**\n * Programmatically open the new-document form for this collection,\n * optionally pre-populating it with initial field values.\n * The form opens in the same mode configured for the collection\n * (side panel, full screen, or split).\n *\n * This is the primary hook for workflows that need to create a document\n * from external data — e.g. fetching content from a URL, importing from\n * a third-party API, or duplicating from another system.\n *\n * @example\n * // Inside a custom CollectionAction component:\n * openNewDocument({ title: \"Fetched title\", body: \"...\" });\n */\n openNewDocument: (defaultValues?: Record<string, unknown>) => void;\n\n}\n\n/**\n * Use this controller to retrieve the selected entities or modify them in\n * an {@link EntityCollection}\n * @group Models\n */\nexport interface SelectionController<M extends Record<string, unknown> = Record<string, unknown>> {\n selectedEntities: Entity<M>[];\n setSelectedEntities(entities: Entity<M>[]): void;\n setSelectedEntities(action: (prev: Entity<M>[]) => Entity<M>[]): void;\n isEntitySelected(entity: Entity<M>): boolean;\n toggleEntitySelection(entity: Entity<M>, newSelectedState?: boolean): void;\n}\n\n/**\n * Filter conditions in a `Query.where()` clause are specified using the\n * strings `<`, `<=`, `==`, `>=`, `>`, `array-contains`, `in`, and `array-contains-any`.\n * @group Models\n */\nexport type WhereFilterOp =\n | \"<\"\n | \"<=\"\n | \"==\"\n | \"!=\"\n | \">=\"\n | \">\"\n | \"array-contains\"\n | \"in\"\n | \"not-in\"\n | \"array-contains-any\";\n\n/**\n * Used to define filters applied in collections\n *\n * e.g. `{ age: [\">=\", 18] }`\n *\n * @group Models\n */\nexport type FilterValues<Key extends string> =\n Partial<Record<Key, [WhereFilterOp, unknown] | [WhereFilterOp, unknown][]>>;\n\n/**\n * A pre-defined filter preset for quick access in the collection toolbar.\n * Users can select a preset to instantly apply a set of filters and\n * optionally a sort order.\n *\n * @group Models\n */\nexport interface FilterPreset<Key extends string = string> {\n /**\n * Display label shown in the preset menu.\n * If omitted, a summary is auto-generated from the filter keys.\n */\n label?: string;\n\n /**\n * The filter values to apply when this preset is selected.\n */\n filterValues: FilterValues<Key>;\n\n /**\n * Optional sort override to apply alongside the filter values.\n */\n sort?: [Key, \"asc\" | \"desc\"];\n}\n\n\n/**\n * Used to indicate valid filter combinations (e.g. created in Firestore)\n * If the user selects a specific filter/sort combination, the CMS checks if it's\n * valid, otherwise it reverts to the simpler valid case\n * @group Models\n */\nexport type FilterCombination<Key extends string> = Partial<Record<Key, \"asc\" | \"desc\">>;\n\n/**\n * Sizes in which a collection can be rendered\n * @group Models\n */\nexport type CollectionSize = \"xs\" | \"s\" | \"m\" | \"l\" | \"xl\";\n\nexport type AdditionalFieldDelegateProps<M extends Record<string, unknown> = Record<string, unknown>, USER extends User = User> = {\n entity: Entity<M>,\n context: RebaseContext<USER>\n};\n\n/**\n * Use this interface for adding additional fields to entity collection views and forms.\n * @group Models\n */\nexport interface AdditionalFieldDelegate<M extends Record<string, unknown> = Record<string, unknown>,\n USER extends User = User> {\n\n /**\n * ID of this column. You can use this id in the `properties` field of the\n * collection in any order you want\n */\n key: string;\n\n /**\n * Header of this column\n */\n name: string;\n\n /**\n * Width of the generated column in pixels\n */\n width?: number;\n\n /**\n * Builder for the custom field\n */\n Builder?(props: { entity: Entity<M>, context: RebaseContext<USER> }): React.ReactNode;\n\n\n /**\n * If this column needs to update dynamically based on other properties,\n * you can define an array of keys as strings with the\n * `dependencies` prop.\n * e.g. [\"name\", \"surname\"]\n * This is a performance optimization, if you don't define dependencies\n * it will be updated in every render.\n */\n dependencies?: NoInfer<Extract<keyof M, string>> | NoInfer<Extract<keyof M, string>>[] | (string & {}) | (string & {})[];\n\n /**\n * Use this prop to define the value of the column as a string or number.\n * This is the value that will be used for exporting the collection.\n * If `Builder` is defined, this prop will be ignored in the collection\n * view.\n * @param entity\n */\n value?(props: {\n entity: Entity<M>,\n context: RebaseContext\n }): string | number | Promise<string | number> | undefined;\n}\n\n\nexport type InferCollectionType<S extends EntityCollection> = S extends EntityCollection<infer M> ? M : never;\n\n/**\n * Used in the {@link EntityCollection#defaultSelectedView} to define the default\n * @group Models\n */\nexport type DefaultSelectedViewBuilder = (params: DefaultSelectedViewParams) => string | undefined;\n\n/**\n * Used in the {@link EntityCollection#defaultSelectedView} to define the default\n * @group Models\n */\nexport type DefaultSelectedViewParams = {\n status?: EntityStatus;\n entityId?: string | number;\n};\n/**\n * You can use this controller to control the table view of a collection.\n */\nexport type EntityTableController<M extends Record<string, unknown> = Record<string, unknown>> = {\n data: Entity<M>[];\n dataLoading: boolean;\n noMoreToLoad: boolean;\n dataLoadingError?: Error;\n filterValues?: FilterValues<Extract<keyof M, string> | (string & {})>;\n setFilterValues?: (filterValues: FilterValues<Extract<keyof M, string> | (string & {})>) => void;\n sortBy?: [Extract<keyof M, string> | (string & {}), \"asc\" | \"desc\"];\n setSortBy?: (sortBy?: [Extract<keyof M, string> | (string & {}), \"asc\" | \"desc\"]) => void;\n searchString?: string;\n setSearchString?: (searchString?: string) => void;\n clearFilter?: () => void;\n itemCount?: number;\n setItemCount?: (itemCount: number) => void;\n initialScroll?: number;\n onScroll?: (props: {\n scrollDirection: \"forward\" | \"backward\",\n scrollOffset: number,\n scrollUpdateWasRequested: boolean\n }) => void;\n paginationEnabled?: boolean;\n pageSize?: number;\n checkFilterCombination?: (filterValues: FilterValues<string>,\n sortBy?: [string, \"asc\" | \"desc\"]) => boolean;\n popupCell?: SelectedCellProps<M>;\n setPopupCell?: (popupCell?: SelectedCellProps<M>) => void;\n\n onAddColumn?: (column: string) => void;\n}\n\nexport type SelectedCellProps<M extends Record<string, unknown> = Record<string, unknown>> = {\n propertyKey: Extract<keyof M, string> | (string & {});\n cellRect: DOMRect;\n width: number;\n height: number;\n entityPath: string;\n entityId: string | number;\n};\n\n/**\n * SQL operation that a policy applies to.\n * @group Models\n */\nexport type SecurityOperation = \"select\" | \"insert\" | \"update\" | \"delete\" | \"all\";\n\n/**\n * Flexible Row Level Security rule for a collection.\n *\n * Inspired by Supabase's approach to PostgreSQL RLS. Rules can range from\n * simple convenience shortcuts to fully custom SQL expressions, giving you the\n * full power of PostgreSQL Row Level Security.\n *\n * The authenticated user's identity is available in raw SQL via:\n * - `auth.uid()` — the user's ID\n * - `auth.roles()` — comma-separated app role IDs\n * - `auth.jwt()` — full JWT claims as JSONB\n *\n * These are set automatically per-transaction by the backend.\n *\n * **How rules combine:** PostgreSQL evaluates all matching policies for an\n * operation. Permissive rules are OR'd together (any one passing is enough).\n * Restrictive rules are AND'd (all must pass). This mirrors Supabase behavior.\n *\n * **Mutual exclusivity:** `ownerField`, `access`, and raw SQL (`using`/`withCheck`)\n * cannot be combined. The type system enforces this — attempting to set\n * conflicting fields will produce a compile-time error.\n *\n * @group Models\n */\nexport type SecurityRule = OwnerSecurityRule | PublicSecurityRule | RawSQLSecurityRule | RolesOnlySecurityRule;\n\n/**\n * Shared fields for all SecurityRule variants.\n * @group Models\n */\nexport interface SecurityRuleBase {\n /**\n * Optional human-readable name for the policy.\n * If not provided, one will be auto-generated from the table name and operation.\n * Must be unique per table.\n *\n * When using `operations` (array), each generated policy will have the\n * operation name appended, e.g. `\"owner_access_select\"`, `\"owner_access_update\"`.\n */\n name?: string;\n\n /**\n * Which SQL operation this policy applies to.\n * Use this when the policy targets a single operation or all operations.\n *\n * For multiple specific operations, use `operations` (array) instead.\n * If neither is specified, defaults to `\"all\"`.\n *\n * @default \"all\"\n */\n operation?: SecurityOperation;\n\n /**\n * Array of SQL operations this policy applies to.\n * The compiler will generate one PostgreSQL policy per operation, sharing\n * the same configuration.\n *\n * This reduces boilerplate when the same rule applies to multiple (but not all)\n * operations.\n *\n * Takes precedence over `operation` (singular) if both are specified.\n *\n * @example\n * // Same rule for select and update\n * { operations: [\"select\", \"update\"], ownerField: \"user_id\" }\n *\n * @example\n * // Equivalent to operation: \"all\"\n * { operations: [\"all\"], ownerField: \"user_id\" }\n */\n operations?: SecurityOperation[];\n\n /**\n * Whether this policy is `\"permissive\"` (default) or `\"restrictive\"`.\n *\n * - **permissive**: Multiple permissive policies for the same operation are\n * OR'd together — if *any* passes, access is granted.\n * - **restrictive**: Restrictive policies are AND'd with all permissive\n * policies — they act as additional gates that *must* also pass.\n *\n * This is the same model as PostgreSQL / Supabase.\n *\n * @default \"permissive\"\n */\n mode?: \"permissive\" | \"restrictive\";\n\n /**\n * **Shortcut.** Restrict this rule to users that have one of these\n * application-level roles.\n *\n * **Important:** These are NOT native PostgreSQL database roles. They are\n * application roles managed by Rebase, stored in the `rebase.user_roles`\n * table, and injected into each transaction via `auth.roles()`.\n *\n * Generates a condition like:\n * `auth.roles() ~ '<role1>|<role2>'`\n *\n * Can be combined with `ownerField`, `access`, or raw `using`/`withCheck`.\n * When combined, the role check is AND'd with the other condition.\n *\n * @example\n * // Only admins can delete\n * { operation: \"delete\", roles: [\"admin\"] }\n *\n * @example\n * // Admins have unfiltered read access to all rows\n * { operation: \"select\", roles: [\"admin\"], using: \"true\" }\n */\n roles?: string[];\n\n // ── Advanced: native PostgreSQL role targeting ───────────────────────\n\n /**\n * **Advanced.** Native PostgreSQL database roles the policy applies to.\n *\n * By default, all generated policies target the `public` role (i.e.\n * every database connection). This is correct for most setups where\n * a single database role is used for all connections.\n *\n * **Important:** These are NOT the same as the application-level `roles`\n * (admin, editor, viewer, etc.) — those are enforced in the USING/WITH\n * CHECK clauses via `auth.roles()`. This field controls the PostgreSQL\n * `TO` clause in `CREATE POLICY ... TO role_name`.\n *\n * Use this if you have dedicated PostgreSQL roles (e.g. `app_read`,\n * `app_write`) and want policies to target specific ones.\n *\n * @default [\"public\"]\n *\n * @example\n * // Only apply this policy when connected as `app_role`\n * { operation: \"select\", access: \"public\", pgRoles: [\"app_role\"] }\n */\n pgRoles?: string[];\n}\n\n/**\n * Security rule that grants access based on row ownership.\n * Generates a USING/WITH CHECK clause like: `<column> = auth.uid()`\n *\n * Cannot be combined with `using`, `withCheck`, or `access`.\n *\n * @example\n * { operation: \"all\", ownerField: \"user_id\" }\n *\n * @group Models\n */\nexport interface OwnerSecurityRule extends SecurityRuleBase {\n /** The property (column) that stores the owner's user ID. */\n ownerField: string;\n access?: never;\n using?: never;\n withCheck?: never;\n}\n\n/**\n * Security rule that grants unrestricted row access (no row filtering).\n * Generates `USING (true)`.\n *\n * This means \"no row-level filter\", NOT \"anonymous/unauthenticated access\".\n * Authentication is still enforced at the API layer — this only controls which\n * *rows* authenticated users can see.\n *\n * Cannot be combined with `using`, `withCheck`, or `ownerField`.\n *\n * @example\n * // Public read (any authenticated user sees all rows)\n * { operation: \"select\", access: \"public\" }\n *\n * @group Models\n */\nexport interface PublicSecurityRule extends SecurityRuleBase {\n /** Grant unrestricted row access for this operation. */\n access: \"public\";\n ownerField?: never;\n using?: never;\n withCheck?: never;\n}\n\n/**\n * Security rule using raw SQL expressions for full PostgreSQL RLS power.\n *\n * Cannot be combined with `ownerField` or `access`.\n *\n * You can reference columns via `{column_name}` which will be resolved to\n * `table.column_name` in the generated Drizzle code.\n *\n * @example\n * // Rows published in the last 30 days are visible\n * { operation: \"select\", using: \"{published_at} > now() - interval '30 days'\" }\n *\n * @example\n * // Only the owner, or users with 'moderator' role\n * {\n * operation: \"select\",\n * using: \"{user_id} = auth.uid() OR auth.roles() ~ 'moderator'\"\n * }\n *\n * @group Models\n */\nexport interface RawSQLSecurityRule extends SecurityRuleBase {\n /**\n * Raw SQL expression for the `USING` clause.\n * This controls which *existing* rows are visible / can be modified / deleted.\n * Applied to SELECT, UPDATE, and DELETE.\n */\n using: string;\n\n /**\n * Raw SQL expression for the `WITH CHECK` clause.\n * This controls which *new/updated* row values are allowed.\n * Applied to INSERT and UPDATE.\n *\n * If not provided on INSERT/UPDATE policies, falls back to `using`\n * (which matches PostgreSQL's own default behavior).\n */\n withCheck?: string;\n\n ownerField?: never;\n access?: never;\n}\n\n/**\n * Security rule that only filters by application roles, without any\n * row-level condition (USING/WITH CHECK).\n *\n * Useful for simple \"only admins can access this table\" rules where\n * no per-row filtering is needed.\n *\n * @example\n * // Only admins can delete\n * { operation: \"delete\", roles: [\"admin\"] }\n *\n * @group Models\n */\nexport interface RolesOnlySecurityRule extends SecurityRuleBase {\n ownerField?: never;\n access?: never;\n using?: never;\n withCheck?: never;\n}\n\n/**\n * Configuration for authentication collections.\n *\n * Controls what happens when admins create users, reset passwords,\n * and which entity actions are auto-injected.\n *\n * Use `auth: true` as sugar for `{ enabled: true }` with all defaults.\n *\n * @example Override user creation\n * ```ts\n * auth: {\n * enabled: true,\n * onCreateUser: async (values, ctx) => {\n * const hash = await ctx.hashPassword(\"welcome123\");\n * return {\n * values: { ...values, passwordHash: hash, emailVerified: true },\n * temporaryPassword: \"welcome123\",\n * };\n * },\n * }\n * ```\n *\n * @example Disable the reset-password entity action\n * ```ts\n * auth: {\n * enabled: true,\n * actions: { resetPassword: false },\n * }\n * ```\n *\n * @group Models\n */\nexport interface AuthCollectionConfig {\n /** Set to true to mark this collection as the authentication collection. */\n enabled: boolean;\n\n /**\n * Called when an admin creates a user via the collection REST API.\n *\n * Default: generate password → hash → normalize email → save →\n * send invitation email (or return temp password if no email configured).\n *\n * Override to implement custom invitation flows, LDAP sync, etc.\n */\n onCreateUser?: (\n values: Record<string, unknown>,\n ctx: AuthCollectionContext\n ) => Promise<AuthCollectionCreateResult>;\n\n /**\n * Called when an admin resets a user's password via the admin panel.\n *\n * Default: generate reset token → send email (or generate + return temp password).\n * Override for custom reset flows.\n */\n onResetPassword?: (\n userId: string,\n ctx: AuthCollectionContext\n ) => Promise<AuthCollectionResetResult>;\n\n /**\n * Control which auth-specific entity actions are auto-injected.\n *\n * Default: `{ resetPassword: true }` — the framework auto-injects\n * the built-in `resetPasswordAction` into the collection's entity actions.\n *\n * Set to `false` to disable, or pass a custom `EntityAction` to replace the UI.\n */\n actions?: {\n resetPassword?: boolean | EntityAction;\n };\n}\n\n/**\n * Context provided to collection-level auth hooks.\n *\n * This is a simplified facade over the server internals —\n * it exposes only what's needed for custom auth flows without\n * coupling collection config to internal interfaces.\n *\n * @group Models\n */\nexport interface AuthCollectionContext {\n /** Hash a password using the configured algorithm (scrypt by default). */\n hashPassword: (password: string) => Promise<string>;\n /** Send an email. Only available when email service is configured. */\n sendEmail?: (options: { to: string; subject: string; html: string; text?: string }) => Promise<void>;\n /** Whether the email service is configured and available. */\n emailConfigured: boolean;\n /** The app name from email config (for templates). */\n appName: string;\n /** The base URL for password reset links. */\n resetPasswordUrl: string;\n}\n\n/**\n * Result of a collection-level `onCreateUser` hook.\n * @group Models\n */\nexport interface AuthCollectionCreateResult {\n /** Processed values to persist (must include passwordHash, NOT raw password). */\n values: Record<string, unknown>;\n /** If set, shown to the admin in the creation result dialog. */\n temporaryPassword?: string;\n /** Whether an invitation email was sent. */\n invitationSent?: boolean;\n}\n\n/**\n * Result of a collection-level `onResetPassword` hook.\n * @group Models\n */\nexport interface AuthCollectionResetResult {\n /** If set, shown to the admin. */\n temporaryPassword?: string;\n /** Whether a reset email was sent. */\n invitationSent?: boolean;\n}\n","import type { Entity } from \"./entities\";\nimport type { EntityCollection, FilterValues, WhereFilterOp } from \"./collections\";\nimport type { AuthAdapter } from \"./auth_adapter\";\n\n// =============================================================================\n// DATABASE CONNECTION INTERFACES\n// =============================================================================\n\n/**\n * Abstract database connection interface.\n * Represents a connection to any database system.\n */\nexport interface DatabaseConnection {\n /**\n * Type identifier for this database (e.g., 'postgres', 'mongodb', 'mysql')\n */\n readonly type: string;\n\n /**\n * Whether the connection is currently active\n */\n readonly isConnected?: boolean;\n\n /**\n * Close the database connection and release resources.\n */\n close?(): Promise<void>;\n}\n\n// =============================================================================\n// QUERY BUILDING INTERFACES\n// =============================================================================\n\n/**\n * A single filter condition for database queries\n */\nexport interface QueryFilter {\n field: string;\n operator: WhereFilterOp;\n value: unknown;\n}\n\n/**\n * Options for fetching a collection of entities\n */\nexport interface FetchCollectionOptions<M extends Record<string, unknown> = Record<string, unknown>> {\n filter?: FilterValues<Extract<keyof M, string>>;\n orderBy?: string;\n order?: \"desc\" | \"asc\";\n limit?: number;\n offset?: number;\n startAfter?: unknown;\n searchString?: string;\n databaseId?: string;\n collection?: EntityCollection;\n}\n\n/**\n * Options for searching entities\n */\nexport interface SearchOptions<M extends Record<string, unknown> = Record<string, unknown>> {\n filter?: FilterValues<Extract<keyof M, string>>;\n orderBy?: string;\n order?: \"desc\" | \"asc\";\n limit?: number;\n databaseId?: string;\n collection?: EntityCollection;\n}\n\n/**\n * Options for counting entities\n */\nexport interface CountOptions<M extends Record<string, unknown> = Record<string, unknown>> {\n filter?: FilterValues<Extract<keyof M, string>>;\n searchString?: string;\n databaseId?: string;\n}\n\n/**\n * Abstract condition builder interface.\n * Implementations translate Rebase filter conditions to database-specific queries.\n *\n * Note: This interface can be implemented as instance methods or as a class with static methods.\n * For static implementations (like DrizzleConditionBuilder), use the ConditionBuilderStatic type.\n *\n * @template T The type of condition returned by the builder (e.g., SQL for PostgreSQL, Filter<Document> for MongoDB)\n */\nexport interface ConditionBuilder<T = unknown> {\n /**\n * Build filter conditions from Rebase FilterValues\n */\n buildFilterConditions<M extends Record<string, unknown>>(\n filter: FilterValues<Extract<keyof M, string>>,\n collectionPath: string,\n ...args: unknown[]\n ): T[];\n\n /**\n * Build search conditions for text search\n */\n buildSearchConditions(\n searchString: string,\n properties: Record<string, unknown>,\n ...args: unknown[]\n ): T[];\n\n /**\n * Combine multiple conditions with AND operator\n */\n combineConditionsWithAnd(conditions: T[]): T | undefined;\n\n /**\n * Combine multiple conditions with OR operator\n */\n combineConditionsWithOr(conditions: T[]): T | undefined;\n}\n\n/**\n * Static condition builder type for implementations using static methods.\n * Use this type when the class provides static methods rather than instance methods.\n *\n * @example\n * // DrizzleConditionBuilder satisfies this type\n * const builder: ConditionBuilderStatic<SQL> = DrizzleConditionBuilder;\n */\nexport type ConditionBuilderStatic<T = unknown> = {\n buildFilterConditions<M extends Record<string, unknown>>(\n filter: FilterValues<Extract<keyof M, string>>,\n ...args: unknown[]\n ): T[];\n buildSearchConditions(\n searchString: string,\n properties: Record<string, unknown>,\n ...args: unknown[]\n ): T[];\n combineConditionsWithAnd(conditions: T[]): T | undefined;\n combineConditionsWithOr(conditions: T[]): T | undefined;\n};\n\n// =============================================================================\n// ENTITY REPOSITORY INTERFACES\n// =============================================================================\n\n/**\n * Abstract entity repository interface.\n * Handles all CRUD operations for entities in the database.\n *\n * Implementations should handle:\n * - Entity serialization/deserialization\n * - Relation resolution\n * - ID generation and conversion\n */\nexport interface EntityRepository {\n /**\n * Fetch a single entity by ID\n */\n fetchEntity<M extends Record<string, unknown>>(\n collectionPath: string,\n entityId: string | number,\n databaseId?: string\n ): Promise<Entity<M> | undefined>;\n\n /**\n * Fetch a collection of entities with optional filtering, ordering, and pagination\n */\n fetchCollection<M extends Record<string, unknown>>(\n collectionPath: string,\n options?: FetchCollectionOptions<M>\n ): Promise<Entity<M>[]>;\n\n /**\n * Search entities by text\n */\n searchEntities<M extends Record<string, unknown>>(\n collectionPath: string,\n searchString: string,\n options?: SearchOptions<M>\n ): Promise<Entity<M>[]>;\n\n /**\n * Count entities in a collection\n */\n countEntities<M extends Record<string, unknown>>(\n collectionPath: string,\n options?: CountOptions<M>\n ): Promise<number>;\n\n /**\n * Save an entity (create or update)\n */\n saveEntity<M extends Record<string, unknown>>(\n collectionPath: string,\n values: Partial<M>,\n entityId?: string | number,\n databaseId?: string\n ): Promise<Entity<M>>;\n\n /**\n * Delete an entity by ID\n */\n deleteEntity(\n collectionPath: string,\n entityId: string | number,\n databaseId?: string\n ): Promise<void>;\n\n /**\n * Check if a field value is unique in a collection\n */\n checkUniqueField(\n collectionPath: string,\n fieldName: string,\n value: unknown,\n excludeEntityId?: string,\n databaseId?: string\n ): Promise<boolean>;\n\n}\n\n// =============================================================================\n// REALTIME INTERFACES\n// =============================================================================\n\n/**\n * Configuration for subscribing to a collection\n */\nexport interface CollectionSubscriptionConfig {\n clientId: string;\n path: string;\n filter?: unknown;\n orderBy?: string;\n order?: \"desc\" | \"asc\";\n limit?: number;\n startAfter?: unknown;\n databaseId?: string;\n searchString?: string;\n}\n\n/**\n * Configuration for subscribing to a single entity\n */\nexport interface EntitySubscriptionConfig {\n clientId: string;\n path: string;\n entityId: string | number;\n}\n\n/**\n * Abstract realtime provider interface.\n * Handles real-time subscriptions and notifications for entity changes.\n */\nexport interface RealtimeProvider {\n /**\n * Subscribe to collection changes\n */\n subscribeToCollection(\n subscriptionId: string,\n config: CollectionSubscriptionConfig,\n callback?: (entities: Entity[]) => void\n ): void;\n\n /**\n * Subscribe to single entity changes\n */\n subscribeToEntity(\n subscriptionId: string,\n config: EntitySubscriptionConfig,\n callback?: (entity: Entity | null) => void\n ): void;\n\n /**\n * Unsubscribe from a subscription\n */\n unsubscribe(subscriptionId: string): void;\n\n /**\n * Notify all relevant subscribers of an entity update\n */\n notifyEntityUpdate(\n path: string,\n entityId: string,\n entity: Entity | null,\n databaseId?: string\n ): Promise<void>;\n\n /**\n * Called when the HTTP server is ready and listening.\n * Useful for providers that need the server address for callbacks.\n */\n onServerReady?(serverInfo: { port: number; hostname?: string }): void;\n\n /**\n * Gracefully shut down the realtime provider.\n * Called during server shutdown to clean up resources.\n */\n destroy?(): Promise<void>;\n\n /**\n * Stop the internal LISTEN client (e.g., PostgreSQL LISTEN/NOTIFY).\n * Called during graceful shutdown before closing database connections.\n */\n stopListening?(): Promise<void>;\n}\n\n// =============================================================================\n// COLLECTION REGISTRY INTERFACES\n// =============================================================================\n\n/**\n * Abstract collection registry interface.\n * Manages registration and lookup of entity collections.\n */\nexport interface CollectionRegistryInterface {\n /**\n * Register a collection\n */\n register(collection: EntityCollection): void;\n\n /**\n * Get a collection by its path\n */\n getCollectionByPath(path: string): EntityCollection | undefined;\n\n /**\n * Get all registered collections\n */\n getCollections(): EntityCollection[];\n}\n\n// =============================================================================\n// DATA TRANSFORMER INTERFACES\n// =============================================================================\n\n/**\n * Abstract data transformer interface.\n * Handles serialization/deserialization between frontend and database formats.\n */\nexport interface DataTransformer {\n /**\n * Transform entity data for storage in the database\n */\n serializeToDatabase<M extends Record<string, unknown>>(\n entity: M,\n collection: EntityCollection\n ): Record<string, unknown>;\n\n /**\n * Transform database data back to entity format\n */\n deserializeFromDatabase<M extends Record<string, unknown>>(\n data: Record<string, unknown>,\n collection: EntityCollection\n ): Promise<M>;\n}\n\n// =============================================================================\n// DATABASE ADMIN — CAPABILITY-SPECIFIC INTERFACES (1.3)\n// =============================================================================\n\n/**\n * Administrative operations for SQL-based databases (PostgreSQL, MySQL, etc.).\n * Used by the SQL Editor, RLS Editor, and schema browser.\n *\n * @group Admin\n */\nexport interface SQLAdmin {\n /**\n * Execute raw SQL against the database.\n */\n executeSql(sql: string, options?: { database?: string; role?: string; params?: unknown[] }): Promise<Record<string, unknown>[]>;\n\n /**\n * Fetch the available databases on the server.\n */\n fetchAvailableDatabases?(): Promise<string[]>;\n\n /**\n * Fetch the available database roles.\n */\n fetchAvailableRoles?(): Promise<string[]>;\n\n /**\n * Fetch the current database name.\n */\n fetchCurrentDatabase?(): Promise<string | undefined>;\n}\n\n/**\n * Administrative operations for document-based databases (MongoDB, Firestore, etc.).\n * Used by future document administration tools.\n *\n * @group Admin\n */\nexport interface DocumentAdmin {\n /**\n * Execute an aggregation pipeline or equivalent query.\n */\n executeAggregate?(pipeline: Record<string, unknown>[]): Promise<Record<string, unknown>[]>;\n\n /**\n * Fetch statistics for a collection (document count, size, etc.).\n */\n fetchCollectionStats?(collectionName: string): Promise<{ count: number; sizeBytes?: number }>;\n}\n\n/**\n * Administrative operations for schema management.\n * Shared across SQL and document databases.\n *\n * @group Admin\n */\nexport interface SchemaAdmin {\n /**\n * Fetch database tables/collections not yet mapped to a Rebase collection.\n */\n fetchUnmappedTables?(mappedPaths?: string[]): Promise<string[]>;\n\n /**\n * Fetch column/field metadata for a single table/collection.\n * The return type is generic — SQL backends return TableMetadata,\n * document backends may return a different shape.\n */\n fetchTableMetadata?(tableName: string): Promise<unknown>;\n}\n\n/**\n * Metadata for a database branch.\n * @group Admin\n */\nexport interface BranchInfo {\n /** Branch name (without prefix). */\n name: string;\n /** The database this branch was created from. */\n parentDatabase: string;\n /** When the branch was created. */\n createdAt: Date;\n /** Size in bytes, if available from the server. */\n sizeBytes?: number;\n}\n\n/**\n * Administrative operations for database branching.\n * Allows creating isolated database copies for development/preview workflows.\n *\n * @group Admin\n */\nexport interface BranchAdmin {\n /** Create a new branch (database copy) from the current or specified source database. */\n createBranch(name: string, options?: { source?: string }): Promise<BranchInfo>;\n\n /** Delete a branch database. Cannot delete the main/default database. */\n deleteBranch(name: string): Promise<void>;\n\n /** List all branches (databases that were created via branching). */\n listBranches(): Promise<BranchInfo[]>;\n\n /** Get info about a specific branch. */\n getBranchInfo(name: string): Promise<BranchInfo | undefined>;\n}\n\n/**\n * Union type for all admin capabilities.\n * A backend may implement any combination of these interfaces.\n *\n * Use type guards (`isSQLAdmin`, `isDocumentAdmin`, `isSchemaAdmin`, `isBranchAdmin`)\n * to safely narrow the type before calling methods.\n *\n * @group Admin\n */\nexport type DatabaseAdmin = Partial<SQLAdmin> & Partial<DocumentAdmin> & Partial<SchemaAdmin> & Partial<BranchAdmin>;\n\n/**\n * Type guard: does this admin support SQL operations?\n * @group Admin\n */\nexport function isSQLAdmin(admin: DatabaseAdmin | undefined): admin is SQLAdmin {\n return !!admin && typeof (admin as SQLAdmin).executeSql === \"function\";\n}\n\n/**\n * Type guard: does this admin support document operations?\n * @group Admin\n */\nexport function isDocumentAdmin(admin: DatabaseAdmin | undefined): admin is DocumentAdmin {\n return !!admin && (\n typeof (admin as DocumentAdmin).executeAggregate === \"function\" ||\n typeof (admin as DocumentAdmin).fetchCollectionStats === \"function\"\n );\n}\n\n/**\n * Type guard: does this admin support schema management?\n * @group Admin\n */\nexport function isSchemaAdmin(admin: DatabaseAdmin | undefined): admin is SchemaAdmin {\n return !!admin && (\n typeof (admin as SchemaAdmin).fetchUnmappedTables === \"function\" ||\n typeof (admin as SchemaAdmin).fetchTableMetadata === \"function\"\n );\n}\n\n/**\n * Type guard: does this admin support database branching?\n * @group Admin\n */\nexport function isBranchAdmin(admin: DatabaseAdmin | undefined): admin is BranchAdmin {\n return !!admin && typeof (admin as BranchAdmin).createBranch === \"function\";\n}\n\n// =============================================================================\n// LIFECYCLE INTERFACES (1.4)\n// =============================================================================\n\n/**\n * Health check result returned by `healthCheck()`.\n * @group Lifecycle\n */\nexport interface HealthCheckResult {\n /** Whether the backend is healthy and able to serve requests. */\n healthy: boolean;\n /** Round-trip latency to the database in milliseconds. */\n latencyMs: number;\n /** Optional details (e.g., pool stats, replication lag). */\n details?: Record<string, unknown>;\n}\n\n/**\n * Lifecycle contract for backend components that hold resources\n * (database connections, WebSocket pools, timers, etc.).\n *\n * All methods are optional — simple backends (e.g., in-memory) can skip them.\n * @group Lifecycle\n */\nexport interface BackendLifecycle {\n /**\n * Initialize the backend: open connections, run migrations, seed data.\n * Called once during startup. Idempotent.\n */\n initialize?(): Promise<void>;\n\n /**\n * Check whether the backend is healthy and reachable.\n * Should be fast (< 1 s) and safe to call frequently.\n */\n healthCheck?(): Promise<HealthCheckResult>;\n\n /**\n * Gracefully shut down: close connections, flush buffers, cancel timers.\n * After calling `destroy()`, no other methods should be called.\n */\n destroy?(): Promise<void>;\n}\n\n// =============================================================================\n// BACKEND FACTORY INTERFACES\n// =============================================================================\n\n/**\n * Configuration for creating a database backend\n */\nexport interface BackendConfig {\n /**\n * Type of database backend\n */\n type: string;\n\n /**\n * Database connection (implementation-specific)\n */\n connection: unknown;\n\n /**\n * Schema definition (implementation-specific, e.g., Drizzle schema for PostgreSQL)\n */\n schema?: unknown;\n}\n\n/**\n * A complete backend instance with all required services.\n *\n * Now includes optional lifecycle management and admin capabilities.\n */\nexport interface BackendInstance extends BackendLifecycle {\n /**\n * Entity repository for CRUD operations\n */\n entityRepository: EntityRepository;\n\n /**\n * Realtime provider for subscriptions\n */\n realtimeProvider: RealtimeProvider;\n\n /**\n * Collection registry\n */\n collectionRegistry: CollectionRegistryInterface;\n\n /**\n * The underlying database connection\n */\n connection: DatabaseConnection;\n\n /**\n * Administrative operations (SQL, schema, documents).\n * What's available depends on the backend type — use type guards\n * (`isSQLAdmin`, `isSchemaAdmin`, etc.) to narrow.\n */\n admin?: DatabaseAdmin;\n}\n\n/**\n * Factory function type for creating backend instances\n */\nexport type BackendFactory<TConfig extends BackendConfig = BackendConfig> =\n (config: TConfig) => BackendInstance;\n\n// =============================================================================\n// BACKEND BOOTSTRAPPER (1.2)\n// =============================================================================\n\n/**\n * A `BackendBootstrapper` encapsulates all driver-specific initialization logic.\n *\n * Instead of hard-coding Postgres setup into `initializeRebaseBackend()`,\n * each database backend provides its own bootstrapper that knows how to:\n * - Create the DataDriver from a config object\n * - Optionally initialize auth tables\n * - Optionally create a realtime service\n * - Mount driver-specific API routes\n *\n * The main `initializeRebaseBackend()` becomes a **coordinator** that iterates\n * registered bootstrappers, calls their hooks, and wires the results together.\n *\n * @group Backend\n *\n * @example\n * ```typescript\n * // Third-party MySQL bootstrapper\n * const mysqlBootstrapper: BackendBootstrapper = {\n * type: \"mysql\",\n * initializeDriver: async (config) => new MySQLDataDriver(config.connection),\n * initializeRealtime: async (config) => new MySQLChangeStreamRealtime(config.connection),\n * };\n *\n * initializeRebaseBackend({\n * ...config,\n * bootstrappers: [postgresBootstrapper, mysqlBootstrapper]\n * });\n * ```\n */\nexport interface BackendBootstrapper {\n /**\n * Which driver type this bootstrapper handles.\n * Must match the `type` field on the driver config object\n * (e.g., `\"postgres\"`, `\"mongodb\"`, `\"mysql\"`).\n */\n type: string;\n\n /**\n * Unique identifier for this bootstrapper instance.\n * Used to register the driver in the driver registry.\n * Defaults to `type` if not set.\n */\n id?: string;\n\n /**\n * Whether this bootstrapper provides the default driver.\n * When true, the coordinator uses this driver as the primary one.\n */\n isDefault?: boolean;\n\n /**\n * Run database migrations for this driver.\n * Called by the coordinator after all drivers are initialized.\n */\n runMigrations?(config: unknown, driverResult: InitializedDriver): Promise<void>;\n\n /**\n * Create a DataDriver from the given config.\n * This is the only **required** method.\n */\n initializeDriver(config: unknown): Promise<InitializedDriver>;\n\n /**\n * Initialize auth tables / services if this driver supports them.\n * Return undefined if auth is not supported by this backend.\n */\n initializeAuth?(config: unknown, driverResult: InitializedDriver): Promise<BootstrappedAuth | undefined>;\n\n /**\n * Initialize history tables / services if this driver supports them.\n * Return undefined if history is not supported by this backend.\n */\n initializeHistory?(config: unknown, driverResult: InitializedDriver): Promise<{ historyService: unknown } | undefined>;\n\n /**\n * Create a realtime provider for this driver.\n * Return undefined if the driver does not support realtime.\n */\n initializeRealtime?(config: unknown, driverResult: InitializedDriver): Promise<RealtimeProvider | undefined>;\n\n /**\n * Mount any driver-specific HTTP routes (e.g., custom admin endpoints).\n * Called after all drivers are initialized.\n */\n mountRoutes?(app: unknown, basePath: string, driverResult: InitializedDriver): void;\n\n /**\n * Return admin capabilities for this driver.\n */\n getAdmin?(driverResult: InitializedDriver): DatabaseAdmin | undefined;\n\n /**\n * Initialize WebSocket server for realtime operations.\n */\n initializeWebsockets?(server: unknown, realtimeService: RealtimeProvider, driver: import(\"../controllers/data_driver\").DataDriver, config?: unknown, authAdapter?: AuthAdapter): Promise<void> | void;\n}\n\n/**\n * Result of `BackendBootstrapper.initializeDriver()`.\n * @group Backend\n */\nexport interface InitializedDriver {\n /** The DataDriver instance, ready for use. */\n driver: import(\"../controllers/data_driver\").DataDriver;\n\n /** The realtime service, if the driver created one during init. */\n realtimeProvider?: RealtimeProvider;\n\n /** A collection registry to register schema / tables into. */\n collectionRegistry?: CollectionRegistryInterface;\n\n /** The underlying database connection (for lifecycle management). */\n connection?: DatabaseConnection;\n\n /**\n * Opaque handle that the bootstrapper can use in subsequent hooks\n * (e.g., `initializeAuth`, `mountRoutes`) to access driver internals.\n * Not used by the coordinator.\n */\n internals?: unknown;\n}\n\n/**\n * Result of `BackendBootstrapper.initializeAuth()`.\n * @group Backend\n */\nexport interface BootstrappedAuth {\n /** User management service. */\n userService: unknown;\n /** Role management service (optional, roles are now simple strings). */\n roleService?: unknown;\n /** Email service (optional). */\n emailService?: unknown;\n /** Combined Auth Repository for unified token and user management. */\n authRepository?: unknown;\n}\n","/**\n * Describes the capabilities and features supported by a data source (driver).\n *\n * Each driver (Postgres, Firebase, MongoDB, etc.) declares which features it\n * supports. The CMS uses this descriptor to:\n * - Show/hide editor tabs (e.g. Relations for SQL, Subcollections for Firebase)\n * - Filter the property type picker (e.g. `relation` for SQL, `reference` for Firebase)\n * - Toggle driver-specific form controls (e.g. `columnType` for SQL)\n *\n * @group Models\n */\nexport interface DataSourceCapabilities {\n /** Unique driver key (e.g. \"postgres\", \"firestore\", \"mongodb\") */\n key: string;\n\n /** Human-readable label for the UI (e.g. \"PostgreSQL\", \"Firebase / Firestore\") */\n label: string;\n\n // ── Feature flags ─────────────────────────────────────────────────\n /** Does this source support SQL-style relations (JOINs)? */\n supportsRelations: boolean;\n\n /** Does this source support nested subcollections? */\n supportsSubcollections: boolean;\n\n /** Does this source support Row Level Security policies? */\n supportsRLS: boolean;\n\n /** Does this source support document references (Firebase-style)? */\n supportsReferences: boolean;\n\n /** Does this source support SQL column type annotations? */\n supportsColumnTypes: boolean;\n\n /** Does this source support real-time listeners? */\n supportsRealtime: boolean;\n\n // ── Admin capability flags ───────────────────────────────────────\n /** Does this source support SQL admin operations (SQL editor, EXPLAIN, etc.)? */\n supportsSQLAdmin: boolean;\n\n /** Does this source support document admin operations (aggregation, stats)? */\n supportsDocumentAdmin: boolean;\n\n /** Does this source support schema admin (unmapped tables, table metadata)? */\n supportsSchemaAdmin: boolean;\n}\n\n/**\n * Subset of DataSourceCapabilities containing only feature flags.\n * Useful when you only need to check capabilities without UI metadata.\n * @group Models\n */\nexport type DataSourceFeatures = Omit<DataSourceCapabilities, \"key\" | \"label\">;\n\n/**\n * The default data-source key, used when a collection does not name a\n * `dataSource`. Shared by the frontend router and the backend driver\n * registry so both agree on \"the default database\".\n * @group Models\n */\nexport const DEFAULT_DATA_SOURCE_KEY = \"(default)\";\n\n/**\n * How the *frontend* reaches a data source.\n *\n * - `\"server\"` — through the Rebase backend (the `RebaseClient`). The backend\n * holds the actual database adapter and routes by data-source key. This is\n * the default and covers Postgres, MongoDB, and any other server-mediated\n * engine.\n * - `\"direct\"` — straight from the client to the external backend via its own\n * SDK driver (e.g. Firestore). The Rebase backend is not in the data path.\n * - `\"custom\"` — a developer-supplied {@link DataDriver}, transport unspecified.\n *\n * @group Models\n */\nexport type DataSourceTransport = \"server\" | \"direct\" | \"custom\";\n\n/**\n * Declarative definition of a data source — a named place data lives.\n *\n * Declared once and shared front and back: the frontend uses it to decide\n * transport (client vs direct driver), the backend uses the same `key` to\n * resolve a database adapter, and the editor derives capabilities from\n * `engine`. Collections reference a definition by its `key` via\n * `collection.dataSource`.\n *\n * @group Models\n */\nexport interface DataSourceDefinition {\n /**\n * Unique identifier for this data source. Collections point at it via\n * `dataSource`. Defaults to {@link DEFAULT_DATA_SOURCE_KEY}.\n */\n key: string;\n\n /**\n * The engine backing this data source (e.g. `\"postgres\"`, `\"mongodb\"`,\n * `\"firestore\"`, or a custom id). Determines the\n * {@link DataSourceCapabilities} surfaced in the editor.\n */\n engine: string;\n\n /**\n * How the frontend reaches this source. Defaults to `\"server\"`.\n */\n transport: DataSourceTransport;\n\n /**\n * The physical database/schema/Firestore-database within the engine.\n * Threaded to drivers/adapters as the existing `databaseId` runtime\n * parameter. Defaults to the engine's own default.\n */\n databaseId?: string;\n\n /** Human-readable label for the UI. */\n label?: string;\n}\n\n/**\n * The resolved data source for a collection: the single source of truth that\n * the frontend router, backend registry, and editor all derive from.\n * Produced by `resolveDataSource(collection, registry)`.\n *\n * @group Models\n */\nexport interface ResolvedDataSource {\n /** Data-source key (routing key, shared front + back). */\n key: string;\n /** Engine backing the source (drives capabilities). */\n engine: string;\n /** Frontend transport. */\n transport: DataSourceTransport;\n /** Within-engine instance, if any (the `databaseId` runtime param). */\n databaseId?: string;\n /** Capabilities derived from {@link engine}. */\n capabilities: DataSourceCapabilities;\n}\n\n// ── Built-in driver capabilities ─────────────────────────────────────\n\n/** @group Models */\nexport const POSTGRES_CAPABILITIES: DataSourceCapabilities = {\n key: \"postgres\",\n label: \"PostgreSQL\",\n supportsRelations: true,\n supportsSubcollections: false,\n supportsRLS: true,\n supportsReferences: false,\n supportsColumnTypes: true,\n supportsRealtime: true,\n supportsSQLAdmin: true,\n supportsDocumentAdmin: false,\n supportsSchemaAdmin: true\n};\n\n/** @group Models */\nexport const FIREBASE_CAPABILITIES: DataSourceCapabilities = {\n key: \"firestore\",\n label: \"Firebase / Firestore\",\n supportsRelations: false,\n supportsSubcollections: true,\n supportsRLS: false,\n supportsReferences: true,\n supportsColumnTypes: false,\n supportsRealtime: true,\n supportsSQLAdmin: false,\n supportsDocumentAdmin: false,\n supportsSchemaAdmin: false\n};\n\n/** @group Models */\nexport const MONGODB_CAPABILITIES: DataSourceCapabilities = {\n key: \"mongodb\",\n label: \"MongoDB\",\n supportsRelations: false,\n supportsSubcollections: true,\n supportsRLS: false,\n supportsReferences: true,\n supportsColumnTypes: false,\n supportsRealtime: false,\n supportsSQLAdmin: false,\n supportsDocumentAdmin: true,\n supportsSchemaAdmin: true\n};\n\n/**\n * Fallback capabilities when the driver is unknown.\n * Enables everything so nothing is hidden unexpectedly.\n * @group Models\n */\nexport const DEFAULT_CAPABILITIES: DataSourceCapabilities = {\n key: \"(default)\",\n label: \"Default\",\n supportsRelations: true,\n supportsSubcollections: true,\n supportsRLS: true,\n supportsReferences: true,\n supportsColumnTypes: true,\n supportsRealtime: true,\n supportsSQLAdmin: true,\n supportsDocumentAdmin: true,\n supportsSchemaAdmin: true\n};\n\nconst CAPABILITIES_REGISTRY: Record<string, DataSourceCapabilities> = {\n postgres: POSTGRES_CAPABILITIES,\n firestore: FIREBASE_CAPABILITIES,\n mongodb: MONGODB_CAPABILITIES,\n \"(default)\": DEFAULT_CAPABILITIES\n};\n\n/**\n * Look up capabilities for a given driver key.\n * If `driver` is undefined or not found, returns `DEFAULT_CAPABILITIES`.\n * @group Models\n */\nexport function getDataSourceCapabilities(driver?: string): DataSourceCapabilities {\n if (!driver) return POSTGRES_CAPABILITIES; // postgres is the default driver\n return CAPABILITIES_REGISTRY[driver] ?? DEFAULT_CAPABILITIES;\n}\n\n/**\n * Register custom capabilities for a third-party driver.\n * @group Models\n */\nexport function registerDataSourceCapabilities(capabilities: DataSourceCapabilities): void {\n CAPABILITIES_REGISTRY[capabilities.key] = capabilities;\n}\n","import type React from \"react\";\n\n/**\n * Internal marker for a lazily-loaded component reference.\n * Created by the Vite transform plugin when converting string paths\n * to deferred `import()` calls. Users should NOT create these manually.\n *\n * @internal\n */\nexport interface LazyComponentRef<P = unknown> {\n readonly __rebaseLazy: true;\n readonly load: () => Promise<{ default: React.ComponentType<P> }>;\n}\n\n/**\n * A reference to a React component that can be provided in three forms:\n *\n * 1. **String path** (recommended for collection configs):\n * ```ts\n * Field: \"../../frontend/src/components/MyField\"\n * ```\n * The Vite plugin transforms this into a `LazyComponentRef` at build time.\n * On the backend, the string stays inert and is never evaluated.\n *\n * 2. **Lazy import function**:\n * ```ts\n * Field: () => import(\"../../frontend/src/components/MyField\")\n * ```\n * Standard ES dynamic import. Backend never calls the function.\n *\n * 3. **Direct component reference** (use only in frontend-only code):\n * ```ts\n * Field: MyFieldComponent\n * ```\n * Importing a component at the top level will pull React into the\n * backend runtime — only safe in code that the backend never imports.\n *\n * @group Types\n */\nexport type ComponentRef<P = any> =\n | React.ComponentType<P>\n | LazyComponentRef<P>\n | (() => Promise<{ default: React.ComponentType<P> }>)\n | string;\n\n/**\n * Type guard: checks if a value is a `LazyComponentRef` produced by the\n * Vite transform plugin.\n */\nexport function isLazyComponentRef<P = unknown>(ref: unknown): ref is LazyComponentRef<P> {\n return (\n typeof ref === \"object\" &&\n ref !== null &&\n \"__rebaseLazy\" in ref &&\n (ref as Record<string, unknown>).__rebaseLazy === true\n );\n}\n"],"mappings":";;;;;;;;;;;;;;AA2EA,IAAa,kBAAb,MAA6B;CAEzB,SAAkB;;;;CAIlB;;;;;CAKA;;;;;CAMA;;;;;CAMA;;;;;;;;;;;CAYA,YAAY,OAA6B;EACrC,KAAK,KAAK,MAAM;EAChB,KAAK,OAAO,MAAM;EAClB,KAAK,SAAS,MAAM;EACpB,KAAK,aAAa,MAAM;CAC5B;CAEA,IAAI,aAAa;EACb,OAAO,GAAG,KAAK,KAAK,GAAG,KAAK;CAChC;;;;;CAMA,IAAI,WAAW;EACX,MAAM,QAAkB,CAAC;EAGzB,IAAI,KAAK,UAAU,KAAK,WAAW,aAC/B,MAAM,KAAK,KAAK,MAAM;EAI1B,IAAI,KAAK,cAAc,KAAK,eAAe,aACvC,MAAM,KAAK,KAAK,UAAU;EAG9B,IAAI,MAAM,SAAS,GACf,OAAO,GAAG,MAAM,KAAK,GAAG,EAAE,KAAK,KAAK,KAAK,GAAG,KAAK;EAErD,OAAO,KAAK;CAChB;CAEA,oBAAoB;EAChB,OAAO;CACX;AACJ;;;;AAKA,IAAa,iBAAb,MAA4B;CAExB,SAAkB;;;;CAIlB;;;;;CAKA;;;;;CAMA;CAEA,YAAY,IAAqB,MAAc,MAAe;EAC1D,KAAK,KAAK;EACV,KAAK,OAAO;EACZ,KAAK,OAAO;CAChB;CAEA,IAAI,aAAa;EACb,OAAO,GAAG,KAAK,KAAK,GAAG,KAAK;CAChC;CAEA,oBAAoB;EAChB,OAAO;CACX;CAEA,mBAAmB;EACf,OAAO;CACX;AACJ;AAEA,IAAa,WAAb,MAAsB;;;;CAKlB;;;;CAIA;CAEA,YAAY,UAAkB,WAAmB;EAC7C,KAAK,WAAW;EAChB,KAAK,YAAY;CACrB;AACJ;AAEA,IAAa,SAAb,MAAoB;CAChB;CAEA,YAAY,OAAiB;EACzB,KAAK,QAAQ;CACjB;AACJ;;;;;;;;AC2ZA,SAAgB,qBACZ,YACyC;CACzC,OAAO,CAAC,WAAW,UAAU,WAAW,WAAW;AACvD;;;;;AAMA,SAAgB,qBACZ,YACyC;CACzC,OAAO,WAAW,WAAW;AACjC;;;;;AAMA,SAAgB,oBACZ,YACwC;CACxC,OAAO,WAAW,WAAW;AACjC;;;;;;;AC7KA,SAAgB,WAAW,OAAqD;CAC5E,OAAO,CAAC,CAAC,SAAS,OAAQ,MAAmB,eAAe;AAChE;;;;;AAMA,SAAgB,gBAAgB,OAA0D;CACtF,OAAO,CAAC,CAAC,UACL,OAAQ,MAAwB,qBAAqB,cACrD,OAAQ,MAAwB,yBAAyB;AAEjE;;;;;AAMA,SAAgB,cAAc,OAAwD;CAClF,OAAO,CAAC,CAAC,UACL,OAAQ,MAAsB,wBAAwB,cACtD,OAAQ,MAAsB,uBAAuB;AAE7D;;;;;AAMA,SAAgB,cAAc,OAAwD;CAClF,OAAO,CAAC,CAAC,SAAS,OAAQ,MAAsB,iBAAiB;AACrE;;;;;;;;;AC9bA,IAAa,0BAA0B;;AAiFvC,IAAa,wBAAgD;CACzD,KAAK;CACL,OAAO;CACP,mBAAmB;CACnB,wBAAwB;CACxB,aAAa;CACb,oBAAoB;CACpB,qBAAqB;CACrB,kBAAkB;CAClB,kBAAkB;CAClB,uBAAuB;CACvB,qBAAqB;AACzB;;AAGA,IAAa,wBAAgD;CACzD,KAAK;CACL,OAAO;CACP,mBAAmB;CACnB,wBAAwB;CACxB,aAAa;CACb,oBAAoB;CACpB,qBAAqB;CACrB,kBAAkB;CAClB,kBAAkB;CAClB,uBAAuB;CACvB,qBAAqB;AACzB;;AAGA,IAAa,uBAA+C;CACxD,KAAK;CACL,OAAO;CACP,mBAAmB;CACnB,wBAAwB;CACxB,aAAa;CACb,oBAAoB;CACpB,qBAAqB;CACrB,kBAAkB;CAClB,kBAAkB;CAClB,uBAAuB;CACvB,qBAAqB;AACzB;;;;;;AAOA,IAAa,uBAA+C;CACxD,KAAK;CACL,OAAO;CACP,mBAAmB;CACnB,wBAAwB;CACxB,aAAa;CACb,oBAAoB;CACpB,qBAAqB;CACrB,kBAAkB;CAClB,kBAAkB;CAClB,uBAAuB;CACvB,qBAAqB;AACzB;AAEA,IAAM,wBAAgE;CAClE,UAAU;CACV,WAAW;CACX,SAAS;CACT,aAAa;AACjB;;;;;;AAOA,SAAgB,0BAA0B,QAAyC;CAC/E,IAAI,CAAC,QAAQ,OAAO;CACpB,OAAO,sBAAsB,WAAW;AAC5C;;;;;AAMA,SAAgB,+BAA+B,cAA4C;CACvF,sBAAsB,aAAa,OAAO;AAC9C;;;;;;;ACnLA,SAAgB,mBAAgC,KAA0C;CACtF,OACI,OAAO,QAAQ,YACf,QAAQ,QACR,kBAAkB,OACjB,IAAgC,iBAAiB;AAE1D"}
|
package/dist/index.umd.js
CHANGED
|
@@ -181,6 +181,13 @@
|
|
|
181
181
|
}
|
|
182
182
|
//#endregion
|
|
183
183
|
//#region src/types/data_source.ts
|
|
184
|
+
/**
|
|
185
|
+
* The default data-source key, used when a collection does not name a
|
|
186
|
+
* `dataSource`. Shared by the frontend router and the backend driver
|
|
187
|
+
* registry so both agree on "the default database".
|
|
188
|
+
* @group Models
|
|
189
|
+
*/
|
|
190
|
+
var DEFAULT_DATA_SOURCE_KEY = "(default)";
|
|
184
191
|
/** @group Models */
|
|
185
192
|
var POSTGRES_CAPABILITIES = {
|
|
186
193
|
key: "postgres",
|
|
@@ -274,6 +281,7 @@
|
|
|
274
281
|
}
|
|
275
282
|
//#endregion
|
|
276
283
|
exports.DEFAULT_CAPABILITIES = DEFAULT_CAPABILITIES;
|
|
284
|
+
exports.DEFAULT_DATA_SOURCE_KEY = DEFAULT_DATA_SOURCE_KEY;
|
|
277
285
|
exports.EntityReference = EntityReference;
|
|
278
286
|
exports.EntityRelation = EntityRelation;
|
|
279
287
|
exports.FIREBASE_CAPABILITIES = FIREBASE_CAPABILITIES;
|