@adaptivestone/framework 2.17.0 → 3.0.3
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/CHANGELOG.md +68 -0
- package/README.md +2 -0
- package/commands/Documentation.js +6 -8
- package/commands/DropIndex.js +4 -0
- package/commands/migration/Create.js +4 -0
- package/commands/migration/Migrate.js +4 -0
- package/config/http.js +1 -1
- package/config/i18n.js +1 -1
- package/config/log.js +2 -1
- package/controllers/Auth.js +19 -28
- package/controllers/Auth.test.js +4 -9
- package/controllers/Home.js +1 -2
- package/models/User.js +1 -10
- package/modules/AbstractCommand.js +4 -0
- package/modules/AbstractController.js +238 -267
- package/modules/AbstractModel.js +15 -22
- package/modules/Base.d.ts +0 -5
- package/modules/Base.js +0 -9
- package/package.json +9 -15
- package/server.d.ts +3 -1
- package/server.js +6 -1
- package/services/cache/Cache.d.ts +22 -0
- package/services/cache/Cache.js +4 -0
- package/services/http/HttpServer.js +5 -3
- package/services/http/middleware/AbstractMiddleware.js +14 -0
- package/services/http/middleware/Auth.js +4 -0
- package/services/http/middleware/GetUserByToken.js +9 -0
- package/services/http/middleware/PrepareAppInfo.js +4 -0
- package/services/http/middleware/RateLimiter.js +5 -1
- package/services/http/middleware/Role.js +29 -0
- package/tests/setup.js +1 -1
|
@@ -1,16 +1,15 @@
|
|
|
1
|
+
/* eslint-disable array-callback-return */
|
|
1
2
|
/* eslint-disable no-restricted-syntax */
|
|
2
3
|
/* eslint-disable guard-for-in */
|
|
3
4
|
const express = require('express');
|
|
4
|
-
const
|
|
5
|
-
const cloneDeep = require('lodash/cloneDeep');
|
|
5
|
+
const merge = require('deepmerge');
|
|
6
6
|
|
|
7
7
|
const Base = require('./Base');
|
|
8
|
-
const PrepareAppInfo = require('../services/http/middleware/PrepareAppInfo');
|
|
9
8
|
const GetUserByToken = require('../services/http/middleware/GetUserByToken');
|
|
10
9
|
const Auth = require('../services/http/middleware/Auth');
|
|
11
10
|
|
|
12
11
|
/**
|
|
13
|
-
* Abstract controller. You
|
|
12
|
+
* Abstract controller. You should extend any controller from them.
|
|
14
13
|
* Place you cintroller into controller folder and it be inited in auto way.
|
|
15
14
|
* By default name of route will be controller name not file name. But please name it in same ways.
|
|
16
15
|
* You can overwrite base controllers byt creating controllers with tha same file name (yes file name, not class name)
|
|
@@ -25,80 +24,106 @@ class AbstractController extends Base {
|
|
|
25
24
|
const { routes } = this;
|
|
26
25
|
const expressPath = this.getExpressPath();
|
|
27
26
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
27
|
+
/**
|
|
28
|
+
* Grab route middleware onlo one Map
|
|
29
|
+
*/
|
|
30
|
+
const routeMiddlewares = new Map();
|
|
31
|
+
Object.entries(routes).forEach(([method, methodRoutes]) => {
|
|
31
32
|
Object.entries(methodRoutes).forEach(([route, routeParam]) => {
|
|
32
|
-
if (routeParam
|
|
33
|
-
const fullRoute = method.toUpperCase() + route
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
allMiddlewares.set(fullRoute, [...allMiddlewares.get(fullRoute), ...routeParam.middleware])
|
|
33
|
+
if (routeParam?.middleware) {
|
|
34
|
+
const fullRoute = method.toUpperCase() + route;
|
|
35
|
+
|
|
36
|
+
if (!routeMiddlewares.has(fullRoute)) {
|
|
37
|
+
routeMiddlewares.set(fullRoute, []);
|
|
38
38
|
}
|
|
39
|
-
}
|
|
40
|
-
})
|
|
41
|
-
})
|
|
42
39
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
40
|
+
routeMiddlewares.set(fullRoute, [
|
|
41
|
+
...routeMiddlewares.get(fullRoute),
|
|
42
|
+
...routeParam.middleware,
|
|
43
|
+
]);
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
});
|
|
46
47
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
this.logger.error(`Path not a string ${realPath}. Please check it`);
|
|
57
|
-
// eslint-disable-next-line no-continue
|
|
58
|
-
continue;
|
|
48
|
+
/**
|
|
49
|
+
* Parse middlewares to be an object.
|
|
50
|
+
*/
|
|
51
|
+
const parseMiddlewares = (middlewareMap) => {
|
|
52
|
+
const middlewaresInfo = [];
|
|
53
|
+
// eslint-disable-next-line prefer-const
|
|
54
|
+
for (let [path, middleware] of middlewareMap) {
|
|
55
|
+
if (!Array.isArray(middleware)) {
|
|
56
|
+
middleware = [middleware];
|
|
59
57
|
}
|
|
60
|
-
|
|
61
|
-
method =
|
|
62
|
-
|
|
63
|
-
|
|
58
|
+
for (const M of middleware) {
|
|
59
|
+
let method = 'all';
|
|
60
|
+
let realPath = path;
|
|
61
|
+
if (typeof realPath !== 'string') {
|
|
62
|
+
this.logger.error(`Path not a string ${realPath}. Please check it`);
|
|
64
63
|
// eslint-disable-next-line no-continue
|
|
65
64
|
continue;
|
|
66
65
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
66
|
+
if (!realPath.startsWith('/')) {
|
|
67
|
+
method = realPath.split('/')[0]?.toLowerCase();
|
|
68
|
+
if (!method) {
|
|
69
|
+
this.logger.error(`Method not found for ${realPath}`);
|
|
70
|
+
// eslint-disable-next-line no-continue
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
realPath = realPath.substring(method.length);
|
|
74
|
+
}
|
|
75
|
+
if (typeof this.router[method] !== 'function') {
|
|
76
|
+
this.logger.error(
|
|
77
|
+
`Method ${method} not exist for middleware. Please check your codebase`,
|
|
78
|
+
);
|
|
79
|
+
// eslint-disable-next-line no-continue
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
const fullPath = `/${expressPath}/${realPath.toUpperCase()}`
|
|
83
|
+
.split('//')
|
|
84
|
+
.join('/')
|
|
85
|
+
.split('//')
|
|
86
|
+
.join('/');
|
|
87
|
+
let MiddlewareFunction = M;
|
|
88
|
+
let middlewareParams = {};
|
|
89
|
+
if (Array.isArray(M)) {
|
|
90
|
+
[MiddlewareFunction, middlewareParams] = M;
|
|
91
|
+
}
|
|
92
|
+
middlewaresInfo.push({
|
|
93
|
+
name: MiddlewareFunction.name,
|
|
94
|
+
method,
|
|
95
|
+
path: realPath,
|
|
96
|
+
fullPath,
|
|
97
|
+
params: middlewareParams,
|
|
98
|
+
MiddlewareFunction,
|
|
99
|
+
});
|
|
85
100
|
}
|
|
86
|
-
middlewaresInfo.push({
|
|
87
|
-
name: MiddlewareFunction.name,
|
|
88
|
-
method: method.toUpperCase(),
|
|
89
|
-
path: realPath,
|
|
90
|
-
fullPath,
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
this.router[method](
|
|
94
|
-
realPath,
|
|
95
|
-
new MiddlewareFunction(this.app, middlewareParams).getMiddleware(),
|
|
96
|
-
);
|
|
97
101
|
}
|
|
98
|
-
|
|
102
|
+
return middlewaresInfo;
|
|
103
|
+
};
|
|
99
104
|
|
|
105
|
+
const routeMiddlewaresReg = parseMiddlewares(routeMiddlewares);
|
|
106
|
+
const middlewaresInfo = parseMiddlewares(this.constructor.middleware);
|
|
100
107
|
|
|
108
|
+
const routesInfo = [];
|
|
109
|
+
let routeObjectClone = {};
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Register controller middleware
|
|
113
|
+
*/
|
|
114
|
+
for (const middleware of middlewaresInfo) {
|
|
115
|
+
this.router[middleware.method](
|
|
116
|
+
middleware.path,
|
|
117
|
+
new middleware.MiddlewareFunction(
|
|
118
|
+
this.app,
|
|
119
|
+
middleware.params,
|
|
120
|
+
).getMiddleware(),
|
|
121
|
+
);
|
|
122
|
+
}
|
|
101
123
|
|
|
124
|
+
/**
|
|
125
|
+
* Register routes itself
|
|
126
|
+
*/
|
|
102
127
|
for (const verb in routes) {
|
|
103
128
|
if (typeof this.router[verb] !== 'function') {
|
|
104
129
|
this.logger.error(
|
|
@@ -108,22 +133,18 @@ class AbstractController extends Base {
|
|
|
108
133
|
continue;
|
|
109
134
|
}
|
|
110
135
|
for (const path in routes[verb]) {
|
|
136
|
+
const routeAdditionalMiddlewares = routeMiddlewaresReg.filter(
|
|
137
|
+
(middleware) => middleware.path === path,
|
|
138
|
+
);
|
|
111
139
|
let routeObject = routes[verb][path];
|
|
112
|
-
routeObjectClone =
|
|
140
|
+
routeObjectClone = merge({}, routeObject);
|
|
113
141
|
if (Object.prototype.toString.call(routeObject) !== '[object Object]') {
|
|
114
142
|
routeObject = {
|
|
115
143
|
handler: routeObject,
|
|
116
144
|
request: null,
|
|
117
|
-
middleware: null
|
|
145
|
+
middleware: null,
|
|
118
146
|
};
|
|
119
147
|
|
|
120
|
-
if (typeof routeObject.handler === 'string') {
|
|
121
|
-
routeObject.handler = this[routeObject];
|
|
122
|
-
this.logger.warn(
|
|
123
|
-
'Using string as a controller callback deprecated. Please use function instead',
|
|
124
|
-
);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
148
|
if (typeof routeObject.handler !== 'function') {
|
|
128
149
|
this.logger.error(
|
|
129
150
|
`Can't resolve function '${
|
|
@@ -156,211 +177,177 @@ class AbstractController extends Base {
|
|
|
156
177
|
// `Controller '${this.getConstructorName()}' register function '${fnName}' for method '${verb}' and path '${path}' Full path '${fullPath}'`,
|
|
157
178
|
// );
|
|
158
179
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
this.
|
|
166
|
-
|
|
180
|
+
let additionalMiddlewares;
|
|
181
|
+
|
|
182
|
+
if (routeAdditionalMiddlewares.length > 0) {
|
|
183
|
+
additionalMiddlewares = Array.from(
|
|
184
|
+
routeAdditionalMiddlewares,
|
|
185
|
+
({ MiddlewareFunction, params }) =>
|
|
186
|
+
new MiddlewareFunction(this.app, params).getMiddleware(),
|
|
187
|
+
);
|
|
188
|
+
}
|
|
167
189
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
190
|
+
this.router[verb](
|
|
191
|
+
path,
|
|
192
|
+
additionalMiddlewares || [],
|
|
193
|
+
async (req, res, next) => {
|
|
194
|
+
if (routeObject.request) {
|
|
195
|
+
if (typeof routeObject.request.validate !== 'function') {
|
|
196
|
+
this.logger.error('request.validate should be a function');
|
|
197
|
+
}
|
|
198
|
+
if (typeof routeObject.request.cast !== 'function') {
|
|
199
|
+
this.logger.error('request.cast should be a function');
|
|
200
|
+
}
|
|
201
|
+
const bodyAndQuery = merge(req.query, req.body);
|
|
202
|
+
|
|
203
|
+
try {
|
|
204
|
+
await routeObject.request.validate(bodyAndQuery);
|
|
205
|
+
} catch (e) {
|
|
206
|
+
let { errors } = e;
|
|
207
|
+
// translate it
|
|
208
|
+
if (req.i18n && errors) {
|
|
209
|
+
errors = errors.map((err) => req.i18n.t(err));
|
|
210
|
+
}
|
|
211
|
+
this.logger.error(
|
|
212
|
+
`Request validation failed with message: ${e.message}. errors: ${errors}`,
|
|
213
|
+
);
|
|
214
|
+
|
|
215
|
+
return res.status(400).json({
|
|
216
|
+
errors: {
|
|
217
|
+
[e.path]: errors,
|
|
218
|
+
},
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
req.appInfo.request = routeObject.request.cast(bodyAndQuery, {
|
|
222
|
+
stripUnknown: true,
|
|
179
223
|
});
|
|
180
224
|
}
|
|
181
|
-
req.
|
|
182
|
-
|
|
225
|
+
req.body = new Proxy(req.body, {
|
|
226
|
+
get: (target, prop) => {
|
|
227
|
+
this.logger.warn(
|
|
228
|
+
'Please not use "req.body" directly. Implement "request" and use "req.appInfo.request" ',
|
|
229
|
+
);
|
|
230
|
+
return target[prop];
|
|
231
|
+
},
|
|
183
232
|
});
|
|
184
|
-
}
|
|
185
|
-
req.body = new Proxy(req.body, {
|
|
186
|
-
get: (target, prop) => {
|
|
187
|
-
this.logger.warn(
|
|
188
|
-
'Please not use "req.body" directly. Implement "request" and use "req.appInfo.request" ',
|
|
189
|
-
);
|
|
190
|
-
return target[prop];
|
|
191
|
-
},
|
|
192
|
-
});
|
|
193
233
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
234
|
+
if (routeObject.handler.constructor.name !== 'AsyncFunction') {
|
|
235
|
+
const error =
|
|
236
|
+
"Handler should be AsyncFunction. Perhabs you miss 'async' of function declaration?";
|
|
237
|
+
this.logger.error(error);
|
|
238
|
+
return res.status(500).json({
|
|
239
|
+
message:
|
|
240
|
+
'Platform error. Please check later or contact support',
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
return routeObject.handler.call(this, req, res, next).catch((e) => {
|
|
244
|
+
this.logger.error(e.message);
|
|
245
|
+
console.error(e);
|
|
246
|
+
return res.status(500).json({
|
|
247
|
+
message:
|
|
248
|
+
'Platform error. Please check later or contact support',
|
|
249
|
+
});
|
|
209
250
|
});
|
|
210
|
-
}
|
|
211
|
-
|
|
251
|
+
},
|
|
252
|
+
);
|
|
212
253
|
}
|
|
213
254
|
}
|
|
214
255
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
256
|
+
/**
|
|
257
|
+
* Generate text info
|
|
258
|
+
*/
|
|
259
|
+
const text = ['', `Controller '${this.getConstructorName()}' registered.`];
|
|
260
|
+
|
|
261
|
+
const reports = {
|
|
262
|
+
'Middlewares:': middlewaresInfo,
|
|
263
|
+
'Route middlewares:': routeMiddlewaresReg,
|
|
264
|
+
'Callbacks:': routesInfo,
|
|
265
|
+
};
|
|
266
|
+
for (const key in reports) {
|
|
267
|
+
text.push(`${key}`);
|
|
268
|
+
for (const item of reports[key]) {
|
|
269
|
+
text.push(
|
|
270
|
+
`Path:'${item.path}'. Full path: '${
|
|
271
|
+
item.fullPath
|
|
272
|
+
}'. Method: '${item.method.toUpperCase()}'. Function: '${item.name}'`,
|
|
273
|
+
);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
227
276
|
|
|
228
|
-
routesInfo.forEach((m) => {
|
|
229
|
-
text.push(
|
|
230
|
-
`Path:'${m.path}'. Full path: '${m.fullPath}'. Method: '${m.method}'. Callback: '${m.name}'`,
|
|
231
|
-
);
|
|
232
|
-
});
|
|
233
277
|
text.push(`Time: ${Date.now() - time} ms`);
|
|
234
278
|
|
|
235
279
|
this.logger.verbose(text.join('\n'));
|
|
236
|
-
if (!this.app.httpServer) {
|
|
237
280
|
|
|
238
|
-
|
|
281
|
+
/**
|
|
282
|
+
* Generate documentation
|
|
283
|
+
*/
|
|
284
|
+
if (!this.app.httpServer) {
|
|
285
|
+
const fields = [];
|
|
239
286
|
if (routeObjectClone.request) {
|
|
240
|
-
const reqFields = routeObjectClone.request.fields
|
|
287
|
+
const reqFields = routeObjectClone.request.fields;
|
|
241
288
|
const entries = Object.entries(reqFields);
|
|
242
289
|
entries.forEach(([key, value]) => {
|
|
243
|
-
const field = {}
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
field.isRequired = value.exclusiveTests.required
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
field.fields = []
|
|
290
|
+
const field = {};
|
|
291
|
+
field.name = key;
|
|
292
|
+
field.type = value.type;
|
|
293
|
+
if (value.exclusiveTests) {
|
|
294
|
+
field.isRequired = value.exclusiveTests.required;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
if (value.fields) {
|
|
298
|
+
field.fields = [];
|
|
299
|
+
// eslint-disable-next-line no-shadow
|
|
252
300
|
const entries = Object.entries(value.fields);
|
|
301
|
+
// eslint-disable-next-line no-shadow
|
|
253
302
|
entries.forEach(([key, value]) => {
|
|
254
303
|
field.fields.push({
|
|
255
304
|
name: key,
|
|
256
|
-
type: value.type
|
|
257
|
-
})
|
|
258
|
-
}
|
|
259
|
-
)
|
|
305
|
+
type: value.type,
|
|
306
|
+
});
|
|
307
|
+
});
|
|
260
308
|
}
|
|
261
|
-
fields.push(field)
|
|
262
|
-
})
|
|
309
|
+
fields.push(field);
|
|
310
|
+
});
|
|
263
311
|
}
|
|
264
312
|
|
|
265
313
|
this.app.documentation.push({
|
|
266
314
|
contollerName: this.getConstructorName(),
|
|
267
|
-
routesInfo: routesInfo.map(
|
|
315
|
+
routesInfo: routesInfo.map((route) => ({
|
|
268
316
|
[route.fullPath]: {
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
317
|
+
method: route.method,
|
|
318
|
+
name: route.name,
|
|
319
|
+
fields,
|
|
320
|
+
routeMiddlewares: routeMiddlewaresReg
|
|
321
|
+
// eslint-disable-next-line consistent-return
|
|
322
|
+
.map((middleware) => {
|
|
323
|
+
if (
|
|
324
|
+
route.fullPath.toUpperCase() ===
|
|
325
|
+
middleware.fullPath.toUpperCase()
|
|
326
|
+
) {
|
|
327
|
+
return {
|
|
328
|
+
name: middleware.name,
|
|
329
|
+
params: middleware.params,
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
})
|
|
333
|
+
.filter(Boolean),
|
|
334
|
+
controllerMiddlewares: [
|
|
335
|
+
...new Set(
|
|
336
|
+
middlewaresInfo
|
|
337
|
+
.filter(
|
|
338
|
+
(middleware) =>
|
|
339
|
+
middleware.fullPath.toUpperCase() ===
|
|
340
|
+
route.fullPath.toUpperCase(),
|
|
341
|
+
)
|
|
342
|
+
.map(({ name, params }) => ({ name, params })),
|
|
343
|
+
),
|
|
344
|
+
],
|
|
345
|
+
},
|
|
274
346
|
})),
|
|
275
|
-
})
|
|
276
|
-
}
|
|
277
|
-
else {
|
|
347
|
+
});
|
|
348
|
+
} else {
|
|
278
349
|
this.app.httpServer.express.use(expressPath, this.router);
|
|
279
350
|
}
|
|
280
|
-
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
/**
|
|
286
|
-
* Internal validation method for params validation.
|
|
287
|
-
* You can pass own function or use validator.js functions
|
|
288
|
-
* From own function you can return a bool then will be treater as rule pass or not. At that case error message will be used from default error. But you also can provide error as output. Where only one arrya element will be an error message
|
|
289
|
-
* @param {object} obj object with params to validate
|
|
290
|
-
* @param {object} rules validation rules. rule name should match parameter name
|
|
291
|
-
* @deprecated
|
|
292
|
-
* @example
|
|
293
|
-
* // We can pass own function
|
|
294
|
-
* validate({
|
|
295
|
-
* someKey:10
|
|
296
|
-
* },{
|
|
297
|
-
* 'someKey':[
|
|
298
|
-
* (val)=>val>10,
|
|
299
|
-
* 'Error message'
|
|
300
|
-
* ]
|
|
301
|
-
* })
|
|
302
|
-
* @example
|
|
303
|
-
* // We can pass function to validator.js
|
|
304
|
-
* validate({
|
|
305
|
-
* someKey: 'test_at_test.com'
|
|
306
|
-
* },{
|
|
307
|
-
* 'someKey':[
|
|
308
|
-
* 'isEmail',
|
|
309
|
-
* 'Please provide valid email'
|
|
310
|
-
* ]
|
|
311
|
-
* })
|
|
312
|
-
* @example
|
|
313
|
-
* // We can pass function to validator.js with params
|
|
314
|
-
* validate({
|
|
315
|
-
* someKey: 'test_at_test.com'
|
|
316
|
-
* },{
|
|
317
|
-
* 'someKey':[
|
|
318
|
-
* ['isEmail',{'require_tld':false}],
|
|
319
|
-
* 'Please provide valid email'
|
|
320
|
-
* ]
|
|
321
|
-
* })
|
|
322
|
-
*/
|
|
323
|
-
validate(obj, rules) {
|
|
324
|
-
this.logger.warn(
|
|
325
|
-
'Validate deprecated. Please do not use it. Will be revomed it future release',
|
|
326
|
-
);
|
|
327
|
-
const errors = {};
|
|
328
|
-
for (const name in rules) {
|
|
329
|
-
let validationResult = false;
|
|
330
|
-
if (typeof rules[name][0] === 'function') {
|
|
331
|
-
validationResult = rules[name][0](obj[name]);
|
|
332
|
-
if (
|
|
333
|
-
Object.prototype.toString.call(validationResult) === '[object Array]'
|
|
334
|
-
) {
|
|
335
|
-
[errors[name]] = validationResult;
|
|
336
|
-
validationResult = false;
|
|
337
|
-
}
|
|
338
|
-
} else if (typeof validator[rules[name][0]] === 'function') {
|
|
339
|
-
// use from validator then
|
|
340
|
-
validationResult = validator[rules[name][0]](obj[name]);
|
|
341
|
-
} else if (
|
|
342
|
-
Object.prototype.toString.call(rules[name][0]) === '[object Array]' &&
|
|
343
|
-
typeof validator[rules[name][0][0]] === 'function'
|
|
344
|
-
) {
|
|
345
|
-
// use from validator then
|
|
346
|
-
validationResult = validator[rules[name][0][0]](
|
|
347
|
-
`${obj[name]}`,
|
|
348
|
-
rules[name][0][1],
|
|
349
|
-
);
|
|
350
|
-
} else {
|
|
351
|
-
this.logger.warn(
|
|
352
|
-
`No rule found for ${name}. Swith to existing checking`,
|
|
353
|
-
);
|
|
354
|
-
validationResult = !!obj[name];
|
|
355
|
-
}
|
|
356
|
-
if (!validationResult && !errors[name]) {
|
|
357
|
-
[, errors[name]] = rules[name];
|
|
358
|
-
}
|
|
359
|
-
}
|
|
360
|
-
if (Object.entries(errors).length === 0 && errors.constructor === Object) {
|
|
361
|
-
return false;
|
|
362
|
-
}
|
|
363
|
-
return errors;
|
|
364
351
|
}
|
|
365
352
|
|
|
366
353
|
/**
|
|
@@ -370,24 +357,14 @@ class AbstractController extends Base {
|
|
|
370
357
|
* Be default path apply to ANY' method, but you can preattach 'METHOD' into patch to scope patch to this METHOD
|
|
371
358
|
* @example
|
|
372
359
|
* return new Map([
|
|
373
|
-
* ['/*', [
|
|
360
|
+
* ['/*', [GetUserByToken]] // for any method for this controller
|
|
374
361
|
* ['POST/', [Auth]] // for POST method
|
|
375
362
|
* ['/superSecretMethod', [OnlySuperSecretUsers]] // route with ANY method
|
|
376
363
|
* ['PUT/superSecretMathod', [OnlySuperSecretAdmin]] // route with PUT method
|
|
377
364
|
* ]);
|
|
378
365
|
*/
|
|
379
366
|
static get middleware() {
|
|
380
|
-
return new Map([['/*', [
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
/**
|
|
384
|
-
* Part of abstract contorller.
|
|
385
|
-
* When you do not need controller name to append in route then return false here.
|
|
386
|
-
* Useful for home(root) controllers
|
|
387
|
-
* @deprecated please use getExpressPath instead
|
|
388
|
-
*/
|
|
389
|
-
static get isUseControllerNameForRouting() {
|
|
390
|
-
return true;
|
|
367
|
+
return new Map([['/*', [GetUserByToken, Auth]]]);
|
|
391
368
|
}
|
|
392
369
|
|
|
393
370
|
/**
|
|
@@ -406,12 +383,6 @@ class AbstractController extends Base {
|
|
|
406
383
|
* Get express path with inheritance of path
|
|
407
384
|
*/
|
|
408
385
|
getExpressPath() {
|
|
409
|
-
if (!this.constructor.isUseControllerNameForRouting) {
|
|
410
|
-
console.warn(
|
|
411
|
-
'isUseControllerNameForRouting is DEPRECATED. Please use getExpressPath instead',
|
|
412
|
-
);
|
|
413
|
-
return '/';
|
|
414
|
-
}
|
|
415
386
|
return `/${this.getConstructorName().toLowerCase()}`.replace('//', '/');
|
|
416
387
|
}
|
|
417
388
|
|
package/modules/AbstractModel.js
CHANGED
|
@@ -20,28 +20,21 @@ class AbstractModel extends Base {
|
|
|
20
20
|
);
|
|
21
21
|
if (!mongoose.connection.readyState) {
|
|
22
22
|
// do not connect on test
|
|
23
|
-
mongoose
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
});
|
|
39
|
-
callback();
|
|
40
|
-
},
|
|
41
|
-
(error) => {
|
|
42
|
-
this.logger.error("Can't install mongodb connection", error);
|
|
43
|
-
},
|
|
44
|
-
);
|
|
23
|
+
mongoose.connect(this.app.getConfig('mongo').connectionString, {}).then(
|
|
24
|
+
() => {
|
|
25
|
+
this.logger.info('Mongo connection success');
|
|
26
|
+
this.app.events.on('die', async () => {
|
|
27
|
+
for (const c of mongoose.connections) {
|
|
28
|
+
c.close(true);
|
|
29
|
+
}
|
|
30
|
+
// await mongoose.disconnect(); // TODO it have problems with replica-set
|
|
31
|
+
});
|
|
32
|
+
callback();
|
|
33
|
+
},
|
|
34
|
+
(error) => {
|
|
35
|
+
this.logger.error("Can't install mongodb connection", error);
|
|
36
|
+
},
|
|
37
|
+
);
|
|
45
38
|
} else {
|
|
46
39
|
callback();
|
|
47
40
|
}
|
package/modules/Base.d.ts
CHANGED
|
@@ -23,11 +23,6 @@ declare class Base {
|
|
|
23
23
|
*/
|
|
24
24
|
getLogger(label: string): winston.Logger;
|
|
25
25
|
|
|
26
|
-
loadFilesWithInheritance(
|
|
27
|
-
internalFolder: string,
|
|
28
|
-
externalFolder: string,
|
|
29
|
-
): Promise<string[]>;
|
|
30
|
-
|
|
31
26
|
getFilesPathWithInheritance(
|
|
32
27
|
internalFolder: string,
|
|
33
28
|
externalFolder: string,
|