@rebasepro/common 0.7.0 → 0.8.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 (42) hide show
  1. package/dist/collections/CollectionRegistry.d.ts +17 -2
  2. package/dist/collections/default-collections.d.ts +255 -2
  3. package/dist/data/filter-dialect.d.ts +61 -0
  4. package/dist/data/query_builder.d.ts +4 -4
  5. package/dist/data/resolveDataSource.d.ts +7 -7
  6. package/dist/index.d.ts +1 -0
  7. package/dist/index.es.js +604 -188
  8. package/dist/index.es.js.map +1 -1
  9. package/dist/index.umd.js +611 -186
  10. package/dist/index.umd.js.map +1 -1
  11. package/dist/util/builders.d.ts +48 -1
  12. package/dist/util/callbacks.d.ts +6 -1
  13. package/dist/util/index.d.ts +1 -0
  14. package/dist/util/permissions.d.ts +26 -2
  15. package/dist/util/policy/evaluatePolicy.d.ts +31 -0
  16. package/dist/util/policy/index.d.ts +3 -0
  17. package/dist/util/policy/policyToPostgres.d.ts +10 -0
  18. package/dist/util/policy/securityRuleToConditions.d.ts +24 -0
  19. package/dist/util/policy/sqlToPolicy.d.ts +20 -0
  20. package/dist/util/storage.d.ts +26 -1
  21. package/package.json +13 -13
  22. package/src/collections/CollectionRegistry.ts +59 -28
  23. package/src/collections/default-collections.ts +4 -4
  24. package/src/data/buildRebaseData.ts +9 -120
  25. package/src/data/filter-dialect.ts +318 -0
  26. package/src/data/query_builder.ts +10 -10
  27. package/src/data/resolveDataSource.ts +9 -9
  28. package/src/index.ts +1 -0
  29. package/src/util/builders.ts +78 -1
  30. package/src/util/callbacks.ts +8 -1
  31. package/src/util/index.ts +1 -0
  32. package/src/util/permissions.test.ts +5 -3
  33. package/src/util/permissions.ts +85 -158
  34. package/src/util/policy/evaluatePolicy.ts +146 -0
  35. package/src/util/policy/index.ts +3 -0
  36. package/src/util/policy/policyToPostgres.ts +85 -0
  37. package/src/util/policy/securityRuleToConditions.ts +67 -0
  38. package/src/util/policy/sqlToPolicy.ts +88 -0
  39. package/src/util/references.ts +1 -1
  40. package/src/util/relations.ts +8 -9
  41. package/src/util/resolutions.ts +6 -6
  42. package/src/util/storage.ts +34 -1
@@ -1,12 +1,27 @@
1
- import { EntityCollection } from "@rebasepro/types";
1
+ import { EntityCallbacks, EntityCollection } from "@rebasepro/types";
2
2
  import { DataSourceRegistry } from "../data/resolveDataSource";
