nodester 0.0.1 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Readme.md +61 -26
- package/docs/GoalController.js +62 -0
- package/docs/request-examples.js +184 -0
- package/examples/rest/controllers/orders.controller.js +15 -0
- package/examples/rest/index.js +29 -9
- package/examples/rest/node_modules/.package-lock.json +5 -3
- package/examples/rest/preprocessors/queries/orders.queries.js +15 -0
- package/examples/rest/router.js +23 -0
- package/lib/application/index.js +86 -35
- package/lib/constants/Operations.js +23 -0
- package/lib/controllers/methods/index.js +170 -0
- package/lib/controllers/mixins/index.js +213 -0
- package/lib/enums/Enum.js +16 -0
- package/lib/factories/errors/CustomError.js +7 -5
- package/lib/factories/responses/html.js +7 -2
- package/lib/factories/responses/rest.js +110 -0
- package/lib/http/codes/index.js +157 -0
- package/lib/{application/http → http}/request.js +6 -30
- package/lib/{application/http → http}/response.js +20 -53
- package/lib/middlewares/etag/index.js +62 -0
- package/lib/middlewares/ql/sequelize/index.js +34 -0
- package/lib/middlewares/ql/sequelize/interpreter/ModelsTree.js +121 -0
- package/lib/middlewares/ql/sequelize/interpreter/QueryLexer.js +456 -0
- package/lib/models/define.js +6 -13
- package/lib/models/mixins.js +28 -15
- package/lib/params/Params.js +34 -0
- package/lib/queries/NodesterQueryParams.js +139 -0
- package/lib/router/handlers.util.js +61 -0
- package/lib/router/index.js +386 -0
- package/lib/router/route.js +124 -0
- package/lib/router/routes.util.js +66 -0
- package/lib/stacks/MarkersStack.js +35 -0
- package/lib/{application → stacks}/MiddlewareStack.js +47 -13
- package/lib/utils/path.util.js +3 -1
- package/lib/utils/types.util.js +51 -1
- package/lib/validators/dates.js +25 -0
- package/lib/validators/numbers.js +14 -0
- package/package.json +16 -2
- package/tests/index.test.js +7 -2
- package/tests/nql.test.js +277 -0
- package/examples/rest/package-lock.json +0 -72
- package/lib/constants/ConstantsEnum.js +0 -13
- package/lib/factories/responses/api.js +0 -90
- package/lib/routers/Default/index.js +0 -143
- package/lib/routers/Default/layer.js +0 -50
- package/lib/routers/Main/index.js +0 -10
- package/lib/routers/Roles/index.js +0 -81
- package/lib/utils/params.util.js +0 -19
- /package/lib/{controllers/Controller.js → _/n_controllers/Controller.js"} +0 -0
- /package/lib/{controllers/JWTController.js → _/n_controllers/JWTController.js"} +0 -0
- /package/lib/{controllers/ServiceController.js → _/n_controllers/ServiceController.js"} +0 -0
- /package/lib/{controllers/WebController.js → _/n_controllers/WebController.js"} +0 -0
- /package/lib/{facades → _facades}/Facade.js +0 -0
- /package/lib/{facades → _facades}/FacadeParams.js +0 -0
- /package/lib/{facades → _facades}/ServiceFacade.js +0 -0
- /package/lib/{facades → _facades}/jwt.facade.js +0 -0
- /package/lib/{application/http → http}/utils.js +0 -0
package/lib/application/index.js
CHANGED
|
@@ -6,13 +6,18 @@
|
|
|
6
6
|
'use strict';
|
|
7
7
|
|
|
8
8
|
const Emitter = require('events');
|
|
9
|
-
const
|
|
9
|
+
const DefaultRouter = require('../router');
|
|
10
10
|
// Server:
|
|
11
11
|
const http = require('http');
|
|
12
|
-
const request = require('
|
|
13
|
-
const response = require('
|
|
12
|
+
const request = require('../http/request');
|
|
13
|
+
const response = require('../http/response');
|
|
14
|
+
// Middlewares:
|
|
15
|
+
const nodesterQL = require('../middlewares/ql/sequelize');
|
|
14
16
|
// Utils:
|
|
15
|
-
const {
|
|
17
|
+
const {
|
|
18
|
+
typeOf,
|
|
19
|
+
isConstructor
|
|
20
|
+
} = require('../utils/types.util');
|
|
16
21
|
const { merge } = require('../utils/objects.util');
|
|
17
22
|
const consl = require('../logger/console');
|
|
18
23
|
const debug = require('debug')('nodester:application');
|
|
@@ -31,11 +36,14 @@ module.exports = class Application extends Emitter {
|
|
|
31
36
|
// Fallback port.
|
|
32
37
|
this.port = opts?.port ?? 8080;
|
|
33
38
|
|
|
34
|
-
// Reference to
|
|
35
|
-
this.
|
|
39
|
+
// Reference to router.
|
|
40
|
+
this._router = new DefaultRouter({ finalhandlerEnabled: true });
|
|
36
41
|
|
|
37
42
|
// Reference to the database connection.
|
|
38
|
-
this.
|
|
43
|
+
this._database = null;
|
|
44
|
+
|
|
45
|
+
// Reference to the Query parser.
|
|
46
|
+
this._queryParser = nodesterQL;
|
|
39
47
|
|
|
40
48
|
// Reference to the http(s) server,
|
|
41
49
|
this.server = null;
|
|
@@ -55,7 +63,7 @@ module.exports = class Application extends Emitter {
|
|
|
55
63
|
*/
|
|
56
64
|
get request() {
|
|
57
65
|
return Object.create(request, {
|
|
58
|
-
app: { configurable: true, enumerable: true, writable: true, value:
|
|
66
|
+
app: { configurable: true, enumerable: true, writable: true, value: this }
|
|
59
67
|
})
|
|
60
68
|
}
|
|
61
69
|
|
|
@@ -67,7 +75,7 @@ module.exports = class Application extends Emitter {
|
|
|
67
75
|
*/
|
|
68
76
|
get response() {
|
|
69
77
|
return Object.create(response, {
|
|
70
|
-
app: { configurable: true, enumerable: true, writable: true, value:
|
|
78
|
+
app: { configurable: true, enumerable: true, writable: true, value: this }
|
|
71
79
|
})
|
|
72
80
|
}
|
|
73
81
|
|
|
@@ -89,6 +97,7 @@ module.exports = class Application extends Emitter {
|
|
|
89
97
|
|
|
90
98
|
/**
|
|
91
99
|
* Sets (or overrides) main database of the application and tries to make connection.
|
|
100
|
+
*
|
|
92
101
|
* @param {Sequilize} sequilizeConnection
|
|
93
102
|
* @param {Boolean} crashOnError
|
|
94
103
|
* @return {sequilizeConnection.authenticate}
|
|
@@ -98,12 +107,17 @@ module.exports = class Application extends Emitter {
|
|
|
98
107
|
setDatabase(sequilizeConnection, crashOnError=true) {
|
|
99
108
|
try {
|
|
100
109
|
if (!sequilizeConnection) {
|
|
101
|
-
const err = new
|
|
110
|
+
const err = new TypeError('Connection to database (Sequilize) can not be null or undefined.');
|
|
111
|
+
throw err;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (this.isListening === true) {
|
|
115
|
+
const err = new Error(`Can't set database after application start.`);
|
|
102
116
|
throw err;
|
|
103
117
|
}
|
|
104
118
|
|
|
105
119
|
const result = sequilizeConnection.authenticate();
|
|
106
|
-
this.
|
|
120
|
+
this._database = sequilizeConnection;
|
|
107
121
|
|
|
108
122
|
return result;
|
|
109
123
|
}
|
|
@@ -118,13 +132,42 @@ module.exports = class Application extends Emitter {
|
|
|
118
132
|
}
|
|
119
133
|
|
|
120
134
|
|
|
135
|
+
/*
|
|
136
|
+
* Returns main database of the application.
|
|
137
|
+
*
|
|
138
|
+
* @return {SequilizeConnection}
|
|
139
|
+
*
|
|
140
|
+
* @public
|
|
141
|
+
*/
|
|
142
|
+
get database() {
|
|
143
|
+
return this._database;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
|
|
121
147
|
/**
|
|
122
148
|
* Overrides default Router.
|
|
123
149
|
*
|
|
124
150
|
* @public
|
|
125
151
|
*/
|
|
126
152
|
setRouter(newRouter) {
|
|
127
|
-
|
|
153
|
+
if (isConstructor(newRouter)) {
|
|
154
|
+
this._router = new newRouter();
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
this._router = newRouter;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
/*
|
|
163
|
+
* Returns NodesterRouter object.
|
|
164
|
+
*
|
|
165
|
+
* @return {NodesterRouter}
|
|
166
|
+
*
|
|
167
|
+
* @public
|
|
168
|
+
*/
|
|
169
|
+
get router() {
|
|
170
|
+
return this._router;
|
|
128
171
|
}
|
|
129
172
|
|
|
130
173
|
|
|
@@ -136,40 +179,39 @@ module.exports = class Application extends Emitter {
|
|
|
136
179
|
*/
|
|
137
180
|
get add() {
|
|
138
181
|
return {
|
|
139
|
-
|
|
182
|
+
controller: this._router.add.controller,
|
|
183
|
+
middleware: this._router.add.middleware,
|
|
184
|
+
marker: this._router.add.marker,
|
|
185
|
+
route: this._router.add.route,
|
|
140
186
|
}
|
|
141
187
|
}
|
|
142
188
|
|
|
143
189
|
|
|
144
190
|
/*
|
|
145
|
-
*
|
|
191
|
+
* Proxy to .add.middleware()
|
|
192
|
+
*
|
|
193
|
+
* @param {Function} fn
|
|
146
194
|
*
|
|
147
195
|
* @api public
|
|
148
196
|
*/
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
const err = new Error(`Can't add more middlewares after application has been started.`);
|
|
152
|
-
throw err;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
this._middlewares.add(fn);
|
|
197
|
+
use(fn) {
|
|
198
|
+
return this._router.add.middleware(fn);
|
|
156
199
|
}
|
|
157
200
|
|
|
158
201
|
|
|
159
202
|
/*
|
|
160
|
-
* Proxy to .add().
|
|
161
203
|
*
|
|
162
|
-
* @param {
|
|
204
|
+
* @param {String} markerName
|
|
163
205
|
*
|
|
164
206
|
* @api public
|
|
165
207
|
*/
|
|
166
|
-
|
|
167
|
-
return this.
|
|
208
|
+
only(markerName='') {
|
|
209
|
+
return this._router.only(markerName);
|
|
168
210
|
}
|
|
169
211
|
|
|
170
212
|
|
|
171
213
|
/**
|
|
172
|
-
*
|
|
214
|
+
* Sets beforeStart hook.
|
|
173
215
|
*
|
|
174
216
|
* @api public
|
|
175
217
|
*/
|
|
@@ -192,20 +234,24 @@ module.exports = class Application extends Emitter {
|
|
|
192
234
|
*
|
|
193
235
|
* @api public
|
|
194
236
|
*/
|
|
195
|
-
start() {
|
|
237
|
+
async start() {
|
|
196
238
|
try {
|
|
197
|
-
this._hooks.beforeStart.call(this);
|
|
239
|
+
await this._hooks.beforeStart.call(this);
|
|
198
240
|
}
|
|
199
241
|
catch(error) {
|
|
200
242
|
console.error('Application did not start due to error.');
|
|
201
243
|
consl.error(error);
|
|
202
|
-
return;
|
|
244
|
+
return Promise.reject(error);
|
|
203
245
|
}
|
|
204
246
|
|
|
205
|
-
//
|
|
206
|
-
this.
|
|
247
|
+
// Add query parser.
|
|
248
|
+
this._router.add.middleware(this._queryParser, 0);
|
|
207
249
|
|
|
208
|
-
|
|
250
|
+
// Prepare router for processing.
|
|
251
|
+
this._router.lock();
|
|
252
|
+
|
|
253
|
+
const handler = this.handle.bind(this);
|
|
254
|
+
return handler;
|
|
209
255
|
}
|
|
210
256
|
|
|
211
257
|
|
|
@@ -220,7 +266,7 @@ module.exports = class Application extends Emitter {
|
|
|
220
266
|
*
|
|
221
267
|
* @api public
|
|
222
268
|
*/
|
|
223
|
-
listen(port, ...args) {
|
|
269
|
+
async listen(port, ...args) {
|
|
224
270
|
// Remember port:
|
|
225
271
|
const _port = port ?? this.port;
|
|
226
272
|
this.port = _port;
|
|
@@ -228,7 +274,8 @@ module.exports = class Application extends Emitter {
|
|
|
228
274
|
debug(`listen on port ${ this.port }`);
|
|
229
275
|
|
|
230
276
|
if (!this.server) {
|
|
231
|
-
|
|
277
|
+
const handler = await this.start();
|
|
278
|
+
this.server = http.createServer(handler);
|
|
232
279
|
}
|
|
233
280
|
|
|
234
281
|
this.isListening = true;
|
|
@@ -250,7 +297,7 @@ module.exports = class Application extends Emitter {
|
|
|
250
297
|
req.res = res;
|
|
251
298
|
res.req = req;
|
|
252
299
|
|
|
253
|
-
return this.
|
|
300
|
+
return this._router.handle(req, res);
|
|
254
301
|
}
|
|
255
302
|
|
|
256
303
|
|
|
@@ -288,5 +335,9 @@ module.exports = class Application extends Emitter {
|
|
|
288
335
|
|
|
289
336
|
this.server.close();
|
|
290
337
|
this.isListening = false;
|
|
338
|
+
|
|
339
|
+
this._router.unlock();
|
|
340
|
+
// Remove query parser.
|
|
341
|
+
this._router.remove.middleware(0);
|
|
291
342
|
}
|
|
292
343
|
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
const Enum = require('../enums/Enum');
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
module.exports = new Enum({
|
|
5
|
+
and: Symbol.for('and'),
|
|
6
|
+
between: Symbol.for('between'),
|
|
7
|
+
contains: Symbol.for('contains'),
|
|
8
|
+
eq: Symbol.for('eq'),
|
|
9
|
+
ne: Symbol.for('ne'),
|
|
10
|
+
gte: Symbol.for('gte'),
|
|
11
|
+
gt: Symbol.for('gt'),
|
|
12
|
+
lte: Symbol.for('lte'),
|
|
13
|
+
lt: Symbol.for('lt'),
|
|
14
|
+
not: Symbol.for('not'),
|
|
15
|
+
is: Symbol.for('is'),
|
|
16
|
+
in: Symbol.for('in'),
|
|
17
|
+
notIn: Symbol.for('notIn'),
|
|
18
|
+
like: Symbol.for('like'),
|
|
19
|
+
notLike: Symbol.for('notLike'),
|
|
20
|
+
notBetween: Symbol.for('notBetween'),
|
|
21
|
+
or: Symbol.for('or'),
|
|
22
|
+
xor: Symbol.for('xor'),
|
|
23
|
+
});
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
|
|
2
|
+
module.exports = {
|
|
3
|
+
getOne: _getOne,
|
|
4
|
+
getMany: _getMany,
|
|
5
|
+
createOne: _createOne,
|
|
6
|
+
updateOne: _updateOne,
|
|
7
|
+
deleteOne: _deleteOne
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
/*
|
|
12
|
+
* @alias getOne
|
|
13
|
+
* @api public
|
|
14
|
+
*/
|
|
15
|
+
async function _getOne(req, res) {
|
|
16
|
+
try {
|
|
17
|
+
|
|
18
|
+
const result = await this.facade.getOne();
|
|
19
|
+
|
|
20
|
+
if (this.afterGetOne) {
|
|
21
|
+
await this.afterGetOne(req, res, result);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return this.respondOk(res, {
|
|
25
|
+
content: { ...result }
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
catch(error) {
|
|
29
|
+
console.error('getOne', error);
|
|
30
|
+
if (this.processError) {
|
|
31
|
+
return this.processError(error, req, res);
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
res.status(500);
|
|
35
|
+
res.json({ error: error.toString() });
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
finally {
|
|
39
|
+
return Promise.resolve();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
/*
|
|
45
|
+
* @alias getMany
|
|
46
|
+
* @api public
|
|
47
|
+
*/
|
|
48
|
+
async function _getMany(req, res) {
|
|
49
|
+
try {
|
|
50
|
+
const result = await this.facade.getMany();
|
|
51
|
+
|
|
52
|
+
if (this.afterGetMany) {
|
|
53
|
+
await this.afterGetMany(req, res, result);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return this.respondOk(res, {
|
|
57
|
+
content: { ...result }
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
catch(error) {
|
|
61
|
+
if (this.processError) {
|
|
62
|
+
return this.processError(error, req, res);
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
res.status(500);
|
|
66
|
+
res.json({ error: error.toString() });
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
finally {
|
|
70
|
+
return Promise.resolve();
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
/*
|
|
76
|
+
* @alias createOne
|
|
77
|
+
* @api public
|
|
78
|
+
*/
|
|
79
|
+
async function _createOne(req, res) {
|
|
80
|
+
try {
|
|
81
|
+
|
|
82
|
+
const result = await this.facade.createOne();
|
|
83
|
+
|
|
84
|
+
if (this.afterCreateOne) {
|
|
85
|
+
await this.afterCreateOne(req, res, result);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return this.respondOk(res, {
|
|
89
|
+
content: { ...result }
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
catch(error) {
|
|
93
|
+
if (this.processError) {
|
|
94
|
+
return this.processError(error, req, res);
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
res.status(500);
|
|
98
|
+
res.json({ error: error.toString() });
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
finally {
|
|
102
|
+
return Promise.resolve();
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
/*
|
|
108
|
+
* @alias updateOne
|
|
109
|
+
* @api public
|
|
110
|
+
*/
|
|
111
|
+
async function _updateOne(req, res) {
|
|
112
|
+
try {
|
|
113
|
+
|
|
114
|
+
const result = await this.facade.updateOne();
|
|
115
|
+
|
|
116
|
+
if (this.afterUpdateOne) {
|
|
117
|
+
await this.afterUpdateOne(req, res, result);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return this.respondOk(res, {
|
|
121
|
+
content: { ...result }
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
catch(error) {
|
|
125
|
+
if (this.processError) {
|
|
126
|
+
return this.processError(error, req, res);
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
res.status(500);
|
|
130
|
+
res.json({ error: error.toString() });
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
finally {
|
|
134
|
+
return Promise.resolve();
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
/*
|
|
140
|
+
* @alias deleteOne
|
|
141
|
+
* @api public
|
|
142
|
+
*/
|
|
143
|
+
async function _deleteOne(req, res) {
|
|
144
|
+
try {
|
|
145
|
+
|
|
146
|
+
const result = await this.facade.deleteOne();
|
|
147
|
+
|
|
148
|
+
if (this.afterDeleteOn) {
|
|
149
|
+
await this.afterDeleteOne(req, res, result);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return this.respondOk(res, {
|
|
153
|
+
content: { ...result }
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
catch(error) {
|
|
157
|
+
if (this.processError) {
|
|
158
|
+
return this.processError(error, req, res);
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
res.status(500);
|
|
162
|
+
res.json({ error: error.toString() });
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
finally {
|
|
166
|
+
return Promise.resolve();
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
const {
|
|
2
|
+
getOne,
|
|
3
|
+
getMany,
|
|
4
|
+
createOne,
|
|
5
|
+
updateOne,
|
|
6
|
+
deleteOne
|
|
7
|
+
} = require('../methods');
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
module.exports = {
|
|
11
|
+
withDefaultCRUD: _withDefaultCRUD,
|
|
12
|
+
withDefaultErrorProcessing: _withDefaultErrorProcessing,
|
|
13
|
+
setMethod: _setMethod
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Sets one of or all of CRUD methods to Controller.
|
|
19
|
+
*
|
|
20
|
+
* @param {Function|Object} controller
|
|
21
|
+
* @param {Object} opts
|
|
22
|
+
* - @param {Function|Object} facade
|
|
23
|
+
* - @param {String} name
|
|
24
|
+
* - @param {Array} only
|
|
25
|
+
*
|
|
26
|
+
* @return {Function|Object} controller
|
|
27
|
+
*
|
|
28
|
+
* @api public
|
|
29
|
+
* @alias withDefaultCRUD
|
|
30
|
+
*/
|
|
31
|
+
function _withDefaultCRUD(controller, opts={}) {
|
|
32
|
+
const {
|
|
33
|
+
facade,
|
|
34
|
+
|
|
35
|
+
// Optional:
|
|
36
|
+
name,
|
|
37
|
+
only
|
|
38
|
+
} = opts;
|
|
39
|
+
|
|
40
|
+
if (!controller) {
|
|
41
|
+
const err = new TypeError(`'controller' argument is not provided.`);
|
|
42
|
+
throw err;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (!facade) {
|
|
46
|
+
const err = new TypeError(`'opts.facade' argument is invalid.`);
|
|
47
|
+
throw err;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Set main facade:
|
|
51
|
+
if (facade.constructor.name === 'Function') {
|
|
52
|
+
controller.facade = new facade();
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
controller.facade = facade;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Set model info:
|
|
59
|
+
const model = facade.model;
|
|
60
|
+
// Extract plural name of this model.
|
|
61
|
+
const modelPluralName = model?.options?.name?.plural;
|
|
62
|
+
// Set name of this controller:
|
|
63
|
+
Object.defineProperty(controller, 'name', {
|
|
64
|
+
value: name ?? `${ modelPluralName ?? controller.name }Controller`,
|
|
65
|
+
writable: false
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
// If only certain methods should be set:
|
|
70
|
+
if (!!only) {
|
|
71
|
+
for (const selectedMethod of only) {
|
|
72
|
+
switch(selectedMethod) {
|
|
73
|
+
case 'getOne':
|
|
74
|
+
controller.getOne = getOne.bind(controller);
|
|
75
|
+
break;
|
|
76
|
+
case 'getMany':
|
|
77
|
+
controller.getMany = getMany.bind(controller);
|
|
78
|
+
break;
|
|
79
|
+
case 'createOne':
|
|
80
|
+
controller.createOne = createOne.bind(controller);
|
|
81
|
+
break;
|
|
82
|
+
case 'updateOne':
|
|
83
|
+
controller.updateOne = updateOne.bind(controller);
|
|
84
|
+
break;
|
|
85
|
+
case 'deleteOne':
|
|
86
|
+
controller.deleteOne = deleteOne.bind(controller);
|
|
87
|
+
break;
|
|
88
|
+
|
|
89
|
+
default:
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
// Or set all methods:
|
|
95
|
+
else {
|
|
96
|
+
controller.getOne = getOne.bind(controller);
|
|
97
|
+
controller.getMany = getMany.bind(controller);
|
|
98
|
+
controller.createOne = createOne.bind(controller);
|
|
99
|
+
controller.updateOne = updateOne.bind(controller);
|
|
100
|
+
controller.deleteOne = deleteOne.bind(controller);
|
|
101
|
+
|
|
102
|
+
// Set empty hooks:
|
|
103
|
+
controller.afterGetOne = async () => {};
|
|
104
|
+
controller.afterGetMany = async () => {};
|
|
105
|
+
controller.afterCreateOne = async () => {};
|
|
106
|
+
controller.afterUpdateOne = async () => {};
|
|
107
|
+
controller.afterDeleteOe = async () => {};
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// TODO: remove.
|
|
111
|
+
controller.respondOk = (res, data) => res.json(data);
|
|
112
|
+
controller.respondNotOk = (res, data) => { res.status(data.status); res.json(data); };
|
|
113
|
+
|
|
114
|
+
return controller;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Sets default error responses to Controller.
|
|
120
|
+
*
|
|
121
|
+
* @param {Function|Object} controller
|
|
122
|
+
* @param {Object} opts
|
|
123
|
+
*
|
|
124
|
+
* @return {Function|Object} controller
|
|
125
|
+
*
|
|
126
|
+
* @api public
|
|
127
|
+
* @alias withDefaultErrorProcessing
|
|
128
|
+
*/
|
|
129
|
+
function _withDefaultErrorProcessing(controller, opts={}) {
|
|
130
|
+
if (!controller) {
|
|
131
|
+
const err = new TypeError(`'controller' argument is not provided.`);
|
|
132
|
+
throw err;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Set processError:
|
|
136
|
+
controller.processError = function (error, req, res) {
|
|
137
|
+
// Default error message.
|
|
138
|
+
let errorMessage = error?.message ?? 'Internal server error';
|
|
139
|
+
// Default HTTP status code.
|
|
140
|
+
let statusCode = error?.status ?? error?.statusCode ?? 500;
|
|
141
|
+
// Error response object.
|
|
142
|
+
let errorResponse = {};
|
|
143
|
+
|
|
144
|
+
switch(error.name) {
|
|
145
|
+
case('Unauthorized'): {
|
|
146
|
+
statusCode = 401;
|
|
147
|
+
errorResponse.details = { message: 'Unauthorized' };
|
|
148
|
+
break;
|
|
149
|
+
}
|
|
150
|
+
case('NotFound'): {
|
|
151
|
+
statusCode = 404;
|
|
152
|
+
errorResponse.details = { message: errorMessage };
|
|
153
|
+
break;
|
|
154
|
+
}
|
|
155
|
+
case('ValidationError'): {
|
|
156
|
+
statusCode = 406;
|
|
157
|
+
errorResponse.details = error?.details;
|
|
158
|
+
break;
|
|
159
|
+
}
|
|
160
|
+
case('ConflictError'): {
|
|
161
|
+
statusCode = 409;
|
|
162
|
+
errorResponse.details = error?.details ?? error?.message;
|
|
163
|
+
break;
|
|
164
|
+
}
|
|
165
|
+
case('SequelizeUniqueConstraintError'): {
|
|
166
|
+
statusCode = 409;
|
|
167
|
+
errorResponse.details = error?.errors;
|
|
168
|
+
break;
|
|
169
|
+
}
|
|
170
|
+
case('InternalValidationError'): {
|
|
171
|
+
statusCode = 500;
|
|
172
|
+
errorResponse.details = { message:'Error' };
|
|
173
|
+
break;
|
|
174
|
+
}
|
|
175
|
+
default: {
|
|
176
|
+
errorResponse.details = { message:errorMessage };
|
|
177
|
+
break;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Send error response with provided status code.
|
|
182
|
+
return this.respondNotOk(res, {
|
|
183
|
+
error: {
|
|
184
|
+
...errorResponse,
|
|
185
|
+
code: statusCode
|
|
186
|
+
},
|
|
187
|
+
status: statusCode
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
return controller;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Sets one of CRUD methods to Controller.
|
|
197
|
+
*
|
|
198
|
+
* @param {Function|Object} controller
|
|
199
|
+
* @param {Object} opts
|
|
200
|
+
*
|
|
201
|
+
* @return {Function|Object} controller
|
|
202
|
+
*
|
|
203
|
+
* @api public
|
|
204
|
+
* @alias withDefaultCRUD
|
|
205
|
+
*/
|
|
206
|
+
function _setMethod(controller,) {
|
|
207
|
+
if (!controller) {
|
|
208
|
+
const err = new TypeError(`'controller' argument is not provided.`);
|
|
209
|
+
throw err;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
|
|
2
|
+
module.exports = Enum;
|
|
3
|
+
|
|
4
|
+
function Enum(constantsList = {}, writable=false) {
|
|
5
|
+
const def = (key, value) => Object.defineProperty(this, key, { value, writable: !!writable });
|
|
6
|
+
|
|
7
|
+
// Set list.
|
|
8
|
+
def('list', constantsList);
|
|
9
|
+
|
|
10
|
+
// Set getters:
|
|
11
|
+
Object.keys(constantsList)
|
|
12
|
+
.forEach(key => def(key, constantsList[key]) );
|
|
13
|
+
|
|
14
|
+
// Set constants in static array.
|
|
15
|
+
def('asArray', Object.values(constantsList) );
|
|
16
|
+
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
|
|
2
|
+
module.exports = class CustomError extends Error {
|
|
2
3
|
constructor(message) {
|
|
3
4
|
super(message);
|
|
5
|
+
|
|
4
6
|
this.name = this.constructor.name;
|
|
5
7
|
this.status = 500;
|
|
6
8
|
|
|
@@ -14,9 +16,9 @@ class CustomError extends Error {
|
|
|
14
16
|
this.status = originalError?.status ?? this.status;
|
|
15
17
|
|
|
16
18
|
// Append stack from original error.
|
|
17
|
-
const
|
|
18
|
-
this.stack = this.stack.split('\n')
|
|
19
|
+
const linesCount = (this.message.match(/\n/g)||[]).length + 1;
|
|
20
|
+
this.stack = this.stack.split('\n')
|
|
21
|
+
.slice(0, linesCount+1)
|
|
22
|
+
.join('\n') + '\n' + originalError.stack;
|
|
19
23
|
}
|
|
20
24
|
}
|
|
21
|
-
|
|
22
|
-
module.exports = CustomError;
|
|
@@ -1,7 +1,12 @@
|
|
|
1
|
-
|
|
1
|
+
/*
|
|
2
|
+
* WARNING: Unfinihsed. Do not use!
|
|
3
|
+
*
|
|
4
|
+
*/
|
|
2
5
|
|
|
6
|
+
const Params = require('../../params/Params');
|
|
3
7
|
|
|
4
|
-
|
|
8
|
+
|
|
9
|
+
module.exports = class HtmlResponseFactory {
|
|
5
10
|
constructor() {}
|
|
6
11
|
|
|
7
12
|
/**
|