@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
@@ -27,6 +27,7 @@ export type PolicyExpression =
27
27
  | RolesOverlapPolicyExpression
28
28
  | RolesContainPolicyExpression
29
29
  | AuthenticatedPolicyExpression
30
+ | ExistsInPolicyExpression
30
31
  | RawPolicyExpression;
31
32
 
32
33
  /** Always allows. Compiles to `true`. @group Models */
@@ -42,13 +43,13 @@ export interface FalsePolicyExpression {
42
43
  /** Logical AND — every operand must pass. @group Models */
43
44
  export interface AndPolicyExpression {
44
45
  kind: "and";
45
- operands: PolicyExpression[];
46
+ operands: readonly PolicyExpression[];
46
47
  }
47
48
 
48
49
  /** Logical OR — at least one operand must pass. @group Models */
49
50
  export interface OrPolicyExpression {
50
51
  kind: "or";
51
- operands: PolicyExpression[];
52
+ operands: readonly PolicyExpression[];
52
53
  }
53
54
 
54
55
  /** Logical negation. @group Models */
@@ -78,7 +79,7 @@ export interface ComparePolicyExpression {
78
79
  */
79
80
  export interface RolesOverlapPolicyExpression {
80
81
  kind: "rolesOverlap";
81
- roles: string[];
82
+ roles: readonly string[];
82
83
  }
83
84
 
84
85
  /**
@@ -88,7 +89,7 @@ export interface RolesOverlapPolicyExpression {
88
89
  */
89
90
  export interface RolesContainPolicyExpression {
90
91
  kind: "rolesContain";
91
- roles: string[];
92
+ roles: readonly string[];
92
93
  }
93
94
 
94
95
  /**
@@ -99,6 +100,45 @@ export interface AuthenticatedPolicyExpression {
99
100
  kind: "authenticated";
100
101
  }
101
102
 
103
+ /**
104
+ * Membership / relational access: true when at least one row exists in another
105
+ * collection (a join/membership table) matching `where`. This is what lets you
106
+ * scope reads to "rows whose team the caller belongs to" without an N+1
107
+ * per-row lookup — it compiles to a single correlated `EXISTS` subquery.
108
+ *
109
+ * Inside `where`, {@link FieldPolicyOperand} (`policy.field`) references a column
110
+ * of the joined collection, while {@link OuterFieldPolicyOperand}
111
+ * (`policy.outerField`) references a column of the row being checked (the outer
112
+ * table under RLS). Combine with {@link AuthUidPolicyOperand} to correlate to
113
+ * the caller.
114
+ *
115
+ * @example
116
+ * ```ts
117
+ * // documents visible only to members of the document's team:
118
+ * policy.existsIn({
119
+ * collection: "team_members",
120
+ * where: policy.and(
121
+ * policy.compare(policy.field("team_id"), "eq", policy.outerField("team_id")),
122
+ * policy.compare(policy.field("user_id"), "eq", policy.authUid()),
123
+ * ),
124
+ * })
125
+ * // → EXISTS (SELECT 1 FROM team_members _ex0
126
+ * // WHERE _ex0.team_id = documents.team_id AND _ex0.user_id = auth.uid())
127
+ * ```
128
+ *
129
+ * Postgres-authoritative: like {@link RawPolicyExpression}, the JavaScript
130
+ * evaluator treats it as *unknown* (it cannot run a subquery client-side), so
131
+ * enforcement is always the database's.
132
+ * @group Models
133
+ */
134
+ export interface ExistsInPolicyExpression {
135
+ kind: "existsIn";
136
+ /** Slug of the collection to search (the join / membership table). */
137
+ collection: string;
138
+ /** Condition evaluated against the joined collection's rows. */
139
+ where: PolicyExpression;
140
+ }
141
+
102
142
  /**
103
143
  * A raw PostgreSQL boolean expression — the full-power escape hatch.
104
144
  *
@@ -118,6 +158,7 @@ export interface RawPolicyExpression {
118
158
  */
119
159
  export type PolicyOperand =
120
160
  | FieldPolicyOperand
161
+ | OuterFieldPolicyOperand
121
162
  | LiteralPolicyOperand
122
163
  | AuthUidPolicyOperand
123
164
  | AuthRolesPolicyOperand;
@@ -129,6 +170,18 @@ export interface FieldPolicyOperand {
129
170
  name: string;
130
171
  }
131
172
 
173
+ /**
174
+ * A column value on the *outer* row when used inside {@link ExistsInPolicyExpression}
175
+ * — i.e. the row the RLS policy is being evaluated for, referenced from within the
176
+ * subquery. Outside an `existsIn` it is equivalent to {@link FieldPolicyOperand}.
177
+ * @group Models
178
+ */
179
+ export interface OuterFieldPolicyOperand {
180
+ kind: "outerField";
181
+ /** The property/column name on the outer collection. */
182
+ name: string;
183
+ }
184
+
132
185
  /** A constant value. @group Models */
133
186
  export interface LiteralPolicyOperand {
134
187
  kind: "literal";
@@ -157,16 +210,19 @@ export interface AuthRolesPolicyOperand {
157
210
  export const policy = {
158
211
  true: (): TruePolicyExpression => ({ kind: "true" }),
159
212
  false: (): FalsePolicyExpression => ({ kind: "false" }),
160
- and: (...operands: PolicyExpression[]): AndPolicyExpression => ({ kind: "and", operands }),
161
- or: (...operands: PolicyExpression[]): OrPolicyExpression => ({ kind: "or", operands }),
213
+ and: (...operands: readonly PolicyExpression[]): AndPolicyExpression => ({ kind: "and", operands: operands as PolicyExpression[] }),
214
+ or: (...operands: readonly PolicyExpression[]): OrPolicyExpression => ({ kind: "or", operands: operands as PolicyExpression[] }),
162
215
  not: (operand: PolicyExpression): NotPolicyExpression => ({ kind: "not", operand }),
163
216
  compare: (left: PolicyOperand, op: PolicyCompareOperator, right: PolicyOperand): ComparePolicyExpression =>
164
217
  ({ kind: "compare", op, left, right }),
165
- rolesOverlap: (roles: string[]): RolesOverlapPolicyExpression => ({ kind: "rolesOverlap", roles }),
166
- rolesContain: (roles: string[]): RolesContainPolicyExpression => ({ kind: "rolesContain", roles }),
218
+ rolesOverlap: (roles: readonly string[]): RolesOverlapPolicyExpression => ({ kind: "rolesOverlap", roles: roles as string[] }),
219
+ rolesContain: (roles: readonly string[]): RolesContainPolicyExpression => ({ kind: "rolesContain", roles: roles as string[] }),
167
220
  authenticated: (): AuthenticatedPolicyExpression => ({ kind: "authenticated" }),
221
+ existsIn: (args: { collection: string; where: PolicyExpression }): ExistsInPolicyExpression =>
222
+ ({ kind: "existsIn", collection: args.collection, where: args.where }),
168
223
  raw: (sql: string): RawPolicyExpression => ({ kind: "raw", sql }),
169
224
  field: (name: string): FieldPolicyOperand => ({ kind: "field", name }),
225
+ outerField: (name: string): OuterFieldPolicyOperand => ({ kind: "outerField", name }),
170
226
  literal: (value: string | number | boolean | null): LiteralPolicyOperand => ({ kind: "literal", value }),
171
227
  authUid: (): AuthUidPolicyOperand => ({ kind: "authUid" }),
172
228
  authRoles: (): AuthRolesPolicyOperand => ({ kind: "authRoles" })
@@ -2,10 +2,10 @@ import type { ComponentRef } from "./component_ref";
2
2
 
3
3
  import type { Entity, EntityReference, EntityRelation, EntityValues, GeoPoint, Vector } from "./entities";
4
4
  import type { JoinStep, OnAction, Relation } from "./relations";
5
- import type { EntityCollection, FilterValues } from "./collections";
5
+ import type { CollectionConfig, FilterValues, WhereFilterOp } from "./collections";
6
6
  import type { ColorKey, ColorScheme } from "./chips";
7
7
  import type { AuthController } from "../controllers/auth";
8
- import type { EntityAfterReadProps, EntityBeforeSaveProps } from "./entity_callbacks";
8
+ import type { AfterReadProps, BeforeSaveProps } from "./entity_callbacks";
9
9
  import type { User } from "../users";
10
10
 
11
11
  /**
@@ -16,7 +16,7 @@ export type PropertyCallbacks<T = unknown, M extends Record<string, unknown> = R
16
16
  /**
17
17
  * Callback used after fetching data, to transform the value before rendering
18
18
  */
19
- afterRead?(props: Omit<EntityAfterReadProps<M, USER>, "entity"> & {
19
+ afterRead?(props: Omit<AfterReadProps<M, USER>, "entity"> & {
20
20
  value: T;
21
21
  entity: Entity<M> | undefined;
22
22
  }): Promise<T> | T;
@@ -25,7 +25,7 @@ export type PropertyCallbacks<T = unknown, M extends Record<string, unknown> = R
25
25
  * Callback used before saving, after validation.
26
26
  * You can modify the value before it's saved.
27
27
  */
28
- beforeSave?(props: Omit<EntityBeforeSaveProps<M, USER>, "values"> & {
28
+ beforeSave?(props: Omit<BeforeSaveProps<M, USER>, "values"> & {
29
29
  value: T;
30
30
  previousValue: T | undefined;
31
31
  values: Partial<M>;
@@ -164,6 +164,33 @@ export interface BaseUIConfig<CustomProps = unknown> {
164
164
  customProps?: CustomProps;
165
165
  Field?: ComponentRef<any>;
166
166
  Preview?: ComponentRef<any>;
167
+
168
+ /**
169
+ * Narrow the filter operators offered for this property in collection
170
+ * filter UIs (table header filters and the Filters dialog).
171
+ *
172
+ * The final offered set is the **intersection** of the engine's
173
+ * capabilities, the property-type defaults, and this list — you can only
174
+ * *restrict*, never enable an operator the underlying engine cannot run.
175
+ *
176
+ * Pass an empty array to disable filtering on this property entirely.
177
+ *
178
+ * @example
179
+ * // Email column: exact match, contains, and null check only
180
+ * ui: { filterOperators: ["==", "ilike", "is-null"] }
181
+ */
182
+ filterOperators?: readonly WhereFilterOp[];
183
+
184
+ /**
185
+ * Replace the filter field rendered for this property in collection
186
+ * filter UIs. The component receives `FilterFieldBindingProps`
187
+ * (property, resolved `operators`, `value`, `setValue`, …).
188
+ *
189
+ * Takes precedence over the collection-level
190
+ * `components["Collection.FilterField"]` override and the built-in
191
+ * per-type filter fields.
192
+ */
193
+ Filter?: ComponentRef<any>;
167
194
  }
168
195
 
169
196
  export interface BaseProperty<CustomProps = unknown> {
@@ -492,7 +519,7 @@ export interface ReferenceUIConfig extends BaseUIConfig {
492
519
  }
493
520
 
494
521
  /**
495
- * A pointer to an entity, stored **as a value** on the row (id + path, and
522
+ * A pointer to a entity, stored **as a value** on the row (id + path, and
496
523
  * optionally a `driver`/`databaseId` for cross-datasource pointers).
497
524
  *
498
525
  * This is the native primitive of **document databases** — it maps 1:1 to a
@@ -511,7 +538,7 @@ export interface ReferenceProperty extends BaseProperty {
511
538
  ui?: ReferenceUIConfig;
512
539
  type: "reference";
513
540
  /**
514
- * Default value for new entities. Must be an EntityReference.
541
+ * Default value for new entities. Must be a EntityReference.
515
542
  */
516
543
  defaultValue?: EntityReference;
517
544
  /**
@@ -575,7 +602,7 @@ export interface RelationProperty extends BaseProperty {
575
602
  ui?: RelationUIConfig;
576
603
  type: "relation";
577
604
  /**
578
- * Default value for new entities. Must be an EntityRelation or array of EntityRelation.
605
+ * Default value for new entities. Must be a EntityRelation or array of EntityRelation.
579
606
  */
580
607
  defaultValue?: EntityRelation | EntityRelation[];
581
608
  /**
@@ -596,7 +623,7 @@ export interface RelationProperty extends BaseProperty {
596
623
  * When set, the framework treats this property as a self-contained relation
597
624
  * definition and no separate `relations[]` entry is needed.
598
625
  */
599
- target?: string | (() => EntityCollection | string);
626
+ target?: string | (() => CollectionConfig | string);
600
627
 
601
628
  /**
602
629
  * Whether this property references one or many records.
@@ -664,7 +691,7 @@ export interface RelationProperty extends BaseProperty {
664
691
  /**
665
692
  * Overrides applied to the target collection when rendered as a subcollection tab.
666
693
  */
667
- overrides?: Partial<EntityCollection>;
694
+ overrides?: Partial<CollectionConfig>;
668
695
 
669
696
  // ─── Framework-managed fields ───
670
697
 
@@ -1006,6 +1033,14 @@ export type StorageConfig = {
1006
1033
  */
1007
1034
  storageSource?: string;
1008
1035
 
1036
+ /**
1037
+ * Store files for this property as **public**: they are placed under the
1038
+ * public prefix and served via stable, token-less, permanent, CDN-cacheable
1039
+ * URLs (safe to persist and hotlink). Use for public assets like avatars or
1040
+ * storefront images. Defaults to `false` (private, short-lived signed URLs).
1041
+ */
1042
+ public?: boolean;
1043
+
1009
1044
  /**
1010
1045
  * File MIME types that can be uploaded to this reference. Don't specify for
1011
1046
  * all.
@@ -1,4 +1,4 @@
1
- import type { EntityCollection } from "./collections";
1
+ import type { CollectionConfig } from "./collections";
2
2
 
3
3
  /**
4
4
  * @group Models
@@ -20,7 +20,7 @@ export interface Relation {
20
20
  /**
21
21
  * The final collection you want to retrieve records from.
22
22
  */
23
- target: (() => EntityCollection) | any;
23
+ target: (() => CollectionConfig) | any;
24
24
 
25
25
  /**
26
26
  * The nature of the relationship, determining if one or many records are returned.
@@ -282,7 +282,7 @@ export interface Relation {
282
282
  */
283
283
  onDelete?: OnAction;
284
284
 
285
- overrides?: Partial<EntityCollection>;
285
+ overrides?: Partial<CollectionConfig>;
286
286
 
287
287
  validation?: {
288
288
  required?: boolean;
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import type { CollectionActionsProps, EntityTableController, SelectionController, EntityCollection } from "./collections";
2
+ import type { CollectionActionsProps, EntityTableController, SelectionController, CollectionConfig } from "./collections";
3
3
  import type { Entity } from "./entities";
4
4
  import type { PluginFormActionProps, PluginGenericProps, PluginHomePageActionsProps, PluginHomePageAdditionalCardsProps } from "./plugins";
5
5
  import type { Property } from "./properties";
@@ -128,7 +128,7 @@ export interface NavigationSlotProps {
128
128
  */
129
129
  export interface CollectionToolbarProps {
130
130
  path: string;
131
- collection: EntityCollection;
131
+ collection: CollectionConfig;
132
132
  parentCollectionSlugs: string[];
133
133
  parentEntityIds: string[];
134
134
  tableController: EntityTableController;
@@ -141,7 +141,7 @@ export interface CollectionToolbarProps {
141
141
  */
142
142
  export interface CollectionEmptyStateProps {
143
143
  path: string;
144
- collection: EntityCollection;
144
+ collection: CollectionConfig;
145
145
  parentCollectionSlugs: string[];
146
146
  parentEntityIds: string[];
147
147
  canCreate: boolean;
@@ -159,7 +159,7 @@ export interface CollectionHeaderActionProps {
159
159
  parentCollectionSlugs: string[];
160
160
  parentEntityIds: string[];
161
161
  onHover: boolean;
162
- collection: EntityCollection;
162
+ collection: CollectionConfig;
163
163
  tableController: EntityTableController;
164
164
  }
165
165
 
@@ -171,7 +171,7 @@ export interface CollectionAddColumnProps {
171
171
  path: string;
172
172
  parentCollectionSlugs: string[];
173
173
  parentEntityIds: string[];
174
- collection: EntityCollection;
174
+ collection: CollectionConfig;
175
175
  tableController: EntityTableController;
176
176
  }
177
177
 
@@ -181,7 +181,7 @@ export interface CollectionAddColumnProps {
181
181
  */
182
182
  export interface CollectionErrorProps {
183
183
  path: string;
184
- collection: EntityCollection;
184
+ collection: CollectionConfig;
185
185
  parentCollectionSlugs?: string[];
186
186
  parentEntityIds?: string[];
187
187
  error: Error;
@@ -192,7 +192,7 @@ export interface CollectionErrorProps {
192
192
  * @group Plugins
193
193
  */
194
194
  export interface KanbanSetupProps {
195
- collection: EntityCollection;
195
+ collection: CollectionConfig;
196
196
  fullPath: string;
197
197
  parentCollectionSlugs: string[];
198
198
  parentEntityIds: string[];
@@ -203,7 +203,7 @@ export interface KanbanSetupProps {
203
203
  * @group Plugins
204
204
  */
205
205
  export interface KanbanAddColumnProps {
206
- collection: EntityCollection;
206
+ collection: CollectionConfig;
207
207
  fullPath: string;
208
208
  parentCollectionSlugs: string[];
209
209
  parentEntityIds: string[];
@@ -214,14 +214,14 @@ export interface KanbanAddColumnProps {
214
214
 
215
215
  /**
216
216
  * Props for `entity.row.actions` slot.
217
- * Rendered for each row in an entity collection table.
217
+ * Rendered for each row in a entity collection table.
218
218
  * @group Plugins
219
219
  */
220
220
  export interface EntityRowActionsProps {
221
221
  entity: Entity;
222
222
  entityId: string;
223
223
  path: string;
224
- collection: EntityCollection;
224
+ collection: CollectionConfig;
225
225
  parentCollectionSlugs: string[];
226
226
  parentEntityIds: string[];
227
227
  selectionController: SelectionController;
@@ -238,7 +238,7 @@ export interface EntityFieldSlotProps {
238
238
  property: Property;
239
239
  path: string;
240
240
  entityId?: string | number;
241
- collection: EntityCollection;
241
+ collection: CollectionConfig;
242
242
  context: RebaseContext;
243
243
  }
244
244
 
@@ -249,7 +249,7 @@ export interface EntityFieldSlotProps {
249
249
  */
250
250
  export interface CollectionFilterPanelProps {
251
251
  path: string;
252
- collection: EntityCollection;
252
+ collection: CollectionConfig;
253
253
  parentCollectionSlugs: string[];
254
254
  parentEntityIds: string[];
255
255
  tableController: EntityTableController;
@@ -290,7 +290,7 @@ export interface ShellToolbarProps {
290
290
  */
291
291
  export interface CollectionInsightsSlotProps {
292
292
  path: string;
293
- collection: EntityCollection;
293
+ collection: CollectionConfig;
294
294
  parentCollectionSlugs: string[];
295
295
  parentEntityIds: string[];
296
296
  }
@@ -302,6 +302,6 @@ export interface CollectionInsightsSlotProps {
302
302
  */
303
303
  export interface HomeCardInsightSlotProps {
304
304
  slug: string;
305
- collection: EntityCollection;
305
+ collection: CollectionConfig;
306
306
  context: RebaseContext;
307
307
  }
@@ -1,5 +1,3 @@
1
- import { Entity } from "./entities";
2
-
3
1
  export interface WebSocketErrorPayload {
4
2
  error?: string | { message: string; code?: string };
5
3
  message?: string;
@@ -11,35 +9,35 @@ export interface WebSocketMessage {
11
9
  payload?: unknown;
12
10
  subscriptionId?: string;
13
11
  requestId?: string;
14
- entities?: Entity<Record<string, unknown>>[];
15
- entity?: Entity<Record<string, unknown>> | null;
12
+ rows?: Record<string, unknown>[];
13
+ row?: Record<string, unknown> | null;
16
14
  error?: string;
17
15
  }
18
16
 
19
17
  export interface CollectionUpdateMessage extends WebSocketMessage {
20
18
  type: "collection_update";
21
19
  subscriptionId: string;
22
- entities: Entity<Record<string, unknown>>[];
20
+ rows: Record<string, unknown>[];
23
21
  }
24
22
 
25
- export interface EntityUpdateMessage extends WebSocketMessage {
26
- type: "entity_update";
23
+ export interface SingleUpdateMessage extends WebSocketMessage {
24
+ type: "single_update";
27
25
  subscriptionId: string;
28
- entity: Entity<Record<string, unknown>> | null;
26
+ row: Record<string, unknown> | null;
29
27
  }
30
28
 
31
29
  /**
32
30
  * Lightweight patch message sent to collection subscribers when a single
33
- * entity is created, updated, or deleted. The client can merge this into
31
+ * row is created, updated, or deleted. The client can merge this into
34
32
  * its cached collection data for near-instant cross-tab updates without
35
33
  * waiting for a full collection refetch.
36
34
  */
37
- export interface CollectionEntityPatchMessage extends WebSocketMessage {
38
- type: "collection_entity_patch";
35
+ export interface CollectionPatchMessage extends WebSocketMessage {
36
+ type: "collection_patch";
39
37
  subscriptionId: string;
40
- entityId: string;
41
- /** The updated entity, or null if deleted */
42
- entity: Entity<Record<string, unknown>> | null;
38
+ id: string;
39
+ /** The updated row, or null if deleted */
40
+ row: Record<string, unknown> | null;
43
41
  }
44
42
 
45
43
  /**
package/src/users/user.ts CHANGED
@@ -1,11 +1,18 @@
1
1
 
2
2
  /**
3
- * This interface represents a user.
4
- * It has some of the same fields as a Firebase User.
5
- * Note that in the default implementation, we simply take the Firebase user
6
- * and use it as a Rebase user, so that means that even if they are not mapped
7
- * in this interface, it contains all the methods of the former, such as `delete`,
8
- * `getIdToken`, etc.
3
+ * The canonical representation of an authenticated user in the Rebase ecosystem.
4
+ *
5
+ * Used by {@link AuthController}, collections, callbacks, and both the
6
+ * `@rebasepro/client` and `@rebasepro/auth` packages. All other user types
7
+ * (`RebaseUser`, `UserInfo`) are deprecated aliases of this type.
8
+ *
9
+ * **Backend-managed fields** (`uid`, `email`, `roles`, `metadata`, `createdAt`)
10
+ * are populated by the server. **Client-visible fields** (`displayName`,
11
+ * `photoURL`, `providerId`, `isAnonymous`, `emailVerified`) may be set during
12
+ * authentication or profile updates.
13
+ *
14
+ * @see AdminUser — the admin-API DTO, which adds audit fields (`createdAt`,
15
+ * `updatedAt`) and required `roles`.
9
16
  *
10
17
  * @group Models
11
18
  */
@@ -27,16 +34,22 @@ export type User = {
27
34
  */
28
35
  readonly photoURL: string | null;
29
36
  /**
30
- * The provider used to authenticate the user.
37
+ * The provider used to authenticate the user (e.g. `"password"`,
38
+ * `"google"`, `"github"`).
31
39
  */
32
40
  readonly providerId: string;
33
41
  /**
34
- *
42
+ * Whether the user is anonymous (created via anonymous sign-in).
35
43
  */
36
44
  readonly isAnonymous: boolean;
37
45
 
38
46
  /**
39
- * Role IDs assigned to this user (e.g. ["admin", "editor"]).
47
+ * Whether the user's email address has been verified.
48
+ */
49
+ readonly emailVerified?: boolean;
50
+
51
+ /**
52
+ * Role IDs assigned to this user (e.g. `["admin", "editor"]`).
40
53
  */
41
54
  roles?: string[];
42
55