@rebasepro/types 0.7.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/README.md +10 -10
  2. package/dist/controllers/auth.d.ts +1 -1
  3. package/dist/controllers/client.d.ts +237 -7
  4. package/dist/controllers/collection_registry.d.ts +3 -3
  5. package/dist/controllers/customization_controller.d.ts +1 -1
  6. package/dist/controllers/data.d.ts +285 -81
  7. package/dist/controllers/data_driver.d.ts +50 -37
  8. package/dist/controllers/index.d.ts +1 -1
  9. package/dist/controllers/local_config_persistence.d.ts +4 -4
  10. package/dist/controllers/navigation.d.ts +2 -2
  11. package/dist/controllers/registry.d.ts +17 -6
  12. package/dist/controllers/{side_entity_controller.d.ts → side_panel_controller.d.ts} +7 -7
  13. package/dist/controllers/storage.d.ts +39 -0
  14. package/dist/errors.d.ts +64 -0
  15. package/dist/index.d.ts +1 -0
  16. package/dist/index.es.js +290 -16
  17. package/dist/index.es.js.map +1 -1
  18. package/dist/index.umd.js +305 -18
  19. package/dist/index.umd.js.map +1 -1
  20. package/dist/rebase_context.d.ts +8 -4
  21. package/dist/types/auth_adapter.d.ts +9 -6
  22. package/dist/types/backend.d.ts +30 -26
  23. package/dist/types/builders.d.ts +2 -2
  24. package/dist/types/collections.d.ts +211 -136
  25. package/dist/types/component_overrides.d.ts +61 -3
  26. package/dist/types/cron.d.ts +10 -1
  27. package/dist/types/data_source.d.ts +18 -5
  28. package/dist/types/database_adapter.d.ts +4 -3
  29. package/dist/types/entities.d.ts +7 -7
  30. package/dist/types/entity_actions.d.ts +7 -7
  31. package/dist/types/entity_callbacks.d.ts +55 -43
  32. package/dist/types/entity_views.d.ts +3 -3
  33. package/dist/types/filter-operators.d.ts +153 -0
  34. package/dist/types/index.d.ts +3 -2
  35. package/dist/types/modify_collections.d.ts +2 -2
  36. package/dist/types/plugins.d.ts +9 -9
  37. package/dist/types/policy.d.ts +191 -0
  38. package/dist/types/properties.d.ts +153 -43
  39. package/dist/types/property_config.d.ts +1 -1
  40. package/dist/types/relations.d.ts +3 -3
  41. package/dist/types/slots.d.ts +14 -14
  42. package/dist/types/storage_source.d.ts +83 -0
  43. package/dist/types/websockets.d.ts +12 -13
  44. package/dist/users/user.d.ts +21 -9
  45. package/package.json +1 -1
  46. package/src/controllers/auth.tsx +1 -1
  47. package/src/controllers/client.ts +275 -7
  48. package/src/controllers/collection_registry.ts +3 -3
  49. package/src/controllers/customization_controller.tsx +1 -1
  50. package/src/controllers/data.ts +309 -97
  51. package/src/controllers/data_driver.ts +49 -40
  52. package/src/controllers/index.ts +1 -1
  53. package/src/controllers/local_config_persistence.tsx +4 -4
  54. package/src/controllers/navigation.ts +2 -2
  55. package/src/controllers/registry.ts +18 -6
  56. package/src/controllers/{side_entity_controller.tsx → side_panel_controller.tsx} +7 -7
  57. package/src/controllers/storage.ts +60 -1
  58. package/src/errors.ts +80 -0
  59. package/src/index.ts +1 -0
  60. package/src/rebase_context.tsx +8 -4
  61. package/src/types/auth_adapter.ts +9 -6
  62. package/src/types/backend.ts +41 -36
  63. package/src/types/builders.ts +2 -2
  64. package/src/types/collections.ts +256 -172
  65. package/src/types/component_overrides.ts +72 -5
  66. package/src/types/cron.ts +10 -1
  67. package/src/types/data_source.ts +29 -7
  68. package/src/types/database_adapter.ts +4 -3
  69. package/src/types/entities.ts +7 -7
  70. package/src/types/entity_actions.tsx +7 -7
  71. package/src/types/entity_callbacks.ts +58 -47
  72. package/src/types/entity_views.tsx +3 -3
  73. package/src/types/filter-operators.ts +240 -0
  74. package/src/types/index.ts +3 -2
  75. package/src/types/modify_collections.tsx +2 -2
  76. package/src/types/plugins.tsx +9 -9
  77. package/src/types/policy.ts +229 -0
  78. package/src/types/properties.ts +164 -44
  79. package/src/types/property_config.tsx +0 -1
  80. package/src/types/relations.ts +3 -3
  81. package/src/types/slots.tsx +14 -14
  82. package/src/types/storage_source.ts +90 -0
  83. package/src/types/websockets.ts +12 -14
  84. package/src/users/user.ts +22 -9
  85. package/dist/types/backend_hooks.d.ts +0 -109
  86. package/dist/types/entity_overrides.d.ts +0 -10
  87. package/src/types/backend_hooks.ts +0 -114
  88. package/src/types/entity_overrides.tsx +0 -11
