@rebasepro/types 0.8.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 (78) hide show
  1. package/README.md +10 -10
  2. package/dist/controllers/auth.d.ts +1 -1
  3. package/dist/controllers/client.d.ts +184 -6
  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 +267 -35
  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 -4
  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 +142 -15
  17. package/dist/index.es.js.map +1 -1
  18. package/dist/index.umd.js +150 -17
  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 +4 -1
  22. package/dist/types/backend.d.ts +26 -26
  23. package/dist/types/builders.d.ts +2 -2
  24. package/dist/types/collections.d.ts +62 -63
  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 +15 -2
  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 +39 -39
  32. package/dist/types/entity_views.d.ts +3 -3
  33. package/dist/types/filter-operators.d.ts +62 -17
  34. package/dist/types/modify_collections.d.ts +2 -2
  35. package/dist/types/plugins.d.ts +9 -9
  36. package/dist/types/policy.d.ts +64 -10
  37. package/dist/types/properties.d.ts +41 -9
  38. package/dist/types/relations.d.ts +3 -3
  39. package/dist/types/slots.d.ts +14 -14
  40. package/dist/types/websockets.d.ts +12 -13
  41. package/dist/users/user.d.ts +21 -9
  42. package/package.json +1 -1
  43. package/src/controllers/auth.tsx +1 -1
  44. package/src/controllers/client.ts +214 -6
  45. package/src/controllers/collection_registry.ts +3 -3
  46. package/src/controllers/customization_controller.tsx +1 -1
  47. package/src/controllers/data.ts +290 -39
  48. package/src/controllers/data_driver.ts +49 -40
  49. package/src/controllers/index.ts +1 -1
  50. package/src/controllers/local_config_persistence.tsx +4 -4
  51. package/src/controllers/navigation.ts +2 -2
  52. package/src/controllers/registry.ts +18 -4
  53. package/src/controllers/{side_entity_controller.tsx → side_panel_controller.tsx} +7 -7
  54. package/src/controllers/storage.ts +60 -1
  55. package/src/errors.ts +80 -0
  56. package/src/index.ts +1 -0
  57. package/src/rebase_context.tsx +8 -4
  58. package/src/types/auth_adapter.ts +4 -1
  59. package/src/types/backend.ts +36 -36
  60. package/src/types/builders.ts +2 -2
  61. package/src/types/collections.ts +78 -79
  62. package/src/types/component_overrides.ts +72 -5
  63. package/src/types/cron.ts +10 -1
  64. package/src/types/data_source.ts +24 -2
  65. package/src/types/database_adapter.ts +4 -3
  66. package/src/types/entities.ts +7 -7
  67. package/src/types/entity_actions.tsx +7 -7
  68. package/src/types/entity_callbacks.ts +42 -42
  69. package/src/types/entity_views.tsx +3 -3
  70. package/src/types/filter-operators.ts +96 -23
  71. package/src/types/modify_collections.tsx +2 -2
  72. package/src/types/plugins.tsx +9 -9
  73. package/src/types/policy.ts +64 -8
  74. package/src/types/properties.ts +44 -9
  75. package/src/types/relations.ts +3 -3
  76. package/src/types/slots.tsx +14 -14
  77. package/src/types/websockets.ts +12 -14
  78. package/src/users/user.ts +22 -9
@@ -1,4 +1,6 @@
1
1
  import type React from "react";
2
+ import type { Property } from "./properties";
3
+ import type { WhereFilterOp } from "./filter-operators";
2
4
  /**
3
5
  * Components that can only be overridden at the **app level** via the
4
6
  * `components` prop on `<Rebase>`.
@@ -20,12 +22,68 @@ export type AppComponentName = "Shell.AppBar" | "Shell.Drawer" | "Shell.DrawerNa
20
22
  *
21
23
  * @group Component Overrides
22
24
  */
23
- export type CollectionComponentName = "Collection.View" | "Collection.Table" | "Collection.Card" | "Collection.EmptyState" | "Collection.Actions" | "Entity.Form" | "Entity.FormActions" | "Entity.DetailView" | "Entity.SidePanel" | "Entity.Preview" | "Entity.MissingReference";
25
+ export type CollectionComponentName = "Collection.View" | "Collection.Table" | "Collection.Card" | "Collection.EmptyState" | "Collection.Actions" | "Collection.FilterField" | "Entity.Form" | "EditView.FormActions" | "DetailView" | "Entity.SidePanel" | "EntityPreview" | "Entity.MissingReference";
24
26
  /**
25
27
  * All overridable component names across all scopes.
26
28
  * @group Component Overrides
27
29
  */
