nodester 0.0.1 → 0.0.6

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 (58) hide show
  1. package/Readme.md +61 -26
  2. package/lib/application/index.js +86 -35
  3. package/lib/constants/Operations.js +23 -0
  4. package/lib/controllers/methods/index.js +170 -0
  5. package/lib/controllers/mixins/index.js +213 -0
  6. package/lib/enums/Enum.js +16 -0
  7. package/lib/factories/errors/CustomError.js +7 -5
  8. package/lib/factories/responses/html.js +7 -2
  9. package/lib/factories/responses/rest.js +110 -0
  10. package/lib/http/codes/index.js +157 -0
  11. package/lib/{application/http → http}/request.js +6 -30
  12. package/lib/{application/http → http}/response.js +20 -53
  13. package/lib/middlewares/etag/index.js +62 -0
  14. package/lib/middlewares/ql/sequelize/index.js +34 -0
  15. package/lib/middlewares/ql/sequelize/interpreter/ModelsTree.js +121 -0
  16. package/lib/middlewares/ql/sequelize/interpreter/QueryLexer.js +456 -0
  17. package/lib/models/define.js +6 -13
  18. package/lib/models/mixins.js +28 -15
  19. package/lib/params/Params.js +34 -0
  20. package/lib/queries/NodesterQueryParams.js +139 -0
  21. package/lib/router/handlers.util.js +61 -0
  22. package/lib/router/index.js +386 -0
  23. package/lib/router/route.js +124 -0
  24. package/lib/router/routes.util.js +66 -0
  25. package/lib/stacks/MarkersStack.js +35 -0
  26. package/lib/{application → stacks}/MiddlewareStack.js +47 -13
  27. package/lib/utils/path.util.js +3 -1
  28. package/lib/utils/types.util.js +51 -1
  29. package/lib/validators/dates.js +25 -0
  30. package/lib/validators/numbers.js +14 -0
  31. package/package.json +16 -2
  32. package/tests/index.test.js +7 -2
  33. package/tests/nql.test.js +277 -0
  34. package/docs/App.md +0 -13
  35. package/docs/Queries.md +0 -61
  36. package/docs/Readme.md +0 -2
  37. package/docs/Routing.md +0 -34
  38. package/examples/goal/index.js +0 -23
  39. package/examples/rest/index.js +0 -25
  40. package/examples/rest/node_modules/.package-lock.json +0 -40
  41. package/examples/rest/package-lock.json +0 -72
  42. package/examples/rest/package.json +0 -14
  43. package/lib/constants/ConstantsEnum.js +0 -13
  44. package/lib/factories/responses/api.js +0 -90
  45. package/lib/routers/Default/index.js +0 -143
  46. package/lib/routers/Default/layer.js +0 -50
  47. package/lib/routers/Main/index.js +0 -10
  48. package/lib/routers/Roles/index.js +0 -81
  49. package/lib/utils/params.util.js +0 -19
  50. /package/lib/{controllers/Controller.js → _/n_controllers/Controller.js"} +0 -0
  51. /package/lib/{controllers/JWTController.js → _/n_controllers/JWTController.js"} +0 -0
  52. /package/lib/{controllers/ServiceController.js → _/n_controllers/ServiceController.js"} +0 -0
  53. /package/lib/{controllers/WebController.js → _/n_controllers/WebController.js"} +0 -0
  54. /package/lib/{facades → _facades}/Facade.js +0 -0
  55. /package/lib/{facades → _facades}/FacadeParams.js +0 -0
  56. /package/lib/{facades → _facades}/ServiceFacade.js +0 -0
  57. /package/lib/{facades → _facades}/jwt.facade.js +0 -0
  58. /package/lib/{application/http → http}/utils.js +0 -0
package/Readme.md CHANGED
@@ -1,10 +1,12 @@
1
1
  # nodester
2
- > A robust boilerplate framework that makes iterative development easy.
2
+ > A robust and flexible boilerplate framework that makes iterative development easy.
3
3
 
4
4
  ## Table of Contents
5
5
 
6
6
  - [Usage](#usage)
7
- - [Extending](#extending-application-functionality)
7
+ - [Markers](#markers)
8
+ - [Router](#router)
9
+ - [Extending App](#extending-application-functionality)
8
10
  - [Philosophy](#philosophy)
9
11
  - [License](#license)
10
12
  - [Copyright](#copyright)
@@ -19,36 +21,69 @@ const app = new nodester();
19
21
  app.set.database(db);
20
22
 
21
23
  app.listen(8080, function() {
22
- console.log('listening on port', app.port);
24
+ console.log('listening on port', app.port);
23
25
  });
24
26
  ```
25
27
 
26
28
  ## Markers
27
29
 
28
- Marker is a functional condition that returns `true | false`, based on data in request.
30
+ Marker is a functional condition that returns `true | false`, based on data in request/response.
29
31
 
32
+ Markers are more powerful indicators than simple route definitions as any parameter in request/response can be used.
30
33
 
31
- ### Adding a Marker
34
+ For example: our application has 2 domains:
35
+ `admin.awesomeapp.com`
36
+ `api.awesomeapp.com`
37
+
38
+ You add markers and handlers specifically for those domains:
32
39
 
33
40
  ```js
34
- app.add.marker('admin', (req) => req.role === 'admin');
41
+ app.add.marker('ADMIN', (req) => req.hostname === 'admin.awesomeapp.com');
42
+ app.add.marker('API', (req) => req.hostname === 'api.awesomeapp.com');
35
43
  ```
36
44
 
37
-
38
- ### Using a Marker
45
+ And then use them:
39
46
 
40
47
  ```js
41
- app.only('admin').route('get /payments', <handler>);
42
- app.only('/api').route('get /payments', <handler>);
48
+ app.only('ADMIN').route('get /payments', <handler/>);
49
+ app.only('API').route('get /payments', <handler/>);
50
+ // Or:
51
+ app.only('ADMIN').use(<handler/>);
52
+ app.only('API').use(<handler/>);
43
53
  ```
44
54
 
55
+ The same can be done for any parameter in request/response:
56
+
57
+ ```js
58
+ app.add.marker('admin_role', (req) => req.role === 'admin');
59
+ app.only('admin_role').route('get /secrets', <handler/>);
60
+ app.only('admin_role').use(<handler/>);
61
+ ```
45
62
 
46
63
  ## Router
47
64
 
65
+ Router is a built-in middleware.
66
+
67
+ ```js
68
+ const Router = require('nodester/router');
69
+
70
+ const controllersPath = <path_to_controllers_directory/>;
71
+ const router = new Router({ controllersPath });
72
+
73
+ router.add.route('get /books', function(req, res) { ... } );
74
+ // Or:
75
+ router.add.route('get /books', { controlledBy: 'BooksController.getMany' } );
76
+ router.add.route('get /books/:id', { controlledBy: 'BooksController.getOne' } );
77
+ ```
78
+
79
+ ### Using Router:
80
+
48
81
  ```js
49
- app.route('get /books', function(req, res) { ... } );
50
- app.route('get /books', { controlledBy: 'BooksController.getMany' } );
51
- app.route('get /books/:id', { controlledBy: 'BooksController.getOne' } );
82
+ const nodester = require('nodester');
83
+ const router = require(<path_to_router_definition/>);
84
+
85
+ const app = new nodester();
86
+ app.use(router());
52
87
  ```
53
88
 
54
89
 
@@ -62,9 +97,9 @@ const serveStatic = require('serve-static');
62
97
 
63
98
  const nodester = require('nodester');
64
99
 
65
- const app = nodester();
100
+ const app = new nodester();
66
101
  app.extend('static', serveStatic);
67
- app.static(<path_to_static_directory>);
102
+ app.static(<path_to_static_directory/>);
68
103
  ```
69
104
 
70
105
  Short:
@@ -73,8 +108,8 @@ const serveStatic = require('serve-static');
73
108
 
74
109
  const nodester = require('nodester');
75
110
 
76
- const app = nodester();
77
- app.extend('static', serveStatic)(<path_to_static_directory>);
111
+ const app = new nodester();
112
+ app.extend('static', serveStatic)(<path_to_static_directory/>);
78
113
  ```
79
114
 
80
115
  Of course you might just do this:
@@ -83,7 +118,7 @@ const serveStatic = require('serve-static');
83
118
 
84
119
  const nodester = require('nodester');
85
120
 
86
- const app = nodester();
121
+ const app = new nodester();
87
122
  app.static = serveStatic;
88
123
  ````
89
124
  But you'll never know if you did override any of the app's properties or did not.
@@ -91,17 +126,17 @@ But you'll never know if you did override any of the app's properties or did not
91
126
 
92
127
  ### Extending class:
93
128
 
94
- If you really want to override properties or use `nodester` as a boilerplate, you should better extend default Application class:
129
+ If you really want to override properties or use `nodester` as a boilerplate, you should extend default Application class:
95
130
 
96
131
  ```js
97
- const DefaultApplication = require('nodester');
132
+ const NodesterApp = require('nodester');
98
133
 
99
- class MyApp extends DefaultApplication {
100
- constructor(opts) {
101
- super(opts)
102
- }
134
+ class MyApp extends NodesterApp {
135
+ constructor(opts) {
136
+ super(opts)
137
+ }
103
138
 
104
- // Override everything you want here...
139
+ // Override everything you want here...
105
140
  }
106
141
 
107
142
  // Don't forget to expose.
@@ -114,7 +149,7 @@ The Philosophy of `nodester` is to provide a developer with a tool that can buil
114
149
 
115
150
  ### Goal
116
151
 
117
- The goal of `nodester` is to be a robust boilerplate that makes iterative development easy.
152
+ The goal of `nodester` is to be a robust and flexible framework that makes iterative development easy.
118
153
 
119
154
 
120
155
  ## LICENSE
@@ -6,13 +6,18 @@
6
6
  'use strict';
7
7
 
8
8
  const Emitter = require('events');
9
- const MiddlewareStack = require('./MiddlewareStack');
9
+ const DefaultRouter = require('../router');
10
10
  // Server:
11
11
  const http = require('http');
12
- const request = require('./http/request');
13
- const response = require('./http/response');
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 { typeOf } = require('../utils/types.util');
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 middlewares stack.
35
- this._middlewares = new MiddlewareStack();
39
+ // Reference to router.
40
+ this._router = new DefaultRouter({ finalhandlerEnabled: true });
36
41
 
37
42
  // Reference to the database connection.
38
- this.database = null;
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: app }
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: app }
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 Error('Connection to database (Sequilize) can not be null or undefined.');
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.database = sequilizeConnection;
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
- this.router = newRouter.init(this);
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
- middleware: this.addMiddleware.bind(this)
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
- * Adds new middleware to the stack.
191
+ * Proxy to .add.middleware()
192
+ *
193
+ * @param {Function} fn
146
194
  *
147
195
  * @api public
148
196
  */
149
- addMiddleware(fn) {
150
- if (this._middlewares.isLocked === true) {
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 {Function} fn
204
+ * @param {String} markerName
163
205
  *
164
206
  * @api public
165
207
  */
166
- use(fn) {
167
- return this.add(fn);
208
+ only(markerName='') {
209
+ return this._router.only(markerName);
168
210
  }
169
211
 
170
212
 
171
213
  /**
172
- * Adds to hooks stack (beforeStart).
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
- // Lock middlewares stack.
206
- this._middlewares.lock();
247
+ // Add query parser.
248
+ this._router.add.middleware(this._queryParser, 0);
207
249
 
208
- return this.handle.bind(this);
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
- this.server = http.createServer(this.start());
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._middlewares.process(req, res)
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
+