nodester 0.0.1 → 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.
Files changed (69) hide show
  1. package/Readme.md +33 -39
  2. package/lib/application/index.js +110 -38
  3. package/lib/constants/Operations.js +23 -0
  4. package/lib/controllers/methods/index.js +194 -0
  5. package/lib/controllers/mixins/index.js +222 -0
  6. package/lib/database/connection.js +34 -0
  7. package/lib/database/migration.js +42 -0
  8. package/lib/database/utils.js +19 -0
  9. package/lib/enums/Enum.js +16 -0
  10. package/lib/facades/methods/index.js +173 -0
  11. package/lib/facades/mixins/index.js +111 -0
  12. package/lib/factories/errors/CustomError.js +7 -5
  13. package/lib/factories/responses/html.js +7 -2
  14. package/lib/factories/responses/rest.js +110 -0
  15. package/lib/http/codes/index.js +157 -0
  16. package/lib/{application/http → http}/request.js +6 -30
  17. package/lib/{application/http → http}/response.js +20 -53
  18. package/lib/middlewares/etag/index.js +62 -0
  19. package/lib/middlewares/ql/sequelize/index.js +34 -0
  20. package/lib/middlewares/ql/sequelize/interpreter/ModelsTree.js +121 -0
  21. package/lib/middlewares/ql/sequelize/interpreter/QueryLexer.js +456 -0
  22. package/lib/models/associate.js +17 -0
  23. package/lib/models/define.js +56 -14
  24. package/lib/models/mixins.js +100 -78
  25. package/lib/params/Params.js +37 -0
  26. package/lib/queries/Colander.js +84 -0
  27. package/lib/queries/NodesterQueryParams.js +139 -0
  28. package/lib/queries/traverse.js +311 -0
  29. package/lib/router/handlers.util.js +81 -0
  30. package/lib/router/index.js +441 -0
  31. package/lib/router/route.js +124 -0
  32. package/lib/router/routes.util.js +85 -0
  33. package/lib/router/utils.js +30 -0
  34. package/lib/stacks/MarkersStack.js +35 -0
  35. package/lib/{application → stacks}/MiddlewareStack.js +47 -13
  36. package/lib/utils/path.util.js +3 -1
  37. package/lib/utils/types.util.js +51 -1
  38. package/lib/validators/dates.js +25 -0
  39. package/lib/validators/numbers.js +14 -0
  40. package/package.json +31 -4
  41. package/tests/index.test.js +7 -2
  42. package/tests/nql.test.js +277 -0
  43. package/docs/App.md +0 -13
  44. package/docs/Queries.md +0 -61
  45. package/docs/Readme.md +0 -2
  46. package/docs/Routing.md +0 -34
  47. package/examples/goal/index.js +0 -23
  48. package/examples/rest/index.js +0 -25
  49. package/examples/rest/node_modules/.package-lock.json +0 -40
  50. package/examples/rest/package-lock.json +0 -72
  51. package/examples/rest/package.json +0 -14
  52. package/lib/constants/ConstantsEnum.js +0 -13
  53. package/lib/controllers/Controller.js +0 -474
  54. package/lib/controllers/JWTController.js +0 -240
  55. package/lib/controllers/ServiceController.js +0 -109
  56. package/lib/controllers/WebController.js +0 -75
  57. package/lib/facades/Facade.js +0 -388
  58. package/lib/facades/FacadeParams.js +0 -11
  59. package/lib/facades/ServiceFacade.js +0 -17
  60. package/lib/facades/jwt.facade.js +0 -273
  61. package/lib/factories/responses/api.js +0 -90
  62. package/lib/models/DisabledRefreshToken.js +0 -68
  63. package/lib/models/Extractor.js +0 -320
  64. package/lib/routers/Default/index.js +0 -143
  65. package/lib/routers/Default/layer.js +0 -50
  66. package/lib/routers/Main/index.js +0 -10
  67. package/lib/routers/Roles/index.js +0 -81
  68. package/lib/utils/params.util.js +0 -19
  69. /package/lib/{application/http → http}/utils.js +0 -0