28
30
  export type OverridableComponentName = AppComponentName | CollectionComponentName;
31
+ /**
32
+ * Props received by a filter field component — whether it is a built-in
33
+ * per-type field, a property-level replacement (`property.ui.Filter`), or a
34
+ * `"Collection.FilterField"` override.
35
+ *
36
+ * The `operators` list is **already resolved**: it is the intersection of the
37
+ * engine's {@link DataSourceCapabilities.filterOperators}, the property-type
38
+ * defaults, and any `property.ui.filterOperators` narrowing. A custom field
39
+ * should only offer operators from this list — anything else may throw at
40
+ * query time on engines that cannot execute it.
41
+ *
42
+ * @example
43
+ * ```tsx
44
+ * function MyStatusFilter({ value, setValue, operators }: FilterFieldBindingProps) {
45
+ * return (
46
+ * <select
47
+ * value={value?.[1] as string ?? ""}
48
+ * onChange={e => setValue(e.target.value ? ["==", e.target.value] : undefined)}>
49
+ * <option value="">Any</option>
50
+ * <option value="active">Active</option>
51
+ * <option value="archived">Archived</option>
52
+ * </select>
53
+ * );
54
+ * }
55
+ * ```
56
+ *
57
+ * @group Component Overrides
58
+ */
59
+ export interface FilterFieldBindingProps {
60
+ /** Key of the property being filtered (the column id). */
61
+ propertyKey: string;
62
+ /**
63
+ * The resolved property. For array properties this is the **item**
64
+ * property (`property.of`), with `isArray` set to true.
65
+ */
66
+ property: Property;
67
+ /** True when the underlying property is an array of `property`. */
68
+ isArray: boolean;
69
+ /**
70
+ * Operators this field may offer, already narrowed by engine
71
+ * capabilities, property-type defaults, and `property.ui.filterOperators`.
72
+ */
73
+ operators: readonly WhereFilterOp[];
74
+ /** Current filter condition for this property, if any. */
75
+ value?: [WhereFilterOp, unknown];
76
+ /** Set (or clear, with `undefined`) the filter condition. */
77
+ setValue: (value?: [WhereFilterOp, unknown]) => void;
78
+ /** Display title for the field (usually the property name). */
79
+ title?: string;
80
+ /**
81
+ * Coordination flags used by fields that open their own dialogs
82
+ * (e.g. the reference picker hides the parent filters dialog).
83
+ */
84
+ hidden?: boolean;
85
+ setHidden?: (hidden: boolean) => void;
86
+ }
29
87
  /**
30
88
  * A single component override entry.
31
89
  *
@@ -55,7 +113,7 @@ export type OverridableComponentName = AppComponentName | CollectionComponentNam
55
113
  *
56
114
  * @group Component Overrides
57
115
  */
