@rebasepro/common 0.2.5 → 0.4.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/data/query_builder.d.ts +6 -2
- package/dist/index.es.js +62 -42
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +62 -42
- package/dist/index.umd.js.map +1 -1
- package/package.json +3 -3
- package/src/collections/default-collections.ts +5 -0
- package/src/data/buildRebaseData.ts +22 -8
- package/src/data/query_builder.ts +37 -27
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rebasepro/common",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.4.0",
|
|
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/types": "0.
|
|
45
|
-
"@rebasepro/utils": "0.
|
|
44
|
+
"@rebasepro/types": "0.4.0",
|
|
45
|
+
"@rebasepro/utils": "0.4.0"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"@jest/globals": "^29.7.0",
|
|
@@ -17,6 +17,10 @@ export const defaultUsersCollection: PostgresCollection = {
|
|
|
17
17
|
group: "Settings",
|
|
18
18
|
openEntityMode: "dialog",
|
|
19
19
|
disableDefaultActions: ["copy"],
|
|
20
|
+
securityRules: [
|
|
21
|
+
{ operation: "select", roles: ["admin"] },
|
|
22
|
+
{ operations: ["insert", "update", "delete"], roles: ["admin"] }
|
|
23
|
+
],
|
|
20
24
|
sort: ["createdAt", "desc"],
|
|
21
25
|
properties: {
|
|
22
26
|
id: {
|
|
@@ -91,6 +95,7 @@ export const defaultUsersCollection: PostgresCollection = {
|
|
|
91
95
|
name: "Created At",
|
|
92
96
|
type: "date",
|
|
93
97
|
columnName: "created_at",
|
|
98
|
+
autoValue: "on_create",
|
|
94
99
|
ui: { readOnly: true }
|
|
95
100
|
},
|
|
96
101
|
updatedAt: {
|
|
@@ -8,7 +8,10 @@ import {
|
|
|
8
8
|
EntityValues,
|
|
9
9
|
FilterValues,
|
|
10
10
|
WhereFilterOp,
|
|
11
|
-
WhereFieldValue
|
|
11
|
+
WhereFieldValue,
|
|
12
|
+
WhereFilterOpShort,
|
|
13
|
+
LogicalCondition,
|
|
14
|
+
WhereValue
|
|
12
15
|
} from "@rebasepro/types";
|
|
13
16
|
import { toSnakeCase } from "@rebasepro/utils";
|
|
14
17
|
import { QueryBuilder } from "./query_builder";
|
|
@@ -69,11 +72,18 @@ function convertWhereToFilter(where?: Record<string, WhereFieldValue>): FilterVa
|
|
|
69
72
|
continue;
|
|
70
73
|
}
|
|
71
74
|
|
|
72
|
-
// Handle tuple
|
|
73
|
-
if (Array.isArray(rawValue)
|
|
74
|
-
const [
|
|
75
|
-
|
|
76
|
-
|
|
75
|
+
// Handle tuple or array of tuples
|
|
76
|
+
if (Array.isArray(rawValue)) {
|
|
77
|
+
const conditions: [WhereFilterOpShort, unknown][] = Array.isArray(rawValue[0])
|
|
78
|
+
? (rawValue as [WhereFilterOpShort, unknown][])
|
|
79
|
+
: [rawValue as [WhereFilterOpShort, unknown]];
|
|
80
|
+
|
|
81
|
+
const mappedConditions: [WhereFilterOp, unknown][] = conditions.map(([rawOp, val]) => {
|
|
82
|
+
const mappedOp = operatorMap[rawOp] ?? "==";
|
|
83
|
+
return [mappedOp, val];
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
filter[field] = Array.isArray(rawValue[0]) ? mappedConditions : mappedConditions[0];
|
|
77
87
|
continue;
|
|
78
88
|
}
|
|
79
89
|
|
|
@@ -244,8 +254,12 @@ values: {} as Record<string, unknown> }
|
|
|
244
254
|
} : undefined,
|
|
245
255
|
|
|
246
256
|
// Fluent Query Builder
|
|
247
|
-
where(
|
|
248
|
-
|
|
257
|
+
where(columnOrCondition: string | LogicalCondition, operator?: WhereFilterOpShort, value?: unknown) {
|
|
258
|
+
const builder = new QueryBuilder<M>(accessor);
|
|
259
|
+
if (typeof columnOrCondition === "object") {
|
|
260
|
+
return builder.where(columnOrCondition);
|
|
261
|
+
}
|
|
262
|
+
return builder.where(columnOrCondition as keyof M & string, operator!, value as WhereValue<M[keyof M & string]>);
|
|
249
263
|
},
|
|
250
264
|
orderBy(column: keyof M & string, ascending?: "asc" | "desc") {
|
|
251
265
|
return new QueryBuilder<M>(accessor).orderBy(column, ascending);
|
|
@@ -1,21 +1,15 @@
|
|
|
1
|
-
import { FindParams, Entity, FindResponse, CollectionAccessor, QueryBuilderInterface, FilterOperator } from "@rebasepro/types";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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
|
-
}
|
|
1
|
+
import { FindParams, Entity, FindResponse, CollectionAccessor, QueryBuilderInterface, FilterOperator, LogicalCondition, WhereValue, FilterCondition } from "@rebasepro/types";
|
|
2
|
+
|
|
3
|
+
export function or(...conditions: (FilterCondition | LogicalCondition)[]): LogicalCondition {
|
|
4
|
+
return { type: "or", conditions };
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function and(...conditions: (FilterCondition | LogicalCondition)[]): LogicalCondition {
|
|
8
|
+
return { type: "and", conditions };
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function cond(column: string, operator: FilterOperator, value: unknown): FilterCondition {
|
|
12
|
+
return { column, operator, value };
|
|
19
13
|
}
|
|
20
14
|
|
|
21
15
|
export class QueryBuilder<M extends Record<string, unknown> = Record<string, unknown>> implements QueryBuilderInterface<M> {
|
|
@@ -28,22 +22,38 @@ export class QueryBuilder<M extends Record<string, unknown> = Record<string, unk
|
|
|
28
22
|
* @example
|
|
29
23
|
* client.collection('users').where('age', '>=', 18).find()
|
|
30
24
|
*/
|
|
31
|
-
where
|
|
25
|
+
where<K extends keyof M & string>(column: K, operator: FilterOperator, value: WhereValue<M[K]>): this;
|
|
26
|
+
where(logicalCondition: LogicalCondition): this;
|
|
27
|
+
where(columnOrCondition: string | LogicalCondition, operator?: FilterOperator, value?: unknown): this {
|
|
28
|
+
// Handle LogicalCondition signature
|
|
29
|
+
if (typeof columnOrCondition === "object" && columnOrCondition !== null && "type" in columnOrCondition) {
|
|
30
|
+
this.params.logical = columnOrCondition as LogicalCondition;
|
|
31
|
+
return this;
|
|
32
|
+
}
|
|
33
|
+
|
|
32
34
|
if (!this.params.where) {
|
|
33
35
|
this.params.where = {};
|
|
34
36
|
}
|
|
35
37
|
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
+
const column = columnOrCondition as string;
|
|
39
|
+
const condition: [FilterOperator, unknown] = [operator!, value];
|
|
40
|
+
const existing = this.params.where[column];
|
|
38
41
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
if (existing === undefined) {
|
|
43
|
+
this.params.where[column] = condition;
|
|
44
|
+
} else if (Array.isArray(existing) && existing.length > 0 && Array.isArray(existing[0])) {
|
|
45
|
+
(this.params.where[column] as [FilterOperator, unknown][]).push(condition);
|
|
46
|
+
} else {
|
|
47
|
+
// Convert existing single tuple/value into array of tuples
|
|
48
|
+
let firstCondition: [FilterOperator, unknown];
|
|
49
|
+
if (Array.isArray(existing) && existing.length === 2 && typeof existing[0] === "string") {
|
|
50
|
+
firstCondition = existing as [FilterOperator, unknown];
|
|
51
|
+
} else {
|
|
52
|
+
firstCondition = ["==", existing];
|
|
53
|
+
}
|
|
54
|
+
this.params.where[column] = [firstCondition, condition];
|
|
44
55
|
}
|
|
45
56
|
|
|
46
|
-
this.params.where[column] = mappedOp === "eq" ? String(formattedValue) : `${mappedOp}.${formattedValue}`;
|
|
47
57
|
return this;
|
|
48
58
|
}
|
|
49
59
|
|