@@ -0,0 +1,441 @@
1
+ /*!
2
+ * /nodester
3
+ * MIT Licensed
4
+ */
5
+
6
+ 'use strict';
7
+
8
+ const MiddlewareStack = require('../stacks/MiddlewareStack');
9
+ const MarkersStack = require('../stacks/MarkersStack');
10
+ const Route = require('./route');
11
+ // Utils:
12
+ const { typeOf } = require('../utils/types.util');
13
+ const { wrapRouteHandler } = require('./routes.util');
14
+ const { parseProviderFileNames } = require('./utils');
15
+ // File system:
16
+ const Path = require('path');
17
+ const fs = require('fs');
18
+ const commonExtensions = require('common-js-file-extensions');
19
+ // Debug & console:
20
+ const consl = require('../logger/console');
21
+ const debug = require('debug')('nodester:router');
22
+
23
+
24
+ module.exports = class NodesterRouter {
25
+
26
+ /**
27
+ * Initialize a new `NodesterRouter`.
28
+ *
29
+ * @param {Object} opts
30
+ * - {Array} codeFileExtensions
31
+ * - {String} controllersPath
32
+ * - {Object} controllers
33
+ * - {Boolean} finalhandlerEnabled
34
+ *
35
+ * @api public
36
+ */
37
+ constructor(opts={}) {
38
+ // Reference to the controllers stack.
39
+ this._controllers = new Map();
40
+
41
+ // Reference to middlewares stack.
42
+ this._middlewares = new MiddlewareStack({ finalhandlerEnabled: !!opts.finalhandlerEnabled });
43
+
44
+ // Reference to the markers stack.
45
+ this._markers = new MarkersStack();
46
+
47
+ // Reference to the providers stack.
48
+ this._providers = new Map();
49
+
50
+ this.codeFileExtensions = commonExtensions.code;
51
+ this.paths = {};
52
+
53
+ // Indicates whether we can add more middlewares or no.
54
+ this.isLocked = false;
55
+
56
+ // Options:
57
+ // if "codeFileExtensions" was set:
58
+ if (!!opts.codeFileExtensions && Array.isArray(opts.codeFileExtensions)) {
59
+ this.codeFileExtensions = [...opts.codeFileExtensions];
60
+ }
61
+
62
+ // If "controllersPath" was set,
63
+ // cache all controllers in directory:
64
+ if (!!opts.controllersPath) {
65
+ // Save path.
66
+ this.paths.controllers = opts.controllersPath;
67
+
68
+ // Only get files, which have available file extensions:
69
+ const availableFileExtensions = this.codeFileExtensions;
70
+ const fileNames = fs.readdirSync(this.paths.controllers);
71
+
72
+ const controllersNames = parseProviderFileNames(fileNames, availableFileExtensions, 'controller');
73
+
74
+ for (const { fileName, controllerName } of controllersNames) {
75
+ const controller = require(Path.join(this.paths.controllers, fileName));
76
+ this.addController(controller, controllerName);
77
+ }
78
+ }
79
+
80
+ // If "controllers" were provided as an Object:
81
+ if (!!opts.controllers) {
82
+ if (typeOf(opts.controllers) !== 'Object') {
83
+ const err = new TypeError(`"controllers" must be an Object.`);
84
+ throw err;
85
+ }
86
+
87
+ const entities = Object.entities(opts.controllers);
88
+ for (const [controllerName, controllerDefinition] of entities) {
89
+ this.addController(controllerDefinition, controllerName);
90
+ }
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
+ }
123
+ }
124
+
125
+
126
+ /*
127
+ * Adds:
128
+ * - (controller) new controller to the stack;
129
+ * - (middleware) new middleware to the stack;
130
+ * - (marker) new marker to the stack;
131
+ * - (route) new route to the stack;
132
+ *
133
+ * @api public
134
+ */
135
+ get add() {
136
+ return {
137
+ controller: this.addController.bind(this),
138
+ middleware: this.addMiddleware.bind(this),
139
+ marker: this.addMarker.bind(this),
140
+ provider: this.addProvider.bind(this),
141
+ route: this.addRoute.bind(this),
142
+ routes: this.addRoutes.bind(this),
143
+ }
144
+ }
145
+
146
+
147
+ /*
148
+ * Adds new controller to the controllers stack.
149
+ *
150
+ * @param {Function|Object} controller
151
+ * @param {String} controllerName
152
+ *
153
+ * @api public
154
+ */
155
+ addController(fnOrObject, controllerName=null) {
156
+ const controllerType = typeOf(fnOrObject);
157
+ const name = controllerName ?? fnOrObject?.name ?? fnOrObject.constructor.name;
158
+
159
+ // If controller was exported as Object:
160
+ if (controllerType === 'Object') {
161
+ this._controllers.set(name, fnOrObject);
162
+ }
163
+ // If controller was exported as a constructor function:
164
+ else if (controllerType === 'function') {
165
+ this._controllers.set(name, new fnOrObject());
166
+ }
167
+ else {
168
+ const err = new TypeError(`Please check how you exported ${ name }, it should be either Object or constructor function.`);
169
+ throw err;
170
+ }
171
+ }
172
+
173
+
174
+ /*
175
+ * Adds new middleware to the stack.
176
+ *
177
+ * @param {Function} fn
178
+ * @param {Integer} index (0 or undefined)
179
+ *
180
+ * @return {Integer} index of new middleware
181
+ *
182
+ * @api public
183
+ */
184
+ addMiddleware(fn, index) {
185
+ return this._middlewares.add(fn, index);
186
+ }
187
+
188
+
189
+ /*
190
+ * Adds new marker to the stack.
191
+ *
192
+ * @param {String} markerName
193
+ * @param {Function} fn
194
+ *
195
+ * @api public
196
+ */
197
+ addMarker(markerName='', fn) {
198
+ if (markerName.length > 0 && markerName.indexOf('/') > -1) {
199
+ const err = new TypeError(`"markerName" can't contain slashes "/"`);
200
+ throw err;
201
+ }
202
+
203
+ if (this._markers.get(markerName)) {
204
+ const err = new Error(`Marker with name ${ markerName } is already set.`);
205
+ throw err;
206
+ }
207
+
208
+ this._markers.add(markerName, fn);
209
+ }
210
+
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
+
239
+ /*
240
+ * Creates route middleware and adds it to the stack.
241
+ *
242
+ * @param {String} route
243
+ * @param {Object|Function} handler
244
+ *
245
+ * @api public
246
+ */
247
+ addRoute(route='', handler) {
248
+ const parsed = new Route(route);
249
+ const handlerType = typeOf(handler);
250
+
251
+ // ToDo: move it to separate validator:
252
+ if (parsed.method === undefined) {
253
+ const err = new TypeError(`"route" should start with one of the following methods: [GET, POST, PUT, DELETE, QUERY, HEADER, OPTIONS]`);
254
+ throw err;
255
+ }
256
+
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);
260
+ throw err;
261
+ }
262
+
263
+ const wrapped = wrapRouteHandler.call(this, parsed, handler);
264
+ return this.addMiddleware(wrapped);
265
+ }
266
+
267
+
268
+ /*
269
+ * Loops through provided "routes" object
270
+ * and adds them throught "addRoute".
271
+ *
272
+ * @param {Object} routes
273
+ *
274
+ * @api public
275
+ */
276
+ addRoutes(routes={}) {
277
+ for (const [route, handler] of Object.entries(routes)) {
278
+ this.addRoute(route, handler);
279
+ }
280
+ }
281
+
282
+
283
+ /*
284
+ * Proxy to .add.middleware()
285
+ *
286
+ * @param {Function} fn
287
+ *
288
+ * @api public
289
+ */
290
+ use(fn) {
291
+ return this.add.middleware(fn);
292
+ }
293
+
294
+
295
+ /*
296
+ * Adds middlewares, which only fires for set marker.
297
+ *
298
+ * @param {String} markerName
299
+ *
300
+ * @api public
301
+ */
302
+ only(markerName='') {
303
+ const self = this;
304
+ const markerFn = this._markers.get(markerName);
305
+
306
+ return {
307
+ route: (route, fn) => {
308
+ const parsed = new Route(route);
309
+ // ToDo: move it to separate validator:
310
+ if (parsed.method === undefined) {
311
+ const err = new TypeError(`"route" should start with one of the following methods: [GET, POST, PUT, DELETE, QUERY, HEADER, OPTIONS]`);
312
+ throw err;
313
+ }
314
+
315
+ const wrapped = async (req, res, next) => {
316
+ const matched = await markerFn.call(self, req, res);
317
+ // Skip, if marker's condition was not matched:
318
+ if (!matched) {
319
+ return next();
320
+ }
321
+
322
+ // Wrap and call:
323
+ const routeHandler = wrapRouteHandler.call(self, parsed, fn);
324
+ await routeHandler.call(self, req, res, next);
325
+
326
+ // If response was not sent,
327
+ // go to next one:
328
+ if (res.headersSent === false) {
329
+ next();
330
+ }
331
+ };
332
+ return self.add.route(wrapped);
333
+ },
334
+ use: (fn) => {
335
+ const wrapped = async (req, res, next) => {
336
+ const matched = await markerFn.call(self, req, res);
337
+ // Skip, if marker's condition was not matched:
338
+ if (!matched) {
339
+ return next();
340
+ }
341
+
342
+ await fn.call(self, req, res, next);
343
+
344
+ // If response was not sent,
345
+ // go to next one:
346
+ if (res.headersSent === false) {
347
+ next();
348
+ }
349
+ };
350
+ return self.use(wrapped);
351
+ }
352
+ }
353
+ }
354
+
355
+
356
+ /**
357
+ * Handles server request.
358
+ *
359
+ * @api public
360
+ */
361
+ handle(req, res, next) {
362
+ return this._middlewares.process(req, res, next)
363
+ }
364
+
365
+
366
+ /*
367
+ * Prepare router for processing.
368
+ *
369
+ * @api public
370
+ */
371
+ lock() {
372
+ // Stack is ready.
373
+ this.isLocked = true;
374
+
375
+ debug(`router is locked`);
376
+
377
+ this._middlewares.lock();
378
+ }
379
+
380
+
381
+ /*
382
+ * Unlocks router.
383
+ *
384
+ * @api public
385
+ */
386
+ unlock() {
387
+ this.isLocked = false;
388
+
389
+ debug(`router is unlocked`);
390
+
391
+ this._middlewares.unlock();
392
+ }
393
+
394
+
395
+ /*
396
+ * Removes something
397
+ */
398
+ get remove() {
399
+ return {
400
+ middleware: this.removeMiddleware.bind(this)
401
+ }
402
+ }
403
+
404
+
405
+ /**
406
+ * Removes middleware at index.
407
+ *
408
+ * @param {Integer} index
409
+ *
410
+ * @return {Integer} middlewares stack length
411
+ *
412
+ * @api public
413
+ */
414
+ removeMiddleware(index=-1) {
415
+ this._middlewares.remove(index);
416
+ return this._middlewares.length;
417
+ }
418
+
419
+
420
+
421
+ /**
422
+ * Extends Router & makes sure, that "key" param is not present already.
423
+ *
424
+ * @param {String} key
425
+ * @param {Any} fnOrProperty
426
+ * @return {Any} fnOrProperty in Router
427
+ *
428
+ * @api public
429
+ */
430
+ extend(key='', fnOrProperty) {
431
+ const keys = Object.keys(this);
432
+ if (keys.indexOf(key) > -1) {
433
+ const err = new TypeError(`Key ${ key } is already present in Router instance`);
434
+ throw err;
435
+ }
436
+
437
+ this[key] = fnOrProperty;
438
+
439
+ return this[key];
440
+ }
441
+ }
@@ -0,0 +1,124 @@
1
+ /*!
2
+ * /nodester
3
+ * MIT Licensed
4
+ */
5
+
6
+ 'use strict';
7
+
8
+ // Utils.
9
+ const { typeOf } = require('../utils/types.util');
10
+
11
+
12
+ module.exports = class NodesterRoute {
13
+
14
+ /**
15
+ * Initialize a new `NodesterRoute`.
16
+ *
17
+ * @param {Object|String} routeStringOrOpts
18
+ * - {String} method
19
+ * - {String} route
20
+ * - {Array} parts
21
+ * - {Object} params
22
+ *
23
+ * @api public
24
+ */
25
+ constructor(routeStringOrOpts={}) {
26
+ if (typeOf(routeStringOrOpts) === 'Object') {
27
+ this.method = opts.method ?? undefined;
28
+ this.route = opts.route ?? null;
29
+ this.parts = opts.parts ?? [];
30
+ this.params = opts.params ?? {};
31
+ }
32
+ else if (typeOf(routeStringOrOpts) === 'string'){
33
+ this.method = undefined;
34
+ this.route = null;
35
+ this.parts = [];
36
+ this.params = {};
37
+
38
+ if (routeStringOrOpts.length === 0) {
39
+ return this;
40
+ }
41
+
42
+ // Parse:
43
+ const parts = routeStringOrOpts.split(' ');
44
+ const cleared = parts.filter(p => p.length > 0);
45
+
46
+ // Set method:
47
+ if (cleared[0].indexOf('/') === -1) {
48
+ const method = cleared.shift().toUpperCase();
49
+ this.method = method;
50
+ }
51
+
52
+ // Build route one again and set it:
53
+ const clearRoute = cleared.join('');
54
+ this.route = clearRoute;
55
+
56
+ // Parse path parts:
57
+ const pathParts = clearRoute.split('/')
58
+ .filter(p => p.length > 0);
59
+ this.parts = pathParts;
60
+ }
61
+ }
62
+
63
+
64
+ /**
65
+ * @param {String} routeToTest
66
+ *
67
+ * @return {Boolean}
68
+ *
69
+ * @alias matches
70
+ * @private
71
+ */
72
+ matches(routeToTest='') {
73
+ const {
74
+ route,
75
+ parts,
76
+ params
77
+ } = this;
78
+
79
+ if (routeToTest === route) {
80
+ return true;
81
+ }
82
+
83
+ // Break route & test:
84
+ const testParts = routeToTest.split('/')
85
+ .filter(p => p.length > 0);
86
+ let matched = true;
87
+ if (testParts.length === 0) {
88
+ matched = route === '/';
89
+ }
90
+ else {
91
+ for (let i=0; i < testParts.length; i++) {
92
+ const part = parts[i];
93
+ const testPart = testParts[i];
94
+
95
+ // If route is shorter:
96
+ if (!part) {
97
+ matched = false;
98
+ break;
99
+ }
100
+
101
+ // If part is wild:
102
+ if (part === '*') {
103
+ matched = true;
104
+ this.params.pathParts = testParts.slice(i);
105
+ break;
106
+ }
107
+
108
+ // If part is param:
109
+ if (part[0] === ':') {
110
+ this.params[part.split(':')[1]] = testPart;
111
+ continue;
112
+ }
113
+
114
+ // If not matched:
115
+ if (part !== testPart) {
116
+ matched = false;
117
+ break;
118
+ }
119
+ }
120
+ }
121
+
122
+ return matched;
123
+ }
124
+ }
@@ -0,0 +1,85 @@
1
+ /*!
2
+ * /nodester
3
+ * MIT Licensed
4
+ */
5
+
6
+ 'use strict';
7
+
8
+ // Utils:
9
+ const { typeOf } = require('../utils/types.util');
10
+ const { parseRouteHandler } = require('./handlers.util');
11
+
12
+
13
+ module.exports = {
14
+ wrapRouteHandler: _wrapRouteHandler
15
+ }
16
+
17
+
18
+ /**
19
+ * Wraps route handler.
20
+ *
21
+ * @param {Route} routeInstance
22
+ * @param {Function} handler
23
+ *
24
+ * @alias wrapRouteHandler
25
+ * @api public
26
+ */
27
+ function _wrapRouteHandler(routeInstance, handler) {
28
+ const handlerType = typeOf(handler);
29
+
30
+ const wrapped = async (req, res, next) => {
31
+ // Get route without SearchParams.
32
+ const route = req.url.split('?')[0];
33
+
34
+ // If route not matched:
35
+ const methodMatched = routeInstance.method === req.method;
36
+ const routeMatched = routeInstance.matches(route);
37
+ if (!methodMatched || !routeMatched) {
38
+ return next();
39
+ }
40
+
41
+ // Populate params.
42
+ req.params = routeInstance.params;
43
+
44
+ if (handlerType === 'function') {
45
+ await handler.call(this, req, res, next);
46
+ }
47
+ // If handler is an Object:
48
+ else {
49
+ const parsedHandler = parseRouteHandler(handler);
50
+
51
+ let providedAction = null;
52
+
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:
75
+ if (typeOf(parsedHandler.before) === 'function') {
76
+ // Expose nquery first.
77
+ await parsedHandler.before(req.nquery, req, res);
78
+ }
79
+
80
+ await providedAction(req, res);
81
+ }
82
+ };
83
+
84
+ return wrapped;
85
+ }
@@ -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
+ }
@@ -0,0 +1,35 @@
1
+ const consl = require('../logger/console');
2
+ const debug = require('debug')('nodester:MiddlewareStack');
3
+
4
+
5
+ module.exports = class MarkersStack {
6
+ constructor() {
7
+ this.markers = new Map();
8
+ }
9
+
10
+
11
+ /**
12
+ * Add the given middleware `fn` to the stack.
13
+ *
14
+ * @param {String} markerName
15
+ * @param {Function} fn
16
+ * @return {Integer} index of new middleware
17
+ *
18
+ * @api public
19
+ */
20
+ add(markerName='', fn) {
21
+ return this.markers.set(markerName, fn);
22
+ }
23
+
24
+
25
+ /**
26
+ * Get middleware function by marker name.
27
+ *
28
+ * @param {String} markerName
29
+ *
30
+ * @api public
31
+ */
32
+ get(markerName='') {
33
+ return this.markers.get(markerName);
34
+ }
35
+ }