@@ -1,25 +1,26 @@
1
1
  import React from "react";
2
2
  import type { Entity, EntityStatus } from "./entities";
3
- import type { EntityCallbacks } from "./entity_callbacks";
4
- import type { Properties } from "./properties";
3
+ import type { CollectionCallbacks } from "./entity_callbacks";
4
+ import type { Properties, PostgresProperties, FirebaseProperties, MongoProperties } from "./properties";
5
5
  import type { ExportConfig } from "./export_import";
6
- import type { EntityOverrides } from "./entity_overrides";
7
6
  import type { User } from "../users";
8
7
  import type { RebaseContext } from "../rebase_context";
9
8
  import type { Relation } from "./relations";
10
9
  import type { EntityCustomView, FormViewConfig } from "./entity_views";
11
10
  import type { EntityAction } from "./entity_actions";
11
+ import type { PolicyExpression } from "./policy";
12
12
  import type { ComponentRef } from "./component_ref";
13
13
  import type { CollectionComponentOverrideMap } from "./component_overrides";
14
+ import type { FilterValues, FilterPreset, OrderByTuple } from "./filter-operators";
14
15
  /**
15
16
  * Base interface containing all driver-agnostic collection properties.
16
- * Use {@link PostgresCollection} or {@link FirebaseCollection} for
17
- * driver-specific type safety, or {@link EntityCollection} when you
17
+ * Use {@link PostgresCollectionConfig} or {@link FirebaseCollectionConfig} for
18
+ * driver-specific type safety, or {@link CollectionConfig} when you
18
19
  * need to handle any collection regardless of backend.
19
20
  *
20
21
  * @group Models
21
22
  */
