@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.
- package/dist/collections/CollectionRegistry.d.ts +17 -2
- package/dist/collections/default-collections.d.ts +255 -2
- package/dist/data/filter-dialect.d.ts +61 -0
- package/dist/data/query_builder.d.ts +4 -4
- package/dist/data/resolveDataSource.d.ts +7 -7
- package/dist/index.d.ts +1 -0
- package/dist/index.es.js +604 -188
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +611 -186
- package/dist/index.umd.js.map +1 -1
- package/dist/util/builders.d.ts +48 -1
- package/dist/util/callbacks.d.ts +6 -1
- package/dist/util/index.d.ts +1 -0
- package/dist/util/permissions.d.ts +26 -2
- package/dist/util/policy/evaluatePolicy.d.ts +31 -0
- package/dist/util/policy/index.d.ts +3 -0
- package/dist/util/policy/policyToPostgres.d.ts +10 -0
- package/dist/util/policy/securityRuleToConditions.d.ts +24 -0
- package/dist/util/policy/sqlToPolicy.d.ts +20 -0
- package/dist/util/storage.d.ts +26 -1
- package/package.json +13 -13
- package/src/collections/CollectionRegistry.ts +59 -28
- package/src/collections/default-collections.ts +4 -4
- package/src/data/buildRebaseData.ts +9 -120
- package/src/data/filter-dialect.ts +318 -0
- package/src/data/query_builder.ts +10 -10
- package/src/data/resolveDataSource.ts +9 -9
- package/src/index.ts +1 -0
- package/src/util/builders.ts +78 -1
- package/src/util/callbacks.ts +8 -1
- package/src/util/index.ts +1 -0
- package/src/util/permissions.test.ts +5 -3
- package/src/util/permissions.ts +85 -158
- package/src/util/policy/evaluatePolicy.ts +146 -0
- package/src/util/policy/index.ts +3 -0
- package/src/util/policy/policyToPostgres.ts +85 -0
- package/src/util/policy/securityRuleToConditions.ts +67 -0
- package/src/util/policy/sqlToPolicy.ts +88 -0
- package/src/util/references.ts +1 -1
- package/src/util/relations.ts +8 -9
- package/src/util/resolutions.ts +6 -6
- 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
|
|
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,
|
|
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:
|
|
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:
|
|
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,
|
|
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
|
-
/**
|
|
12
|
-
|
|
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
|
|
30
|
-
*
|
|
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
|
|
34
|
-
*
|
|
35
|
-
*
|
|
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