@adaptivestone/framework 2.17.0 → 3.0.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/CHANGELOG.md +55 -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 +236 -267
- package/modules/AbstractModel.js +15 -22
- package/modules/Base.d.ts +0 -5
- package/modules/Base.js +0 -9
- package/package.json +8 -14
- 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 +4 -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,175 @@ 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) {
|
|
209
|
+
errors = e.errors.map((err) => req.i18n.t(err));
|
|
210
|
+
}
|
|
211
|
+
this.logger.error(`Request validation failed: ${errors}`);
|
|
212
|
+
|
|
213
|
+
return res.status(400).json({
|
|
214
|
+
errors: {
|
|
215
|
+
[e.path]: errors,
|
|
216
|
+
},
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
req.appInfo.request = routeObject.request.cast(bodyAndQuery, {
|
|
220
|
+
stripUnknown: true,
|
|
179
221
|
});
|
|
180
222
|
}
|
|
181
|
-
req.
|
|
182
|
-
|
|
223
|
+
req.body = new Proxy(req.body, {
|
|
224
|
+
get: (target, prop) => {
|
|
225
|
+
this.logger.warn(
|
|
226
|
+
'Please not use "req.body" directly. Implement "request" and use "req.appInfo.request" ',
|
|
227
|
+
);
|
|
228
|
+
return target[prop];
|
|
229
|
+
},
|
|
183
230
|
});
|
|
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
231
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
232
|
+
if (routeObject.handler.constructor.name !== 'AsyncFunction') {
|
|
233
|
+
const error =
|
|
234
|
+
"Handler should be AsyncFunction. Perhabs you miss 'async' of function declaration?";
|
|
235
|
+
this.logger.error(error);
|
|
236
|
+
return res.status(500).json({
|
|
237
|
+
message:
|
|
238
|
+
'Platform error. Please check later or contact support',
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
return routeObject.handler.call(this, req, res, next).catch((e) => {
|
|
242
|
+
this.logger.error(e.message);
|
|
243
|
+
console.error(e);
|
|
244
|
+
return res.status(500).json({
|
|
245
|
+
message:
|
|
246
|
+
'Platform error. Please check later or contact support',
|
|
247
|
+
});
|
|
209
248
|
});
|
|
210
|
-
}
|
|
211
|
-
|
|
249
|
+
},
|
|
250
|
+
);
|
|
212
251
|
}
|
|
213
252
|
}
|
|
214
253
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
254
|
+
/**
|
|
255
|
+
* Generate text info
|
|
256
|
+
*/
|
|
257
|
+
const text = ['', `Controller '${this.getConstructorName()}' registered.`];
|
|
258
|
+
|
|
259
|
+
const reports = {
|
|
260
|
+
'Middlewares:': middlewaresInfo,
|
|
261
|
+
'Route middlewares:': routeMiddlewaresReg,
|
|
262
|
+
'Callbacks:': routesInfo,
|
|
263
|
+
};
|
|
264
|
+
for (const key in reports) {
|
|
265
|
+
text.push(`${key}`);
|
|
266
|
+
for (const item of reports[key]) {
|
|
267
|
+
text.push(
|
|
268
|
+
`Path:'${item.path}'. Full path: '${
|
|
269
|
+
item.fullPath
|
|
270
|
+
}'. Method: '${item.method.toUpperCase()}'. Function: '${item.name}'`,
|
|
271
|
+
);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
227
274
|
|
|
228
|
-
routesInfo.forEach((m) => {
|
|
229
|
-
text.push(
|
|
230
|
-
`Path:'${m.path}'. Full path: '${m.fullPath}'. Method: '${m.method}'. Callback: '${m.name}'`,
|
|
231
|
-
);
|
|
232
|
-
});
|
|
233
275
|
text.push(`Time: ${Date.now() - time} ms`);
|
|
234
276
|
|
|
235
277
|
this.logger.verbose(text.join('\n'));
|
|
236
|
-
if (!this.app.httpServer) {
|
|
237
278
|
|
|
238
|
-
|
|
279
|
+
/**
|
|
280
|
+
* Generate documentation
|
|
281
|
+
*/
|
|
282
|
+
if (!this.app.httpServer) {
|
|
283
|
+
const fields = [];
|
|
239
284
|
if (routeObjectClone.request) {
|
|
240
|
-
const reqFields = routeObjectClone.request.fields
|
|
285
|
+
const reqFields = routeObjectClone.request.fields;
|
|
241
286
|
const entries = Object.entries(reqFields);
|
|
242
287
|
entries.forEach(([key, value]) => {
|
|
243
|
-
const field = {}
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
field.isRequired = value.exclusiveTests.required
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
field.fields = []
|
|
288
|
+
const field = {};
|
|
289
|
+
field.name = key;
|
|
290
|
+
field.type = value.type;
|
|
291
|
+
if (value.exclusiveTests) {
|
|
292
|
+
field.isRequired = value.exclusiveTests.required;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
if (value.fields) {
|
|
296
|
+
field.fields = [];
|
|
297
|
+
// eslint-disable-next-line no-shadow
|
|
252
298
|
const entries = Object.entries(value.fields);
|
|
299
|
+
// eslint-disable-next-line no-shadow
|
|
253
300
|
entries.forEach(([key, value]) => {
|
|
254
301
|
field.fields.push({
|
|
255
302
|
name: key,
|
|
256
|
-
type: value.type
|
|
257
|
-
})
|
|
258
|
-
}
|
|
259
|
-
)
|
|
303
|
+
type: value.type,
|
|
304
|
+
});
|
|
305
|
+
});
|
|
260
306
|
}
|
|
261
|
-
fields.push(field)
|
|
262
|
-
})
|
|
307
|
+
fields.push(field);
|
|
308
|
+
});
|
|
263
309
|
}
|
|
264
310
|
|
|
265
311
|
this.app.documentation.push({
|
|
266
312
|
contollerName: this.getConstructorName(),
|
|
267
|
-
routesInfo: routesInfo.map(
|
|
313
|
+
routesInfo: routesInfo.map((route) => ({
|
|
268
314
|
[route.fullPath]: {
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
315
|
+
method: route.method,
|
|
316
|
+
name: route.name,
|
|
317
|
+
fields,
|
|
318
|
+
routeMiddlewares: routeMiddlewaresReg
|
|
319
|
+
// eslint-disable-next-line consistent-return
|
|
320
|
+
.map((middleware) => {
|
|
321
|
+
if (
|
|
322
|
+
route.fullPath.toUpperCase() ===
|
|
323
|
+
middleware.fullPath.toUpperCase()
|
|
324
|
+
) {
|
|
325
|
+
return {
|
|
326
|
+
name: middleware.name,
|
|
327
|
+
params: middleware.params,
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
})
|
|
331
|
+
.filter(Boolean),
|
|
332
|
+
controllerMiddlewares: [
|
|
333
|
+
...new Set(
|
|
334
|
+
middlewaresInfo
|
|
335
|
+
.filter(
|
|
336
|
+
(middleware) =>
|
|
337
|
+
middleware.fullPath.toUpperCase() ===
|
|
338
|
+
route.fullPath.toUpperCase(),
|
|
339
|
+
)
|
|
340
|
+
.map(({ name, params }) => ({ name, params })),
|
|
341
|
+
),
|
|
342
|
+
],
|
|
343
|
+
},
|
|
274
344
|
})),
|
|
275
|
-
})
|
|
276
|
-
}
|
|
277
|
-
else {
|
|
345
|
+
});
|
|
346
|
+
} else {
|
|
278
347
|
this.app.httpServer.express.use(expressPath, this.router);
|
|
279
348
|
}
|
|
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
349
|
}
|
|
365
350
|
|
|
366
351
|
/**
|
|
@@ -370,24 +355,14 @@ class AbstractController extends Base {
|
|
|
370
355
|
* Be default path apply to ANY' method, but you can preattach 'METHOD' into patch to scope patch to this METHOD
|
|
371
356
|
* @example
|
|
372
357
|
* return new Map([
|
|
373
|
-
* ['/*', [
|
|
358
|
+
* ['/*', [GetUserByToken]] // for any method for this controller
|
|
374
359
|
* ['POST/', [Auth]] // for POST method
|
|
375
360
|
* ['/superSecretMethod', [OnlySuperSecretUsers]] // route with ANY method
|
|
376
361
|
* ['PUT/superSecretMathod', [OnlySuperSecretAdmin]] // route with PUT method
|
|
377
362
|
* ]);
|
|
378
363
|
*/
|
|
379
364
|
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;
|
|
365
|
+
return new Map([['/*', [GetUserByToken, Auth]]]);
|
|
391
366
|
}
|
|
392
367
|
|
|
393
368
|
/**
|
|
@@ -406,12 +381,6 @@ class AbstractController extends Base {
|
|
|
406
381
|
* Get express path with inheritance of path
|
|
407
382
|
*/
|
|
408
383
|
getExpressPath() {
|
|
409
|
-
if (!this.constructor.isUseControllerNameForRouting) {
|
|
410
|
-
console.warn(
|
|
411
|
-
'isUseControllerNameForRouting is DEPRECATED. Please use getExpressPath instead',
|
|
412
|
-
);
|
|
413
|
-
return '/';
|
|
414
|
-
}
|
|
415
384
|
return `/${this.getConstructorName().toLowerCase()}`.replace('//', '/');
|
|
416
385
|
}
|
|
417
386
|
|
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,
|
package/modules/Base.js
CHANGED
|
@@ -95,15 +95,6 @@ class Base {
|
|
|
95
95
|
});
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
-
async loadFilesWithInheritance(internalFolder, externalFolder) {
|
|
99
|
-
this.logger.warn(
|
|
100
|
-
'Method "loadFilesWithInheritance" deprecated. Please use "getFilesPathWithInheritance"',
|
|
101
|
-
);
|
|
102
|
-
return (
|
|
103
|
-
await this.getFilesPathWithInheritance(internalFolder, externalFolder)
|
|
104
|
-
).map((file) => file.path);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
98
|
async getFilesPathWithInheritance(internalFolder, externalFolder) {
|
|
108
99
|
async function rreaddir(dir, allFiles = []) {
|
|
109
100
|
const files = (await fs.readdir(dir)).map((f) => join(dir, f));
|