@webtypen/webframez-core 0.2.13 → 0.2.15
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 +73 -25
- package/dist/Database/Model.d.ts +4 -0
- package/dist/Database/Model.js +80 -3
- package/dist/Datatable/Datatable.d.ts +2 -0
- package/dist/Datatable/Datatable.js +32 -1
- package/package.json +1 -1
- package/src/Database/Model.ts +85 -4
- package/src/Datatable/Datatable.ts +27 -1
- package/tsconfig.json +2 -1
package/README.md
CHANGED
|
@@ -28,9 +28,7 @@ Alternatively, a function can be specified directly or a previously imported one
|
|
|
28
28
|
|
|
29
29
|
```ts
|
|
30
30
|
// Directly
|
|
31
|
-
Route.get("/", (req: Request, res: Response) =>
|
|
32
|
-
res.send({ status: "success" })
|
|
33
|
-
);
|
|
31
|
+
Route.get("/", (req: Request, res: Response) => res.send({ status: "success" }));
|
|
34
32
|
|
|
35
33
|
// Imported
|
|
36
34
|
import { myFunction } from "./myfunction";
|
|
@@ -43,10 +41,10 @@ Middleware functions are also registered in `app/Kernel.ts.` A middleware functi
|
|
|
43
41
|
|
|
44
42
|
Middleware functions are usually created under `app/Middleware`. A middleware function is called with the parameters (next, abort, req and res):
|
|
45
43
|
|
|
46
|
-
-
|
|
47
|
-
-
|
|
48
|
-
-
|
|
49
|
-
-
|
|
44
|
+
- `next`: Function that signals when called that the request may be continued
|
|
45
|
+
- `abort`: Function that aborts the request when called. An HTTP status code can be specified in the first parameter and a request body (usually text or JSON) in the second.
|
|
46
|
+
- `req`: The Request-Object
|
|
47
|
+
- `res`: The Response-Object
|
|
50
48
|
|
|
51
49
|
Alternatively, middleware functions can also be defined directly in Kernel.ts:
|
|
52
50
|
|
|
@@ -73,7 +71,7 @@ Route.get("/auth-data", "AuthController@authData", { middleware: ["auth"] });
|
|
|
73
71
|
|
|
74
72
|
With the grouping of routes, the code of the application can be significantly reduced and kept clear. Here's how the following configurations can be used with a multiple route definition:
|
|
75
73
|
|
|
76
|
-
-
|
|
74
|
+
- `prefix`: A route path prefix used for all routes in this group:
|
|
77
75
|
|
|
78
76
|
```ts
|
|
79
77
|
Route.group({ prefix: "/admin", () => {
|
|
@@ -82,7 +80,7 @@ Route.group({ prefix: "/admin", () => {
|
|
|
82
80
|
}});
|
|
83
81
|
```
|
|
84
82
|
|
|
85
|
-
-
|
|
83
|
+
- `middleware`: An array of middleware-keys used for all routes in this group:
|
|
86
84
|
|
|
87
85
|
```ts
|
|
88
86
|
Route.group({ middleware: ["auth"], () => {
|
|
@@ -100,12 +98,12 @@ Nesting of the route groups is also possible:
|
|
|
100
98
|
|
|
101
99
|
```ts
|
|
102
100
|
Route.group({ prefix: "/test" }, () => {
|
|
103
|
-
|
|
104
|
-
|
|
101
|
+
Route.get("/", "TestController@test"); // Path: /test/
|
|
102
|
+
Route.get("/test2", "TestController@test"); // Path: /test2/
|
|
105
103
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
104
|
+
Route.group({ middleware: ["auth"], prefix: "/auth" }, () => {
|
|
105
|
+
Route.get("/data", "AuthController@data"); // Path: /test/auth/data; Middleware: auth
|
|
106
|
+
});
|
|
109
107
|
});
|
|
110
108
|
```
|
|
111
109
|
|
|
@@ -117,7 +115,7 @@ The application can handle multiple database connections, but one is defined as
|
|
|
117
115
|
|
|
118
116
|
The connections are configured in the `config/database.ts` file. Each connection is given a unique key in the `connections` object and uses a driver. The following drivers are currently available:
|
|
119
117
|
|
|
120
|
-
-
|
|
118
|
+
- MongoDB Driver
|
|
121
119
|
|
|
122
120
|
Depending on the driver, the database connection must be configured with different parameters.
|
|
123
121
|
|
|
@@ -125,13 +123,13 @@ Depending on the driver, the database connection must be configured with differe
|
|
|
125
123
|
|
|
126
124
|
```ts
|
|
127
125
|
export default {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
126
|
+
defaultConnection: "default",
|
|
127
|
+
connections: {
|
|
128
|
+
["default"]: {
|
|
129
|
+
driver: "mongodb",
|
|
130
|
+
url: "mongodb://...",
|
|
131
|
+
},
|
|
133
132
|
},
|
|
134
|
-
},
|
|
135
133
|
};
|
|
136
134
|
```
|
|
137
135
|
|
|
@@ -140,9 +138,59 @@ export default {
|
|
|
140
138
|
Models are usually placed under `app/Models`. Each model class inherits from `Model` and must store the table / collection name, in which the models data sets are stored, in the `__table` attribute.
|
|
141
139
|
|
|
142
140
|
```ts
|
|
143
|
-
import { Model } from "@webtypen/webframez-core";
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
141
|
+
import { Model, hasMany, QueryBuilder } from "@webtypen/webframez-core";
|
|
142
|
+
import { File } from "./File";
|
|
143
|
+
import { Session } from "./Session";
|
|
144
|
+
|
|
145
|
+
export class User extends Model {
|
|
146
|
+
__table = "users";
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* @param File Dependency Model
|
|
150
|
+
* @param foreignKey
|
|
151
|
+
* @param localKey (optional)
|
|
152
|
+
* @param queryBuilderFunction (optional) customize the query
|
|
153
|
+
**/
|
|
154
|
+
@hasOne(() => File, "_user_avatar", "_id", (query: QueryBuilder) => {
|
|
155
|
+
query.where("status", "=", "uploaded");
|
|
156
|
+
})
|
|
157
|
+
avatar!: () => File;
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* @param File Dependency Model
|
|
161
|
+
* @param foreignKey
|
|
162
|
+
* @param localKey (optional)
|
|
163
|
+
* @param queryBuilderFunction (optional) customize the query
|
|
164
|
+
**/
|
|
165
|
+
@hasMany(() => Session, "_user")
|
|
166
|
+
sessions!: () => Session[];
|
|
147
167
|
}
|
|
148
168
|
```
|
|
169
|
+
|
|
170
|
+
### Load a model
|
|
171
|
+
|
|
172
|
+
```ts
|
|
173
|
+
import { User } from "../Models/User";
|
|
174
|
+
|
|
175
|
+
const users = await User.where("is_active", "=", true).get();
|
|
176
|
+
const testUser = await User.where("email", "=", "test@test.de").where("is_active", "=", true).first();
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
#### Dependency Injection
|
|
180
|
+
|
|
181
|
+
```ts
|
|
182
|
+
const sessions = await testUser.session();
|
|
183
|
+
const avatarUrl = await testUser.avatar()?.url;
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
##### Disable cache / force dependency-reload:
|
|
187
|
+
|
|
188
|
+
```ts
|
|
189
|
+
const refreshedData = await testUser.session({ force: true });
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
##### Get dependency-query:
|
|
193
|
+
|
|
194
|
+
```ts
|
|
195
|
+
const oldSessions = await testUser.session({ query: true }).where("date", "<", moment().subtract(30, "days").format("YYYY-MM-DD")).get();
|
|
196
|
+
```
|
package/dist/Database/Model.d.ts
CHANGED
|
@@ -2,12 +2,15 @@ import { QueryBuilder } from "./QueryBuilder";
|
|
|
2
2
|
type ObjectIDType = {
|
|
3
3
|
noExceptions?: Boolean;
|
|
4
4
|
};
|
|
5
|
+
export declare function hasOne(modelGetter: () => any, foreignKey: string, localKey?: string, queryFunction?: Function): (target: any, propertyKey: string, v2?: any) => void;
|
|
6
|
+
export declare function hasMany(modelGetter: () => any, foreignKey: string, localKey?: string, queryFunction?: Function): (target: any, propertyKey: string) => void;
|
|
5
7
|
export declare class Model {
|
|
6
8
|
[key: string]: any | undefined;
|
|
7
9
|
__primaryKey: string;
|
|
8
10
|
__table: string;
|
|
9
11
|
__connection: string | undefined;
|
|
10
12
|
__hidden: string[];
|
|
13
|
+
__dependencies: any;
|
|
11
14
|
__unmapped: string[];
|
|
12
15
|
__unmappedSystem: string[];
|
|
13
16
|
static objectId(val?: any, options?: ObjectIDType): Promise<any>;
|
|
@@ -52,6 +55,7 @@ export declare class Model {
|
|
|
52
55
|
* @returns any
|
|
53
56
|
*/
|
|
54
57
|
static aggregate(aggregation: any, options?: any, collection?: string): Promise<any>;
|
|
58
|
+
buildRelationship(model: any, foreignKey: string, localKey?: string): any;
|
|
55
59
|
/**
|
|
56
60
|
* Returns the model-data without system- and unmapped-fields (new js-object)
|
|
57
61
|
* @returns object
|
package/dist/Database/Model.js
CHANGED
|
@@ -9,17 +9,91 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.Model = void 0;
|
|
12
|
+
exports.Model = exports.hasMany = exports.hasOne = void 0;
|
|
13
13
|
const DBConnection_1 = require("./DBConnection");
|
|
14
14
|
const QueryBuilder_1 = require("./QueryBuilder");
|
|
15
|
+
function hasOne(modelGetter, foreignKey, localKey, queryFunction) {
|
|
16
|
+
return function (target, propertyKey, v2) {
|
|
17
|
+
Object.defineProperty(target, propertyKey, {
|
|
18
|
+
value: function (options) {
|
|
19
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
20
|
+
if ((!options || !options.force) && this.__dependencies && this.__dependencies[propertyKey] !== undefined) {
|
|
21
|
+
return this.__dependencies[propertyKey];
|
|
22
|
+
}
|
|
23
|
+
const model = modelGetter();
|
|
24
|
+
if (!model) {
|
|
25
|
+
throw new Error(`Model for foreignKey "${foreignKey}" konnte nicht aufgelöst werden.`);
|
|
26
|
+
}
|
|
27
|
+
if (!this.__dependencies) {
|
|
28
|
+
this.__dependencies = {};
|
|
29
|
+
}
|
|
30
|
+
const query = this.buildRelationship(model, localKey !== null && localKey !== void 0 ? localKey : "_id", foreignKey);
|
|
31
|
+
if (queryFunction && typeof queryFunction === "function") {
|
|
32
|
+
queryFunction(query);
|
|
33
|
+
}
|
|
34
|
+
if (options && options.query) {
|
|
35
|
+
return query;
|
|
36
|
+
}
|
|
37
|
+
this.__dependencies[propertyKey] = yield query.first();
|
|
38
|
+
return this.__dependencies[propertyKey];
|
|
39
|
+
});
|
|
40
|
+
},
|
|
41
|
+
writable: false,
|
|
42
|
+
configurable: true,
|
|
43
|
+
});
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
exports.hasOne = hasOne;
|
|
47
|
+
function hasMany(modelGetter, foreignKey, localKey, queryFunction) {
|
|
48
|
+
return function (target, propertyKey) {
|
|
49
|
+
Object.defineProperty(target, propertyKey, {
|
|
50
|
+
value: function (options) {
|
|
51
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
52
|
+
if ((!options || !options.force) && this.__dependencies && this.__dependencies[propertyKey] !== undefined) {
|
|
53
|
+
return this.__dependencies[propertyKey];
|
|
54
|
+
}
|
|
55
|
+
const model = modelGetter();
|
|
56
|
+
if (!model) {
|
|
57
|
+
throw new Error(`Model for foreignKey "${foreignKey}" konnte nicht aufgelöst werden.`);
|
|
58
|
+
}
|
|
59
|
+
if (!this.__dependencies) {
|
|
60
|
+
this.__dependencies = {};
|
|
61
|
+
}
|
|
62
|
+
const query = this.buildRelationship(model, foreignKey, localKey);
|
|
63
|
+
if (queryFunction && typeof queryFunction === "function") {
|
|
64
|
+
queryFunction(query);
|
|
65
|
+
}
|
|
66
|
+
if (options && options.query) {
|
|
67
|
+
return query;
|
|
68
|
+
}
|
|
69
|
+
this.__dependencies[propertyKey] = yield query.get();
|
|
70
|
+
return this.__dependencies[propertyKey];
|
|
71
|
+
});
|
|
72
|
+
},
|
|
73
|
+
writable: false,
|
|
74
|
+
configurable: true,
|
|
75
|
+
});
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
exports.hasMany = hasMany;
|
|
15
79
|
class Model {
|
|
16
80
|
constructor() {
|
|
17
81
|
this.__primaryKey = "_id";
|
|
18
82
|
this.__table = "";
|
|
19
83
|
this.__connection = undefined;
|
|
20
84
|
this.__hidden = [];
|
|
85
|
+
this.__dependencies = {};
|
|
21
86
|
this.__unmapped = [];
|
|
22
|
-
this.__unmappedSystem = [
|
|
87
|
+
this.__unmappedSystem = [
|
|
88
|
+
"__primaryKey",
|
|
89
|
+
"__table",
|
|
90
|
+
"__connection",
|
|
91
|
+
"__unmapped",
|
|
92
|
+
"__unmappedSystem",
|
|
93
|
+
"__is_deleted",
|
|
94
|
+
"__hidden",
|
|
95
|
+
"__dependencies",
|
|
96
|
+
];
|
|
23
97
|
}
|
|
24
98
|
static objectId(val, options) {
|
|
25
99
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -141,9 +215,12 @@ class Model {
|
|
|
141
215
|
type: "aggregation",
|
|
142
216
|
table: collection ? collection : model ? model.__table : undefined,
|
|
143
217
|
aggregation: aggregation,
|
|
144
|
-
}, model.__connection
|
|
218
|
+
}, model.__connection);
|
|
145
219
|
});
|
|
146
220
|
}
|
|
221
|
+
buildRelationship(model, foreignKey, localKey) {
|
|
222
|
+
return model.where(foreignKey, "=", this[localKey !== null && localKey !== void 0 ? localKey : "_id"]);
|
|
223
|
+
}
|
|
147
224
|
/**
|
|
148
225
|
* Returns the model-data without system- and unmapped-fields (new js-object)
|
|
149
226
|
* @returns object
|
|
@@ -18,6 +18,8 @@ export declare class Datatable {
|
|
|
18
18
|
perPage: number;
|
|
19
19
|
onRow?: Function;
|
|
20
20
|
onAttributes?: Function;
|
|
21
|
+
autoApplyFilter: boolean;
|
|
22
|
+
autoApplySearch: boolean;
|
|
21
23
|
getInit(req: Request): Promise<any>;
|
|
22
24
|
getAggregation(req: Request): Promise<any>;
|
|
23
25
|
getSubAggregation(req: Request): Promise<any>;
|
|
@@ -22,6 +22,8 @@ class Datatable {
|
|
|
22
22
|
this.onPressLink = null;
|
|
23
23
|
this.exports = null;
|
|
24
24
|
this.perPage = 25;
|
|
25
|
+
this.autoApplyFilter = true;
|
|
26
|
+
this.autoApplySearch = false;
|
|
25
27
|
}
|
|
26
28
|
getInit(req) {
|
|
27
29
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -62,7 +64,14 @@ class Datatable {
|
|
|
62
64
|
}
|
|
63
65
|
getAggregation(req) {
|
|
64
66
|
return __awaiter(this, void 0, void 0, function* () {
|
|
65
|
-
|
|
67
|
+
const aggr = typeof this.aggregation === "function" ? yield this.aggregation(req) : this.aggregation;
|
|
68
|
+
if (this.autoApplyFilter && req.body.filter && typeof req.body.filter === "object") {
|
|
69
|
+
return [{ $match: Object.assign({}, this.getFilterMatch(req, req.body.filter)) }];
|
|
70
|
+
}
|
|
71
|
+
else if (this.autoApplySearch && req.body.search && typeof req.body.search === "object") {
|
|
72
|
+
return [{ $match: Object.assign({}, this.getFilterMatch(req, req.body.search)) }];
|
|
73
|
+
}
|
|
74
|
+
return aggr;
|
|
66
75
|
});
|
|
67
76
|
}
|
|
68
77
|
getSubAggregation(req) {
|
|
@@ -317,6 +326,28 @@ class Datatable {
|
|
|
317
326
|
}
|
|
318
327
|
break;
|
|
319
328
|
}
|
|
329
|
+
if (value !== undefined && filterEl && filterEl.cast) {
|
|
330
|
+
if (typeof filterEl.cast === "function") {
|
|
331
|
+
value = yield filterEl.cast(value, entry, req);
|
|
332
|
+
}
|
|
333
|
+
else if (filterEl.cast === "string") {
|
|
334
|
+
value = value.toString();
|
|
335
|
+
}
|
|
336
|
+
else if (filterEl.cast === "objectId") {
|
|
337
|
+
if (value.length === 12 || value.length === 24) {
|
|
338
|
+
value = yield DBConnection_1.DBConnection.objectId(value);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
else if (filterEl.cast === "integer") {
|
|
342
|
+
value = parseInt(value);
|
|
343
|
+
}
|
|
344
|
+
else if (filterEl.cast === "float") {
|
|
345
|
+
value = parseFloat(value);
|
|
346
|
+
}
|
|
347
|
+
else if (filterEl.cast === "boolean") {
|
|
348
|
+
value = value === true || value === 1 || value.toString() === "1" || value.toString() === "true" ? true : false;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
320
351
|
if (value !== undefined) {
|
|
321
352
|
out[filterEl && filterEl.mapping && filterEl.mapping.trim() !== "" ? filterEl.mapping : key] = value;
|
|
322
353
|
}
|
package/package.json
CHANGED
package/src/Database/Model.ts
CHANGED
|
@@ -5,14 +5,92 @@ type ObjectIDType = {
|
|
|
5
5
|
noExceptions?: Boolean;
|
|
6
6
|
};
|
|
7
7
|
|
|
8
|
+
export function hasOne(modelGetter: () => any, foreignKey: string, localKey?: string, queryFunction?: Function) {
|
|
9
|
+
return function (target: any, propertyKey: string, v2?: any) {
|
|
10
|
+
Object.defineProperty(target, propertyKey, {
|
|
11
|
+
value: async function (options?: any) {
|
|
12
|
+
if ((!options || !options.force) && this.__dependencies && this.__dependencies[propertyKey] !== undefined) {
|
|
13
|
+
return this.__dependencies[propertyKey];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const model = modelGetter();
|
|
17
|
+
if (!model) {
|
|
18
|
+
throw new Error(`Model for foreignKey "${foreignKey}" konnte nicht aufgelöst werden.`);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (!this.__dependencies) {
|
|
22
|
+
this.__dependencies = {};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const query = this.buildRelationship(model, localKey ?? "_id", foreignKey);
|
|
26
|
+
if (queryFunction && typeof queryFunction === "function") {
|
|
27
|
+
queryFunction(query);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (options && options.query) {
|
|
31
|
+
return query;
|
|
32
|
+
}
|
|
33
|
+
this.__dependencies[propertyKey] = await query.first();
|
|
34
|
+
return this.__dependencies[propertyKey];
|
|
35
|
+
},
|
|
36
|
+
writable: false,
|
|
37
|
+
configurable: true,
|
|
38
|
+
});
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function hasMany(modelGetter: () => any, foreignKey: string, localKey?: string, queryFunction?: Function) {
|
|
43
|
+
return function (target: any, propertyKey: string) {
|
|
44
|
+
Object.defineProperty(target, propertyKey, {
|
|
45
|
+
value: async function (options?: any) {
|
|
46
|
+
if ((!options || !options.force) && this.__dependencies && this.__dependencies[propertyKey] !== undefined) {
|
|
47
|
+
return this.__dependencies[propertyKey];
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const model = modelGetter();
|
|
51
|
+
if (!model) {
|
|
52
|
+
throw new Error(`Model for foreignKey "${foreignKey}" konnte nicht aufgelöst werden.`);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (!this.__dependencies) {
|
|
56
|
+
this.__dependencies = {};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const query = this.buildRelationship(model, foreignKey, localKey);
|
|
60
|
+
if (queryFunction && typeof queryFunction === "function") {
|
|
61
|
+
queryFunction(query);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (options && options.query) {
|
|
65
|
+
return query;
|
|
66
|
+
}
|
|
67
|
+
this.__dependencies[propertyKey] = await query.get();
|
|
68
|
+
return this.__dependencies[propertyKey];
|
|
69
|
+
},
|
|
70
|
+
writable: false,
|
|
71
|
+
configurable: true,
|
|
72
|
+
});
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
|
|
8
76
|
export class Model {
|
|
9
77
|
[key: string]: any | undefined; // allow-custom-properties
|
|
10
78
|
__primaryKey = "_id";
|
|
11
79
|
__table: string = "";
|
|
12
80
|
__connection: string | undefined = undefined;
|
|
13
81
|
__hidden: string[] = [];
|
|
82
|
+
__dependencies: any = {};
|
|
14
83
|
__unmapped: string[] = [];
|
|
15
|
-
__unmappedSystem: string[] = [
|
|
84
|
+
__unmappedSystem: string[] = [
|
|
85
|
+
"__primaryKey",
|
|
86
|
+
"__table",
|
|
87
|
+
"__connection",
|
|
88
|
+
"__unmapped",
|
|
89
|
+
"__unmappedSystem",
|
|
90
|
+
"__is_deleted",
|
|
91
|
+
"__hidden",
|
|
92
|
+
"__dependencies",
|
|
93
|
+
];
|
|
16
94
|
|
|
17
95
|
static async objectId(val?: any, options?: ObjectIDType) {
|
|
18
96
|
const model = new this();
|
|
@@ -124,7 +202,7 @@ export class Model {
|
|
|
124
202
|
* @param aggregation
|
|
125
203
|
* @returns any
|
|
126
204
|
*/
|
|
127
|
-
static async aggregate(aggregation: any, options?: any,collection?: string) {
|
|
205
|
+
static async aggregate(aggregation: any, options?: any, collection?: string) {
|
|
128
206
|
const model = new this();
|
|
129
207
|
return await DBConnection.execute(
|
|
130
208
|
{
|
|
@@ -132,11 +210,14 @@ export class Model {
|
|
|
132
210
|
table: collection ? collection : model ? model.__table : undefined,
|
|
133
211
|
aggregation: aggregation,
|
|
134
212
|
},
|
|
135
|
-
model.__connection
|
|
136
|
-
options
|
|
213
|
+
model.__connection
|
|
137
214
|
);
|
|
138
215
|
}
|
|
139
216
|
|
|
217
|
+
buildRelationship(model: any, foreignKey: string, localKey?: string): any {
|
|
218
|
+
return model.where(foreignKey, "=", this[localKey ?? "_id"]);
|
|
219
|
+
}
|
|
220
|
+
|
|
140
221
|
/**
|
|
141
222
|
* Returns the model-data without system- and unmapped-fields (new js-object)
|
|
142
223
|
* @returns object
|
|
@@ -13,6 +13,8 @@ export class Datatable {
|
|
|
13
13
|
perPage: number = 25;
|
|
14
14
|
onRow?: Function;
|
|
15
15
|
onAttributes?: Function;
|
|
16
|
+
autoApplyFilter = true;
|
|
17
|
+
autoApplySearch = false;
|
|
16
18
|
|
|
17
19
|
async getInit(req: Request) {
|
|
18
20
|
const out: any = { table: req.body._table };
|
|
@@ -60,7 +62,13 @@ export class Datatable {
|
|
|
60
62
|
}
|
|
61
63
|
|
|
62
64
|
async getAggregation(req: Request) {
|
|
63
|
-
|
|
65
|
+
const aggr = typeof this.aggregation === "function" ? await this.aggregation(req) : this.aggregation;
|
|
66
|
+
if (this.autoApplyFilter && req.body.filter && typeof req.body.filter === "object") {
|
|
67
|
+
return [{ $match: { ...this.getFilterMatch(req, req.body.filter) } }];
|
|
68
|
+
} else if (this.autoApplySearch && req.body.search && typeof req.body.search === "object") {
|
|
69
|
+
return [{ $match: { ...this.getFilterMatch(req, req.body.search) } }];
|
|
70
|
+
}
|
|
71
|
+
return aggr;
|
|
64
72
|
}
|
|
65
73
|
|
|
66
74
|
async getSubAggregation(req: Request) {
|
|
@@ -331,6 +339,24 @@ export class Datatable {
|
|
|
331
339
|
break;
|
|
332
340
|
}
|
|
333
341
|
|
|
342
|
+
if (value !== undefined && filterEl && filterEl.cast) {
|
|
343
|
+
if (typeof filterEl.cast === "function") {
|
|
344
|
+
value = await filterEl.cast(value, entry, req);
|
|
345
|
+
} else if (filterEl.cast === "string") {
|
|
346
|
+
value = value.toString();
|
|
347
|
+
} else if (filterEl.cast === "objectId") {
|
|
348
|
+
if (value.length === 12 || value.length === 24) {
|
|
349
|
+
value = await DBConnection.objectId(value);
|
|
350
|
+
}
|
|
351
|
+
} else if (filterEl.cast === "integer") {
|
|
352
|
+
value = parseInt(value);
|
|
353
|
+
} else if (filterEl.cast === "float") {
|
|
354
|
+
value = parseFloat(value);
|
|
355
|
+
} else if (filterEl.cast === "boolean") {
|
|
356
|
+
value = value === true || value === 1 || value.toString() === "1" || value.toString() === "true" ? true : false;
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
334
360
|
if (value !== undefined) {
|
|
335
361
|
out[filterEl && filterEl.mapping && filterEl.mapping.trim() !== "" ? filterEl.mapping : key] = value;
|
|
336
362
|
}
|