22
- export interface BaseEntityCollection<M extends Record<string, unknown> = Record<string, unknown>, USER extends User = User> {
23
+ export interface BaseCollectionConfig<M extends Record<string, unknown> = Record<string, unknown>, USER extends User = User> {
23
24
  /**
24
25
  * You can set an alias that will be used internally instead of the collection name.
25
26
  * The `slug` value will be used to determine the URL of the collection.
@@ -47,12 +48,12 @@ export interface BaseEntityCollection<M extends Record<string, unknown> = Record
47
48
  *
48
49
  * Custom drivers can set this directly to expose child collections to the UI.
49
50
  */
50
- childCollections?: () => EntityCollection<Record<string, unknown>>[];
51
+ childCollections?: () => CollectionConfig<Record<string, unknown>>[];
51
52
  /**
52
53
  * The data source this collection belongs to — the routing key shared by
53
54
  * the frontend router and the backend driver registry. It points at a
54
55
  * {@link DataSourceDefinition} registered on `<Rebase dataSources>` (front)
55
- * and `initRebase({ dataSources })` (back).
56
+ * and `initializeRebaseBackend({ dataSources })` (back).
56
57
  *
57
58
  * If not specified, the default data source `"(default)"` is used, which
58
59
  * for a standard Rebase app is the server-mediated Postgres backend.
@@ -66,17 +67,18 @@ export interface BaseEntityCollection<M extends Record<string, unknown> = Record
66
67
  */
67
68
  dataSource?: string;
68
69
  /**
69
- * The engine backing this collection (`"postgres"`, `"firestore"`,
70
- * `"mongodb"`, or a custom id). Drives editor capabilities (relations vs
71
- * subcollections, RLS, column types).
70
+ * The database engine backing this collection (`"postgres"`, `"firestore"`,
71
+ * `"mongodb"`, or a custom id).
72
72
  *
73
- * @deprecated Prefer {@link dataSource} for routing. `driver` is retained
74
- * as an engine hint and for backward compatibility: when `dataSource` is
75
- * omitted it also acts as the data-source key.
73
+ * On concrete collection types ({@link PostgresCollectionConfig},
74
+ * {@link FirebaseCollectionConfig}, {@link MongoDBCollectionConfig}) this is a literal
75
+ * discriminant. On the base type it is optional and gets stamped
76
+ * automatically during collection normalization from the registered
77
+ * {@link DataSourceDefinition}.
76
78
  *
77
- * If not specified, `"postgres"` is assumed.
79
+ * Prefer setting {@link dataSource} and letting the engine be resolved.
78
80
  */
79
- driver?: string;
81
+ engine?: string;
80
82
  /**
81
83
  * Which database within the engine.
82
84
  * - For Firestore: The Firestore database ID (e.g., for multi-database projects)
@@ -88,7 +90,7 @@ export interface BaseEntityCollection<M extends Record<string, unknown> = Record
88
90
  */
89
91
  databaseId?: string;
90
92
  /**
91
- * Set of properties that compose an entity
93
+ * Set of properties that compose a entity
92
94
  */
93
95
  properties: Properties;
94
96
  /**
@@ -123,12 +125,12 @@ export interface BaseEntityCollection<M extends Record<string, unknown> = Record
123
125
  */
124
126
  readonly titleProperty?: Extract<keyof M, string> | (string & {});
125
127
  /**
126
- * When editing an entity, you can choose to open the entity in a side dialog
128
+ * When editing a entity, you can choose to open the entity in a side dialog
127
129
  * or in a full screen dialog. Defaults to `full_screen`.
128
130
  */
129
131
  openEntityMode?: "side_panel" | "full_screen" | "split" | "dialog";
130
132
  /**
131
- * Controls what happens when a user clicks on an entity in the collection view.
133
+ * Controls what happens when a user clicks on a entity in the collection view.
132
134
  * - `"edit"` (default): Opens the entity in the edit form.
133
135
  * - `"view"`: Opens a read-only detail view with an "Edit" button.
134
136
  */
@@ -175,19 +177,18 @@ export interface BaseEntityCollection<M extends Record<string, unknown> = Record
175
177
  * If you are specifying your collection as code, the order is the same as the
176
178
  * one you define in `properties`. Additional columns are added at the
177
179
  * end of the list, if the order is not specified.
180
+ *
178
181
  * You can use this prop to hide some properties from the table view.
179
182
  * Note that if you set this prop, other ways to hide fields, like
180
183
  * `hidden` in the property definition, will be ignored.
181
184
  * `propertiesOrder` has precedence over `hidden`.
182
- * - For properties use the property key.
183
- * - For additional fields use the field key.
184
- * - If you have subcollections, you get a column for each subcollection,
185
- * with the path (or alias) as the subcollection, prefixed with
186
- * `subcollection:`. e.g. `subcollection:orders`.
187
- * You can use this prop to hide some properties from the table view.
188
- * Note that if you set this prop, other ways to hide fields, like
189
- * `hidden` in the property definition,will be ignored.
190
- * `propertiesOrder` has precedence over `hidden`.
185
+ *
186
+ * Supported entry formats:
187
+ * - For properties, use the property key.
188
+ * - For additional fields, use the field key.
189
+ * - Child collections (Firestore subcollections, or Postgres relations
190
+ * with `many` cardinality) each get a column with id
191
+ * `subcollection:<slug>`, e.g. `subcollection:orders`.
191
192
  */
192
193
  propertiesOrder?: (Extract<keyof M, string> | (string & {}) | string | `subcollection:${string}`)[];
193
194
  /**
@@ -200,11 +201,11 @@ export interface BaseEntityCollection<M extends Record<string, unknown> = Record
200
201
  pagination?: boolean | number;
201
202
  selectionEnabled?: boolean;
202
203
  /**
203
- * This interface defines all the callbacks that can be used when an entity
204
+ * This interface defines all the callbacks that can be used when a entity
204
205
  * is being created, updated or deleted.
205
206
  * Useful for adding your own logic or blocking the execution of the operation.
206
207
  */
207
- readonly callbacks?: EntityCallbacks<M, USER>;
208
+ readonly callbacks?: CollectionCallbacks<M, USER>;
208
209
  /**
209
210
  * Pass your own selection controller if you want to control selected
210
211
  * entities externally.
@@ -249,7 +250,7 @@ export interface BaseEntityCollection<M extends Record<string, unknown> = Record
249
250
  * applied in the collection.
250
251
  * e.g. `sort: ["order", "asc"]`
251
252
  */
252
- readonly sort?: [Extract<keyof M, string> | (string & {}), "asc" | "desc"];
253
+ readonly sort?: OrderByTuple<Extract<keyof M, string> | (string & {})>;
253
254
  /**
254
255
  * You can add additional fields to the collection view by implementing
255
256
  * an additional field delegate.
@@ -261,8 +262,8 @@ export interface BaseEntityCollection<M extends Record<string, unknown> = Record
261
262
  defaultSize?: CollectionSize;
262
263
  /**
263
264
  * Can the elements in this collection be edited inline in the collection
264
- * view. If this flag is set to false but `permissions.edit` is `true`, entities
265
- * can still be edited in the side panel
265
+ * view. Even when inline editing is disabled, entities can still be
266
+ * edited in the side panel (subject to `securityRules`).
266
267
  */
267
268
  inlineEditing?: boolean;
268
269
  /**
@@ -275,7 +276,7 @@ export interface BaseEntityCollection<M extends Record<string, unknown> = Record
275
276
  hideFromNavigation?: boolean;
276
277
  /**
277
278
  * If you want to open custom views or subcollections by default when opening the edit
278
- * view of an entity, you can specify the path to the view here.
279
+ * view of a entity, you can specify the path to the view here.
279
280
  * The path is relative to the current collection. For example if you have a collection
280
281
  * that has a custom view as well as a subcollection that refers to another entity, you can
281
282
  * either specify the path to the custom view or the path to the subcollection.
@@ -312,11 +313,7 @@ export interface BaseEntityCollection<M extends Record<string, unknown> = Record
312
313
  */
313
314
  metadata?: Record<string, unknown>;
314
315
  /**
315
- * Overrides for the entity view, like the data source or the storage source.
316
- */
317
- overrides?: EntityOverrides;
318
- /**
319
- * Width of the side dialog (in pixels) when opening an entity in this collection.
316
+ * Width of the side dialog (in pixels) when opening a entity in this collection.
320
317
  */
321
318
  sideDialogWidth?: number | string;
322
319
  /**
@@ -337,9 +334,9 @@ export interface BaseEntityCollection<M extends Record<string, unknown> = Record
337
334
  /**
338
335
  * Should local changes be backed up in local storage, to prevent data loss on
339
336
  * accidental navigations.
340
- * - `manual_apply`: When the user navigates back to an entity with local changes,
337
+ * - `manual_apply`: When the user navigates back to a entity with local changes,
341
338
  * they will be prompted to restore the changes.
342
- * - `auto_apply`: When the user navigates back to an entity with local changes,
339
+ * - `auto_apply`: When the user navigates back to a entity with local changes,
343
340
  * the changes will be automatically applied.
344
341
  * - `false`: Local changes will not be backed up.
345
342
  * Defaults to `manual_apply`.
@@ -399,7 +396,7 @@ export interface BaseEntityCollection<M extends Record<string, unknown> = Record
399
396
  * Security rules for this collection (Row Level Security).
400
397
  * When defined, the backend enforces access control policies.
401
398
  */
402
- securityRules?: SecurityRule[];
399
+ securityRules?: readonly SecurityRule[];
403
400
  /**
404
401
  * Collection-scoped component overrides. These take precedence over
405
402
  * global overrides set on `<Rebase>`, but only within this collection's
@@ -411,7 +408,7 @@ export interface BaseEntityCollection<M extends Record<string, unknown> = Record
411
408
  *
412
409
  * @example
413
410
  * ```tsx
414
- * const productsCollection: PostgresCollection = {
411
+ * const productsCollection: PostgresCollectionConfig = {
415
412
  * name: "Products",
416
413
  * slug: "products",
417
414
  * table: "products",
@@ -429,18 +426,18 @@ export interface BaseEntityCollection<M extends Record<string, unknown> = Record
429
426
  * A collection backed by PostgreSQL (or any SQL database).
430
427
  * Adds support for SQL-style relations (JOINs) and Row Level Security.
431
428
  *
432
- * Use this type instead of {@link EntityCollection} when you want
429
+ * Use this type instead of {@link CollectionConfig} when you want
433
430
  * compile-time safety that only SQL-relevant fields appear.
434
431
  *
435
432
  * @group Models
436
433
  */
437
- export interface PostgresCollection<M extends Record<string, unknown> = Record<string, unknown>, USER extends User = User> extends BaseEntityCollection<M, USER> {
438
- properties: Properties;
434
+ export interface PostgresCollectionConfig<M extends Record<string, unknown> = Record<string, unknown>, USER extends User = User> extends BaseCollectionConfig<M, USER> {
435
+ properties: PostgresProperties;
439
436
  /**
440
- * The driver for this collection. For Postgres collections this
437
+ * The database engine for this collection. For Postgres collections this
441
438
  * can be omitted (Postgres is the default) or set to `"postgres"`.
442
439
  */
443
- driver?: "postgres" | undefined;
440
+ engine?: "postgres" | undefined;
444
441
  /**
445
442
  * The PostgreSQL table name for this collection.
446
443
  */
@@ -457,7 +454,7 @@ export interface PostgresCollection<M extends Record<string, unknown> = Record<s
457
454
  */
458
455
  relations?: Relation[];
459
456
  /**
460
- * Security rules for this collection (Supabase-style Row Level Security).
457
+ * Security rules for this collection (PostgreSQL Row Level Security).
461
458
  * When defined, the schema generator will enable RLS on the table and
462
459
  * create the corresponding PostgreSQL policies.
463
460
  *
@@ -471,81 +468,129 @@ export interface PostgresCollection<M extends Record<string, unknown> = Record<s
471
468
  * - `auth.roles()` — comma-separated app role IDs
472
469
  * - `auth.jwt()` — full JWT claims as JSONB
473
470
  */
474
- securityRules?: SecurityRule[];
471
+ securityRules?: readonly SecurityRule[];
475
472
  }
476
473
  /**
477
474
  * A collection backed by Firebase / Firestore.
478
475
  * Adds support for subcollections (nested document collections).
479
476
  *
480
- * Use this type instead of {@link EntityCollection} when you want
477
+ * Use this type instead of {@link CollectionConfig} when you want
481
478
  * compile-time safety that only Firestore-relevant fields appear.
482
479
  *
483
480
  * @group Models
484
481
  */
485
- export interface FirebaseCollection<M extends Record<string, unknown> = Record<string, unknown>, USER extends User = User> extends BaseEntityCollection<M, USER> {
482
+ export interface FirebaseCollectionConfig<M extends Record<string, unknown> = Record<string, unknown>, USER extends User = User> extends BaseCollectionConfig<M, USER> {
483
+ /**
484
+ * The database engine for this collection. Must be set to `"firestore"`.
485
+ */
486
+ engine: "firestore";
486
487
  /**
487
- * The driver for this collection. Must be set to `"firestore"`.
488
+ * Set of properties that compose a entity.
489
+ * Firestore collections support `reference` properties but not `relation`.
488
490
  */
489
- driver: "firestore";
491
+ properties: FirebaseProperties;
492
+ /**
493
+ * The Firestore collection path to query. Defaults to `slug` if not set.
494
+ * Use this when the Firestore path differs from the slug
495
+ * (e.g., when a PostgreSQL collection already uses the same slug).
496
+ *
497
+ * @example
498
+ * ```typescript
499
+ * const fsCustomer: FirebaseCollectionConfig = {
500
+ * slug: "fs_customer", // URL: /c/fs_customer
501
+ * path: "customer", // Firestore path: customer
502
+ * name: "Customers (Firestore)",
503
+ * engine: "firestore",
504
+ * properties: { ... }
505
+ * };
506
+ * ```
507
+ */
508
+ path?: string;
490
509
  /**
491
510
  * You can add subcollections to your entity in the same way you define the root
492
511
  * collections. The collections added here will be displayed when opening
493
- * the side dialog of an entity.
512
+ * the side dialog of a entity.
494
513
  */
495
- subcollections?: () => EntityCollection<Record<string, unknown>>[];
514
+ subcollections?: () => CollectionConfig<Record<string, unknown>>[];
496
515
  }
497
516
  /**
498
517
  * A collection backed by MongoDB.
499
518
  *
500
- * Use this type instead of {@link EntityCollection} when you want
519
+ * Use this type instead of {@link CollectionConfig} when you want
501
520
  * compile-time safety that only MongoDB-relevant fields appear.
502
521
  *
503
522
  * @group Models
504
523
  */
505
- export interface MongoDBCollection<M extends Record<string, unknown> = Record<string, unknown>, USER extends User = User> extends BaseEntityCollection<M, USER> {
524
+ export interface MongoDBCollectionConfig<M extends Record<string, unknown> = Record<string, unknown>, USER extends User = User> extends BaseCollectionConfig<M, USER> {
506
525
  /**
507
- * The driver for this collection. Must be set to `"mongodb"`.
526
+ * The database engine for this collection. Must be set to `"mongodb"`.
508
527
  */
509
- driver: "mongodb";
528
+ engine: "mongodb";
529
+ /**
530
+ * Set of properties that compose a entity.
531
+ * MongoDB collections support `reference` properties but not `relation`.
532
+ */
533
+ properties: MongoProperties;
534
+ /**
535
+ * The MongoDB collection name to use. Defaults to `slug` if not set.
536
+ * Use this when the MongoDB collection name differs from the slug
537
+ * (e.g., when a PostgreSQL collection already uses the same slug).
538
+ *
539
+ * @example
540
+ * ```typescript
541
+ * const mongoCustomer: MongoDBCollectionConfig = {
542
+ * slug: "mongo_customer", // URL: /c/mongo_customer
543
+ * path: "customer", // MongoDB collection: customer
544
+ * name: "Customers (MongoDB)",
545
+ * engine: "mongodb",
546
+ * properties: { ... }
547
+ * };
548
+ * ```
549
+ */
550
+ path?: string;
510
551
  }
511
552
  /**
512
553
  * A collection backed by any data source.
513
- * This is a discriminated union — use {@link PostgresCollection},
514
- * {@link FirebaseCollection}, or {@link MongoDBCollection} for
554
+ * This is a discriminated union — use {@link PostgresCollectionConfig},
555
+ * {@link FirebaseCollectionConfig}, or {@link MongoDBCollectionConfig} for
515
556
  * driver-specific type safety.
516
557
  *
517
558
  * @group Models
518
559
  */
519
- export type EntityCollection<M extends Record<string, unknown> = Record<string, unknown>, USER extends User = User> = PostgresCollection<M, USER> | FirebaseCollection<M, USER> | MongoDBCollection<M, USER>;
520
- /**
521
- * An EntityCollection that supports SQL-style relations (e.g. Postgres).
522
- * @deprecated Use `EntityCollection` directly — `table`, `relations`, and `securityRules` are now on `BaseEntityCollection`.
523
- */
524
- export type CollectionWithRelations<M extends Record<string, unknown> = Record<string, unknown>> = EntityCollection<M> & {
525
- table?: string;
526
- relations?: Relation[];
527
- securityRules?: SecurityRule[];
528
- };
529
- /** An EntityCollection that supports subcollections (e.g. Firestore). */
530
- export type CollectionWithSubcollections<M extends Record<string, unknown> = Record<string, unknown>> = EntityCollection<M> & {
531
- subcollections?: () => EntityCollection<Record<string, unknown>>[];
532
- };
560
+ export type CollectionConfig<M extends Record<string, unknown> = Record<string, unknown>, USER extends User = User> = PostgresCollectionConfig<M, USER> | FirebaseCollectionConfig<M, USER> | MongoDBCollectionConfig<M, USER>;
533
561
  /**
534
562
  * Type guard for PostgreSQL collections.
535
- * Returns true if the collection uses the Postgres driver (or the default driver).
563
+ * Returns true if the collection uses the Postgres engine (or the default engine).
536
564
  * @group Models
537
565
  */
538
- export declare function isPostgresCollection<M extends Record<string, unknown> = Record<string, unknown>, USER extends User = User>(collection: EntityCollection<M, USER>): collection is PostgresCollection<M, USER>;
566
+ export declare function isPostgresCollectionConfig<M extends Record<string, unknown> = Record<string, unknown>, USER extends User = User>(collection: CollectionConfig<M, USER>): collection is PostgresCollectionConfig<M, USER>;
539
567
  /**
540
568
  * Type guard for Firebase / Firestore collections.
541
569
  * @group Models
542
570
  */
543
- export declare function isFirebaseCollection<M extends Record<string, unknown> = Record<string, unknown>, USER extends User = User>(collection: EntityCollection<M, USER>): collection is FirebaseCollection<M, USER>;
571
+ export declare function isFirebaseCollectionConfig<M extends Record<string, unknown> = Record<string, unknown>, USER extends User = User>(collection: CollectionConfig<M, USER>): collection is FirebaseCollectionConfig<M, USER>;
544
572
  /**
545
573
  * Type guard for MongoDB collections.
546
574
  * @group Models
547
575
  */
548
- export declare function isMongoDBCollection<M extends Record<string, unknown> = Record<string, unknown>, USER extends User = User>(collection: EntityCollection<M, USER>): collection is MongoDBCollection<M, USER>;
576
+ export declare function isMongoDBCollectionConfig<M extends Record<string, unknown> = Record<string, unknown>, USER extends User = User>(collection: CollectionConfig<M, USER>): collection is MongoDBCollectionConfig<M, USER>;
577
+ /**
578
+ * Returns the data path for a collection.
579
+ * For Firestore or MongoDB collections with a `path`, returns that value;
580
+ * otherwise falls back to `slug`.
581
+ */
582
+ export declare function getCollectionDataPath<M extends Record<string, unknown> = Record<string, unknown>, USER extends User = User>(collection: CollectionConfig<M, USER>): string;
583
+ /**
584
+ * Reads a collection's driver-declared subcollections thunk (the `subcollections`
585
+ * field) independent of engine identity, so engine-agnostic code doesn't have to
586
+ * type-guard against a specific driver. Returns `undefined` when the collection
587
+ * declares none.
588
+ *
589
+ * Pair with `getDataSourceCapabilities(engine).supportsSubcollections` to decide
590
+ * whether the engine honours subcollections at all before reading them.
591
+ * @group Models
592
+ */
593
+ export declare function getDeclaredSubcollections<M extends Record<string, unknown> = Record<string, unknown>, USER extends User = User>(collection: CollectionConfig<M, USER>): (() => CollectionConfig<Record<string, unknown>>[]) | undefined;
549
594
  /**
550
595
  * Configuration for Kanban board view mode.
551
596
  * @group Collections
@@ -575,7 +620,7 @@ export type ViewMode = "list" | "table" | "cards" | "kanban";
575
620
  *
576
621
  * @group Models
577
622
  */
578
- export interface CollectionActionsProps<M extends Record<string, unknown> = Record<string, unknown>, USER extends User = User, EC extends EntityCollection<M> = EntityCollection<M>> {
623
+ export interface CollectionActionsProps<M extends Record<string, unknown> = Record<string, unknown>, USER extends User = User, EC extends CollectionConfig<M> = CollectionConfig<M>> {
579
624
  /**
580
625
  * Full collection path of this entity. This is the full path, like
581
626
  * `users/1234/addresses`
@@ -631,7 +676,7 @@ export interface CollectionActionsProps<M extends Record<string, unknown> = Reco
631
676
  }
632
677
  /**
633
678
  * Use this controller to retrieve the selected entities or modify them in
634
- * an {@link EntityCollection}
679
+ * an {@link CollectionConfig}
635
680
  * @group Models
636
681
  */
637
682
  export interface SelectionController<M extends Record<string, unknown> = Record<string, unknown>> {
@@ -641,42 +686,7 @@ export interface SelectionController<M extends Record<string, unknown> = Record<
641
686
  isEntitySelected(entity: Entity<M>): boolean;
642
687
  toggleEntitySelection(entity: Entity<M>, newSelectedState?: boolean): void;
643
688
  }
644
- /**
645
- * Filter conditions in a `Query.where()` clause are specified using the
646
- * strings `<`, `<=`, `==`, `>=`, `>`, `array-contains`, `in`, and `array-contains-any`.
647
- * @group Models
648
- */
649
- export type WhereFilterOp = "<" | "<=" | "==" | "!=" | ">=" | ">" | "array-contains" | "in" | "not-in" | "array-contains-any";
650
- /**
651
- * Used to define filters applied in collections
652
- *
653
- * e.g. `{ age: [">=", 18] }`
654
- *
655
- * @group Models
656
- */
657
- export type FilterValues<Key extends string> = Partial<Record<Key, [WhereFilterOp, unknown] | [WhereFilterOp, unknown][]>>;
658
- /**
659
- * A pre-defined filter preset for quick access in the collection toolbar.
660
- * Users can select a preset to instantly apply a set of filters and
661
- * optionally a sort order.
662
- *
663
- * @group Models
664
- */
665
- export interface FilterPreset<Key extends string = string> {
666
- /**
667
- * Display label shown in the preset menu.
668
- * If omitted, a summary is auto-generated from the filter keys.
669
- */
670
- label?: string;
671
- /**
672
- * The filter values to apply when this preset is selected.
673
- */
674
- filterValues: FilterValues<Key>;
675
- /**
676
- * Optional sort override to apply alongside the filter values.
677
- */
678
- sort?: [Key, "asc" | "desc"];
679
- }
689
+ export type { WhereFilterOp, FilterValues, WireFilterValues, FilterPreset } from "./filter-operators";
680
690
  /**
681
691
  * Used to indicate valid filter combinations (e.g. created in Firestore)
682
692
  * If the user selects a specific filter/sort combination, the CMS checks if it's
@@ -739,14 +749,14 @@ export interface AdditionalFieldDelegate<M extends Record<string, unknown> = Rec
739
749
  context: RebaseContext;
740
750
  }): string | number | Promise<string | number> | undefined;
741
751
  }
742
- export type InferCollectionType<S extends EntityCollection> = S extends EntityCollection<infer M> ? M : never;
752
+ export type InferCollectionConfigType<S extends CollectionConfig> = S extends CollectionConfig<infer M> ? M : never;
743
753
  /**
744
- * Used in the {@link EntityCollection#defaultSelectedView} to define the default
754
+ * Used in the {@link CollectionConfig#defaultSelectedView} to define the default
745
755
  * @group Models
746
756
  */
747
757
  export type DefaultSelectedViewBuilder = (params: DefaultSelectedViewParams) => string | undefined;
748
758
  /**
749
- * Used in the {@link EntityCollection#defaultSelectedView} to define the default
759
+ * Used in the {@link CollectionConfig#defaultSelectedView} to define the default
750
760
  * @group Models
751
761
  */
752
762
  export type DefaultSelectedViewParams = {
@@ -799,7 +809,7 @@ export type SecurityOperation = "select" | "insert" | "update" | "delete" | "all
799
809
  /**
800
810
  * Flexible Row Level Security rule for a collection.
801
811
  *
802
- * Inspired by Supabase's approach to PostgreSQL RLS. Rules can range from
812
+ * Built on PostgreSQL Row Level Security. Rules can range from
803
813
  * simple convenience shortcuts to fully custom SQL expressions, giving you the
804
814
  * full power of PostgreSQL Row Level Security.
805
815
  *
@@ -812,15 +822,23 @@ export type SecurityOperation = "select" | "insert" | "update" | "delete" | "all
812
822
  *
813
823
  * **How rules combine:** PostgreSQL evaluates all matching policies for an
814
824
  * operation. Permissive rules are OR'd together (any one passing is enough).
815
- * Restrictive rules are AND'd (all must pass). This mirrors Supabase behavior.
825
+ * Restrictive rules are AND'd (all must pass). This is standard PostgreSQL RLS behavior.
816
826
  *
817
- * **Mutual exclusivity:** `ownerField`, `access`, and raw SQL (`using`/`withCheck`)
818
- * cannot be combined. The type system enforces this — attempting to set
819
- * conflicting fields will produce a compile-time error.
827
+ * **Mutual exclusivity:** `ownerField`, `access`, structured `condition`, and
828
+ * raw SQL (`using`/`withCheck`) cannot be combined. The type system enforces
829
+ * this — attempting to set conflicting fields will produce a compile-time
830
+ * error.
831
+ *
832
+ * **Which form to reach for:** prefer the structured {@link StructuredSecurityRule}
833
+ * (`condition`/`check`) or the shortcuts (`ownerField`, `access`, `roles`). These
834
+ * are engine-agnostic and evaluated identically by the database and the admin UI,
835
+ * so the UI never shows an action the database will reject. Raw SQL
836
+ * ({@link RawSQLSecurityRule}) keeps full PostgreSQL power but is Postgres-only
837
+ * and server-authoritative (the UI cannot evaluate arbitrary SQL locally).
820
838
  *
821
839
  * @group Models
822
840
  */
823
- export type SecurityRule = OwnerSecurityRule | PublicSecurityRule | RawSQLSecurityRule | RolesOnlySecurityRule;
841
+ export type SecurityRule = OwnerSecurityRule | PublicSecurityRule | StructuredSecurityRule | RawSQLSecurityRule | RolesOnlySecurityRule;
824
842
  /**
825
843
  * Shared fields for all SecurityRule variants.
826
844
  * @group Models
@@ -863,7 +881,7 @@ export interface SecurityRuleBase {
863
881
  * // Equivalent to operation: "all"
864
882
  * { operations: ["all"], ownerField: "user_id" }
865
883
  */
866
- operations?: SecurityOperation[];
884
+ operations?: readonly SecurityOperation[];
867
885
  /**
868
886
  * Whether this policy is `"permissive"` (default) or `"restrictive"`.
869
887
  *
@@ -872,7 +890,7 @@ export interface SecurityRuleBase {
872
890
  * - **restrictive**: Restrictive policies are AND'd with all permissive
873
891
  * policies — they act as additional gates that *must* also pass.
874
892
  *
875
- * This is the same model as PostgreSQL / Supabase.
893
+ * This is the standard PostgreSQL RLS model.
876
894
  *
877
895
  * @default "permissive"
878
896
  */
@@ -885,11 +903,16 @@ export interface SecurityRuleBase {
885
903
  * application roles managed by Rebase, stored in the `rebase.user_roles`
886
904
  * table, and injected into each transaction via `auth.roles()`.
887
905
  *
888
- * Generates a condition like:
889
- * `auth.roles() ~ '<role1>|<role2>'`
906
+ * Generates a safe array-overlap condition — the user passes if they hold
907
+ * *any* of the listed roles:
908
+ * `string_to_array(auth.roles(), ',') && ARRAY['<role1>', '<role2>']`
909
+ *
910
+ * (Note: this is a true set intersection, NOT a regex/substring match, so
911
+ * a role named `admin` never matches `nonadmin` or `superadmin`.)
890
912
  *
891
- * Can be combined with `ownerField`, `access`, or raw `using`/`withCheck`.
892
- * When combined, the role check is AND'd with the other condition.
913
+ * Can be combined with `ownerField`, `access`, `condition`, or raw
914
+ * `using`/`withCheck`. When combined, the role check is AND'd with the
915
+ * other condition.
893
916
  *
894
917
  * @example
895
918
  * // Only admins can delete
@@ -899,7 +922,7 @@ export interface SecurityRuleBase {
899
922
  * // Admins have unfiltered read access to all rows
900
923
  * { operation: "select", roles: ["admin"], using: "true" }
901
924
  */
902
- roles?: string[];
925
+ roles?: readonly string[];
903
926
  /**
904
927
  * **Advanced.** Native PostgreSQL database roles the policy applies to.
905
928
  *
@@ -921,7 +944,7 @@ export interface SecurityRuleBase {
921
944
  * // Only apply this policy when connected as `app_role`
922
945
  * { operation: "select", access: "public", pgRoles: ["app_role"] }
923
946
  */
924
- pgRoles?: string[];
947
+ pgRoles?: readonly string[];
925
948
  }
926
949
  /**
927
950
  * Security rule that grants access based on row ownership.
@@ -940,6 +963,8 @@ export interface OwnerSecurityRule extends SecurityRuleBase {
940
963
  access?: never;
941
964
  using?: never;
942
965
  withCheck?: never;
966
+ condition?: never;
967
+ check?: never;
943
968
  }
944
969
  /**
945
970
  * Security rule that grants unrestricted row access (no row filtering).
@@ -963,11 +988,57 @@ export interface PublicSecurityRule extends SecurityRuleBase {
963
988
  ownerField?: never;
964
989
  using?: never;
965
990
  withCheck?: never;
991
+ condition?: never;
992
+ check?: never;
993
+ }
994
+ /**
995
+ * Security rule expressed as a structured, engine-agnostic
996
+ * {@link PolicyExpression}. This is the **recommended** way to write a
997
+ * non-trivial condition: it compiles to PostgreSQL `USING`/`WITH CHECK` SQL
998
+ * *and* is evaluated identically by the admin UI, so the UI can never show an
999
+ * action the database will reject.
1000
+ *
1001
+ * Cannot be combined with `ownerField`, `access`, or raw `using`/`withCheck`.
1002
+ *
1003
+ * @example
1004
+ * // Owner, or any user holding the `moderator` role
1005
+ * {
1006
+ * operation: "update",
1007
+ * condition: policy.or(
1008
+ * policy.compare(policy.field("user_id"), "eq", policy.authUid()),
1009
+ * policy.rolesOverlap(["moderator"])
1010
+ * )
1011
+ * }
1012
+ *
1013
+ * @group Models
1014
+ */
1015
+ export interface StructuredSecurityRule extends SecurityRuleBase {
1016
+ /**
1017
+ * Structured condition for the `USING` clause — which *existing* rows are
1018
+ * visible / can be modified / deleted (SELECT, UPDATE, DELETE).
1019
+ */
1020
+ condition: PolicyExpression;
1021
+ /**
1022
+ * Structured condition for the `WITH CHECK` clause — which *new/updated*
1023
+ * row values are allowed (INSERT, UPDATE). Defaults to `condition` when
1024
+ * omitted, mirroring PostgreSQL's own behavior.
1025
+ */
1026
+ check?: PolicyExpression;
1027
+ ownerField?: never;
1028
+ access?: never;
1029
+ using?: never;
1030
+ withCheck?: never;
966
1031
  }
967
1032
  /**
968
1033
  * Security rule using raw SQL expressions for full PostgreSQL RLS power.
969
1034
  *
970
- * Cannot be combined with `ownerField` or `access`.
1035
+ * **Postgres-only and server-authoritative.** Arbitrary SQL cannot be
1036
+ * evaluated by the admin UI, so a rule using this form is treated as *unknown*
1037
+ * client-side (never silently allowed) and its effect on visible actions is
1038
+ * reflected from the server. For conditions that should also drive the UI
1039
+ * precisely, prefer the structured {@link StructuredSecurityRule}.
1040
+ *
1041
+ * Cannot be combined with `ownerField`, `access`, or structured `condition`.
971
1042
  *
972
1043
  * You can reference columns via `{column_name}` which will be resolved to
973
1044
  * `table.column_name` in the generated Drizzle code.
@@ -1003,6 +1074,8 @@ export interface RawSQLSecurityRule extends SecurityRuleBase {
1003
1074
  withCheck?: string;
1004
1075
  ownerField?: never;
1005
1076
  access?: never;
1077
+ condition?: never;
1078
+ check?: never;
1006
1079
  }
1007
1080
  /**
1008
1081
  * Security rule that only filters by application roles, without any
@@ -1022,6 +1095,8 @@ export interface RolesOnlySecurityRule extends SecurityRuleBase {
1022
1095
  access?: never;
1023
1096
  using?: never;
1024
1097
  withCheck?: never;
1098
+ condition?: never;
1099
+ check?: never;
1025
1100
  }
1026
1101
  /**
1027
1102
  * Configuration for authentication collections.