@adaptivestone/framework 2.16.0 → 3.0.2
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 +71 -0
- package/README.md +2 -0
- package/commands/Documentation.js +14 -0
- 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 +4 -3
- 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 +253 -218
- package/modules/AbstractModel.js +15 -22
- package/modules/Base.d.ts +0 -5
- package/modules/Base.js +0 -9
- package/package.json +10 -16
- 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,15 +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 merge = require('deepmerge');
|
|
5
6
|
|
|
6
7
|
const Base = require('./Base');
|
|
7
|
-
const PrepareAppInfo = require('../services/http/middleware/PrepareAppInfo');
|
|
8
8
|
const GetUserByToken = require('../services/http/middleware/GetUserByToken');
|
|
9
9
|
const Auth = require('../services/http/middleware/Auth');
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
|
-
* Abstract controller. You
|
|
12
|
+
* Abstract controller. You should extend any controller from them.
|
|
13
13
|
* Place you cintroller into controller folder and it be inited in auto way.
|
|
14
14
|
* By default name of route will be controller name not file name. But please name it in same ways.
|
|
15
15
|
* You can overwrite base controllers byt creating controllers with tha same file name (yes file name, not class name)
|
|
@@ -22,66 +22,108 @@ class AbstractController extends Base {
|
|
|
22
22
|
this.prefix = prefix;
|
|
23
23
|
this.router = express.Router();
|
|
24
24
|
const { routes } = this;
|
|
25
|
-
|
|
26
25
|
const expressPath = this.getExpressPath();
|
|
27
26
|
|
|
28
|
-
|
|
27
|
+
/**
|
|
28
|
+
* Grab route middleware onlo one Map
|
|
29
|
+
*/
|
|
30
|
+
const routeMiddlewares = new Map();
|
|
31
|
+
Object.entries(routes).forEach(([method, methodRoutes]) => {
|
|
32
|
+
Object.entries(methodRoutes).forEach(([route, routeParam]) => {
|
|
33
|
+
if (routeParam?.middleware) {
|
|
34
|
+
const fullRoute = method.toUpperCase() + route;
|
|
29
35
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
if (typeof realPath !== 'string') {
|
|
39
|
-
this.logger.error(`Path not a string ${realPath}. Please check it`);
|
|
40
|
-
// eslint-disable-next-line no-continue
|
|
41
|
-
continue;
|
|
36
|
+
if (!routeMiddlewares.has(fullRoute)) {
|
|
37
|
+
routeMiddlewares.set(fullRoute, []);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
routeMiddlewares.set(fullRoute, [
|
|
41
|
+
...routeMiddlewares.get(fullRoute),
|
|
42
|
+
...routeParam.middleware,
|
|
43
|
+
]);
|
|
42
44
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
|
|
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];
|
|
57
|
+
}
|
|
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`);
|
|
47
63
|
// eslint-disable-next-line no-continue
|
|
48
64
|
continue;
|
|
49
65
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
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
|
+
});
|
|
68
100
|
}
|
|
69
|
-
middlewaresInfo.push({
|
|
70
|
-
name: M.name,
|
|
71
|
-
method: method.toUpperCase(),
|
|
72
|
-
path: realPath,
|
|
73
|
-
fullPath,
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
this.router[method](
|
|
77
|
-
realPath,
|
|
78
|
-
new MiddlewareFunction(this.app, middlewareParams).getMiddleware(),
|
|
79
|
-
);
|
|
80
101
|
}
|
|
81
|
-
|
|
102
|
+
return middlewaresInfo;
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
const routeMiddlewaresReg = parseMiddlewares(routeMiddlewares);
|
|
106
|
+
const middlewaresInfo = parseMiddlewares(this.constructor.middleware);
|
|
82
107
|
|
|
83
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
|
+
}
|
|
84
123
|
|
|
124
|
+
/**
|
|
125
|
+
* Register routes itself
|
|
126
|
+
*/
|
|
85
127
|
for (const verb in routes) {
|
|
86
128
|
if (typeof this.router[verb] !== 'function') {
|
|
87
129
|
this.logger.error(
|
|
@@ -91,20 +133,18 @@ class AbstractController extends Base {
|
|
|
91
133
|
continue;
|
|
92
134
|
}
|
|
93
135
|
for (const path in routes[verb]) {
|
|
136
|
+
const routeAdditionalMiddlewares = routeMiddlewaresReg.filter(
|
|
137
|
+
(middleware) => middleware.path === path,
|
|
138
|
+
);
|
|
94
139
|
let routeObject = routes[verb][path];
|
|
140
|
+
routeObjectClone = merge({}, routeObject);
|
|
95
141
|
if (Object.prototype.toString.call(routeObject) !== '[object Object]') {
|
|
96
142
|
routeObject = {
|
|
97
143
|
handler: routeObject,
|
|
98
144
|
request: null,
|
|
145
|
+
middleware: null,
|
|
99
146
|
};
|
|
100
147
|
|
|
101
|
-
if (typeof routeObject.handler === 'string') {
|
|
102
|
-
routeObject.handler = this[routeObject];
|
|
103
|
-
this.logger.warn(
|
|
104
|
-
'Using string as a controller callback deprecated. Please use function instead',
|
|
105
|
-
);
|
|
106
|
-
}
|
|
107
|
-
|
|
108
148
|
if (typeof routeObject.handler !== 'function') {
|
|
109
149
|
this.logger.error(
|
|
110
150
|
`Can't resolve function '${
|
|
@@ -137,166 +177,177 @@ class AbstractController extends Base {
|
|
|
137
177
|
// `Controller '${this.getConstructorName()}' register function '${fnName}' for method '${verb}' and path '${path}' Full path '${fullPath}'`,
|
|
138
178
|
// );
|
|
139
179
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
this.
|
|
147
|
-
|
|
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
|
+
}
|
|
189
|
+
|
|
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
|
+
);
|
|
148
214
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
errors: {
|
|
158
|
-
[e.path]: errors,
|
|
159
|
-
},
|
|
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,
|
|
160
223
|
});
|
|
161
224
|
}
|
|
162
|
-
req.
|
|
163
|
-
|
|
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
|
+
},
|
|
164
232
|
});
|
|
165
|
-
}
|
|
166
|
-
req.body = new Proxy(req.body, {
|
|
167
|
-
get: (target, prop) => {
|
|
168
|
-
this.logger.warn(
|
|
169
|
-
'Please not use "req.body" directly. Implement "request" and use "req.appInfo.request" ',
|
|
170
|
-
);
|
|
171
|
-
return target[prop];
|
|
172
|
-
},
|
|
173
|
-
});
|
|
174
233
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
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
|
+
});
|
|
190
250
|
});
|
|
191
|
-
}
|
|
192
|
-
|
|
251
|
+
},
|
|
252
|
+
);
|
|
193
253
|
}
|
|
194
254
|
}
|
|
195
255
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
];
|
|
256
|
+
/**
|
|
257
|
+
* Generate text info
|
|
258
|
+
*/
|
|
259
|
+
const text = ['', `Controller '${this.getConstructorName()}' registered.`];
|
|
201
260
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
}
|
|
207
|
-
|
|
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
|
+
}
|
|
208
276
|
|
|
209
|
-
routesInfo.forEach((m) => {
|
|
210
|
-
text.push(
|
|
211
|
-
`Path:'${m.path}'. Full path: '${m.fullPath}'. Method: '${m.method}'. Callback: '${m.name}'`,
|
|
212
|
-
);
|
|
213
|
-
});
|
|
214
277
|
text.push(`Time: ${Date.now() - time} ms`);
|
|
215
278
|
|
|
216
279
|
this.logger.verbose(text.join('\n'));
|
|
217
280
|
|
|
218
|
-
|
|
219
|
-
|
|
281
|
+
/**
|
|
282
|
+
* Generate documentation
|
|
283
|
+
*/
|
|
284
|
+
if (!this.app.httpServer) {
|
|
285
|
+
const fields = [];
|
|
286
|
+
if (routeObjectClone.request) {
|
|
287
|
+
const reqFields = routeObjectClone.request.fields;
|
|
288
|
+
const entries = Object.entries(reqFields);
|
|
289
|
+
entries.forEach(([key, value]) => {
|
|
290
|
+
const field = {};
|
|
291
|
+
field.name = key;
|
|
292
|
+
field.type = value.type;
|
|
293
|
+
if (value.exclusiveTests) {
|
|
294
|
+
field.isRequired = value.exclusiveTests.required;
|
|
295
|
+
}
|
|
220
296
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
* 'Error message'
|
|
236
|
-
* ]
|
|
237
|
-
* })
|
|
238
|
-
* @example
|
|
239
|
-
* // We can pass function to validator.js
|
|
240
|
-
* validate({
|
|
241
|
-
* someKey: 'test_at_test.com'
|
|
242
|
-
* },{
|
|
243
|
-
* 'someKey':[
|
|
244
|
-
* 'isEmail',
|
|
245
|
-
* 'Please provide valid email'
|
|
246
|
-
* ]
|
|
247
|
-
* })
|
|
248
|
-
* @example
|
|
249
|
-
* // We can pass function to validator.js with params
|
|
250
|
-
* validate({
|
|
251
|
-
* someKey: 'test_at_test.com'
|
|
252
|
-
* },{
|
|
253
|
-
* 'someKey':[
|
|
254
|
-
* ['isEmail',{'require_tld':false}],
|
|
255
|
-
* 'Please provide valid email'
|
|
256
|
-
* ]
|
|
257
|
-
* })
|
|
258
|
-
*/
|
|
259
|
-
validate(obj, rules) {
|
|
260
|
-
this.logger.warn(
|
|
261
|
-
'Validate deprecated. Please do not use it. Will be revomed it future release',
|
|
262
|
-
);
|
|
263
|
-
const errors = {};
|
|
264
|
-
for (const name in rules) {
|
|
265
|
-
let validationResult = false;
|
|
266
|
-
if (typeof rules[name][0] === 'function') {
|
|
267
|
-
validationResult = rules[name][0](obj[name]);
|
|
268
|
-
if (
|
|
269
|
-
Object.prototype.toString.call(validationResult) === '[object Array]'
|
|
270
|
-
) {
|
|
271
|
-
[errors[name]] = validationResult;
|
|
272
|
-
validationResult = false;
|
|
273
|
-
}
|
|
274
|
-
} else if (typeof validator[rules[name][0]] === 'function') {
|
|
275
|
-
// use from validator then
|
|
276
|
-
validationResult = validator[rules[name][0]](obj[name]);
|
|
277
|
-
} else if (
|
|
278
|
-
Object.prototype.toString.call(rules[name][0]) === '[object Array]' &&
|
|
279
|
-
typeof validator[rules[name][0][0]] === 'function'
|
|
280
|
-
) {
|
|
281
|
-
// use from validator then
|
|
282
|
-
validationResult = validator[rules[name][0][0]](
|
|
283
|
-
`${obj[name]}`,
|
|
284
|
-
rules[name][0][1],
|
|
285
|
-
);
|
|
286
|
-
} else {
|
|
287
|
-
this.logger.warn(
|
|
288
|
-
`No rule found for ${name}. Swith to existing checking`,
|
|
289
|
-
);
|
|
290
|
-
validationResult = !!obj[name];
|
|
291
|
-
}
|
|
292
|
-
if (!validationResult && !errors[name]) {
|
|
293
|
-
[, errors[name]] = rules[name];
|
|
297
|
+
if (value.fields) {
|
|
298
|
+
field.fields = [];
|
|
299
|
+
// eslint-disable-next-line no-shadow
|
|
300
|
+
const entries = Object.entries(value.fields);
|
|
301
|
+
// eslint-disable-next-line no-shadow
|
|
302
|
+
entries.forEach(([key, value]) => {
|
|
303
|
+
field.fields.push({
|
|
304
|
+
name: key,
|
|
305
|
+
type: value.type,
|
|
306
|
+
});
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
fields.push(field);
|
|
310
|
+
});
|
|
294
311
|
}
|
|
312
|
+
|
|
313
|
+
this.app.documentation.push({
|
|
314
|
+
contollerName: this.getConstructorName(),
|
|
315
|
+
routesInfo: routesInfo.map((route) => ({
|
|
316
|
+
[route.fullPath]: {
|
|
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
|
+
},
|
|
346
|
+
})),
|
|
347
|
+
});
|
|
348
|
+
} else {
|
|
349
|
+
this.app.httpServer.express.use(expressPath, this.router);
|
|
295
350
|
}
|
|
296
|
-
if (Object.entries(errors).length === 0 && errors.constructor === Object) {
|
|
297
|
-
return false;
|
|
298
|
-
}
|
|
299
|
-
return errors;
|
|
300
351
|
}
|
|
301
352
|
|
|
302
353
|
/**
|
|
@@ -306,24 +357,14 @@ class AbstractController extends Base {
|
|
|
306
357
|
* Be default path apply to ANY' method, but you can preattach 'METHOD' into patch to scope patch to this METHOD
|
|
307
358
|
* @example
|
|
308
359
|
* return new Map([
|
|
309
|
-
* ['/*', [
|
|
360
|
+
* ['/*', [GetUserByToken]] // for any method for this controller
|
|
310
361
|
* ['POST/', [Auth]] // for POST method
|
|
311
362
|
* ['/superSecretMethod', [OnlySuperSecretUsers]] // route with ANY method
|
|
312
363
|
* ['PUT/superSecretMathod', [OnlySuperSecretAdmin]] // route with PUT method
|
|
313
364
|
* ]);
|
|
314
365
|
*/
|
|
315
366
|
static get middleware() {
|
|
316
|
-
return new Map([['/*', [
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
/**
|
|
320
|
-
* Part of abstract contorller.
|
|
321
|
-
* When you do not need controller name to append in route then return false here.
|
|
322
|
-
* Useful for home(root) controllers
|
|
323
|
-
* @deprecated please use getExpressPath instead
|
|
324
|
-
*/
|
|
325
|
-
static get isUseControllerNameForRouting() {
|
|
326
|
-
return true;
|
|
367
|
+
return new Map([['/*', [GetUserByToken, Auth]]]);
|
|
327
368
|
}
|
|
328
369
|
|
|
329
370
|
/**
|
|
@@ -342,12 +383,6 @@ class AbstractController extends Base {
|
|
|
342
383
|
* Get express path with inheritance of path
|
|
343
384
|
*/
|
|
344
385
|
getExpressPath() {
|
|
345
|
-
if (!this.constructor.isUseControllerNameForRouting) {
|
|
346
|
-
console.warn(
|
|
347
|
-
'isUseControllerNameForRouting is DEPRECATED. Please use getExpressPath instead',
|
|
348
|
-
);
|
|
349
|
-
return '/';
|
|
350
|
-
}
|
|
351
386
|
return `/${this.getConstructorName().toLowerCase()}`.replace('//', '/');
|
|
352
387
|
}
|
|
353
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,
|
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));
|