nodester 0.0.2 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/controllers/mixins/index.js +2 -2
- package/lib/router/handlers.util.js +22 -2
- package/lib/router/index.js +73 -18
- package/lib/router/routes.util.js +24 -5
- package/lib/router/utils.js +30 -0
- package/package.json +1 -1
|
@@ -170,7 +170,7 @@ function _withDefaultErrorProcessing(controller, opts={}) {
|
|
|
170
170
|
}
|
|
171
171
|
case('InternalValidationError'): {
|
|
172
172
|
statusCode = 500;
|
|
173
|
-
errorResponse.details = { message:'Error' };
|
|
173
|
+
errorResponse.details = { message: 'Error' };
|
|
174
174
|
break;
|
|
175
175
|
}
|
|
176
176
|
default: {
|
|
@@ -181,7 +181,7 @@ function _withDefaultErrorProcessing(controller, opts={}) {
|
|
|
181
181
|
|
|
182
182
|
// Send error response with provided status code:
|
|
183
183
|
const data = {
|
|
184
|
-
|
|
184
|
+
error: {
|
|
185
185
|
...errorResponse,
|
|
186
186
|
code: statusCode
|
|
187
187
|
},
|
|
@@ -26,19 +26,24 @@ function _parseRouteHandler(routeHandler={}) {
|
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
const result = {
|
|
29
|
+
actionName: undefined,
|
|
29
30
|
before: null,
|
|
30
31
|
controllerName: undefined,
|
|
31
|
-
|
|
32
|
+
providerName: undefined
|
|
32
33
|
};
|
|
33
34
|
|
|
34
35
|
const {
|
|
36
|
+
action,
|
|
35
37
|
before,
|
|
36
38
|
|
|
37
39
|
controller,
|
|
38
40
|
controlledBy,
|
|
39
|
-
|
|
41
|
+
|
|
42
|
+
provider,
|
|
43
|
+
providedBy,
|
|
40
44
|
} = routeHandler;
|
|
41
45
|
|
|
46
|
+
// Controllers:
|
|
42
47
|
if (!!controlledBy) {
|
|
43
48
|
const parts = controlledBy.split('.');
|
|
44
49
|
const controllerName = parts[0];
|
|
@@ -49,6 +54,21 @@ function _parseRouteHandler(routeHandler={}) {
|
|
|
49
54
|
else if (!!controller) {
|
|
50
55
|
result.controllerName = `${ controller }`;
|
|
51
56
|
}
|
|
57
|
+
// Controllers\
|
|
58
|
+
|
|
59
|
+
// Providers:
|
|
60
|
+
else if (!!providedBy) {
|
|
61
|
+
const parts = providedBy.split('.');
|
|
62
|
+
const providerName = parts[0];
|
|
63
|
+
const actionName = parts[1];
|
|
64
|
+
result.providerName = providerName;
|
|
65
|
+
result.actionName = actionName;
|
|
66
|
+
}
|
|
67
|
+
else if (!!provider) {
|
|
68
|
+
result.providerName = `${ provider }`;
|
|
69
|
+
}
|
|
70
|
+
// Providers\
|
|
71
|
+
|
|
52
72
|
else if (!!action) {
|
|
53
73
|
result.actionName = `${ action }`;
|
|
54
74
|
}
|
package/lib/router/index.js
CHANGED
|
@@ -11,6 +11,7 @@ const Route = require('./route');
|
|
|
11
11
|
// Utils:
|
|
12
12
|
const { typeOf } = require('../utils/types.util');
|
|
13
13
|
const { wrapRouteHandler } = require('./routes.util');
|
|
14
|
+
const { parseProviderFileNames } = require('./utils');
|
|
14
15
|
// File system:
|
|
15
16
|
const Path = require('path');
|
|
16
17
|
const fs = require('fs');
|
|
@@ -34,14 +35,17 @@ module.exports = class NodesterRouter {
|
|
|
34
35
|
* @api public
|
|
35
36
|
*/
|
|
36
37
|
constructor(opts={}) {
|
|
38
|
+
// Reference to the controllers stack.
|
|
39
|
+
this._controllers = new Map();
|
|
40
|
+
|
|
37
41
|
// Reference to middlewares stack.
|
|
38
42
|
this._middlewares = new MiddlewareStack({ finalhandlerEnabled: !!opts.finalhandlerEnabled });
|
|
39
43
|
|
|
40
44
|
// Reference to the markers stack.
|
|
41
45
|
this._markers = new MarkersStack();
|
|
42
46
|
|
|
43
|
-
// Reference to the
|
|
44
|
-
this.
|
|
47
|
+
// Reference to the providers stack.
|
|
48
|
+
this._providers = new Map();
|
|
45
49
|
|
|
46
50
|
this.codeFileExtensions = commonExtensions.code;
|
|
47
51
|
this.paths = {};
|
|
@@ -55,29 +59,20 @@ module.exports = class NodesterRouter {
|
|
|
55
59
|
this.codeFileExtensions = [...opts.codeFileExtensions];
|
|
56
60
|
}
|
|
57
61
|
|
|
58
|
-
// If "controllersPath" was set,
|
|
62
|
+
// If "controllersPath" was set,
|
|
63
|
+
// cache all controllers in directory:
|
|
59
64
|
if (!!opts.controllersPath) {
|
|
60
65
|
// Save path.
|
|
61
66
|
this.paths.controllers = opts.controllersPath;
|
|
62
67
|
|
|
63
|
-
const availableFileExtensions = this.codeFileExtensions;
|
|
64
68
|
// Only get files, which have available file extensions:
|
|
69
|
+
const availableFileExtensions = this.codeFileExtensions;
|
|
65
70
|
const fileNames = fs.readdirSync(this.paths.controllers);
|
|
66
|
-
for (const fileName of fileNames) {
|
|
67
71
|
|
|
68
|
-
|
|
69
|
-
const extension = nameParts.pop();
|
|
70
|
-
if (availableFileExtensions.indexOf(extension) === -1) {
|
|
71
|
-
continue;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// If the name format is <model>.<controller>,
|
|
75
|
-
// but second part is not "controller":
|
|
76
|
-
if (nameParts.length > 1 && nameParts[1] !== 'controller')
|
|
77
|
-
continue;
|
|
72
|
+
const controllersNames = parseProviderFileNames(fileNames, availableFileExtensions, 'controller');
|
|
78
73
|
|
|
74
|
+
for (const { fileName, controllerName } of controllersNames) {
|
|
79
75
|
const controller = require(Path.join(this.paths.controllers, fileName));
|
|
80
|
-
const controllerName = nameParts[0];
|
|
81
76
|
this.addController(controller, controllerName);
|
|
82
77
|
}
|
|
83
78
|
}
|
|
@@ -94,6 +89,37 @@ module.exports = class NodesterRouter {
|
|
|
94
89
|
this.addController(controllerDefinition, controllerName);
|
|
95
90
|
}
|
|
96
91
|
}
|
|
92
|
+
|
|
93
|
+
// If "providersPath" was set,
|
|
94
|
+
// cache all providers in directory:
|
|
95
|
+
if (!!opts.providersPath) {
|
|
96
|
+
// Save path.
|
|
97
|
+
this.paths.providers = opts.providersPath;
|
|
98
|
+
|
|
99
|
+
// Only get files, which have available file extensions:
|
|
100
|
+
const availableFileExtensions = this.codeFileExtensions;
|
|
101
|
+
const fileNames = fs.readdirSync(this.paths.providers);
|
|
102
|
+
|
|
103
|
+
const providersNames = parseProviderFileNames(fileNames, availableFileExtensions, 'provider');
|
|
104
|
+
|
|
105
|
+
for (const { fileName, providerName } of providersNames) {
|
|
106
|
+
const provider = require(Path.join(this.paths.providers, fileName));
|
|
107
|
+
this.addProvider(provider, providerName);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// If "providers" were provided as an Object:
|
|
112
|
+
if (!!opts.providers) {
|
|
113
|
+
if (typeOf(opts.providers) !== 'Object') {
|
|
114
|
+
const err = new TypeError(`"providers" must be an Object.`);
|
|
115
|
+
throw err;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const entities = Object.entities(opts.providers);
|
|
119
|
+
for (const [providerName, providerDefinition] of entities) {
|
|
120
|
+
this.addProvider(providerDefinition, providerName);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
97
123
|
}
|
|
98
124
|
|
|
99
125
|
|
|
@@ -111,6 +137,7 @@ module.exports = class NodesterRouter {
|
|
|
111
137
|
controller: this.addController.bind(this),
|
|
112
138
|
middleware: this.addMiddleware.bind(this),
|
|
113
139
|
marker: this.addMarker.bind(this),
|
|
140
|
+
provider: this.addProvider.bind(this),
|
|
114
141
|
route: this.addRoute.bind(this),
|
|
115
142
|
routes: this.addRoutes.bind(this),
|
|
116
143
|
}
|
|
@@ -182,6 +209,33 @@ module.exports = class NodesterRouter {
|
|
|
182
209
|
}
|
|
183
210
|
|
|
184
211
|
|
|
212
|
+
/*
|
|
213
|
+
* Adds new provider to the providers stack.
|
|
214
|
+
*
|
|
215
|
+
* @param {Function|Object} provider
|
|
216
|
+
* @param {String} providerName
|
|
217
|
+
*
|
|
218
|
+
* @api public
|
|
219
|
+
*/
|
|
220
|
+
addProvider(fnOrObject, providerName=null) {
|
|
221
|
+
const providerType = typeOf(fnOrObject);
|
|
222
|
+
const name = providerName ?? fnOrObject?.name ?? fnOrObject.constructor.name;
|
|
223
|
+
|
|
224
|
+
// If provider was exported as Object:
|
|
225
|
+
if (providerType === 'Object') {
|
|
226
|
+
this._providers.set(name, fnOrObject);
|
|
227
|
+
}
|
|
228
|
+
// If provider was exported as a constructor function:
|
|
229
|
+
else if (providerType === 'function') {
|
|
230
|
+
this._providers.set(name, new fnOrObject());
|
|
231
|
+
}
|
|
232
|
+
else {
|
|
233
|
+
const err = new TypeError(`Please check how you exported ${ name }, it should be either Object or constructor function.`);
|
|
234
|
+
throw err;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
|
|
185
239
|
/*
|
|
186
240
|
* Creates route middleware and adds it to the stack.
|
|
187
241
|
*
|
|
@@ -200,8 +254,9 @@ module.exports = class NodesterRouter {
|
|
|
200
254
|
throw err;
|
|
201
255
|
}
|
|
202
256
|
|
|
203
|
-
if (handlerType === 'Object' && !this.paths.controllers) {
|
|
204
|
-
const
|
|
257
|
+
if (handlerType === 'Object' && !this.paths.controllers && !this.paths.providers) {
|
|
258
|
+
const msg = `Please set "controllersPath" or "providersPath" during Router initialization.`;
|
|
259
|
+
const err = new TypeError(msg);
|
|
205
260
|
throw err;
|
|
206
261
|
}
|
|
207
262
|
|
|
@@ -48,17 +48,36 @@ function _wrapRouteHandler(routeInstance, handler) {
|
|
|
48
48
|
else {
|
|
49
49
|
const parsedHandler = parseRouteHandler(handler);
|
|
50
50
|
|
|
51
|
-
|
|
52
|
-
const controller = this._controllers.get(parsedHandler.controllerName);
|
|
53
|
-
const controllerAction = controller[parsedHandler.actionName];
|
|
51
|
+
let providedAction = null;
|
|
54
52
|
|
|
55
|
-
// If
|
|
53
|
+
// If Controller:
|
|
54
|
+
if (parsedHandler.controllerName !== undefined) {
|
|
55
|
+
// Get method (action) from Controller:
|
|
56
|
+
const controller = this._controllers.get(parsedHandler.controllerName);
|
|
57
|
+
const controllerAction = controller[parsedHandler.actionName];
|
|
58
|
+
|
|
59
|
+
providedAction = controllerAction;
|
|
60
|
+
}
|
|
61
|
+
// If Controller\
|
|
62
|
+
|
|
63
|
+
// If Provider:
|
|
64
|
+
else {
|
|
65
|
+
// Get method (action) from Provider:
|
|
66
|
+
const provider = this._providers.get(parsedHandler.providerName);
|
|
67
|
+
const providerAction = provider[parsedHandler.actionName];
|
|
68
|
+
|
|
69
|
+
providedAction = providerAction;
|
|
70
|
+
}
|
|
71
|
+
// If Provider\
|
|
72
|
+
|
|
73
|
+
// If User set any handler before,
|
|
74
|
+
// call it first:
|
|
56
75
|
if (typeOf(parsedHandler.before) === 'function') {
|
|
57
76
|
// Expose nquery first.
|
|
58
77
|
await parsedHandler.before(req.nquery, req, res);
|
|
59
78
|
}
|
|
60
79
|
|
|
61
|
-
await
|
|
80
|
+
await providedAction(req, res);
|
|
62
81
|
}
|
|
63
82
|
};
|
|
64
83
|
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
|
|
2
|
+
module.exports = {
|
|
3
|
+
parseProviderFileNames: _parseProviderFileNames
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
function _parseProviderFileNames(fileNames, availableFileExtensions, term='controller') {
|
|
7
|
+
const resultNames = [];
|
|
8
|
+
|
|
9
|
+
for (const fileName of fileNames) {
|
|
10
|
+
|
|
11
|
+
const nameParts = fileName.split('.');
|
|
12
|
+
const extension = nameParts.pop();
|
|
13
|
+
if (availableFileExtensions.indexOf(extension) === -1) {
|
|
14
|
+
continue;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// If the name format is <model>.<term>,
|
|
18
|
+
// but second part is not "term":
|
|
19
|
+
if (nameParts.length > 1 && nameParts[1] !== term)
|
|
20
|
+
continue;
|
|
21
|
+
|
|
22
|
+
const result = {
|
|
23
|
+
fileName: fileName,
|
|
24
|
+
[`${ term }Name`]: nameParts[0]
|
|
25
|
+
}
|
|
26
|
+
resultNames.push(result);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return resultNames;
|
|
30
|
+
}
|