@rebasepro/common 0.2.1 → 0.2.4
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/default-collections.d.ts +12 -0
- package/dist/collections/index.d.ts +1 -0
- package/dist/data/query_builder.d.ts +51 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.es.js +471 -240
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +470 -239
- package/dist/index.umd.js.map +1 -1
- package/dist/util/permissions.d.ts +1 -0
- package/package.json +7 -4
- package/src/collections/CollectionRegistry.ts +12 -1
- package/src/collections/default-collections.ts +79 -0
- package/src/collections/index.ts +1 -0
- package/src/data/buildRebaseData.ts +25 -5
- package/src/data/query_builder.ts +117 -0
- package/src/index.ts +2 -0
- package/src/util/permissions.ts +1 -1
- package/src/util/relations.ts +15 -15
- package/src/util/resolutions.ts +5 -2
- package/src/collections/CollectionRegistry.d.ts +0 -56
- package/src/collections/index.d.ts +0 -1
- package/src/data/buildRebaseData.d.ts +0 -14
- package/src/index.d.ts +0 -3
- package/src/util/builders.d.ts +0 -57
- package/src/util/callbacks.d.ts +0 -6
- package/src/util/collections.d.ts +0 -11
- package/src/util/common.d.ts +0 -2
- package/src/util/conditions.d.ts +0 -26
- package/src/util/entities.d.ts +0 -58
- package/src/util/enums.d.ts +0 -3
- package/src/util/index.d.ts +0 -16
- package/src/util/navigation_from_path.d.ts +0 -34
- package/src/util/navigation_utils.d.ts +0 -20
- package/src/util/parent_references_from_path.d.ts +0 -6
- package/src/util/paths.d.ts +0 -14
- package/src/util/permissions.d.ts +0 -5
- package/src/util/references.d.ts +0 -2
- package/src/util/relations.d.ts +0 -22
- package/src/util/resolutions.d.ts +0 -72
- package/src/util/storage.d.ts +0 -24
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { AuthController, Entity, EntityCollection, User } from "@rebasepro/types";
|
|
2
|
+
export declare function checkOperation<M extends Record<string, unknown>, USER extends User>(collection: EntityCollection<M>, authController: AuthController<USER>, entity: Entity<M> | null, targetOperation: "select" | "insert" | "update" | "delete"): boolean;
|
|
2
3
|
export declare function canReadCollection<M extends Record<string, unknown>, USER extends User>(collection: EntityCollection<M>, authController: AuthController<USER>): boolean;
|
|
3
4
|
export declare function canEditEntity<M extends Record<string, unknown>, USER extends User>(collection: EntityCollection<M>, authController: AuthController<USER>, path: string, entity: Entity<M> | null): boolean;
|
|
4
5
|
export declare function canCreateEntity<M extends Record<string, unknown>, USER extends User>(collection: EntityCollection<M>, authController: AuthController<USER>, path: string, entity: Entity<M> | null): boolean;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rebasepro/common",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.4",
|
|
5
5
|
"description": "Awesome Firebase/Firestore-based headless open-source CMS",
|
|
6
6
|
"funding": {
|
|
7
7
|
"url": "https://github.com/sponsors/rebaseco"
|
|
@@ -41,8 +41,8 @@
|
|
|
41
41
|
"dependencies": {
|
|
42
42
|
"fast-equals": "6.0.0",
|
|
43
43
|
"json-logic-js": "^2.0.5",
|
|
44
|
-
"@rebasepro/
|
|
45
|
-
"@rebasepro/
|
|
44
|
+
"@rebasepro/utils": "0.2.4",
|
|
45
|
+
"@rebasepro/types": "0.2.4"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"@jest/globals": "^29.7.0",
|
|
@@ -92,7 +92,10 @@
|
|
|
92
92
|
],
|
|
93
93
|
"testEnvironment": "node",
|
|
94
94
|
"moduleNameMapper": {
|
|
95
|
-
"\\.(css|less)$": "<rootDir>/test/__mocks__/styleMock.js"
|
|
95
|
+
"\\.(css|less)$": "<rootDir>/test/__mocks__/styleMock.js",
|
|
96
|
+
"^@rebasepro/client$": "<rootDir>/../client/src/index.ts",
|
|
97
|
+
"^@rebasepro/types$": "<rootDir>/../types/src/index.ts",
|
|
98
|
+
"^@rebasepro/utils$": "<rootDir>/../utils/src/index.ts"
|
|
96
99
|
}
|
|
97
100
|
},
|
|
98
101
|
"scripts": {
|
|
@@ -172,8 +172,19 @@ export class CollectionRegistry {
|
|
|
172
172
|
const mergedRelationsRaw = [...extractedRelations];
|
|
173
173
|
for (const manual of manualRelations) {
|
|
174
174
|
const name = manual.relationName;
|
|
175
|
-
if (!name
|
|
175
|
+
if (!name) {
|
|
176
176
|
mergedRelationsRaw.push(manual);
|
|
177
|
+
} else {
|
|
178
|
+
const existingIndex = mergedRelationsRaw.findIndex(r => r.relationName === name);
|
|
179
|
+
if (existingIndex === -1) {
|
|
180
|
+
mergedRelationsRaw.push(manual);
|
|
181
|
+
} else {
|
|
182
|
+
// Merge manual into existing, preserving custom fields like 'collection'
|
|
183
|
+
mergedRelationsRaw[existingIndex] = {
|
|
184
|
+
...manual,
|
|
185
|
+
...mergedRelationsRaw[existingIndex]
|
|
186
|
+
};
|
|
187
|
+
}
|
|
177
188
|
}
|
|
178
189
|
}
|
|
179
190
|
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { PostgresCollection } from "@rebasepro/types";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Default users collection definition.
|
|
5
|
+
*
|
|
6
|
+
* Shared between the admin UI (for navigation/display) and the backend
|
|
7
|
+
* (for schema generation). Both consumers prepend this to the developer's
|
|
8
|
+
* collections array and rely on generic slug-based deduplication
|
|
9
|
+
* (Map keyed by slug, last-write-wins) so that developer-defined
|
|
10
|
+
* collections with the same slug override this default — no hardcoded
|
|
11
|
+
* string checks required.
|
|
12
|
+
*/
|
|
13
|
+
export const defaultUsersCollection: PostgresCollection = {
|
|
14
|
+
name: "Users",
|
|
15
|
+
singularName: "User",
|
|
16
|
+
slug: "users",
|
|
17
|
+
table: "users",
|
|
18
|
+
schema: "rebase",
|
|
19
|
+
icon: "Users",
|
|
20
|
+
group: "Settings",
|
|
21
|
+
properties: {
|
|
22
|
+
id: {
|
|
23
|
+
name: "ID",
|
|
24
|
+
type: "string",
|
|
25
|
+
isId: "uuid"
|
|
26
|
+
},
|
|
27
|
+
email: {
|
|
28
|
+
name: "Email",
|
|
29
|
+
type: "string",
|
|
30
|
+
validation: { required: true, unique: true }
|
|
31
|
+
},
|
|
32
|
+
password_hash: {
|
|
33
|
+
name: "Password Hash",
|
|
34
|
+
type: "string",
|
|
35
|
+
ui: { hideFromCollection: true }
|
|
36
|
+
},
|
|
37
|
+
display_name: {
|
|
38
|
+
name: "Display Name",
|
|
39
|
+
type: "string"
|
|
40
|
+
},
|
|
41
|
+
photo_url: {
|
|
42
|
+
name: "Photo URL",
|
|
43
|
+
type: "string"
|
|
44
|
+
},
|
|
45
|
+
email_verified: {
|
|
46
|
+
name: "Email Verified",
|
|
47
|
+
type: "boolean",
|
|
48
|
+
defaultValue: false
|
|
49
|
+
},
|
|
50
|
+
email_verification_token: {
|
|
51
|
+
name: "Email Verification Token",
|
|
52
|
+
type: "string",
|
|
53
|
+
ui: { hideFromCollection: true }
|
|
54
|
+
},
|
|
55
|
+
email_verification_sent_at: {
|
|
56
|
+
name: "Email Verification Sent At",
|
|
57
|
+
type: "date",
|
|
58
|
+
ui: { hideFromCollection: true }
|
|
59
|
+
},
|
|
60
|
+
metadata: {
|
|
61
|
+
name: "Metadata",
|
|
62
|
+
type: "map",
|
|
63
|
+
defaultValue: {},
|
|
64
|
+
ui: { hideFromCollection: true }
|
|
65
|
+
},
|
|
66
|
+
created_at: {
|
|
67
|
+
name: "Created At",
|
|
68
|
+
type: "date",
|
|
69
|
+
autoValue: "on_create",
|
|
70
|
+
ui: { readOnly: true, hideFromCollection: true }
|
|
71
|
+
},
|
|
72
|
+
updated_at: {
|
|
73
|
+
name: "Updated At",
|
|
74
|
+
type: "date",
|
|
75
|
+
autoValue: "on_update",
|
|
76
|
+
ui: { readOnly: true, hideFromCollection: true }
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
};
|
package/src/collections/index.ts
CHANGED
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
WhereFieldValue
|
|
12
12
|
} from "@rebasepro/types";
|
|
13
13
|
import { toSnakeCase } from "@rebasepro/utils";
|
|
14
|
+
import { QueryBuilder } from "./query_builder";
|
|
14
15
|
|
|
15
16
|
/**
|
|
16
17
|
* Convert where-clause filter object to the internal DataDriver FilterValues format.
|
|
@@ -129,14 +130,11 @@ function parseOrderBy(orderBy?: string): [string, "asc" | "desc"] | undefined {
|
|
|
129
130
|
return [field, direction];
|
|
130
131
|
}
|
|
131
132
|
|
|
132
|
-
/**
|
|
133
|
-
* Create a CollectionAccessor that delegates to a DataDriver for a given collection slug.
|
|
134
|
-
*/
|
|
135
133
|
function createDriverAccessor<M extends Record<string, unknown> = Record<string, unknown>>(
|
|
136
134
|
driver: DataDriver,
|
|
137
135
|
slug: string
|
|
138
136
|
): CollectionAccessor<M> {
|
|
139
|
-
|
|
137
|
+
const accessor: CollectionAccessor<M> = {
|
|
140
138
|
async find(params?: FindParams): Promise<FindResponse<M>> {
|
|
141
139
|
const orderParsed = parseOrderBy(params?.orderBy);
|
|
142
140
|
const entities = await driver.fetchCollection<M>({
|
|
@@ -237,8 +235,30 @@ values: {} as Record<string, unknown> }
|
|
|
237
235
|
onUpdate: (entity) => onUpdate(entity ?? undefined),
|
|
238
236
|
onError
|
|
239
237
|
});
|
|
240
|
-
} : undefined
|
|
238
|
+
} : undefined,
|
|
239
|
+
|
|
240
|
+
// Fluent Query Builder
|
|
241
|
+
where(column: keyof M & string, operator: WhereFilterOp, value: unknown) {
|
|
242
|
+
return new QueryBuilder<M>(accessor).where(column, operator, value);
|
|
243
|
+
},
|
|
244
|
+
orderBy(column: keyof M & string, ascending?: "asc" | "desc") {
|
|
245
|
+
return new QueryBuilder<M>(accessor).orderBy(column, ascending);
|
|
246
|
+
},
|
|
247
|
+
limit(count: number) {
|
|
248
|
+
return new QueryBuilder<M>(accessor).limit(count);
|
|
249
|
+
},
|
|
250
|
+
offset(count: number) {
|
|
251
|
+
return new QueryBuilder<M>(accessor).offset(count);
|
|
252
|
+
},
|
|
253
|
+
search(searchString: string) {
|
|
254
|
+
return new QueryBuilder<M>(accessor).search(searchString);
|
|
255
|
+
},
|
|
256
|
+
include(...relations: string[]) {
|
|
257
|
+
return new QueryBuilder<M>(accessor).include(...relations);
|
|
258
|
+
}
|
|
241
259
|
};
|
|
260
|
+
|
|
261
|
+
return accessor;
|
|
242
262
|
}
|
|
243
263
|
|
|
244
264
|
/**
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { FindParams, Entity, FindResponse, CollectionAccessor, QueryBuilderInterface, FilterOperator } from "@rebasepro/types";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Maps standard operators to Rebase backend's string-based operators
|
|
5
|
+
*/
|
|
6
|
+
function mapOperator(op: FilterOperator): string {
|
|
7
|
+
switch (op) {
|
|
8
|
+
case "==": return "eq";
|
|
9
|
+
case "!=": return "neq";
|
|
10
|
+
case ">": return "gt";
|
|
11
|
+
case ">=": return "gte";
|
|
12
|
+
case "<": return "lt";
|
|
13
|
+
case "<=": return "lte";
|
|
14
|
+
case "array-contains": return "cs";
|
|
15
|
+
case "array-contains-any": return "csa";
|
|
16
|
+
case "not-in": return "nin";
|
|
17
|
+
default: return op;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export class QueryBuilder<M extends Record<string, unknown> = Record<string, unknown>> implements QueryBuilderInterface<M> {
|
|
22
|
+
private params: FindParams = { where: {} };
|
|
23
|
+
|
|
24
|
+
constructor(private collection: CollectionAccessor<M>) {}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Add a filter condition to your query.
|
|
28
|
+
* @example
|
|
29
|
+
* client.collection('users').where('age', '>=', 18).find()
|
|
30
|
+
*/
|
|
31
|
+
where(column: keyof M & string, operator: FilterOperator, value: unknown): this {
|
|
32
|
+
if (!this.params.where) {
|
|
33
|
+
this.params.where = {};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const mappedOp = mapOperator(operator);
|
|
37
|
+
let formattedValue = value;
|
|
38
|
+
|
|
39
|
+
// Handle arrays for in, nin, cs, csa
|
|
40
|
+
if (Array.isArray(value) && ["in", "nin", "cs", "csa"].includes(mappedOp)) {
|
|
41
|
+
formattedValue = `(${value.join(",")})`;
|
|
42
|
+
} else if (value === null) {
|
|
43
|
+
formattedValue = "null";
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
this.params.where[column] = mappedOp === "eq" ? String(formattedValue) : `${mappedOp}.${formattedValue}`;
|
|
47
|
+
return this;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Order the results by a specific column.
|
|
52
|
+
* @example
|
|
53
|
+
* client.collection('users').orderBy('createdAt', 'desc').find()
|
|
54
|
+
*/
|
|
55
|
+
orderBy(column: keyof M & string, ascending: "asc" | "desc" = "asc"): this {
|
|
56
|
+
this.params.orderBy = `${column}:${ascending}`;
|
|
57
|
+
return this;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Limit the number of results returned.
|
|
62
|
+
*/
|
|
63
|
+
limit(count: number): this {
|
|
64
|
+
this.params.limit = count;
|
|
65
|
+
return this;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Skip the first N results.
|
|
70
|
+
*/
|
|
71
|
+
offset(count: number): this {
|
|
72
|
+
this.params.offset = count;
|
|
73
|
+
return this;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Set a free-text search string if supported by the backend.
|
|
78
|
+
*/
|
|
79
|
+
search(searchString: string): this {
|
|
80
|
+
this.params.searchString = searchString;
|
|
81
|
+
return this;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Include related entities in the response.
|
|
86
|
+
* Relations will be populated with full entity data instead of just IDs.
|
|
87
|
+
*
|
|
88
|
+
* @param relations - Relation names to include, or "*" for all.
|
|
89
|
+
* @example
|
|
90
|
+
* // Include specific relations
|
|
91
|
+
* client.data.posts.include("tags", "author").find()
|
|
92
|
+
*
|
|
93
|
+
* // Include all relations
|
|
94
|
+
* client.data.posts.include("*").find()
|
|
95
|
+
*/
|
|
96
|
+
include(...relations: string[]): this {
|
|
97
|
+
this.params.include = relations;
|
|
98
|
+
return this;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Execute the find query and return the results.
|
|
103
|
+
*/
|
|
104
|
+
async find(): Promise<FindResponse<M>> {
|
|
105
|
+
return this.collection.find(this.params) as Promise<FindResponse<M>>;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Listen to realtime updates matching this query.
|
|
110
|
+
*/
|
|
111
|
+
listen(onUpdate: (data: FindResponse<M>) => void, onError?: (error: Error) => void): () => void {
|
|
112
|
+
if (!this.collection.listen) {
|
|
113
|
+
throw new Error("Listen is only available when RebaseClient is configured with a websocketUrl.");
|
|
114
|
+
}
|
|
115
|
+
return this.collection.listen(this.params, onUpdate, onError);
|
|
116
|
+
}
|
|
117
|
+
}
|
package/src/index.ts
CHANGED
package/src/util/permissions.ts
CHANGED
|
@@ -135,7 +135,7 @@ function evaluateRule<USER extends User, M extends Record<string, unknown>>(rule
|
|
|
135
135
|
return true;
|
|
136
136
|
}
|
|
137
137
|
|
|
138
|
-
function checkOperation<M extends Record<string, unknown>, USER extends User>(
|
|
138
|
+
export function checkOperation<M extends Record<string, unknown>, USER extends User>(
|
|
139
139
|
collection: EntityCollection<M>,
|
|
140
140
|
authController: AuthController<USER>,
|
|
141
141
|
entity: Entity<M> | null,
|
package/src/util/relations.ts
CHANGED
|
@@ -33,6 +33,8 @@ export function sanitizeRelation(
|
|
|
33
33
|
} else {
|
|
34
34
|
targetCollection = evaluated;
|
|
35
35
|
}
|
|
36
|
+
} else if (rawTarget && typeof rawTarget === "object") {
|
|
37
|
+
targetCollection = rawTarget as EntityCollection;
|
|
36
38
|
}
|
|
37
39
|
|
|
38
40
|
if (!targetCollection) {
|
|
@@ -215,11 +217,15 @@ export function resolveCollectionRelations(
|
|
|
215
217
|
// Each relation is stored once under its canonical relationName key.
|
|
216
218
|
if (relCollection.relations) {
|
|
217
219
|
relCollection.relations.forEach((relation: Relation) => {
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
220
|
+
try {
|
|
221
|
+
const normalizedRelation = sanitizeRelation(relation, collection);
|
|
222
|
+
const relationKey = normalizedRelation.relationName;
|
|
223
|
+
if (relationKey) {
|
|
224
|
+
relations[relationKey] = normalizedRelation;
|
|
225
|
+
registeredRelationNames.add(relationKey);
|
|
226
|
+
}
|
|
227
|
+
} catch (e) {
|
|
228
|
+
// Ignore incomplete or invalid relations (e.g. missing target during registry setup)
|
|
223
229
|
}
|
|
224
230
|
});
|
|
225
231
|
}
|
|
@@ -274,7 +280,8 @@ export function resolvePropertyRelation({
|
|
|
274
280
|
|
|
275
281
|
const relProp = property as RelationProperty;
|
|
276
282
|
|
|
277
|
-
//
|
|
283
|
+
// If the property has inline config (target set), build a Relation from it.
|
|
284
|
+
// We only support the flat format where properties are directly on the RelationProperty.
|
|
278
285
|
if (relProp.target) {
|
|
279
286
|
return {
|
|
280
287
|
relationName: relProp.relationName || propertyKey,
|
|
@@ -292,15 +299,8 @@ export function resolvePropertyRelation({
|
|
|
292
299
|
} as Relation;
|
|
293
300
|
}
|
|
294
301
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
if (!relation) {
|
|
298
|
-
console.warn(`Unrecognized relation format for property '${propertyKey}' in collection '${sourceCollection.slug}'`);
|
|
299
|
-
return undefined;
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
return relation as Relation;
|
|
303
|
-
|
|
302
|
+
console.warn(`Unrecognized or missing relation target for property '${propertyKey}' in collection '${sourceCollection.slug}'`);
|
|
303
|
+
return undefined;
|
|
304
304
|
}
|
|
305
305
|
|
|
306
306
|
export function getTableName(collection: EntityCollection): string {
|
package/src/util/resolutions.ts
CHANGED
|
@@ -21,6 +21,7 @@ import { enumToObjectEntries } from "./enums";
|
|
|
21
21
|
import { DEFAULT_ONE_OF_TYPE } from "./common";
|
|
22
22
|
import { isDefaultFieldConfigId } from "@rebasepro/utils";
|
|
23
23
|
import { getIn, mergeDeep } from "@rebasepro/utils";
|
|
24
|
+
import { resolveCollectionRelations } from "./relations";
|
|
24
25
|
|
|
25
26
|
/**
|
|
26
27
|
* Resolve property builders, enums and arrays.
|
|
@@ -350,8 +351,10 @@ export function getSubcollections<M extends Record<string, unknown> = Record<str
|
|
|
350
351
|
return (collection as CollectionWithSubcollections).subcollections!() ?? [];
|
|
351
352
|
}
|
|
352
353
|
|
|
353
|
-
if (getDataSourceCapabilities(collection.driver).supportsRelations
|
|
354
|
-
const
|
|
354
|
+
if (getDataSourceCapabilities(collection.driver).supportsRelations) {
|
|
355
|
+
const resolvedRelations = resolveCollectionRelations(collection);
|
|
356
|
+
const manyRelations = Object.values(resolvedRelations).filter((r: Relation) => r.cardinality === "many");
|
|
357
|
+
|
|
355
358
|
return manyRelations.map((r: Relation) => {
|
|
356
359
|
const target = r.target();
|
|
357
360
|
if (!target) return undefined;
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { EntityCollection } from "@rebasepro/types";
|
|
2
|
-
export declare class CollectionRegistry {
|
|
3
|
-
private collectionsByTableName;
|
|
4
|
-
private collectionsBySlug;
|
|
5
|
-
private rootCollections;
|
|
6
|
-
private cachedCollectionsList;
|
|
7
|
-
private rawCollectionsByTableName;
|
|
8
|
-
private rawCollectionsBySlug;
|
|
9
|
-
private rawRootCollections;
|
|
10
|
-
private cachedRawCollectionsList;
|
|
11
|
-
private lastRawInputSnapshot;
|
|
12
|
-
constructor(collections?: EntityCollection[]);
|
|
13
|
-
reset(): void;
|
|
14
|
-
/**
|
|
15
|
-
* Registers a collection and its subcollections recursively.
|
|
16
|
-
* Returns true if the collections have changed, false otherwise.
|
|
17
|
-
*
|
|
18
|
-
* Idempotent: compares the raw input (before normalization) against a stored
|
|
19
|
-
* snapshot. Only re-normalizes and re-registers when the raw input actually changed.
|
|
20
|
-
* @param collections
|
|
21
|
-
*/
|
|
22
|
-
registerMultiple(collections: EntityCollection[]): boolean;
|
|
23
|
-
register(collection: EntityCollection, rawCollection?: EntityCollection): void;
|
|
24
|
-
private _registerRecursively;
|
|
25
|
-
normalizeCollection(collection: EntityCollection): EntityCollection;
|
|
26
|
-
/**
|
|
27
|
-
* Extract Relation[] from properties that have inline relation config (i.e. `target` is set).
|
|
28
|
-
* This allows developers to define relations directly on properties without a separate
|
|
29
|
-
* `relations[]` entry on the collection.
|
|
30
|
-
*/
|
|
31
|
-
private extractRelationsFromProperties;
|
|
32
|
-
private normalizeProperties;
|
|
33
|
-
private normalizeProperty;
|
|
34
|
-
get(path: string): EntityCollection | undefined;
|
|
35
|
-
/**
|
|
36
|
-
* Gets the pristine, un-normalized collection exactly as it was provided.
|
|
37
|
-
* Useful for the AST editor so it doesn't accidentally serialize injected metadata back to disk.
|
|
38
|
-
*/
|
|
39
|
-
getRaw(path: string): EntityCollection | undefined;
|
|
40
|
-
/**
|
|
41
|
-
* Get collection by resolving multi-segment paths through relations
|
|
42
|
-
* e.g., "authors/70/posts" resolves to the posts collection
|
|
43
|
-
*/
|
|
44
|
-
getCollectionByPath(collectionPath: string): EntityCollection | undefined;
|
|
45
|
-
getCollections(): EntityCollection[];
|
|
46
|
-
getRawCollections(): EntityCollection[];
|
|
47
|
-
/**
|
|
48
|
-
* Resolves a multi-segment path like "products/123/locales" and returns
|
|
49
|
-
* information about the collections and entity IDs along the path
|
|
50
|
-
*/
|
|
51
|
-
resolvePathToCollections(path: string): {
|
|
52
|
-
collections: EntityCollection[];
|
|
53
|
-
entityIds: (string | number)[];
|
|
54
|
-
finalCollection: EntityCollection;
|
|
55
|
-
};
|
|
56
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "./CollectionRegistry";
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { DataDriver, RebaseData } from "@rebasepro/types";
|
|
2
|
-
/**
|
|
3
|
-
* Build a `RebaseData` object from a `DataDriver` using JavaScript Proxy.
|
|
4
|
-
*
|
|
5
|
-
* This is the key bridge: any property access like `data.products` returns
|
|
6
|
-
* a `CollectionAccessor` backed by the underlying DataDriver, without
|
|
7
|
-
* needing per-collection code generation.
|
|
8
|
-
*
|
|
9
|
-
* @example
|
|
10
|
-
* const data = buildRebaseData(driver);
|
|
11
|
-
* await data.products.create({ name: "Camera", price: 299 });
|
|
12
|
-
* const { data: items } = await data.products.find({ where: { status: "eq.published" } });
|
|
13
|
-
*/
|
|
14
|
-
export declare function buildRebaseData(driver: DataDriver): RebaseData;
|
package/src/index.d.ts
DELETED
package/src/util/builders.d.ts
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import { AdditionalFieldDelegate, ArrayProperty, BooleanProperty, DateProperty, EntityCallbacks, EntityCollection, EnumValueConfig, EnumValues, GeopointProperty, MapProperty, NumberProperty, Properties, Property, ReferenceProperty, StringProperty, User } from "@rebasepro/types";
|
|
2
|
-
/**
|
|
3
|
-
* Identity function we use to defeat the type system of Typescript and build
|
|
4
|
-
* collection views with all its properties
|
|
5
|
-
* @param collection
|
|
6
|
-
* @group Builder
|
|
7
|
-
*/
|
|
8
|
-
export declare function buildCollection<M extends Record<string, unknown> = Record<string, unknown>, USER extends User = User>(collection: EntityCollection<M, USER>): EntityCollection<M, USER>;
|
|
9
|
-
/**
|
|
10
|
-
* Identity function we use to defeat the type system of Typescript and preserve
|
|
11
|
-
* the property keys.
|
|
12
|
-
* @param property
|
|
13
|
-
* @group Builder
|
|
14
|
-
*/
|
|
15
|
-
export declare function buildProperty<T, P extends Property = Property>(property: P): P extends StringProperty ? StringProperty : P extends NumberProperty ? NumberProperty : P extends BooleanProperty ? BooleanProperty : P extends DateProperty ? DateProperty : P extends GeopointProperty ? GeopointProperty : P extends ReferenceProperty ? ReferenceProperty : P extends ArrayProperty ? ArrayProperty : P extends MapProperty ? MapProperty : never;
|
|
16
|
-
/**
|
|
17
|
-
* Identity function we use to defeat the type system of Typescript and preserve
|
|
18
|
-
* the properties keys.
|
|
19
|
-
* @param properties
|
|
20
|
-
* @group Builder
|
|
21
|
-
*/
|
|
22
|
-
export declare function buildProperties<M extends Record<string, unknown>>(properties: Properties): Properties;
|
|
23
|
-
/**
|
|
24
|
-
* Identity function we use to defeat the type system of Typescript and preserve
|
|
25
|
-
* the properties keys.
|
|
26
|
-
* @param propertiesOrBuilder
|
|
27
|
-
* @group Builder
|
|
28
|
-
*/
|
|
29
|
-
export declare function buildPropertiesOrBuilder<M extends Record<string, unknown>>(propertiesOrBuilder: Properties): Properties;
|
|
30
|
-
/**
|
|
31
|
-
* Identity function we use to defeat the type system of Typescript and preserve
|
|
32
|
-
* the properties keys.
|
|
33
|
-
* @param enumValues
|
|
34
|
-
* @group Builder
|
|
35
|
-
*/
|
|
36
|
-
export declare function buildEnum(enumValues: EnumValues): EnumValues;
|
|
37
|
-
/**
|
|
38
|
-
* Identity function we use to defeat the type system of Typescript and preserve
|
|
39
|
-
* the properties keys.
|
|
40
|
-
* @param enumValueConfig
|
|
41
|
-
* @group Builder
|
|
42
|
-
*/
|
|
43
|
-
export declare function buildEnumValueConfig(enumValueConfig: EnumValueConfig): EnumValueConfig;
|
|
44
|
-
/**
|
|
45
|
-
* Identity function we use to defeat the type system of Typescript and preserve
|
|
46
|
-
* the properties keys.
|
|
47
|
-
* @param callbacks
|
|
48
|
-
* @group Builder
|
|
49
|
-
*/
|
|
50
|
-
export declare function buildEntityCallbacks<M extends Record<string, unknown> = Record<string, unknown>>(callbacks: EntityCallbacks<M>): EntityCallbacks<M>;
|
|
51
|
-
/**
|
|
52
|
-
* Identity function we use to defeat the type system of Typescript and build
|
|
53
|
-
* additional field delegates views with all its properties
|
|
54
|
-
* @param additionalFieldDelegate
|
|
55
|
-
* @group Builder
|
|
56
|
-
*/
|
|
57
|
-
export declare function buildAdditionalFieldDelegate<M extends Record<string, unknown>, USER extends User = User>(additionalFieldDelegate: AdditionalFieldDelegate<M, USER>): AdditionalFieldDelegate<M, USER>;
|
package/src/util/callbacks.d.ts
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import { EntityCallbacks, Properties } from "@rebasepro/types";
|
|
2
|
-
/**
|
|
3
|
-
* Helper function to extract field-level PropertyCallbacks from a properties schema
|
|
4
|
-
* and wrap them into an EntityCallbacks object recursively.
|
|
5
|
-
*/
|
|
6
|
-
export declare const buildPropertyCallbacks: (properties: Properties) => EntityCallbacks | undefined;
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { DefaultSelectedViewBuilder, DefaultSelectedViewParams, EntityCollection, Properties } from "@rebasepro/types";
|
|
2
|
-
export declare function sortProperties<M extends Record<string, unknown>>(properties: Properties, propertiesOrder?: string[]): Properties;
|
|
3
|
-
export declare function resolveDefaultSelectedView(defaultSelectedView: string | DefaultSelectedViewBuilder | undefined, params: DefaultSelectedViewParams): string | undefined;
|
|
4
|
-
export declare function getLocalChangesBackup(collection: EntityCollection): "manual_apply" | "auto_apply";
|
|
5
|
-
/**
|
|
6
|
-
* Returns the primary keys for an entity collection by inspecting the properties
|
|
7
|
-
* and finding any properties with `isId`.
|
|
8
|
-
* Fallbacks to `["id"]` if no properties are marked as `isId: true`.
|
|
9
|
-
* @param collection
|
|
10
|
-
*/
|
|
11
|
-
export declare function getPrimaryKeys<M extends Record<string, unknown>>(collection: EntityCollection<M>): Extract<keyof M, string>[];
|
package/src/util/common.d.ts
DELETED
package/src/util/conditions.d.ts
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { AuthController, ConditionContext, JsonLogicRule, Property } from "@rebasepro/types";
|
|
2
|
-
/**
|
|
3
|
-
* Register custom JSON Logic operations for Rebase.
|
|
4
|
-
* Call this once at app initialization.
|
|
5
|
-
*/
|
|
6
|
-
export declare function registerConditionOperations(): void;
|
|
7
|
-
/**
|
|
8
|
-
* Evaluate a JSON Logic rule against the given context.
|
|
9
|
-
*/
|
|
10
|
-
export declare function evaluateCondition(rule: JsonLogicRule, context: ConditionContext): unknown;
|
|
11
|
-
/**
|
|
12
|
-
* Build a ConditionContext from the current property resolution context.
|
|
13
|
-
*/
|
|
14
|
-
export declare function buildConditionContext(params: {
|
|
15
|
-
propertyKey?: string;
|
|
16
|
-
values?: Record<string, unknown>;
|
|
17
|
-
previousValues?: Record<string, unknown>;
|
|
18
|
-
path: string;
|
|
19
|
-
entityId?: string;
|
|
20
|
-
index?: number;
|
|
21
|
-
authController: AuthController;
|
|
22
|
-
}): ConditionContext;
|
|
23
|
-
/**
|
|
24
|
-
* Apply PropertyConditions to a resolved property, evaluating all JSON Logic rules.
|
|
25
|
-
*/
|
|
26
|
-
export declare function applyPropertyConditions(property: Property, context: ConditionContext): Property;
|
package/src/util/entities.d.ts
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import { DataType, Entity, EntityReference, EntityRelation, EntityStatus, EntityValues, Properties, Property } from "@rebasepro/types";
|
|
2
|
-
export declare function isReadOnly(property: Property): boolean;
|
|
3
|
-
export declare function isHidden(property: Property): boolean;
|
|
4
|
-
export declare function isPropertyBuilder(property?: Property): boolean;
|
|
5
|
-
export declare function getDefaultValuesFor<M extends Record<string, unknown>>(properties: Properties): Partial<EntityValues<M>>;
|
|
6
|
-
export declare function getDefaultValueFor(property?: Property): unknown;
|
|
7
|
-
export declare function getDefaultValueFortype(type: DataType): unknown;
|
|
8
|
-
/**
|
|
9
|
-
* Update the automatic values in an entity before save
|
|
10
|
-
* @group Driver
|
|
11
|
-
*/
|
|
12
|
-
export declare function updateDateAutoValues<M extends Record<string, unknown>>({ inputValues, properties, status, timestampNowValue }: {
|
|
13
|
-
inputValues: Partial<EntityValues<M>>;
|
|
14
|
-
properties: Properties;
|
|
15
|
-
status: EntityStatus;
|
|
16
|
-
timestampNowValue: unknown;
|
|
17
|
-
}): EntityValues<M>;
|
|
18
|
-
/**
|
|
19
|
-
* Add missing required fields, expected in the collection, to the values of an entity
|
|
20
|
-
* @param values
|
|
21
|
-
* @param properties
|
|
22
|
-
* @group Driver
|
|
23
|
-
*/
|
|
24
|
-
export declare function sanitizeData<M extends Record<string, unknown>>(values: EntityValues<M>, properties: Properties): Record<string, unknown>;
|
|
25
|
-
export declare function getReferenceFrom<M extends Record<string, unknown>>(entity: Entity<M>): EntityReference;
|
|
26
|
-
export declare function getRelationFrom<M extends Record<string, unknown>>(entity: Entity<M>): EntityRelation;
|
|
27
|
-
/**
|
|
28
|
-
* Normalize a value into a proper EntityRelation instance.
|
|
29
|
-
* Handles EntityRelation class instances, and plain objects
|
|
30
|
-
* with `__type === "relation"` or an `isEntityRelation()` method.
|
|
31
|
-
*
|
|
32
|
-
* Returns null if the value cannot be coerced.
|
|
33
|
-
*/
|
|
34
|
-
export declare function normalizeToEntityRelation(value: unknown): EntityRelation | null;
|
|
35
|
-
export declare function traverseValuesProperties<M extends Record<string, unknown>>(inputValues: Partial<EntityValues<M>>, properties: Properties, operation: (value: unknown, property: Property) => unknown): EntityValues<M> | undefined;
|
|
36
|
-
export declare function traverseValueProperty(inputValue: unknown, property: Property, operation: (value: unknown, property: Property) => unknown): unknown;
|
|
37
|
-
/**
|
|
38
|
-
* Relation reference types used throughout the server layer.
|
|
39
|
-
* These replace the 50+ manual `{ id, path, __type: "relation" }` constructions.
|
|
40
|
-
*/
|
|
41
|
-
export interface RelationRef {
|
|
42
|
-
readonly id: string | number;
|
|
43
|
-
readonly path: string;
|
|
44
|
-
readonly __type: "relation";
|
|
45
|
-
}
|
|
46
|
-
export interface RelationRefWithData extends RelationRef {
|
|
47
|
-
readonly data: Entity;
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* Create a lightweight relation stub for CMS views.
|
|
51
|
-
* Replaces inline `{ id, path, __type: "relation" }` object literals.
|
|
52
|
-
*/
|
|
53
|
-
export declare function createRelationRef(id: string | number, path: string): RelationRef;
|
|
54
|
-
/**
|
|
55
|
-
* Create a hydrated relation reference that includes the full entity data.
|
|
56
|
-
* Used when entity data has been pre-fetched (e.g., via batch loading or JOINs).
|
|
57
|
-
*/
|
|
58
|
-
export declare function createRelationRefWithData(id: string | number, path: string, data: Entity): RelationRefWithData;
|