@rebasepro/common 0.7.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/dist/collections/CollectionRegistry.d.ts +30 -15
- package/dist/collections/default-collections.d.ts +255 -2
- package/dist/data/buildRebaseData.d.ts +30 -2
- package/dist/data/buildRoutedRebaseData.d.ts +14 -9
- package/dist/data/filter-dialect.d.ts +75 -0
- package/dist/data/query_builder.d.ts +4 -4
- package/dist/data/resolveDataSource.d.ts +8 -8
- package/dist/data/sort-dialect.d.ts +41 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.es.js +1125 -299
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +1138 -303
- package/dist/index.umd.js.map +1 -1
- package/dist/util/builders.d.ts +52 -42
- package/dist/util/callbacks.d.ts +8 -3
- package/dist/util/collections.d.ts +4 -4
- package/dist/util/entities.d.ts +2 -2
- package/dist/util/filter-operator-resolution.d.ts +32 -0
- package/dist/util/index.d.ts +2 -0
- package/dist/util/navigation_from_path.d.ts +4 -4
- package/dist/util/navigation_utils.d.ts +3 -3
- package/dist/util/parent_references_from_path.d.ts +2 -2
- package/dist/util/permissions.d.ts +30 -6
- 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 +22 -0
- package/dist/util/policy/securityRuleToConditions.d.ts +24 -0
- package/dist/util/policy/sqlToPolicy.d.ts +20 -0
- package/dist/util/references.d.ts +2 -2
- package/dist/util/relations.d.ts +5 -5
- package/dist/util/resolutions.d.ts +2 -2
- package/dist/util/storage.d.ts +26 -1
- package/package.json +13 -13
- package/src/collections/CollectionRegistry.ts +92 -61
- package/src/collections/default-collections.ts +4 -4
- package/src/data/buildRebaseData.ts +336 -172
- package/src/data/buildRoutedRebaseData.ts +22 -16
- package/src/data/filter-dialect.ts +403 -0
- package/src/data/query_builder.ts +19 -10
- package/src/data/resolveDataSource.ts +10 -10
- package/src/data/sort-dialect.ts +56 -0
- package/src/index.ts +2 -0
- package/src/util/builders.ts +87 -84
- package/src/util/callbacks.ts +15 -8
- package/src/util/collections.ts +4 -4
- package/src/util/entities.ts +4 -4
- package/src/util/filter-operator-resolution.ts +81 -0
- package/src/util/index.ts +2 -0
- package/src/util/navigation_from_path.ts +4 -4
- package/src/util/navigation_utils.ts +8 -8
- package/src/util/parent_references_from_path.ts +3 -3
- package/src/util/permissions.test.ts +7 -5
- package/src/util/permissions.ts +90 -163
- package/src/util/policy/evaluatePolicy.ts +152 -0
- package/src/util/policy/index.ts +3 -0
- package/src/util/policy/policyToPostgres.ts +165 -0
- package/src/util/policy/securityRuleToConditions.ts +67 -0
- package/src/util/policy/sqlToPolicy.ts +88 -0
- package/src/util/references.ts +3 -3
- package/src/util/relations.ts +19 -20
- package/src/util/resolutions.ts +11 -11
- package/src/util/storage.ts +34 -1
package/README.md
CHANGED
|
@@ -15,7 +15,7 @@ pnpm add @rebasepro/common
|
|
|
15
15
|
- **Collection utilities** — collection registry, default collection definitions, path resolution, navigation helpers
|
|
16
16
|
- **Data driver adapter** — `buildRebaseData()` bridges any `DataDriver` implementation into a `RebaseData` proxy with typed collection accessors
|
|
17
17
|
- **Query builder** — fluent `QueryBuilder` class plus `or()`, `and()`, `cond()` helpers for composing complex queries
|
|
18
|
-
- **
|
|
18
|
+
- **Snapshot/property utilities** — snapshot resolution, enum helpers, permission checks, reference/relation helpers, storage path utils, callback utilities
|
|
19
19
|
|
|
20
20
|
This package has no React dependency — it's pure TypeScript and can be used in both client and server contexts.
|
|
21
21
|
|
|
@@ -44,7 +44,7 @@ This package has no React dependency — it's pure TypeScript and can be used in
|
|
|
44
44
|
|---|---|
|
|
45
45
|
| `collections` | Collection config helpers |
|
|
46
46
|
| `common` | General-purpose utilities |
|
|
47
|
-
| `
|
|
47
|
+
| `snapshots` | Snapshot value resolution |
|
|
48
48
|
| `enums` | Enum type helpers |
|
|
49
49
|
| `paths` | Path parsing and manipulation |
|
|
50
50
|
| `resolutions` | Property and collection resolution |
|
|
@@ -69,7 +69,7 @@ const data = buildRebaseData(myDriver);
|
|
|
69
69
|
|
|
70
70
|
// Access collections by name (camelCase auto-converts to snake_case)
|
|
71
71
|
const { data: products } = await data.products.find({ limit: 10 });
|
|
72
|
-
const
|
|
72
|
+
const snapshot = await data.products.findById("abc-123");
|
|
73
73
|
|
|
74
74
|
// Fluent query builder
|
|
75
75
|
const { data: results } = await data.products
|
|
@@ -89,7 +89,7 @@ const { data: filtered } = await data.products
|
|
|
89
89
|
|
|
90
90
|
## Related Packages
|
|
91
91
|
|
|
92
|
-
- [`@rebasepro/types`](../types) — `DataDriver`, `RebaseData`, `CollectionAccessor`, `
|
|
92
|
+
- [`@rebasepro/types`](../types) — `DataDriver`, `RebaseData`, `CollectionAccessor`, `Snapshot`, `FindResponse`, etc.
|
|
93
93
|
- [`@rebasepro/utils`](../utils) — Low-level utilities (`toSnakeCase`, etc.)
|
|
94
94
|
- [`@rebasepro/core`](../core) — Runtime layer that consumes `@rebasepro/common`
|
|
95
95
|
- [`@rebasepro/client`](../client) — HTTP client that re-exports and extends the `QueryBuilder`
|
|
@@ -1,12 +1,27 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { CollectionCallbacks, CollectionConfig } 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: CollectionCallbacks): void;
|
|
21
|
+
/**
|
|
22
|
+
* Get the currently registered global callbacks, if any.
|
|
23
|
+
*/
|
|
24
|
+
getGlobalCallbacks(): CollectionCallbacks | undefined;
|
|
10
25
|
private collectionsByTableName;
|
|
11
26
|
private collectionsBySlug;
|
|
12
27
|
private rootCollections;
|
|
@@ -15,8 +30,8 @@ export declare class CollectionRegistry {
|
|
|
15
30
|
private rawCollectionsBySlug;
|
|
16
31
|
private rawRootCollections;
|
|
17
32
|
private cachedRawCollectionsList;
|
|
18
|
-
private
|
|
19
|
-
constructor(collections?:
|
|
33
|
+
private lastRawInputEntity;
|
|
34
|
+
constructor(collections?: CollectionConfig[], dataSources?: DataSourceRegistry);
|
|
20
35
|
/**
|
|
21
36
|
* Provide the declared data sources used to resolve each collection's
|
|
22
37
|
* engine during normalization. Set this before registering collections.
|
|
@@ -29,13 +44,13 @@ export declare class CollectionRegistry {
|
|
|
29
44
|
* Returns true if the collections have changed, false otherwise.
|
|
30
45
|
*
|
|
31
46
|
* Idempotent: compares the raw input (before normalization) against a stored
|
|
32
|
-
*
|
|
47
|
+
* entity. Only re-normalizes and re-registers when the raw input actually changed.
|
|
33
48
|
* @param collections
|
|
34
49
|
*/
|
|
35
|
-
registerMultiple(collections:
|
|
36
|
-
register(collection:
|
|
50
|
+
registerMultiple(collections: CollectionConfig[]): boolean;
|
|
51
|
+
register(collection: CollectionConfig, rawCollection?: CollectionConfig): void;
|
|
37
52
|
private _registerRecursively;
|
|
38
|
-
normalizeCollection(collection:
|
|
53
|
+
normalizeCollection(collection: CollectionConfig): CollectionConfig;
|
|
39
54
|
/**
|
|
40
55
|
* Extract Relation[] from properties that have inline relation config (i.e. `target` is set).
|
|
41
56
|
* This allows developers to define relations directly on properties without a separate
|
|
@@ -44,26 +59,26 @@ export declare class CollectionRegistry {
|
|
|
44
59
|
private extractRelationsFromProperties;
|
|
45
60
|
private normalizeProperties;
|
|
46
61
|
private normalizeProperty;
|
|
47
|
-
get(path: string):
|
|
62
|
+
get(path: string): CollectionConfig | undefined;
|
|
48
63
|
/**
|
|
49
64
|
* Gets the pristine, un-normalized collection exactly as it was provided.
|
|
50
65
|
* Useful for the AST editor so it doesn't accidentally serialize injected metadata back to disk.
|
|
51
66
|
*/
|
|
52
|
-
getRaw(path: string):
|
|
67
|
+
getRaw(path: string): CollectionConfig | undefined;
|
|
53
68
|
/**
|
|
54
69
|
* Get collection by resolving multi-segment paths through relations
|
|
55
70
|
* e.g., "authors/70/posts" resolves to the posts collection
|
|
56
71
|
*/
|
|
57
|
-
getCollectionByPath(collectionPath: string):
|
|
58
|
-
getCollections():
|
|
59
|
-
getRawCollections():
|
|
72
|
+
getCollectionByPath(collectionPath: string): CollectionConfig | undefined;
|
|
73
|
+
getCollections(): CollectionConfig[];
|
|
74
|
+
getRawCollections(): CollectionConfig[];
|
|
60
75
|
/**
|
|
61
76
|
* Resolves a multi-segment path like "products/123/locales" and returns
|
|
62
77
|
* information about the collections and entity IDs along the path
|
|
63
78
|
*/
|
|
64
79
|
resolvePathToCollections(path: string): {
|
|
65
|
-
collections:
|
|
80
|
+
collections: CollectionConfig[];
|
|
66
81
|
entityIds: (string | number)[];
|
|
67
|
-
finalCollection:
|
|
82
|
+
finalCollection: CollectionConfig;
|
|
68
83
|
};
|
|
69
84
|
}
|
|
@@ -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:
|
|
8
|
+
export declare const defaultUsersCollection: import("@rebasepro/types").PostgresCollectionConfig<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
|
+
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DataDriver, RebaseData } from "@rebasepro/types";
|
|
1
|
+
import { DataDriver, RebaseData, RebaseSdkData } from "@rebasepro/types";
|
|
2
2
|
/**
|
|
3
3
|
* Build a `RebaseData` object from a `DataDriver` using JavaScript Proxy.
|
|
4
4
|
*
|
|
@@ -9,6 +9,34 @@ import { DataDriver, RebaseData } from "@rebasepro/types";
|
|
|
9
9
|
* @example
|
|
10
10
|
* const data = buildRebaseData(driver);
|
|
11
11
|
* await data.products.create({ name: "Camera", price: 299 });
|
|
12
|
-
* const { data: items } = await data.products.find({ where: { status: "
|
|
12
|
+
* const { data: items } = await data.products.find({ where: { status: ["==", "published"] } });
|
|
13
13
|
*/
|
|
14
14
|
export declare function buildRebaseData(driver: DataDriver): RebaseData;
|
|
15
|
+
/**
|
|
16
|
+
* Wrap a flat {@link RebaseSdkData} into a Entity-shaped {@link RebaseData}.
|
|
17
|
+
*
|
|
18
|
+
* This is the **CMS boundary**: the SDK client (`client.data`) returns flat
|
|
19
|
+
* rows, but the admin renders the `Entity` view-model (`entity.values.*`).
|
|
20
|
+
* `core/Rebase.tsx` wraps `client.data` through this before handing it to the
|
|
21
|
+
* CMS `RebaseDataContext` — without it the admin renders rows with only their
|
|
22
|
+
* `id`.
|
|
23
|
+
*/
|
|
24
|
+
export declare function wrapAsEntityData(sdkData: RebaseSdkData): RebaseData;
|
|
25
|
+
/**
|
|
26
|
+
* Wrap a Entity-shaped {@link RebaseData} into a flat {@link RebaseSdkData}.
|
|
27
|
+
*
|
|
28
|
+
* Every collection accessor is adapted to return flat rows. Use this to derive
|
|
29
|
+
* the flat SDK data layer (`context.data`) from an existing Entity data layer
|
|
30
|
+
* — e.g. the admin routes its Entity data via `useData()` and exposes the
|
|
31
|
+
* same routing as flat `context.data` for callbacks by wrapping it here.
|
|
32
|
+
*/
|
|
33
|
+
export declare function wrapAsSdkData(entityData: RebaseData): RebaseSdkData;
|
|
34
|
+
/**
|
|
35
|
+
* Build a flat {@link RebaseSdkData} from a `DataDriver`.
|
|
36
|
+
*
|
|
37
|
+
* This is the developer-facing SDK data layer used by backend framework
|
|
38
|
+
* callbacks & scripts (`context.data` / `rebase.data`). It returns flat rows —
|
|
39
|
+
* identical in shape to the frontend SDK client — so the API is symmetric
|
|
40
|
+
* across front and back. The admin CMS uses {@link buildRebaseData} (Entity).
|
|
41
|
+
*/
|
|
42
|
+
export declare function buildSdkData(driver: DataDriver): RebaseSdkData;
|
|
@@ -1,21 +1,26 @@
|
|
|
1
|
-
import { RebaseData } from "@rebasepro/types";
|
|
1
|
+
import { RebaseData, RebaseSdkData } from "@rebasepro/types";
|
|
2
|
+
/**
|
|
3
|
+
* The two data-layer shapes that can be routed: the Entity-shaped admin
|
|
4
|
+
* {@link RebaseData} or the flat SDK {@link RebaseSdkData}. Both expose a
|
|
5
|
+
* `.collection(slug)` accessor, which is all the router needs.
|
|
6
|
+
*/
|
|
7
|
+
export type RoutableData = RebaseData | RebaseSdkData;
|
|
2
8
|
/**
|
|
3
9
|
* Parameters for {@link buildRoutedRebaseData}.
|
|
4
10
|
*/
|
|
5
|
-
export interface RoutedRebaseDataParams {
|
|
11
|
+
export interface RoutedRebaseDataParams<T extends RoutableData = RebaseData> {
|
|
6
12
|
/**
|
|
7
13
|
* The default data source. Handles every collection that does not
|
|
8
14
|
* resolve to an entry in `sources` (i.e. server-transport collections,
|
|
9
15
|
* which ride the Rebase client).
|
|
10
16
|
*/
|
|
11
|
-
defaultData:
|
|
17
|
+
defaultData: T;
|
|
12
18
|
/**
|
|
13
|
-
* Per-data-source
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* `defaultData`.
|
|
19
|
+
* Per-data-source instances for direct and custom transports, keyed by
|
|
20
|
+
* data-source key (e.g. `"analytics"`). Server-mediated sources are not
|
|
21
|
+
* listed here — they fall through to `defaultData`.
|
|
17
22
|
*/
|
|
18
|
-
sources: Record<string,
|
|
23
|
+
sources: Record<string, T>;
|
|
19
24
|
/**
|
|
20
25
|
* Resolve the data-source key for a given collection slug or path.
|
|
21
26
|
* Typically backed by the collection registry + `resolveDataSource`
|
|
@@ -50,4 +55,4 @@ export interface RoutedRebaseDataParams {
|
|
|
50
55
|
* await data.products.find(); // → default (server / Postgres)
|
|
51
56
|
* await data.events.find(); // → Firestore, if `events.dataSource === "analytics"`
|
|
52
57
|
*/
|
|
53
|
-
export declare function buildRoutedRebaseData({ defaultData, sources, resolveKey }: RoutedRebaseDataParams):
|
|
58
|
+
export declare function buildRoutedRebaseData<T extends RoutableData = RebaseData>({ defaultData, sources, resolveKey }: RoutedRebaseDataParams<T>): T;
|
|
@@ -0,0 +1,75 @@
|
|
|
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
|
+
* Wire-format values are always strings — the wire format carries no type
|
|
9
|
+
* metadata, so type coercion is the responsibility of the server-side data
|
|
10
|
+
* driver which has access to the collection schema.
|
|
11
|
+
*
|
|
12
|
+
* Commas inside list values are backslash-escaped (`\,`), and literal
|
|
13
|
+
* backslashes are escaped as `\\`.
|
|
14
|
+
*
|
|
15
|
+
* @module
|
|
16
|
+
*/
|
|
17
|
+
import { FilterValues, LogicalCondition, FilterCondition } from "@rebasepro/types";
|
|
18
|
+
/**
|
|
19
|
+
* Convert `FilterValues` (or `WireFilterValues`) to a PostgREST-style
|
|
20
|
+
* querystring record.
|
|
21
|
+
*
|
|
22
|
+
* - Canonical `[WhereFilterOp, value]` tuples are serialized strictly.
|
|
23
|
+
* - Pre-serialized PostgREST strings (e.g. `"eq.published"`) are passed through.
|
|
24
|
+
* - Single conditions produce a string value.
|
|
25
|
+
* - Multiple conditions on the same field produce a string array (repeated params).
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* serializeFilter({ status: ["==", "active"] })
|
|
29
|
+
* // → { status: "eq.active" }
|
|
30
|
+
*
|
|
31
|
+
* serializeFilter({ age: [[">=", 18], ["<", 65]] })
|
|
32
|
+
* // → { age: ["gte.18", "lt.65"] }
|
|
33
|
+
*
|
|
34
|
+
* // Pre-serialized strings pass through unchanged:
|
|
35
|
+
* serializeFilter({ status: "eq.published" })
|
|
36
|
+
* // → { status: "eq.published" }
|
|
37
|
+
*/
|
|
38
|
+
export declare function serializeFilter(filter: FilterValues<string> | Record<string, unknown>): Record<string, string | string[]>;
|
|
39
|
+
/**
|
|
40
|
+
* Convert a PostgREST-style querystring record to `FilterValues`.
|
|
41
|
+
*
|
|
42
|
+
* - String values are parsed as single conditions.
|
|
43
|
+
* - String arrays (repeated query params) become multiple conditions on the same field.
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* deserializeFilter({ status: "eq.active" })
|
|
47
|
+
* // → { status: ["==", "active"] }
|
|
48
|
+
*
|
|
49
|
+
* deserializeFilter({ age: ["gte.18", "lt.65"] })
|
|
50
|
+
* // → { age: [[">=", "18"], ["<", "65"]] }
|
|
51
|
+
*/
|
|
52
|
+
export declare function deserializeFilter(query: Record<string, unknown>): FilterValues<string>;
|
|
53
|
+
/**
|
|
54
|
+
* Serialize a `LogicalCondition` or `FilterCondition` to its wire-format string.
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* serializeLogicalCondition({ column: "status", operator: "==", value: "active" })
|
|
58
|
+
* // → "status.eq.active"
|
|
59
|
+
*
|
|
60
|
+
* serializeLogicalCondition({ type: "or", conditions: [...] })
|
|
61
|
+
* // → "or(status.eq.active,status.eq.pending)"
|
|
62
|
+
*/
|
|
63
|
+
export declare function serializeLogicalCondition(cond: LogicalCondition | FilterCondition): string;
|
|
64
|
+
/**
|
|
65
|
+
* Parse a logical condition wire-format string back into a
|
|
66
|
+
* `LogicalCondition` or `FilterCondition`.
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* deserializeLogicalCondition("status.eq.active")
|
|
70
|
+
* // → { column: "status", operator: "==", value: "active" }
|
|
71
|
+
*
|
|
72
|
+
* deserializeLogicalCondition("or(status.eq.active,age.gte.18)")
|
|
73
|
+
* // → { type: "or", conditions: [...] }
|
|
74
|
+
*/
|
|
75
|
+
export declare function deserializeLogicalCondition(str: string): LogicalCondition | FilterCondition;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { CollectionAccessor, FilterCondition, FindResponse, LogicalCondition, QueryBuilderInterface, WhereFilterOp, WhereValue } 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
|
*/
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { DataSourceDefinition, ResolvedDataSource } from "@rebasepro/types";
|
|
2
2
|
/**
|
|
3
3
|
* The subset of a collection needed to resolve its data source. Accepting a
|
|
4
|
-
* structural type (rather than the full `
|
|
4
|
+
* structural type (rather than the full `CollectionConfig`) keeps this usable
|
|
5
5
|
* from anywhere — frontend router, backend registry, editor — without coupling
|
|
6
6
|
* to the collection union.
|
|
7
7
|
*/
|
|
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.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { OrderByTuple } from "@rebasepro/types";
|
|
2
|
+
/**
|
|
3
|
+
* Sort-order wire codec.
|
|
4
|
+
*
|
|
5
|
+
* This is the ONLY module that knows about the colon-delimited wire format
|
|
6
|
+
* (`"field:direction"`) used in HTTP query parameters.
|
|
7
|
+
* Everything else speaks {@link OrderByTuple} exclusively.
|
|
8
|
+
*
|
|
9
|
+
* Mirrors the filter architecture in `filter-dialect.ts`.
|
|
10
|
+
*
|
|
11
|
+
* @module
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Serialize an {@link OrderByTuple} to the wire format `"field:direction"`.
|
|
15
|
+
*
|
|
16
|
+
* **Runtime tolerance:** if the input is already a well-formed wire string
|
|
17
|
+
* (from an untyped JS caller), it is returned unchanged.
|
|
18
|
+
* This is undocumented tolerance, not public API — don't rely on it.
|
|
19
|
+
*
|
|
20
|
+
* @param orderBy - A canonical `[field, direction]` tuple, or at runtime
|
|
21
|
+
* possibly a pre-serialized string (undocumented tolerance).
|
|
22
|
+
* @returns The wire-format string, or `undefined` if the input is falsy.
|
|
23
|
+
*
|
|
24
|
+
* @remarks
|
|
25
|
+
* Field names containing `:` are representable in the tuple form but
|
|
26
|
+
* **not** on the wire — this is an inherent limitation of the colon-delimited
|
|
27
|
+
* encoding and is not resolved here.
|
|
28
|
+
*/
|
|
29
|
+
export declare function serializeOrderBy(orderBy?: OrderByTuple | string): string | undefined;
|
|
30
|
+
/**
|
|
31
|
+
* Deserialize a wire-format `"field:direction"` string into an {@link OrderByTuple}.
|
|
32
|
+
*
|
|
33
|
+
* Lenient parsing (matches existing server behaviour):
|
|
34
|
+
* - Bare field name (no colon): `"name"` → `["name", "asc"]`
|
|
35
|
+
* - Unknown direction: `"name:foo"` → `["name", "asc"]`
|
|
36
|
+
* - Empty / falsy input: → `undefined`
|
|
37
|
+
*
|
|
38
|
+
* @param raw - The wire-format string from an HTTP query parameter.
|
|
39
|
+
* @returns The canonical tuple, or `undefined` if the input is empty/falsy.
|
|
40
|
+
*/
|
|
41
|
+
export declare function deserializeOrderBy(raw?: string): OrderByTuple | undefined;
|
package/dist/index.d.ts
CHANGED
|
@@ -4,4 +4,6 @@ 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";
|
|
8
|
+
export * from "./data/sort-dialect";
|
|
7
9
|
export * from "./table-classification";
|