58
- export interface ComponentOverride<P = any> {
116
+ export interface ComponentOverride<P = Record<string, unknown>> {
59
117
  /**
60
118
  * The replacement component. Receives the same props as the built-in
61
119
  * component it replaces.
@@ -122,7 +180,7 @@ export type CollectionComponentOverrideMap = {
122
180
  * "HomePage": { Component: MyDashboard },
123
181
  *
124
182
  * // Collection defaults: apply to ALL collections
125
- * "Entity.FormActions": {
183
+ * "EditView.FormActions": {
126
184
  * Component: MyFormActions,
127
185
  * wrap: true
128
186
  * },
@@ -43,7 +43,16 @@ export interface CronJobContext {
43
43
  scheduledAt: Date;
44
44
  /** A simple logger scoped to this job run. */
45
45
  log: (...args: unknown[]) => void;
46
- /** The RebaseClient instance to interact with the database. */
46
+ /**
47
+ * The server-side {@link RebaseClient}. This is the **same singleton**
48
+ * exposed as `rebase` (imported from `@rebasepro/server-core`) and as
49
+ * `context` in collection callbacks — it is only named `client` here.
50
+ *
51
+ * Its data plane (`client.data`) runs with **admin privileges and bypasses
52
+ * RLS** (`{ uid: "service", roles: ["admin"] }`). There is no per-request
53
+ * user in a cron, so treat every query as fully trusted and scope your own
54
+ * filters explicitly.
55
+ */
47
56
  client: RebaseClient;
48
57
  }
49
58
  export type CronJobRunState = "idle" | "running" | "success" | "error" | "disabled";
@@ -1,3 +1,4 @@
1
+ import { WhereFilterOp } from "./filter-operators";
1
2
  /**
2
3
  * Describes the capabilities and features supported by a data source (driver).
3
4
  *
@@ -26,6 +27,16 @@ export interface DataSourceCapabilities {
26
27
  supportsColumnTypes: boolean;
27
28
  /** Does this source support real-time listeners? */
28
29
  supportsRealtime: boolean;
30
+ /**
31
+ * Canonical filter operators this engine can execute.
32
+ *
33
+ * The admin UI intersects this set with the property-type defaults and
34
+ * any per-property narrowing (`property.ui.filterOperators`) to decide
35
+ * which operators to offer in filter fields — so an engine that cannot
36
+ * run `ilike` (e.g. Firestore) never shows a "Contains" filter that
37
+ * would throw at query time.
38
+ */
39
+ filterOperators: readonly WhereFilterOp[];
29
40
  /** Does this source support SQL admin operations (SQL editor, EXPLAIN, etc.)? */
30
41
  supportsSQLAdmin: boolean;
31
42
  /** Does this source support document admin operations (aggregation, stats)? */
@@ -84,9 +95,11 @@ export interface DataSourceDefinition {
84
95
  */
85
96
  engine: string;
86
97
  /**
87
- * How the frontend reaches this source. Defaults to `"server"`.
98
+ * How the frontend reaches this source. Optional when omitted it is
99
+ * inferred: `"direct"` if the definition carries a client-side driver,
100
+ * `"server"` otherwise.
88
101
  */
89
- transport: DataSourceTransport;
102
+ transport?: DataSourceTransport;
90
103
  /**
91
104
  * The physical database/schema/Firestore-database within the engine.
92
105
  * Threaded to drivers/adapters as the existing `databaseId` runtime
@@ -20,8 +20,9 @@
20
20
  * @group Backend
21
21
  */
22
22
  import type { DataDriver } from "../controllers/data_driver";
23
- import type { EntityCollection } from "./collections";
23
+ import type { CollectionConfig } from "./collections";
24
24
  import type { CollectionRegistryInterface, DatabaseAdmin, InitializedDriver, RealtimeProvider, BootstrappedAuth } from "./backend";
25
+ import type { HistoryConfig } from "../controllers/client";
25
26
  /**
26
27
  * A `DatabaseAdapter` provides data persistence for Rebase.
27
28
  *
@@ -59,7 +60,7 @@ export interface DatabaseAdapter {
59
60
  *
60
61
  * Return `undefined` if the database does not support history.
61
62
  */
62
- initializeHistory?(config: unknown, driverResult: InitializedDriver): Promise<{
63
+ initializeHistory?(config: HistoryConfig, driverResult: InitializedDriver): Promise<{
63
64
  historyService: unknown;
64
65
  } | undefined>;
65
66
  /**
@@ -88,7 +89,7 @@ export interface DatabaseAdapter {
88
89
  */
89
90
  export interface DatabaseAdapterInitConfig {
90
91
  /** Registered collection definitions. */
91
- collections: EntityCollection[];
92
+ collections: CollectionConfig[];
92
93
  /** The shared collection registry to register into. */
93
94
  collectionRegistry: CollectionRegistryInterface;
94
95
  }
@@ -4,7 +4,7 @@
4
4
  */
5
5
  export type EntityStatus = "new" | "existing" | "copy";
6
6
  /**
7
- * Representation of an entity fetched from the driver
7
+ * Representation of a entity fetched from the driver
8
8
  * @group Models
9
9
  */
10
10
  export interface Entity<M extends Record<string, unknown> = Record<string, unknown>> {
@@ -39,7 +39,7 @@ export interface Entity<M extends Record<string, unknown> = Record<string, unkno
39
39
  */
40
40
  export type EntityValues<M extends Record<string, unknown>> = M;
41
41
  /**
42
- * Props for creating an EntityReference
42
+ * Props for creating a EntityReference
43
43
  */
44
44
  export interface EntityReferenceProps {
45
45
  /** ID of the entity */
@@ -52,7 +52,7 @@ export interface EntityReferenceProps {
52
52
  databaseId?: string;
53
53
  }
54
54
  /**
55
- * Class used to create a reference to an entity in a different path.
55
+ * Class used to create a reference to a entity in a different path.
56
56
  *
57
57
  * @example
58
58
  * // Simple reference (most common case - single driver, single db)
@@ -86,7 +86,7 @@ export declare class EntityReference {
86
86
  */
87
87
  readonly databaseId?: string;
88
88
  /**
89
- * Create a reference to an entity.
89
+ * Create a reference to a entity.
90
90
  *
91
91
  * @example
92
92
  * // Simple reference (most common case)
@@ -105,7 +105,7 @@ export declare class EntityReference {
105
105
  isEntityReference(): boolean;
106
106
  }
107
107
  /**
108
- * Class used to create a reference to an entity in a different path
108
+ * Class used to create a reference to a entity in a different path
109
109
  */
110
110
  export declare class EntityRelation {
111
111
  readonly __type = "relation";
@@ -122,8 +122,8 @@ export declare class EntityRelation {
122
122
  * Pre-fetched data payload to eliminate N+1 queries.
123
123
  * When present, clients can use this directly instead of fetching.
124
124
  */
125
- readonly data?: Entity;
126
- constructor(id: string | number, path: string, data?: Entity);
125
+ readonly data?: Record<string, unknown>;
126
+ constructor(id: string | number, path: string, data?: Record<string, unknown>);
127
127
  get pathWithId(): string;
128
128
  isEntityReference(): boolean;
129
129
  isEntityRelation(): boolean;
@@ -1,12 +1,12 @@
1
1
  import React from "react";
2
2
  import type { Entity } from "./entities";
3
- import type { EntityCollection, SelectionController } from "./collections";
3
+ import type { CollectionConfig, SelectionController } from "./collections";
4
4
  import type { FormContext } from "./entity_views";
5
5
  import type { User } from "../users";
6
6
  import type { RebaseContext } from "../rebase_context";
7
- import type { SideEntityController } from "../controllers/side_entity_controller";
7
+ import type { SidePanelController } from "../controllers/side_panel_controller";
8
8
  /**
9
- * An entity action is a custom action that can be performed on an entity.
9
+ * A entity action is a custom action that can be performed on a entity.
10
10
  * They are displayed in the entity view and in the collection view.
11
11
  */
12
12
  export interface EntityAction<M extends Record<string, unknown> = Record<string, unknown>, USER extends User = User> {
@@ -61,7 +61,7 @@ export type EntityActionClickProps<M extends Record<string, unknown>, USER exten
61
61
  entity?: Entity<M>;
62
62
  context?: RebaseContext<USER>;
63
63
  path?: string;
64
- collection?: EntityCollection<M>;
64
+ collection?: CollectionConfig<M>;
65
65
  /**
66
66
  * Optional form context, present if the action is being called from a form.
67
67
  * This allows you to access the form state and methods, including modifying the form values.
@@ -70,7 +70,7 @@ export type EntityActionClickProps<M extends Record<string, unknown>, USER exten
70
70
  /**
71
71
  * Present if this actions is being called from a side dialog only
72
72
  */
73
- sideEntityController?: SideEntityController;
73
+ sidePanelController?: SidePanelController;
74
74
  /**
75
75
  * Is the action being called from the collection view or from the entity form view?
76
76
  */
@@ -94,11 +94,11 @@ export type EntityActionClickProps<M extends Record<string, unknown>, USER exten
94
94
  */
95
95
  unhighlightEntity?: (entity: Entity<Record<string, unknown>>) => void;
96
96
  /**
97
- * Optional function to navigate back (e.g. when deleting an entity or navigating from a form)
97
+ * Optional function to navigate back (e.g. when deleting a entity or navigating from a form)
98
98
  */
99
99
  navigateBack?: () => void;
100
100
  /**
101
- * Callback to be called when the collection changes, e.g. after an entity is deleted or created.
101
+ * Callback to be called when the collection changes, e.g. after a entity is deleted or created.
102
102
  */
103
103
  onCollectionChange?: () => void;
104
104
  };
@@ -1,12 +1,12 @@
1
- import type { EntityCollection } from "./collections";
2
- import type { Entity, EntityStatus, EntityValues } from "./entities";
1
+ import type { CollectionConfig } from "./collections";
2
+ import type { EntityStatus, EntityValues } from "./entities";
3
3
  import type { User } from "../users";
4
4
  import type { RebaseCallContext } from "../rebase_context";
5
5
  /**
6
6
  * Lifecycle callbacks for entity CRUD operations.
7
7
  *
8
8
  * Register per-collection on the collection's `callbacks` field, or globally
9
- * via `initBackend({ callbacks })`. Fires on **every** data path — REST API,
9
+ * via `initializeRebaseBackend({ callbacks })`. Fires on **every** data path — REST API,
10
10
  * WebSocket / realtime subscriptions, and server-side `rebase.data`.
11
11
  *
12
12
  * When both global and per-collection callbacks are registered, execution
@@ -14,7 +14,7 @@ import type { RebaseCallContext } from "../rebase_context";
14
14
  *
15
15
  * @group Models
16
16
  */
17
- export type EntityCallbacks<M extends Record<string, unknown> = Record<string, unknown>, USER extends User = User> = {
17
+ export type CollectionCallbacks<M extends Record<string, unknown> = Record<string, unknown>, USER extends User = User> = {
18
18
  /**
19
19
  * Callback used after fetching data.
20
20
  *
@@ -23,88 +23,88 @@ export type EntityCallbacks<M extends Record<string, unknown> = Record<string, u
23
23
  *
24
24
  * @param props
25
25
  */
26
- afterRead?(props: EntityAfterReadProps<M, USER>): Promise<Entity<M>> | Entity<M>;
26
+ afterRead?(props: AfterReadProps<M, USER>): Promise<Record<string, unknown>> | Record<string, unknown>;
27
27
  /**
28
28
  * Callback used before saving, you need to return the values that will get
29
29
  * saved. If you throw an error in this method the process stops, and an
30
- * error snackbar gets displayed.
30
+ * HTTP error response is returned to the client.
31
31
  * This runs after schema validation.
32
32
  *
33
33
  * @param props
34
34
  */
35
- beforeSave?(props: EntityBeforeSaveProps<M, USER>): Promise<Partial<EntityValues<M>>> | Partial<EntityValues<M>>;
35
+ beforeSave?(props: BeforeSaveProps<M, USER>): Promise<Partial<EntityValues<M>>> | Partial<EntityValues<M>>;
36
36
  /**
37
37
  * Callback used when save is successful.
38
38
  *
39
39
  * @param props
40
40
  */
41
- afterSave?(props: EntityAfterSaveProps<M, USER>): Promise<void> | void;
41
+ afterSave?(props: AfterSaveProps<M, USER>): Promise<void> | void;
42
42
  /**
43
43
  * Callback used when saving fails
44
44
  * @param props
45
45
  */
46
- afterSaveError?(props: EntityAfterSaveErrorProps<M, USER>): Promise<void> | void;
46
+ afterSaveError?(props: AfterSaveErrorProps<M, USER>): Promise<void> | void;
47
47
  /**
48
48
  * Callback used before the entity is deleted.
49
49
  * If you throw an error in this method the process stops, and an
50
- * error snackbar gets displayed.
50
+ * HTTP error response is returned to the client.
51
51
  *
52
52
  * @param props
53
53
  */
54
- beforeDelete?(props: EntityBeforeDeleteProps<M, USER>): Promise<boolean | void> | boolean | void;
54
+ beforeDelete?(props: BeforeDeleteProps<M, USER>): Promise<boolean | void> | boolean | void;
55
55
  /**
56
56
  * Callback used after the entity is deleted.
57
57
  *
58
58
  * @param props
59
59
  */
60
- afterDelete?(props: EntityAfterDeleteProps<M, USER>): Promise<void> | void;
60
+ afterDelete?(props: AfterDeleteProps<M, USER>): Promise<void> | void;
61
61
  };
62
62
  /**
63
- * Parameters passed to hooks when an entity is fetched
63
+ * Parameters passed to hooks when a entity is fetched
64
64
  * @group Models
65
65
  */
66
- export interface EntityAfterReadProps<M extends Record<string, unknown> = Record<string, unknown>, USER extends User = User> {
66
+ export interface AfterReadProps<M extends Record<string, unknown> = Record<string, unknown>, USER extends User = User> {
67
67
  /**
68
68
  * Collection of the entity
69
69
  */
70
- collection: EntityCollection<M>;
70
+ collection: CollectionConfig<M>;
71
71
  /**
72
72
  * Full path of the CMS where this collection is being fetched.
73
73
  * Might contain unresolved aliases.
74
74
  */
75
75
  path: string;
76
76
  /**
77
- * Fetched entity
77
+ * Fetched row (flat — `{ id, ...columns }`)
78
78
  */
79
- entity: Entity<M>;
79
+ row: Record<string, unknown>;
80
80
  /**
81
81
  * Context of the app status
82
82
  */
83
83
  context: RebaseCallContext<USER>;
84
84
  }
85
85
  /**
86
- * Parameters passed to hooks before an entity is saved
86
+ * Parameters passed to hooks before a entity is saved
87
87
  * @group Models
88
88
  */
89
- export type EntityBeforeSaveProps<M extends Record<string, unknown> = Record<string, unknown>, USER extends User = User> = Omit<EntityAfterSaveProps<M, USER>, "entityId"> & {
90
- entityId?: string | number;
89
+ export type BeforeSaveProps<M extends Record<string, unknown> = Record<string, unknown>, USER extends User = User> = Omit<AfterSaveProps<M, USER>, "id"> & {
90
+ id?: string | number;
91
91
  };
92
92
  /**
93
- * Parameters passed to hooks before an entity is saved
93
+ * Parameters passed to hooks before a entity is saved
94
94
  * @group Models
95
95
  */
96
- export type EntityAfterSaveErrorProps<M extends Record<string, unknown> = Record<string, unknown>, USER extends User = User> = Omit<EntityAfterSaveProps<M, USER>, "entityId"> & {
97
- entityId?: string | number;
96
+ export type AfterSaveErrorProps<M extends Record<string, unknown> = Record<string, unknown>, USER extends User = User> = Omit<AfterSaveProps<M, USER>, "id"> & {
97
+ id?: string | number;
98
98
  };
99
99
  /**
100
- * Parameters passed to hooks when an entity is saved
100
+ * Parameters passed to hooks when a entity is saved
101
101
  * @group Models
102
102
  */
103
- export interface EntityAfterSaveProps<M extends Record<string, unknown> = Record<string, unknown>, USER extends User = User> {
103
+ export interface AfterSaveProps<M extends Record<string, unknown> = Record<string, unknown>, USER extends User = User> {
104
104
  /**
105
105
  * Resolved collection of the entity
106
106
  */
107
- collection: EntityCollection<M>;
107
+ collection: CollectionConfig<M>;
108
108
  /**
109
109
  * Full path of the CMS where this entity is being saved.
110
110
  * Might contain unresolved aliases.
@@ -113,7 +113,7 @@ export interface EntityAfterSaveProps<M extends Record<string, unknown> = Record
113
113
  /**
114
114
  * ID of the entity
115
115
  */
116
- entityId: string | number;
116
+ id: string | number;
117
117
  /**
118
118
  * Values being saved
119
119
  */
@@ -132,14 +132,14 @@ export interface EntityAfterSaveProps<M extends Record<string, unknown> = Record
132
132
  context: RebaseCallContext<USER>;
133
133
  }
134
134
  /**
135
- * Parameters passed to hooks when an entity is deleted
135
+ * Parameters passed to hooks when a entity is deleted
136
136
  * @group Models
137
137
  */
138
- export interface EntityBeforeDeleteProps<M extends Record<string, unknown> = Record<string, unknown>, USER extends User = User> {
138
+ export interface BeforeDeleteProps<M extends Record<string, unknown> = Record<string, unknown>, USER extends User = User> {
139
139
  /**
140
140
  * collection of the entity being deleted
141
141
  */
142
- collection: EntityCollection<M>;
142
+ collection: CollectionConfig<M>;
143
143
  /**
144
144
  * Path of the parent collection
145
145
  */
@@ -147,25 +147,25 @@ export interface EntityBeforeDeleteProps<M extends Record<string, unknown> = Rec
147
147
  /**
148
148
  * Deleted entity id
149
149
  */
150
- entityId: string | number;
150
+ id: string | number;
151
151
  /**
152
- * Deleted entity
152
+ * Deleted row (flat — `{ id, ...columns }`)
153
153
  */
154
- entity: Entity<M>;
154
+ row: Record<string, unknown>;
155
155
  /**
156
156
  * Context of the app status
157
157
  */
158
158
  context: RebaseCallContext<USER>;
159
159
  }
160
160
  /**
161
- * Parameters passed to hooks after an entity is deleted
161
+ * Parameters passed to hooks after a entity is deleted
162
162
  * @group Models
163
163
  */
164
- export interface EntityAfterDeleteProps<M extends Record<string, unknown> = Record<string, unknown>, USER extends User = User> {
164
+ export interface AfterDeleteProps<M extends Record<string, unknown> = Record<string, unknown>, USER extends User = User> {
165
165
  /**
166
166
  * collection of the entity being deleted
167
167
  */
168
- collection: EntityCollection<M>;
168
+ collection: CollectionConfig<M>;
169
169
  /**
170
170
  * Path of the parent collection
171
171
  */
@@ -173,11 +173,11 @@ export interface EntityAfterDeleteProps<M extends Record<string, unknown> = Reco
173
173
  /**
174
174
  * Deleted entity id
175
175
  */
176
- entityId: string | number;
176
+ id: string | number;
177
177
  /**
178
- * Deleted entity
178
+ * Deleted row (flat — `{ id, ...columns }`)
179
179
  */
180
- entity: Entity<M>;
180
+ row: Record<string, unknown>;
181
181
  /**
182
182
  * Context of the app status
183
183
  */
@@ -1,6 +1,6 @@
1
1
  import React from "react";
2
2
  import type { Entity, EntityValues } from "./entities";
3
- import type { EntityCollection } from "./collections";
3
+ import type { CollectionConfig } from "./collections";
4
4
  import type { FormexController } from "./formex";
5
5
  import type { ComponentRef } from "./component_ref";
6
6
  /**
@@ -31,7 +31,7 @@ export interface FormContext<M extends Record<string, unknown> = Record<string,
31
31
  /**
32
32
  * Collection of the entity being modified
33
33
  */
34
- collection?: EntityCollection<M>;
34
+ collection?: CollectionConfig<M>;
35
35
  /**
36
36
  * Entity id, it can be undefined if it's a new entity
37
37
  */
@@ -86,7 +86,7 @@ export type FormViewConfig<M extends Record<string, unknown> = Record<string, un
86
86
  includeActions?: boolean;
87
87
  };
88
88
  export interface EntityCustomViewParams<M extends Record<string, unknown> = Record<string, unknown>> {
89
- collection: EntityCollection<M>;
89
+ collection: CollectionConfig<M>;
90
90
  entity?: Entity<M>;
91
91
  modifiedValues?: EntityValues<M>;
92
92
  formContext: FormContext<M>;
@@ -8,30 +8,55 @@
8
8
  * HTTP wire boundary, handled by `serializeFilter` / `deserializeFilter`
9
9
  * in `@rebasepro/common`.
10
10
  *
11
- * ┌──────────────────┬───────────────┬──────────────────────────┐
12
- * │ Canonical │ REST short │ Meaning
13
- * ├──────────────────┼───────────────┼──────────────────────────┤
14
- * │ "==" │ "eq" │ Equal
15
- * │ "!=" │ "neq" │ Not equal
16
- * │ ">" │ "gt" │ Greater than
17
- * │ ">=" │ "gte" │ Greater than or equal
18
- * │ "<" │ "lt" │ Less than
19
- * │ "<=" │ "lte" │ Less than or equal
20
- * │ "in" │ "in" │ Value in list
21
- * │ "not-in" │ "nin" │ Value not in list
22
- * │ "array-contains" │ "cs" │ Array contains element
23
- * │ "array-contains-any" │ "csa" │ Array contains any of
24
- * └──────────────────┴───────────────┴──────────────────────────┘
11
+ * ┌──────────────────────┬───────────────┬──────────────────────────────┐
12
+ * │ Canonical │ REST short │ Meaning
13
+ * ├──────────────────────┼───────────────┼──────────────────────────────┤
14
+ * │ "==" │ "eq" │ Equal
15
+ * │ "!=" │ "neq" │ Not equal
16
+ * │ ">" │ "gt" │ Greater than
17
+ * │ ">=" │ "gte" │ Greater than or equal
18
+ * │ "<" │ "lt" │ Less than
19
+ * │ "<=" │ "lte" │ Less than or equal
20
+ * │ "in" │ "in" │ Value in list
21
+ * │ "not-in" │ "nin" │ Value not in list
22
+ * │ "array-contains" │ "cs" │ Array contains element
23
+ * │ "array-contains-any" │ "csa" │ Array contains any of
24
+ * │ "like" │ "like" │ SQL LIKE (case-sensitive) │
25
+ * │ "ilike" │ "ilike" │ SQL ILIKE (case-insensitive) │
26
+ * │ "not-like" │ "nlike" │ NOT LIKE (case-sensitive) │
27
+ * │ "not-ilike" │ "nilike" │ NOT ILIKE (case-insensitive) │
28
+ * │ "is-null" │ "isnull" │ Field IS NULL │
29
+ * │ "is-not-null" │ "notnull" │ Field IS NOT NULL │
30
+ * └──────────────────────┴───────────────┴──────────────────────────────┘
31
+ *
32
+ * Pattern matching (`like`/`ilike`) uses SQL wildcard syntax: `%` matches any
33
+ * sequence of characters, `_` matches a single character. On MongoDB these are
34
+ * translated to anchored regular expressions; Firestore has no native pattern
35
+ * matching and rejects these operators (use `searchString` instead).
25
36
  *
26
37
  * @module
27
38
  */
39
+ /**
40
+ * Canonical sort representation: `[fieldName, direction]`.
41
+ *
42
+ * Used in `FindParams.orderBy`, `collection.sort`, and `FilterPreset.sort`.
43
+ * The colon-string form (`"field:direction"`) exists only at the HTTP wire
44
+ * boundary, handled by `serializeOrderBy` / `deserializeOrderBy` in
45
+ * `@rebasepro/common`.
46
+ *
47
+ * Design note: the natural extension for multi-column sort is
48
+ * `OrderByTuple[]` — not implemented yet (server consumes only the first).
49
+ *
50
+ * @group Models
51
+ */
52
+ export type OrderByTuple<Key extends string = string> = [Key, "asc" | "desc"];
28
53
  /**
29
54
  * Canonical filter operators supported across all database backends.
30
55
  * Each DB driver translates these to its native query format.
31
56
  *
32
57
  * @group Models
33
58
  */
34
- export type WhereFilterOp = "<" | "<=" | "==" | "!=" | ">=" | ">" | "array-contains" | "in" | "not-in" | "array-contains-any";
59
+ export type WhereFilterOp = "<" | "<=" | "==" | "!=" | ">=" | ">" | "array-contains" | "in" | "not-in" | "array-contains-any" | "like" | "ilike" | "not-like" | "not-ilike" | "is-null" | "is-not-null";
35
60
  /**
36
61
  * Used to define filters applied in collections.
37
62
  *
@@ -49,6 +74,14 @@ export type WhereFilterOp = "<" | "<=" | "==" | "!=" | ">=" | ">" | "array-conta
49
74
  * { role: ["in", ["admin", "editor"]] }
50
75
  * { tags: ["array-contains", "featured"] }
51
76
  *
77
+ * // Pattern matching (SQL wildcards: % and _)
78
+ * { name: ["ilike", "%john%"] }
79
+ * { slug: ["like", "post-%"] }
80
+ *
81
+ * // Null checks (the value is ignored; `null` is conventional)
82
+ * { deleted_at: ["is-null", null] }
83
+ * { published_at: ["is-not-null", null] }
84
+ *
52
85
  * @group Models
53
86
  */
54
87
  export type FilterValues<Key extends string> = Partial<Record<Key, [WhereFilterOp, unknown] | [WhereFilterOp, unknown][]>>;
@@ -83,18 +116,30 @@ export interface FilterPreset<Key extends string = string> {
83
116
  /**
84
117
  * Optional sort override to apply alongside the filter values.
85
118
  */
86
- sort?: [Key, "asc" | "desc"];
119
+ sort?: OrderByTuple<Key>;
87
120
  }
88
121
  /**
89
122
  * PostgREST short-code operators. Wire format only — these never appear
90
123
  * in application code. Used by `serializeFilter`/`deserializeFilter`
91
124
  * in `@rebasepro/common`.
92
125
  */
93
- export type RestFilterOp = "eq" | "neq" | "gt" | "gte" | "lt" | "lte" | "in" | "nin" | "cs" | "csa";
126
+ export type RestFilterOp = "eq" | "neq" | "gt" | "gte" | "lt" | "lte" | "in" | "nin" | "cs" | "csa" | "like" | "ilike" | "nlike" | "nilike" | "isnull" | "notnull";
94
127
  /** Maps canonical operators to their REST short-code equivalents. */
95
128
  export declare const CANONICAL_TO_REST: Readonly<Record<WhereFilterOp, RestFilterOp>>;
96
129
  /** Maps REST short-code operators to their canonical equivalents. */
97
130
  export declare const REST_TO_CANONICAL: Readonly<Record<RestFilterOp, WhereFilterOp>>;
131
+ /**
132
+ * Operators that test for null/not-null and therefore ignore their value.
133
+ * Codecs normalize the value of these conditions to `null`.
134
+ */
135
+ export declare const NULL_OPS: ReadonlySet<WhereFilterOp>;
136
+ /**
137
+ * Every canonical operator, in a stable order. Useful for engine capability
138
+ * declarations ({@link DataSourceCapabilities.filterOperators}) and for
139
+ * building operator subsets.
140
+ * @group Models
141
+ */
142
+ export declare const ALL_WHERE_FILTER_OPS: readonly WhereFilterOp[];
98
143
  /**
99
144
  * Resolve any operator string (canonical or REST short-code) to its
100
145
  * canonical `WhereFilterOp` form. Returns `undefined` for unknown operators.
@@ -1,5 +1,5 @@
1
- import { EntityCollection } from "./collections";
1
+ import { CollectionConfig } from "./collections";
2
2
  export type ModifyCollectionProps = {
3
- collection: EntityCollection;
3
+ collection: CollectionConfig;
4
4
  parentPaths: string[];
5
5
  };