3
3
  export declare class CollectionRegistry {
4
4
  /**
5
5
  * Declared data sources, used during normalization to resolve each
6
6
  * collection's engine (so `dataSource`-only collections get the right
7
- * capabilities). Empty by default → behaviour keys off `driver` as before.
7
+ * capabilities). Empty by default.
8
8
  */
9
9
  private dataSources;
10
+ /**
11
+ * Global lifecycle callbacks applied to every collection.
12
+ * Runs on all data paths (REST, WebSocket, `rebase.data`).
13
+ * Execution order: global → collection → property callbacks.
14
+ */
15
+ private _globalCallbacks?;
16
+ /**
17
+ * Set global lifecycle callbacks that apply to every collection.
18
+ * Typically called once during backend initialization.
19
+ */
20
+ setGlobalCallbacks(callbacks: EntityCallbacks): void;
21
+ /**
22
+ * Get the currently registered global callbacks, if any.
23
+ */
24
+ getGlobalCallbacks(): EntityCallbacks | undefined;
10
25
  private collectionsByTableName;
11
26
  private collectionsBySlug;
12
27
  private rootCollections;
@@ -1,4 +1,3 @@
1
- import type { PostgresCollection } from "@rebasepro/types";
2
1
  /**
3
2
  * Default users collection.
4
3
  *
@@ -6,4 +5,258 @@ import type { PostgresCollection } from "@rebasepro/types";
6
5
  * Slug-based dedup (Map keyed by slug, last-write-wins) lets developers
7
6
  * override by defining their own collection with `slug: "users"`.
8
7
  */
9
- export declare const defaultUsersCollection: PostgresCollection;
8
+ export declare const defaultUsersCollection: import("@rebasepro/types").PostgresCollection<import("@rebasepro/types").InferEntityType<{
9
+ readonly id: {
10
+ readonly name: "ID";
11
+ readonly type: "string";
12
+ readonly isId: "uuid";
13
+ readonly ui: {
14
+ readonly readOnly: true;
15
+ };
16
+ };
17
+ readonly email: {
18
+ readonly name: "Email";
19
+ readonly type: "string";
20
+ readonly validation: {
21
+ readonly required: true;
22
+ readonly unique: true;
23
+ };
24
+ };
25
+ readonly displayName: {
26
+ readonly name: "Name";
27
+ readonly type: "string";
28
+ readonly columnName: "display_name";
29
+ readonly validation: {
30
+ readonly required: true;
31
+ };
32
+ };
33
+ readonly photoURL: {
34
+ readonly name: "Photo URL";
35
+ readonly type: "string";
36
+ readonly columnName: "photo_url";
37
+ readonly ui: {
38
+ readonly url: "image";
39
+ };
40
+ };
41
+ readonly roles: {
42
+ readonly name: "Roles";
43
+ readonly type: "array";
44
+ readonly columnType: "text[]";
45
+ readonly of: {
46
+ readonly name: "Role";
47
+ readonly type: "string";
48
+ readonly enum: {
49
+ readonly admin: "Admin";
50
+ readonly editor: "Editor";
51
+ readonly viewer: "Viewer";
52
+ };
53
+ };
54
+ };
55
+ readonly passwordHash: {
56
+ readonly name: "Password Hash";
57
+ readonly type: "string";
58
+ readonly columnName: "password_hash";
59
+ readonly ui: {
60
+ readonly hideFromCollection: true;
61
+ readonly disabled: {
62
+ readonly hidden: true;
63
+ };
64
+ };
65
+ };
66
+ readonly emailVerified: {
67
+ readonly name: "Email Verified";
68
+ readonly type: "boolean";
69
+ readonly columnName: "email_verified";
70
+ readonly defaultValue: false;
71
+ readonly ui: {
72
+ readonly hideFromCollection: true;
73
+ readonly disabled: {
74
+ readonly hidden: true;
75
+ };
76
+ };
77
+ };
78
+ readonly emailVerificationToken: {
79
+ readonly name: "Email Verification Token";
80
+ readonly type: "string";
81
+ readonly columnName: "email_verification_token";
82
+ readonly ui: {
83
+ readonly hideFromCollection: true;
84
+ readonly disabled: {
85
+ readonly hidden: true;
86
+ };
87
+ };
88
+ };
89
+ readonly emailVerificationSentAt: {
90
+ readonly name: "Email Verification Sent At";
91
+ readonly type: "date";
92
+ readonly columnName: "email_verification_sent_at";
93
+ readonly ui: {
94
+ readonly hideFromCollection: true;
95
+ readonly disabled: {
96
+ readonly hidden: true;
97
+ };
98
+ };
99
+ };
100
+ readonly metadata: {
101
+ readonly name: "Metadata";
102
+ readonly type: "map";
103
+ readonly keyValue: true;
104
+ readonly properties: {};
105
+ readonly defaultValue: {};
106
+ readonly ui: {
107
+ readonly hideFromCollection: true;
108
+ readonly disabled: {
109
+ readonly hidden: true;
110
+ };
111
+ };
112
+ };
113
+ readonly createdAt: {
114
+ readonly name: "Created At";
115
+ readonly type: "date";
116
+ readonly columnName: "created_at";
117
+ readonly autoValue: "on_create";
118
+ readonly ui: {
119
+ readonly readOnly: true;
120
+ };
121
+ };
122
+ readonly updatedAt: {
123
+ readonly name: "Updated At";
124
+ readonly type: "date";
125
+ readonly columnName: "updated_at";
126
+ readonly autoValue: "on_update";
127
+ readonly ui: {
128
+ readonly hideFromCollection: true;
129
+ readonly disabled: {
130
+ readonly hidden: true;
131
+ };
132
+ };
133
+ };
134
+ }>, import("@rebasepro/types").User> & {
135
+ properties: {
136
+ readonly id: {
137
+ readonly name: "ID";
138
+ readonly type: "string";
139
+ readonly isId: "uuid";
140
+ readonly ui: {
141
+ readonly readOnly: true;
142
+ };
143
+ };
144
+ readonly email: {
145
+ readonly name: "Email";
146
+ readonly type: "string";
147
+ readonly validation: {
148
+ readonly required: true;
149
+ readonly unique: true;
150
+ };
151
+ };
152
+ readonly displayName: {
153
+ readonly name: "Name";
154
+ readonly type: "string";
155
+ readonly columnName: "display_name";
156
+ readonly validation: {
157
+ readonly required: true;
158
+ };
159
+ };
160
+ readonly photoURL: {
161
+ readonly name: "Photo URL";
162
+ readonly type: "string";
163
+ readonly columnName: "photo_url";
164
+ readonly ui: {
165
+ readonly url: "image";
166
+ };
167
+ };
168
+ readonly roles: {
169
+ readonly name: "Roles";
170
+ readonly type: "array";
171
+ readonly columnType: "text[]";
172
+ readonly of: {
173
+ readonly name: "Role";
174
+ readonly type: "string";
175
+ readonly enum: {
176
+ readonly admin: "Admin";
177
+ readonly editor: "Editor";
178
+ readonly viewer: "Viewer";
179
+ };
180
+ };
181
+ };
182
+ readonly passwordHash: {
183
+ readonly name: "Password Hash";
184
+ readonly type: "string";
185
+ readonly columnName: "password_hash";
186
+ readonly ui: {
187
+ readonly hideFromCollection: true;
188
+ readonly disabled: {
189
+ readonly hidden: true;
190
+ };
191
+ };
192
+ };
193
+ readonly emailVerified: {
194
+ readonly name: "Email Verified";
195
+ readonly type: "boolean";
196
+ readonly columnName: "email_verified";
197
+ readonly defaultValue: false;
198
+ readonly ui: {
199
+ readonly hideFromCollection: true;
200
+ readonly disabled: {
201
+ readonly hidden: true;
202
+ };
203
+ };
204
+ };
205
+ readonly emailVerificationToken: {
206
+ readonly name: "Email Verification Token";
207
+ readonly type: "string";
208
+ readonly columnName: "email_verification_token";
209
+ readonly ui: {
210
+ readonly hideFromCollection: true;
211
+ readonly disabled: {
212
+ readonly hidden: true;
213
+ };
214
+ };
215
+ };
216
+ readonly emailVerificationSentAt: {
217
+ readonly name: "Email Verification Sent At";
218
+ readonly type: "date";
219
+ readonly columnName: "email_verification_sent_at";
220
+ readonly ui: {
221
+ readonly hideFromCollection: true;
222
+ readonly disabled: {
223
+ readonly hidden: true;
224
+ };
225
+ };
226
+ };
227
+ readonly metadata: {
228
+ readonly name: "Metadata";
229
+ readonly type: "map";
230
+ readonly keyValue: true;
231
+ readonly properties: {};
232
+ readonly defaultValue: {};
233
+ readonly ui: {
234
+ readonly hideFromCollection: true;
235
+ readonly disabled: {
236
+ readonly hidden: true;
237
+ };
238
+ };
239
+ };
240
+ readonly createdAt: {
241
+ readonly name: "Created At";
242
+ readonly type: "date";
243
+ readonly columnName: "created_at";
244
+ readonly autoValue: "on_create";
245
+ readonly ui: {
246
+ readonly readOnly: true;
247
+ };
248
+ };
249
+ readonly updatedAt: {
250
+ readonly name: "Updated At";
251
+ readonly type: "date";
252
+ readonly columnName: "updated_at";
253
+ readonly autoValue: "on_update";
254
+ readonly ui: {
255
+ readonly hideFromCollection: true;
256
+ readonly disabled: {
257
+ readonly hidden: true;
258
+ };
259
+ };
260
+ };
261
+ };
262
+ };
@@ -0,0 +1,61 @@
1
+ /**
2
+ * REST wire-format adapter for the unified filter system.
3
+ *
4
+ * This module is the ONLY code in the entire codebase that knows about
5
+ * PostgREST-style dot-syntax strings (`eq.active`, `gt.18`, `in.(a,b)`).
6
+ * Everything else speaks `FilterValues` exclusively.
7
+ *
8
+ * @module
9
+ */
10
+ import { FilterValues, LogicalCondition, FilterCondition } from "@rebasepro/types";
11
+ /**
12
+ * Convert `FilterValues` to a PostgREST-style querystring record.
13
+ *
14
+ * - Single conditions produce a string value.
15
+ * - Multiple conditions on the same field produce a string array (repeated params).
16
+ *
17
+ * @example
18
+ * serializeFilter({ status: ["==", "active"] })
19
+ * // → { status: "eq.active" }
20
+ *
21
+ * serializeFilter({ age: [[">=", 18], ["<", 65]] })
22
+ * // → { age: ["gte.18", "lt.65"] }
23
+ */
24
+ export declare function serializeFilter(filter: FilterValues<string> | Record<string, any>): Record<string, string | string[]>;
25
+ /**
26
+ * Convert a PostgREST-style querystring record to `FilterValues`.
27
+ *
28
+ * - String values are parsed as single conditions.
29
+ * - String arrays (repeated query params) become multiple conditions on the same field.
30
+ *
31
+ * @example
32
+ * deserializeFilter({ status: "eq.active" })
33
+ * // → { status: ["==", "active"] }
34
+ *
35
+ * deserializeFilter({ age: ["gte.18", "lt.65"] })
36
+ * // → { age: [[">=", 18], ["<", 65]] }
37
+ */
38
+ export declare function deserializeFilter(query: Record<string, any>): FilterValues<string>;
39
+ /**
40
+ * Serialize a `LogicalCondition` or `FilterCondition` to its wire-format string.
41
+ *
42
+ * @example
43
+ * serializeLogicalCondition({ column: "status", operator: "==", value: "active" })
44
+ * // → "status.eq.active"
45
+ *
46
+ * serializeLogicalCondition({ type: "or", conditions: [...] })
47
+ * // → "or(status.eq.active,status.eq.pending)"
48
+ */
49
+ export declare function serializeLogicalCondition(cond: LogicalCondition | FilterCondition): string;
50
+ /**
51
+ * Parse a logical condition wire-format string back into a
52
+ * `LogicalCondition` or `FilterCondition`.
53
+ *
54
+ * @example
55
+ * deserializeLogicalCondition("status.eq.active")
56
+ * // → { column: "status", operator: "==", value: "active" }
57
+ *
58
+ * deserializeLogicalCondition("or(status.eq.active,age.gte.18)")
59
+ * // → { type: "or", conditions: [...] }
60
+ */
61
+ export declare function deserializeLogicalCondition(str: string): LogicalCondition | FilterCondition;
@@ -1,7 +1,7 @@
1
- import { FindResponse, CollectionAccessor, QueryBuilderInterface, FilterOperator, LogicalCondition, WhereValue, FilterCondition } from "@rebasepro/types";
1
+ import { FindResponse, CollectionAccessor, QueryBuilderInterface, WhereFilterOp, LogicalCondition, WhereValue, FilterCondition } from "@rebasepro/types";
2
2
  export declare function or(...conditions: (FilterCondition | LogicalCondition)[]): LogicalCondition;
3
3
  export declare function and(...conditions: (FilterCondition | LogicalCondition)[]): LogicalCondition;
4
- export declare function cond(column: string, operator: FilterOperator, value: unknown): FilterCondition;
4
+ export declare function cond(column: string, operator: WhereFilterOp, value: unknown): FilterCondition;
5
5
  export declare class QueryBuilder<M extends Record<string, unknown> = Record<string, unknown>> implements QueryBuilderInterface<M> {
6
6
  private collection;
7
7
  private params;
@@ -11,14 +11,14 @@ export declare class QueryBuilder<M extends Record<string, unknown> = Record<str
11
11
  * @example
12
12
  * client.collection('users').where('age', '>=', 18).find()
13
13
  */
14
- where<K extends keyof M & string>(column: K, operator: FilterOperator, value: WhereValue<M[K]>): this;
14
+ where<K extends keyof M & string>(column: K, operator: WhereFilterOp, value: WhereValue<M[K]>): this;
15
15
  where(logicalCondition: LogicalCondition): this;
16
16
  /**
17
17
  * Order the results by a specific column.
18
18
  * @example
19
19
  * client.collection('users').orderBy('createdAt', 'desc').find()
20
20
  */
21
- orderBy(column: keyof M & string, ascending?: "asc" | "desc"): this;
21
+ orderBy(column: keyof M & string, direction?: "asc" | "desc"): this;
22
22
  /**
23
23
  * Limit the number of results returned.
24
24
  */
@@ -8,8 +8,8 @@ import { DataSourceDefinition, ResolvedDataSource } from "@rebasepro/types";
8
8
  export interface DataSourceResolvable {
9
9
  /** Preferred routing key. */
10
10
  dataSource?: string;
11
- /** Legacy engine hint / fallback routing key. */
12
- driver?: string;
11
+ /** Engine type discriminant (set on variant collection types). */
12
+ engine?: string;
13
13
  /** Within-engine instance. */
14
14
  databaseId?: string;
15
15
  }
@@ -26,13 +26,13 @@ export declare function createDataSourceRegistry(definitions?: DataSourceDefinit
26
26
  * editor's capability lookups.
27
27
  *
28
28
  * Resolution order:
29
- * 1. The routing **key** is `collection.dataSource`, else the legacy
30
- * `collection.driver`, else {@link DEFAULT_DATA_SOURCE_KEY}.
29
+ * 1. The routing **key** is `collection.dataSource`, else
30
+ * {@link DEFAULT_DATA_SOURCE_KEY}.
31
31
  * 2. If a definition is registered for that key, it provides `engine`,
32
32
  * `transport`, and `databaseId`.
33
- * 3. Otherwise values are synthesized for backward compatibility: `engine`
34
- * from the legacy `driver` (or the key, or `"postgres"`), `transport`
35
- * defaults to `"server"`, and `databaseId` from the collection.
33
+ * 3. Otherwise values are synthesized: `engine` from `collection.engine`
34
+ * (or the key, or `"postgres"`), `transport` defaults to `"server"`,
35
+ * and `databaseId` from the collection.
36
36
  *
37
37
  * `capabilities` are always derived from the resolved `engine`, so two
38
38
  * data sources sharing an engine share capabilities.
package/dist/index.d.ts CHANGED
@@ -4,4 +4,5 @@ export * from "./data/buildRebaseData";
4
4
  export * from "./data/buildRoutedRebaseData";
5
5
  export * from "./data/resolveDataSource";
6
6
  export * from "./data/query_builder";
7
+ export * from "./data/filter-dialect";
7
8
  export * from "./table-classification";