@webtypen/webframez-core 0.2.14 → 0.2.16
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/Datatable/Datatable.d.ts +4 -0
- package/dist/Datatable/Datatable.js +42 -1
- package/package.json +1 -1
- package/src/Datatable/Datatable.ts +37 -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
|
+
```
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Request } from "../Router/Request";
|
|
2
|
+
type DatatableAutoApplyMatchModeType = "begin" | "end" | null;
|
|
2
3
|
export declare class Datatable {
|
|
3
4
|
collection: string | Function;
|
|
4
5
|
aggregation: {
|
|
@@ -18,6 +19,8 @@ export declare class Datatable {
|
|
|
18
19
|
perPage: number;
|
|
19
20
|
onRow?: Function;
|
|
20
21
|
onAttributes?: Function;
|
|
22
|
+
autoApplyFilter: DatatableAutoApplyMatchModeType;
|
|
23
|
+
autoApplySearch: DatatableAutoApplyMatchModeType;
|
|
21
24
|
getInit(req: Request): Promise<any>;
|
|
22
25
|
getAggregation(req: Request): Promise<any>;
|
|
23
26
|
getSubAggregation(req: Request): Promise<any>;
|
|
@@ -36,3 +39,4 @@ export declare class Datatable {
|
|
|
36
39
|
private formatFilterEntryVal;
|
|
37
40
|
getFilterMatch(req: Request, searchOrFilter: any): Promise<any>;
|
|
38
41
|
}
|
|
42
|
+
export {};
|
|
@@ -22,6 +22,8 @@ class Datatable {
|
|
|
22
22
|
this.onPressLink = null;
|
|
23
23
|
this.exports = null;
|
|
24
24
|
this.perPage = 25;
|
|
25
|
+
this.autoApplyFilter = "begin";
|
|
26
|
+
this.autoApplySearch = null;
|
|
25
27
|
}
|
|
26
28
|
getInit(req) {
|
|
27
29
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -62,7 +64,24 @@ 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
|
+
if (this.autoApplyFilter === "begin") {
|
|
70
|
+
return [{ $match: Object.assign({}, this.getFilterMatch(req, req.body.filter)) }, ...aggr];
|
|
71
|
+
}
|
|
72
|
+
else if (this.autoApplyFilter === "end") {
|
|
73
|
+
return [...aggr, { $match: Object.assign({}, this.getFilterMatch(req, req.body.filter)) }];
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
else if (this.autoApplySearch && req.body.search && typeof req.body.search === "object") {
|
|
77
|
+
if (this.autoApplySearch === "begin") {
|
|
78
|
+
return [{ $match: Object.assign({}, this.getFilterMatch(req, req.body.search)) }, ...aggr];
|
|
79
|
+
}
|
|
80
|
+
else if (this.autoApplySearch === "end") {
|
|
81
|
+
return [...aggr, { $match: Object.assign({}, this.getFilterMatch(req, req.body.search)) }];
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return aggr;
|
|
66
85
|
});
|
|
67
86
|
}
|
|
68
87
|
getSubAggregation(req) {
|
|
@@ -317,6 +336,28 @@ class Datatable {
|
|
|
317
336
|
}
|
|
318
337
|
break;
|
|
319
338
|
}
|
|
339
|
+
if (value !== undefined && filterEl && filterEl.cast) {
|
|
340
|
+
if (typeof filterEl.cast === "function") {
|
|
341
|
+
value = yield filterEl.cast(value, entry, req);
|
|
342
|
+
}
|
|
343
|
+
else if (filterEl.cast === "string") {
|
|
344
|
+
value = value.toString();
|
|
345
|
+
}
|
|
346
|
+
else if (filterEl.cast === "objectId") {
|
|
347
|
+
if (value.length === 12 || value.length === 24) {
|
|
348
|
+
value = yield DBConnection_1.DBConnection.objectId(value);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
else if (filterEl.cast === "integer") {
|
|
352
|
+
value = parseInt(value);
|
|
353
|
+
}
|
|
354
|
+
else if (filterEl.cast === "float") {
|
|
355
|
+
value = parseFloat(value);
|
|
356
|
+
}
|
|
357
|
+
else if (filterEl.cast === "boolean") {
|
|
358
|
+
value = value === true || value === 1 || value.toString() === "1" || value.toString() === "true" ? true : false;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
320
361
|
if (value !== undefined) {
|
|
321
362
|
out[filterEl && filterEl.mapping && filterEl.mapping.trim() !== "" ? filterEl.mapping : key] = value;
|
|
322
363
|
}
|
package/package.json
CHANGED
|
@@ -2,6 +2,8 @@ import { DBConnection } from "../Database/DBConnection";
|
|
|
2
2
|
import { NumericFunctions } from "../Functions/NumericFunctions";
|
|
3
3
|
import { Request } from "../Router/Request";
|
|
4
4
|
|
|
5
|
+
type DatatableAutoApplyMatchModeType = "begin" | "end" | null;
|
|
6
|
+
|
|
5
7
|
export class Datatable {
|
|
6
8
|
collection: string | Function = "";
|
|
7
9
|
aggregation: { [key: string]: any } | Function | null = null;
|
|
@@ -13,6 +15,8 @@ export class Datatable {
|
|
|
13
15
|
perPage: number = 25;
|
|
14
16
|
onRow?: Function;
|
|
15
17
|
onAttributes?: Function;
|
|
18
|
+
autoApplyFilter: DatatableAutoApplyMatchModeType = "begin";
|
|
19
|
+
autoApplySearch: DatatableAutoApplyMatchModeType = null;
|
|
16
20
|
|
|
17
21
|
async getInit(req: Request) {
|
|
18
22
|
const out: any = { table: req.body._table };
|
|
@@ -60,7 +64,21 @@ export class Datatable {
|
|
|
60
64
|
}
|
|
61
65
|
|
|
62
66
|
async getAggregation(req: Request) {
|
|
63
|
-
|
|
67
|
+
const aggr = typeof this.aggregation === "function" ? await this.aggregation(req) : this.aggregation;
|
|
68
|
+
if (this.autoApplyFilter && req.body.filter && typeof req.body.filter === "object") {
|
|
69
|
+
if (this.autoApplyFilter === "begin") {
|
|
70
|
+
return [{ $match: { ...this.getFilterMatch(req, req.body.filter) } }, ...aggr];
|
|
71
|
+
} else if (this.autoApplyFilter === "end") {
|
|
72
|
+
return [...aggr, { $match: { ...this.getFilterMatch(req, req.body.filter) } }];
|
|
73
|
+
}
|
|
74
|
+
} else if (this.autoApplySearch && req.body.search && typeof req.body.search === "object") {
|
|
75
|
+
if (this.autoApplySearch === "begin") {
|
|
76
|
+
return [{ $match: { ...this.getFilterMatch(req, req.body.search) } }, ...aggr];
|
|
77
|
+
} else if (this.autoApplySearch === "end") {
|
|
78
|
+
return [...aggr, { $match: { ...this.getFilterMatch(req, req.body.search) } }];
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return aggr;
|
|
64
82
|
}
|
|
65
83
|
|
|
66
84
|
async getSubAggregation(req: Request) {
|
|
@@ -331,6 +349,24 @@ export class Datatable {
|
|
|
331
349
|
break;
|
|
332
350
|
}
|
|
333
351
|
|
|
352
|
+
if (value !== undefined && filterEl && filterEl.cast) {
|
|
353
|
+
if (typeof filterEl.cast === "function") {
|
|
354
|
+
value = await filterEl.cast(value, entry, req);
|
|
355
|
+
} else if (filterEl.cast === "string") {
|
|
356
|
+
value = value.toString();
|
|
357
|
+
} else if (filterEl.cast === "objectId") {
|
|
358
|
+
if (value.length === 12 || value.length === 24) {
|
|
359
|
+
value = await DBConnection.objectId(value);
|
|
360
|
+
}
|
|
361
|
+
} else if (filterEl.cast === "integer") {
|
|
362
|
+
value = parseInt(value);
|
|
363
|
+
} else if (filterEl.cast === "float") {
|
|
364
|
+
value = parseFloat(value);
|
|
365
|
+
} else if (filterEl.cast === "boolean") {
|
|
366
|
+
value = value === true || value === 1 || value.toString() === "1" || value.toString() === "true" ? true : false;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
|
|
334
370
|
if (value !== undefined) {
|
|
335
371
|
out[filterEl && filterEl.mapping && filterEl.mapping.trim() !== "" ? filterEl.mapping : key] = value;
|
|
336
372
|
}
|