@adaptivestone/framework 3.4.3 → 4.1.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 +37 -3
- package/LICENCE +21 -0
- package/cluster.js +3 -3
- package/commands/CreateUser.js +27 -0
- package/commands/Documentation.js +1 -1
- package/commands/GetOpenApiJson.js +53 -23
- package/commands/migration/Create.js +2 -2
- package/config/auth.js +1 -1
- package/config/i18n.js +4 -3
- package/config/mail.js +5 -1
- package/controllers/Home.js +2 -2
- package/controllers/Home.test.js +11 -0
- package/controllers/index.js +15 -15
- package/folderConfig.js +1 -1
- package/helpers/yup.js +24 -0
- package/index.js +8 -0
- package/models/User.js +40 -30
- package/models/User.test.js +68 -18
- package/modules/AbstractController.js +144 -208
- package/modules/AbstractModel.js +2 -1
- package/modules/Base.js +3 -2
- package/modules/BaseCli.js +6 -2
- package/package.json +20 -16
- package/server.d.ts +1 -1
- package/server.js +25 -8
- package/services/cache/Cache.d.ts +3 -3
- package/services/cache/Cache.js +17 -3
- package/services/documentation/DocumentationGenerator.js +171 -0
- package/services/http/HttpServer.js +16 -96
- package/services/http/middleware/AbstractMiddleware.js +20 -0
- package/services/http/middleware/GetUserByToken.js +4 -0
- package/services/http/middleware/I18n.js +119 -0
- package/services/http/middleware/I18n.test.js +77 -0
- package/services/http/middleware/Pagination.js +56 -0
- package/services/http/middleware/PrepareAppInfo.test.js +22 -0
- package/services/http/middleware/{Middlewares.test.js → RateLimiter.test.js} +1 -1
- package/services/http/middleware/RequestLogger.js +22 -0
- package/services/http/middleware/RequestParser.js +36 -0
- package/services/messaging/email/index.js +162 -42
- package/services/messaging/email/resources/.gitkeep +1 -0
- package/services/validate/ValidateService.js +161 -0
- package/services/validate/ValidateService.test.js +105 -0
- package/services/validate/drivers/AbstractValidator.js +37 -0
- package/services/validate/drivers/CustomValidator.js +52 -0
- package/services/validate/drivers/YupValidator.js +103 -0
- package/tests/setup.js +2 -0
- package/services/messaging/email/templates/emptyTemplate/style.less +0 -0
- package/services/messaging/email/templates/password/html.handlebars +0 -13
- package/services/messaging/email/templates/password/style.less +0 -0
- package/services/messaging/email/templates/password/subject.handlebars +0 -1
- package/services/messaging/email/templates/password/text.handlebars +0 -1
- package/services/messaging/email/templates/verification/style.less +0 -0
package/models/User.test.js
CHANGED
|
@@ -22,7 +22,7 @@ describe('user model', () => {
|
|
|
22
22
|
const user = await global.server.app.getModel('User').findOne({
|
|
23
23
|
email: userEmail,
|
|
24
24
|
});
|
|
25
|
-
expect(user.password
|
|
25
|
+
expect(user.password).not.toBe(userPassword);
|
|
26
26
|
});
|
|
27
27
|
|
|
28
28
|
it('passwords should not be changed on other fields save', async () => {
|
|
@@ -32,22 +32,74 @@ describe('user model', () => {
|
|
|
32
32
|
});
|
|
33
33
|
const psw = user.password;
|
|
34
34
|
user.email = 'rrrr';
|
|
35
|
-
user.save();
|
|
35
|
+
await user.save();
|
|
36
|
+
user.email = userEmail;
|
|
37
|
+
await user.save();
|
|
36
38
|
|
|
37
|
-
expect(user.password
|
|
39
|
+
expect(user.password).toBe(psw);
|
|
38
40
|
});
|
|
39
41
|
|
|
40
|
-
describe('
|
|
42
|
+
describe('getUserByEmailAndPassword', () => {
|
|
43
|
+
it('should WORK with valid creds', async () => {
|
|
44
|
+
expect.assertions(1);
|
|
45
|
+
const userModel = await global.server.app.getModel('User');
|
|
46
|
+
const user = await userModel.getUserByEmailAndPassword(
|
|
47
|
+
userEmail,
|
|
48
|
+
userPassword,
|
|
49
|
+
);
|
|
50
|
+
expect(user.id).toBe(globalUser.id);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it('should NOT with INvalid creds', async () => {
|
|
54
|
+
expect.assertions(1);
|
|
55
|
+
const userModel = await global.server.app.getModel('User');
|
|
56
|
+
const user = await userModel.getUserByEmailAndPassword(
|
|
57
|
+
userEmail,
|
|
58
|
+
'wrongPassword',
|
|
59
|
+
);
|
|
60
|
+
expect(user).toBe(false);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it('should NOT with wrong email', async () => {
|
|
64
|
+
expect.assertions(1);
|
|
65
|
+
const userModel = await global.server.app.getModel('User');
|
|
66
|
+
const user = await userModel.getUserByEmailAndPassword(
|
|
67
|
+
'not@exists.com',
|
|
68
|
+
userPassword,
|
|
69
|
+
);
|
|
70
|
+
expect(user).toBe(false);
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
describe('getUserByToken', () => {
|
|
41
75
|
it('should NOT work for non valid token', async () => {
|
|
42
|
-
expect.assertions(
|
|
76
|
+
expect.assertions(1);
|
|
77
|
+
|
|
78
|
+
const user = await global.server.app
|
|
79
|
+
.getModel('User')
|
|
80
|
+
.getUserByToken('fake one');
|
|
81
|
+
expect(user).toBe(false);
|
|
82
|
+
});
|
|
43
83
|
|
|
84
|
+
it('should work for VALID token', async () => {
|
|
85
|
+
expect.assertions(1);
|
|
86
|
+
const token = await globalUser.generateToken();
|
|
44
87
|
const user = await global.server.app
|
|
45
88
|
.getModel('User')
|
|
46
|
-
.
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
89
|
+
.getUserByToken(token.token);
|
|
90
|
+
expect(user.id).toBe(globalUser.id);
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
describe('getUserByVerificationToken', () => {
|
|
95
|
+
it('should NOT work for non valid token', async () => {
|
|
96
|
+
expect.assertions(1);
|
|
97
|
+
|
|
98
|
+
await expect(
|
|
99
|
+
global.server.app
|
|
100
|
+
.getModel('User')
|
|
101
|
+
.getUserByVerificationToken('fake one'),
|
|
102
|
+
).rejects.toStrictEqual(new Error('User not exists'));
|
|
51
103
|
});
|
|
52
104
|
|
|
53
105
|
it('should work for VALID token', async () => {
|
|
@@ -65,15 +117,13 @@ describe('user model', () => {
|
|
|
65
117
|
|
|
66
118
|
describe('getUserByPasswordRecoveryToken', () => {
|
|
67
119
|
it('should NOT work for non valid token', async () => {
|
|
68
|
-
expect.assertions(
|
|
120
|
+
expect.assertions(1);
|
|
69
121
|
|
|
70
|
-
|
|
71
|
-
.
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
});
|
|
76
|
-
expect(user).toBeUndefined();
|
|
122
|
+
await expect(
|
|
123
|
+
global.server.app
|
|
124
|
+
.getModel('User')
|
|
125
|
+
.getUserByPasswordRecoveryToken('fake one'),
|
|
126
|
+
).rejects.toStrictEqual(new Error('User not exists'));
|
|
77
127
|
});
|
|
78
128
|
|
|
79
129
|
it('should work for VALID token', async () => {
|
|
@@ -1,19 +1,17 @@
|
|
|
1
|
-
/* eslint-disable array-callback-return */
|
|
2
1
|
/* eslint-disable no-restricted-syntax */
|
|
3
2
|
/* eslint-disable guard-for-in */
|
|
4
3
|
const express = require('express');
|
|
5
|
-
const merge = require('deepmerge');
|
|
6
|
-
|
|
7
4
|
const Base = require('./Base');
|
|
8
5
|
const GetUserByToken = require('../services/http/middleware/GetUserByToken');
|
|
9
6
|
const Auth = require('../services/http/middleware/Auth');
|
|
10
|
-
|
|
7
|
+
const ValidateService = require('../services/validate/ValidateService');
|
|
8
|
+
const DocumentationGenerator = require('../services/documentation/DocumentationGenerator');
|
|
11
9
|
/**
|
|
12
10
|
* Abstract controller. You should extend any controller from them.
|
|
13
11
|
* Place you cintroller into controller folder and it be inited in auto way.
|
|
14
12
|
* By default name of route will be controller name not file name. But please name it in same ways.
|
|
15
13
|
* You can overwrite base controllers byt creating controllers with tha same file name (yes file name, not class name)
|
|
16
|
-
* In most cases you will want to have a 'home' route that not include controller name. For this case please check '
|
|
14
|
+
* In most cases you will want to have a 'home' route that not include controller name. For this case please check ' getHttpPath'
|
|
17
15
|
*/
|
|
18
16
|
class AbstractController extends Base {
|
|
19
17
|
constructor(app, prefix, isExpressMergeParams = false) {
|
|
@@ -24,7 +22,14 @@ class AbstractController extends Base {
|
|
|
24
22
|
mergeParams: isExpressMergeParams,
|
|
25
23
|
});
|
|
26
24
|
const { routes } = this;
|
|
27
|
-
|
|
25
|
+
let httpPath = this.getHttpPath();
|
|
26
|
+
|
|
27
|
+
if (this.getExpressPath) {
|
|
28
|
+
this.logger.warn(
|
|
29
|
+
`getExpressPath deprecated. Please use getHttpPath instead. Will be removed on v5`,
|
|
30
|
+
);
|
|
31
|
+
httpPath = this.getExpressPath();
|
|
32
|
+
}
|
|
28
33
|
|
|
29
34
|
/**
|
|
30
35
|
* Grab route middleware onlo one Map
|
|
@@ -47,69 +52,15 @@ class AbstractController extends Base {
|
|
|
47
52
|
});
|
|
48
53
|
});
|
|
49
54
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
middleware = [middleware];
|
|
59
|
-
}
|
|
60
|
-
for (const M of middleware) {
|
|
61
|
-
let method = 'all';
|
|
62
|
-
let realPath = path;
|
|
63
|
-
if (typeof realPath !== 'string') {
|
|
64
|
-
this.logger.error(`Path not a string ${realPath}. Please check it`);
|
|
65
|
-
// eslint-disable-next-line no-continue
|
|
66
|
-
continue;
|
|
67
|
-
}
|
|
68
|
-
if (!realPath.startsWith('/')) {
|
|
69
|
-
method = realPath.split('/')[0]?.toLowerCase();
|
|
70
|
-
if (!method) {
|
|
71
|
-
this.logger.error(`Method not found for ${realPath}`);
|
|
72
|
-
// eslint-disable-next-line no-continue
|
|
73
|
-
continue;
|
|
74
|
-
}
|
|
75
|
-
realPath = realPath.substring(method.length);
|
|
76
|
-
}
|
|
77
|
-
if (typeof this.router[method] !== 'function') {
|
|
78
|
-
this.logger.error(
|
|
79
|
-
`Method ${method} not exist for middleware. Please check your codebase`,
|
|
80
|
-
);
|
|
81
|
-
// eslint-disable-next-line no-continue
|
|
82
|
-
continue;
|
|
83
|
-
}
|
|
84
|
-
const fullPath = `/${expressPath}/${realPath.toUpperCase()}`
|
|
85
|
-
.split('//')
|
|
86
|
-
.join('/')
|
|
87
|
-
.split('//')
|
|
88
|
-
.join('/');
|
|
89
|
-
let MiddlewareFunction = M;
|
|
90
|
-
let middlewareParams = {};
|
|
91
|
-
if (Array.isArray(M)) {
|
|
92
|
-
[MiddlewareFunction, middlewareParams] = M;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
middlewaresInfo.push({
|
|
96
|
-
name: MiddlewareFunction.name,
|
|
97
|
-
method,
|
|
98
|
-
path: realPath,
|
|
99
|
-
fullPath,
|
|
100
|
-
params: middlewareParams,
|
|
101
|
-
authParams: new MiddlewareFunction(this.app, middlewareParams)
|
|
102
|
-
?.usedAuthParameters,
|
|
103
|
-
MiddlewareFunction,
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
return middlewaresInfo;
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
const routeMiddlewaresReg = parseMiddlewares(routeMiddlewares);
|
|
55
|
+
const routeMiddlewaresReg = this.parseMiddlewares(
|
|
56
|
+
routeMiddlewares,
|
|
57
|
+
httpPath,
|
|
58
|
+
);
|
|
59
|
+
const middlewaresInfo = this.parseMiddlewares(
|
|
60
|
+
this.constructor.middleware,
|
|
61
|
+
httpPath,
|
|
62
|
+
);
|
|
111
63
|
|
|
112
|
-
const middlewaresInfo = parseMiddlewares(this.constructor.middleware);
|
|
113
64
|
const routesInfo = [];
|
|
114
65
|
|
|
115
66
|
/**
|
|
@@ -141,11 +92,13 @@ class AbstractController extends Base {
|
|
|
141
92
|
(middleware) =>
|
|
142
93
|
middleware.path === path && middleware.method === verb,
|
|
143
94
|
);
|
|
95
|
+
|
|
144
96
|
let routeObject = routes[verb][path];
|
|
145
97
|
if (Object.prototype.toString.call(routeObject) !== '[object Object]') {
|
|
146
98
|
routeObject = {
|
|
147
99
|
handler: routeObject,
|
|
148
100
|
request: null,
|
|
101
|
+
query: null,
|
|
149
102
|
middleware: null,
|
|
150
103
|
};
|
|
151
104
|
|
|
@@ -165,7 +118,7 @@ class AbstractController extends Base {
|
|
|
165
118
|
fnName = fnName.name;
|
|
166
119
|
}
|
|
167
120
|
|
|
168
|
-
const fullPath = `/${
|
|
121
|
+
const fullPath = `/${httpPath}/${path}`
|
|
169
122
|
.split('//')
|
|
170
123
|
.join('/')
|
|
171
124
|
.split('//')
|
|
@@ -176,6 +129,7 @@ class AbstractController extends Base {
|
|
|
176
129
|
description: routeObject?.description,
|
|
177
130
|
method: verb.toUpperCase(),
|
|
178
131
|
fields: routeObject?.request?.fields,
|
|
132
|
+
queryFields: routeObject?.query?.fields,
|
|
179
133
|
path,
|
|
180
134
|
fullPath,
|
|
181
135
|
});
|
|
@@ -192,61 +146,51 @@ class AbstractController extends Base {
|
|
|
192
146
|
new MiddlewareFunction(this.app, params).getMiddleware(),
|
|
193
147
|
);
|
|
194
148
|
}
|
|
195
|
-
|
|
196
|
-
this.app.getConfig('validate');
|
|
149
|
+
|
|
197
150
|
this.router[verb](
|
|
198
151
|
path,
|
|
199
152
|
additionalMiddlewares || [],
|
|
200
153
|
async (req, res, next) => {
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
}
|
|
221
|
-
this.logger.error(
|
|
222
|
-
`Request validation failed with message: ${e.message}. errors: ${errors}`,
|
|
223
|
-
);
|
|
224
|
-
|
|
225
|
-
const errorAnswer = {};
|
|
226
|
-
if (!e.inner || !e.inner.length) {
|
|
227
|
-
errorAnswer[e.path] = errors;
|
|
228
|
-
} else {
|
|
229
|
-
e.inner.forEach((err) => {
|
|
230
|
-
errorAnswer[err.path] = err.errors;
|
|
231
|
-
if (req.i18n && err.errors) {
|
|
232
|
-
errorAnswer[err.path] = err.errors.map((err1) =>
|
|
233
|
-
req.i18n.t(err1),
|
|
234
|
-
);
|
|
235
|
-
}
|
|
236
|
-
});
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
return res.status(400).json({
|
|
240
|
-
errors: errorAnswer,
|
|
241
|
-
});
|
|
242
|
-
}
|
|
243
|
-
req.appInfo.request = await routeObject.request.cast(
|
|
244
|
-
bodyAndQuery,
|
|
245
|
-
{
|
|
246
|
-
stripUnknown: true,
|
|
247
|
-
req,
|
|
154
|
+
const requestObj = {
|
|
155
|
+
query: req.query,
|
|
156
|
+
body: req.body,
|
|
157
|
+
appInfo: req.appInfo,
|
|
158
|
+
};
|
|
159
|
+
try {
|
|
160
|
+
req.appInfo.request = await new ValidateService(
|
|
161
|
+
this.app,
|
|
162
|
+
routeObject?.request,
|
|
163
|
+
).validateReqData(requestObj, {
|
|
164
|
+
selectedReqData: req.body,
|
|
165
|
+
additionalMiddlewareFieldsData: {
|
|
166
|
+
middlewaresInfo,
|
|
167
|
+
routeMiddlewaresReg,
|
|
168
|
+
options: {
|
|
169
|
+
method: verb,
|
|
170
|
+
path: fullPath,
|
|
171
|
+
prefix: 'request',
|
|
172
|
+
},
|
|
248
173
|
},
|
|
249
|
-
);
|
|
174
|
+
});
|
|
175
|
+
req.appInfo.query = await new ValidateService(
|
|
176
|
+
this.app,
|
|
177
|
+
routeObject?.query,
|
|
178
|
+
).validateReqData(requestObj, {
|
|
179
|
+
selectedReqData: req.query,
|
|
180
|
+
additionalMiddlewareFieldsData: {
|
|
181
|
+
middlewaresInfo,
|
|
182
|
+
routeMiddlewaresReg,
|
|
183
|
+
options: {
|
|
184
|
+
method: verb,
|
|
185
|
+
path: fullPath,
|
|
186
|
+
prefix: 'query',
|
|
187
|
+
},
|
|
188
|
+
},
|
|
189
|
+
});
|
|
190
|
+
} catch (err) {
|
|
191
|
+
return res.status(400).json({
|
|
192
|
+
errors: err.message,
|
|
193
|
+
});
|
|
250
194
|
}
|
|
251
195
|
req.body = new Proxy(req.body, {
|
|
252
196
|
get: (target, prop) => {
|
|
@@ -256,6 +200,14 @@ class AbstractController extends Base {
|
|
|
256
200
|
return target[prop];
|
|
257
201
|
},
|
|
258
202
|
});
|
|
203
|
+
req.query = new Proxy(req.query, {
|
|
204
|
+
get: (target, prop) => {
|
|
205
|
+
this.logger.warn(
|
|
206
|
+
'Please not use "req.query" directly. Implement "query" and use "req.appInfo.query" ',
|
|
207
|
+
);
|
|
208
|
+
return target[prop];
|
|
209
|
+
},
|
|
210
|
+
});
|
|
259
211
|
|
|
260
212
|
if (!routeObject.handler) {
|
|
261
213
|
this.logger.error(`Route object have no handler defined`);
|
|
@@ -276,6 +228,7 @@ class AbstractController extends Base {
|
|
|
276
228
|
}
|
|
277
229
|
return routeObject.handler.call(this, req, res, next).catch((e) => {
|
|
278
230
|
this.logger.error(e.message);
|
|
231
|
+
// eslint-disable-next-line no-console
|
|
279
232
|
console.error(e);
|
|
280
233
|
return res.status(500).json({
|
|
281
234
|
message:
|
|
@@ -311,104 +264,87 @@ class AbstractController extends Base {
|
|
|
311
264
|
text.push(`Time: ${Date.now() - time} ms`);
|
|
312
265
|
|
|
313
266
|
this.logger.verbose(text.join('\n'));
|
|
267
|
+
this.loadedTime = Date.now() - time;
|
|
314
268
|
|
|
315
269
|
/**
|
|
316
270
|
* Generate documentation
|
|
317
271
|
*/
|
|
272
|
+
if (!this.app.httpServer) {
|
|
273
|
+
this.app.documentation.push(
|
|
274
|
+
DocumentationGenerator.convertDataToDocumentationElement(
|
|
275
|
+
this.getConstructorName(),
|
|
276
|
+
routesInfo,
|
|
277
|
+
middlewaresInfo,
|
|
278
|
+
routeMiddlewaresReg,
|
|
279
|
+
),
|
|
280
|
+
);
|
|
281
|
+
} else {
|
|
282
|
+
this.app.httpServer.express.use(httpPath, this.router);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
318
285
|
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
286
|
+
/**
|
|
287
|
+
* Parse middlewares to be an object.
|
|
288
|
+
*/
|
|
289
|
+
parseMiddlewares(middlewareMap, httpPath) {
|
|
290
|
+
const middlewaresInfo = [];
|
|
291
|
+
// eslint-disable-next-line prefer-const
|
|
292
|
+
for (let [path, middleware] of middlewareMap) {
|
|
293
|
+
if (!Array.isArray(middleware)) {
|
|
294
|
+
middleware = [middleware];
|
|
323
295
|
}
|
|
324
|
-
const
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
296
|
+
for (const M of middleware) {
|
|
297
|
+
let method = 'all';
|
|
298
|
+
let realPath = path;
|
|
299
|
+
if (typeof realPath !== 'string') {
|
|
300
|
+
this.logger.error(`Path not a string ${realPath}. Please check it`);
|
|
301
|
+
// eslint-disable-next-line no-continue
|
|
302
|
+
continue;
|
|
331
303
|
}
|
|
332
|
-
if (
|
|
333
|
-
|
|
304
|
+
if (!realPath.startsWith('/')) {
|
|
305
|
+
method = realPath.split('/')[0]?.toLowerCase();
|
|
306
|
+
if (!method) {
|
|
307
|
+
this.logger.error(`Method not found for ${realPath}`);
|
|
308
|
+
// eslint-disable-next-line no-continue
|
|
309
|
+
continue;
|
|
310
|
+
}
|
|
311
|
+
realPath = realPath.substring(method.length);
|
|
334
312
|
}
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
313
|
+
if (typeof this.router[method] !== 'function') {
|
|
314
|
+
this.logger.error(
|
|
315
|
+
`Method ${method} not exist for middleware. Please check your codebase`,
|
|
316
|
+
);
|
|
317
|
+
// eslint-disable-next-line no-continue
|
|
318
|
+
continue;
|
|
319
|
+
}
|
|
320
|
+
const fullPath = `/${httpPath}/${realPath.toUpperCase()}`
|
|
321
|
+
.split('//')
|
|
322
|
+
.join('/')
|
|
323
|
+
.split('//')
|
|
324
|
+
.join('/');
|
|
325
|
+
let MiddlewareFunction = M;
|
|
326
|
+
let middlewareParams = {};
|
|
327
|
+
if (Array.isArray(M)) {
|
|
328
|
+
[MiddlewareFunction, middlewareParams] = M;
|
|
347
329
|
}
|
|
348
|
-
fields.push(field);
|
|
349
|
-
});
|
|
350
|
-
return fields;
|
|
351
|
-
};
|
|
352
|
-
|
|
353
|
-
if (!this.app.httpServer) {
|
|
354
|
-
this.app.documentation.push({
|
|
355
|
-
contollerName: this.getConstructorName(),
|
|
356
|
-
routesInfo: routesInfo.map((route) => ({
|
|
357
|
-
[route.fullPath]: {
|
|
358
|
-
method: route.method,
|
|
359
|
-
name: route.name,
|
|
360
|
-
description: route?.description,
|
|
361
|
-
fields: processingFields(route.fields),
|
|
362
|
-
routeMiddlewares: routeMiddlewaresReg
|
|
363
|
-
// eslint-disable-next-line consistent-return
|
|
364
|
-
.map((middleware) => {
|
|
365
|
-
const routeFullPath = route.fullPath.toUpperCase();
|
|
366
|
-
const middlewareFullPath = middleware.fullPath.toUpperCase();
|
|
367
|
-
if (
|
|
368
|
-
route.method.toLowerCase() ===
|
|
369
|
-
middleware.method.toLowerCase() &&
|
|
370
|
-
(middlewareFullPath === routeFullPath ||
|
|
371
|
-
middlewareFullPath === `${routeFullPath}*`)
|
|
372
|
-
) {
|
|
373
|
-
return {
|
|
374
|
-
name: middleware.name,
|
|
375
|
-
params: middleware.params,
|
|
376
|
-
authParams: middleware.authParams,
|
|
377
|
-
};
|
|
378
|
-
}
|
|
379
|
-
})
|
|
380
|
-
.filter(Boolean),
|
|
381
|
-
controllerMiddlewares: [
|
|
382
|
-
...new Set(
|
|
383
|
-
middlewaresInfo
|
|
384
|
-
.filter((middleware) => {
|
|
385
|
-
const routeFullPath = route.fullPath.toUpperCase();
|
|
386
|
-
const middlewareFullPath =
|
|
387
|
-
middleware.fullPath.toUpperCase();
|
|
388
|
-
const middlewareFullPathWithSliced = middleware.fullPath
|
|
389
|
-
.toUpperCase()
|
|
390
|
-
.slice(0, -1);
|
|
391
330
|
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
})),
|
|
408
|
-
});
|
|
409
|
-
} else {
|
|
410
|
-
this.app.httpServer.express.use(expressPath, this.router);
|
|
331
|
+
middlewaresInfo.push({
|
|
332
|
+
name: MiddlewareFunction.name,
|
|
333
|
+
method,
|
|
334
|
+
path: realPath,
|
|
335
|
+
fullPath,
|
|
336
|
+
params: middlewareParams,
|
|
337
|
+
relatedQueryParameters: new MiddlewareFunction(
|
|
338
|
+
this.app,
|
|
339
|
+
middlewareParams,
|
|
340
|
+
)?.relatedQueryParameters,
|
|
341
|
+
authParams: new MiddlewareFunction(this.app, middlewareParams)
|
|
342
|
+
?.usedAuthParameters,
|
|
343
|
+
MiddlewareFunction,
|
|
344
|
+
});
|
|
345
|
+
}
|
|
411
346
|
}
|
|
347
|
+
return middlewaresInfo;
|
|
412
348
|
}
|
|
413
349
|
|
|
414
350
|
/**
|
|
@@ -460,9 +396,9 @@ class AbstractController extends Base {
|
|
|
460
396
|
}
|
|
461
397
|
|
|
462
398
|
/**
|
|
463
|
-
* Get
|
|
399
|
+
* Get http path with inheritance of path
|
|
464
400
|
*/
|
|
465
|
-
|
|
401
|
+
getHttpPath() {
|
|
466
402
|
return `/${this.getConstructorName().toLowerCase()}`.replace('//', '/');
|
|
467
403
|
}
|
|
468
404
|
|
package/modules/AbstractModel.js
CHANGED
|
@@ -3,12 +3,13 @@ const Base = require('./Base');
|
|
|
3
3
|
|
|
4
4
|
class AbstractModel extends Base {
|
|
5
5
|
/**
|
|
6
|
-
* @param {import('../
|
|
6
|
+
* @param {import('../server')} app //TODO change to *.d.ts as this is a Server, not app
|
|
7
7
|
* @param function callback optional callback when connection ready
|
|
8
8
|
*/
|
|
9
9
|
constructor(app, callback = () => {}) {
|
|
10
10
|
super(app);
|
|
11
11
|
this.mongooseSchema = mongoose.Schema(this.modelSchema);
|
|
12
|
+
mongoose.set('strictQuery', true);
|
|
12
13
|
this.mongooseSchema.set('timestamps', true);
|
|
13
14
|
this.mongooseSchema.set('minimize', false);
|
|
14
15
|
this.mongooseSchema.loadClass(this.constructor);
|
package/modules/Base.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
const fs = require('fs').promises;
|
|
2
|
-
const { join, normalize } = require('path');
|
|
1
|
+
const fs = require('node:fs').promises;
|
|
2
|
+
const { join, normalize } = require('node:path');
|
|
3
3
|
|
|
4
4
|
class Base {
|
|
5
5
|
#realLogger = null;
|
|
@@ -77,6 +77,7 @@ class Base {
|
|
|
77
77
|
if (!IsConstructor(Tr) && Tr.default) {
|
|
78
78
|
Tr = Tr.default;
|
|
79
79
|
} else {
|
|
80
|
+
// eslint-disable-next-line no-console
|
|
80
81
|
console.error(
|
|
81
82
|
`${log.transport} not a constructor. Please check it`,
|
|
82
83
|
);
|
package/modules/BaseCli.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
/* eslint-disable no-console */
|
|
2
|
+
const path = require('node:path');
|
|
2
3
|
const Base = require('./Base');
|
|
3
4
|
|
|
4
5
|
class Cli extends Base {
|
|
@@ -46,9 +47,12 @@ class Cli extends Base {
|
|
|
46
47
|
);
|
|
47
48
|
return false;
|
|
48
49
|
}
|
|
50
|
+
// TODO wait until https://github.com/nodejs/node/issues/35889
|
|
51
|
+
// const { default: Command } = await import(this.commands[command]);
|
|
49
52
|
|
|
50
|
-
// eslint-disable-next-line
|
|
53
|
+
// eslint-disable-next-line import/no-dynamic-require, global-require
|
|
51
54
|
const Command = require(this.commands[command]);
|
|
55
|
+
|
|
52
56
|
const c = new Command(this.app, this.commands, args);
|
|
53
57
|
let result = false;
|
|
54
58
|
|