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.
Files changed (57) hide show
  1. package/Readme.md +61 -26
  2. package/docs/GoalController.js +62 -0
  3. package/docs/request-examples.js +184 -0
  4. package/examples/rest/controllers/orders.controller.js +15 -0
  5. package/examples/rest/index.js +29 -9
  6. package/examples/rest/node_modules/.package-lock.json +5 -3
  7. package/examples/rest/preprocessors/queries/orders.queries.js +15 -0
  8. package/examples/rest/router.js +23 -0
  9. package/lib/application/index.js +86 -35
  10. package/lib/constants/Operations.js +23 -0
  11. package/lib/controllers/methods/index.js +170 -0
  12. package/lib/controllers/mixins/index.js +213 -0
  13. package/lib/enums/Enum.js +16 -0
  14. package/lib/factories/errors/CustomError.js +7 -5
  15. package/lib/factories/responses/html.js +7 -2
  16. package/lib/factories/responses/rest.js +110 -0
  17. package/lib/http/codes/index.js +157 -0
  18. package/lib/{application/http → http}/request.js +6 -30
  19. package/lib/{application/http → http}/response.js +20 -53
  20. package/lib/middlewares/etag/index.js +62 -0
  21. package/lib/middlewares/ql/sequelize/index.js +34 -0
  22. package/lib/middlewares/ql/sequelize/interpreter/ModelsTree.js +121 -0
  23. package/lib/middlewares/ql/sequelize/interpreter/QueryLexer.js +456 -0
  24. package/lib/models/define.js +6 -13
  25. package/lib/models/mixins.js +28 -15
  26. package/lib/params/Params.js +34 -0
  27. package/lib/queries/NodesterQueryParams.js +139 -0
  28. package/lib/router/handlers.util.js +61 -0
  29. package/lib/router/index.js +386 -0
  30. package/lib/router/route.js +124 -0
  31. package/lib/router/routes.util.js +66 -0
  32. package/lib/stacks/MarkersStack.js +35 -0
  33. package/lib/{application → stacks}/MiddlewareStack.js +47 -13
  34. package/lib/utils/path.util.js +3 -1
  35. package/lib/utils/types.util.js +51 -1
  36. package/lib/validators/dates.js +25 -0
  37. package/lib/validators/numbers.js +14 -0
  38. package/package.json +16 -2
  39. package/tests/index.test.js +7 -2
  40. package/tests/nql.test.js +277 -0
  41. package/examples/rest/package-lock.json +0 -72
  42. package/lib/constants/ConstantsEnum.js +0 -13
  43. package/lib/factories/responses/api.js +0 -90
  44. package/lib/routers/Default/index.js +0 -143
  45. package/lib/routers/Default/layer.js +0 -50
  46. package/lib/routers/Main/index.js +0 -10
  47. package/lib/routers/Roles/index.js +0 -81
  48. package/lib/utils/params.util.js +0 -19
  49. /package/lib/{controllers/Controller.js → _/n_controllers/Controller.js"} +0 -0
  50. /package/lib/{controllers/JWTController.js → _/n_controllers/JWTController.js"} +0 -0
  51. /package/lib/{controllers/ServiceController.js → _/n_controllers/ServiceController.js"} +0 -0
  52. /package/lib/{controllers/WebController.js → _/n_controllers/WebController.js"} +0 -0
  53. /package/lib/{facades → _facades}/Facade.js +0 -0
  54. /package/lib/{facades → _facades}/FacadeParams.js +0 -0
  55. /package/lib/{facades → _facades}/ServiceFacade.js +0 -0
  56. /package/lib/{facades → _facades}/jwt.facade.js +0 -0
  57. /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
@@ -0,0 +1,62 @@
1
+ const {
2
+ withDefaultCRUD
3
+ } = require('nodester/controllers/mixins');
4
+ const {
5
+ getOne,
6
+ getMany,
7
+ createOne,
8
+ updateOne,
9
+ deleteOne
10
+ } = require('nodester/controllers/methods');
11
+
12
+
13
+ #nodester
14
+ function withDefaultCRUD(instance, opts={}) {}
15
+ function getOne(req, res) {}
16
+ function getMany(req, res) {}
17
+ function createOne(req, res) {}
18
+
19
+ const with = (fn1, fn2) => {
20
+ const caller = this;
21
+
22
+ // If Async:
23
+ if (fn1.constructor.name === 'AsyncFunction')
24
+ return async (req, res) => {
25
+ await fn1.call(caller, req, res);
26
+ return fn2.call(caller, req, res);
27
+ }
28
+
29
+ // If Sync:
30
+ return (req, res) => {
31
+ fn1.call(caller, req, res);
32
+ return fn2.call(caller, req, res);
33
+ }
34
+ };
35
+
36
+ // Basic example
37
+ module.exports = function OrdersController() {
38
+ withDefaultCRUD(this, {
39
+ model: Order,
40
+ });
41
+ }
42
+
43
+ // Configurable
44
+ module.exports = function OrdersController() {
45
+ withDefaultCRUD(this, {
46
+ model: Order,
47
+ // Optional:
48
+ name: 'OrdersController',
49
+ only: [
50
+ 'getOne',
51
+ 'getMany'
52
+ ]
53
+ });
54
+ };
55
+
56
+ // Or:
57
+ module.exports = function OrdersController() {
58
+ this.model = Order;
59
+
60
+ this.getOne = with(queryPreprocessor, getOne);
61
+ };
62
+
@@ -0,0 +1,184 @@
1
+ /posts?in=comments,comments.author,comments.likes.user
2
+ /posts?in=comments(in=author,likes.user)
3
+
4
+ /posts?id=100.0&in=comments(in=author.avatar&order=desc).user,likes&order_by=comments.id
5
+ /posts?id=not(100.0)&&order_by=comments.id
6
+
7
+ /orders?position=1&status=PUBLISHED&in=products(limit=20)
8
+ {
9
+ model: "orders",
10
+ where: {
11
+ and: [
12
+ {
13
+ status: ["PUBLISHED"]
14
+ },
15
+ {
16
+ position: [1]
17
+ }
18
+ ]
19
+ },
20
+ includes: [
21
+ {
22
+ model: "products",
23
+ limit: 20,
24
+ skip: 0
25
+ }
26
+ ],
27
+ limit: -1,
28
+ skip: 0
29
+ }
30
+
31
+
32
+ /orders?in=user(vk_user_id=like(john))&skip=10
33
+
34
+ {
35
+ model: "orders",
36
+ includes: [
37
+ {
38
+ model: "user",
39
+ where: {
40
+ vk_user_id: {
41
+ like: "john"
42
+ }
43
+ },
44
+ limit: -1,
45
+ skip: 0
46
+ }
47
+ ],
48
+ limit: -1,
49
+ skip: 10
50
+ }
51
+
52
+ /orders?in=user&or(user.vk_user_id=like(),user.name=like())
53
+
54
+ {
55
+ model: "orders",
56
+ where: {
57
+ or: {
58
+ user.vk_user_id: like(),
59
+ user.name: like()
60
+ }
61
+ }
62
+ }
63
+
64
+ /orders?id=10
65
+
66
+ param: id,
67
+ value: {
68
+ token: 10,
69
+ value: 10
70
+ }
71
+
72
+ {
73
+ model: orders,
74
+ where: {
75
+ id: [10]
76
+ },
77
+ skip: -1,
78
+ limit: 0
79
+ }
80
+
81
+ /orders?id=[10,20]
82
+
83
+ param: id,
84
+ value: {
85
+ token: in,
86
+ value: [10,20]
87
+ }
88
+
89
+ /orders?id=or(10,100)
90
+
91
+ param: id,
92
+ value: {
93
+ token: or,
94
+ value: [10,100)
95
+ }
96
+
97
+ /orders?id=!(10,100)
98
+
99
+ param: id,
100
+ value: {
101
+ token: not,
102
+ value: [10,100)
103
+ }
104
+
105
+
106
+ /orders?or(user.name=leo,id=100)&in=user
107
+
108
+ param:
109
+
110
+
111
+ {
112
+ where: {
113
+ param: where,
114
+ value: { id: 100 }
115
+ children: {}
116
+ },
117
+ in: {
118
+ param: in
119
+ value: null,
120
+ children: {
121
+
122
+ }
123
+ }
124
+ }
125
+
126
+ {
127
+ param: id
128
+ value: 10
129
+ parent: root
130
+ children: {}
131
+ }
132
+
133
+
134
+
135
+ /posts?id=100.0&in=comments(in=author.avatar&order=desc).user.followers(id=gt(10)&limit=1),likes&order_by=comments.id
136
+
137
+ {
138
+ model: 'root',
139
+ where: {
140
+ id: [100.0]
141
+ },
142
+ includes: [
143
+ {
144
+ model: 'comments',
145
+ where: {},
146
+ includes: [
147
+ {
148
+ model: 'author',
149
+ where: {},
150
+ includes: [
151
+ {
152
+ model: 'avatar',
153
+ limit: -1,
154
+ skip: 0
155
+ }
156
+ ],
157
+ limit: -1,
158
+ skip: 0
159
+ },
160
+ {
161
+ model: 'user',
162
+ includes: [
163
+ {
164
+ model: 'followers',
165
+ where: {
166
+ id: {
167
+ 'gt': [10]
168
+ }
169
+ },
170
+ limit: 1,
171
+ skip: 0
172
+ }
173
+ ],
174
+ limit: -1,
175
+ skip: 0
176
+ }
177
+ ],
178
+ order: 'desc'
179
+ }
180
+ ],
181
+ limit: -1,
182
+ skip: 0,
183
+ order_by: 'comments.id'
184
+ }
@@ -0,0 +1,15 @@
1
+
2
+ function OrdersController() {
3
+
4
+ this.getMany = function(req, res) {
5
+ console.log({ query: req.query });
6
+ res.json({ controller: 'OrdersController', method: 'getMany' });
7
+ }
8
+
9
+ this.getOne = function(req, res) {
10
+ const { params } = req;
11
+ res.json({ controller: 'OrdersController', method: 'getOne', params });
12
+ }
13
+ }
14
+
15
+ module.exports = new OrdersController();
@@ -1,20 +1,40 @@
1
- const Nodester = require('nodester');
1
+ 'use strict'
2
+
3
+ const nodester = require('nodester');
4
+ const router = require('./router');
2
5
 
3
6
  // Init.
4
- const app = new Nodester();
7
+ const app = new nodester();
5
8
 
6
9
  // app.setDatabase();
7
10
  // app.set('database');
8
11
 
9
- // app.add('marker', 'GET_M', (req)=>req.method === 'GET');
12
+ app.use(router());
13
+
14
+ // app.add.marker('GET_M', (req)=>req.method === 'GET');
15
+
16
+ // app.only('GET_M').use(async (req, res) => {
17
+ // res.json(req.nquery);
18
+ // });
19
+
20
+ // app.use((req, res)=>res.json({ msg: 'last' }));
21
+
22
+ // app.only('GET_M').route('get /orders', async (req, res) => {
23
+ // res.json({ route: 'orders' });
24
+ // });
25
+
26
+ // app.add.middleware((req, res, next)=>{
27
+ // console.log('1st', 'hello!');
28
+ // next();
29
+ // });
10
30
 
11
- app.add.middleware((req, res, next)=>{
12
- console.log('1st');
31
+ // app.add.middleware((req, res, next)=>{
32
+ // console.log('Last!');
13
33
 
14
- res.setHeader("Content-type", "text/html");
15
- res.write("Hello!<br/>...my friend");
16
- res.end();
17
- })
34
+ // res.setHeader("Content-type", "text/html");
35
+ // res.write("Hello!<br/>...my friend");
36
+ // res.end();
37
+ // });
18
38
 
19
39
  app.beforeStart(()=>{
20
40
  console.log('Before start passed!');
@@ -5,7 +5,7 @@
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "../..": {
8
- "version": "0.6.1",
8
+ "version": "0.0.1",
9
9
  "license": "MIT",
10
10
  "dependencies": {
11
11
  "accepts": "^1.3.8",
@@ -16,12 +16,14 @@
16
16
  "debug": "^4.3.4",
17
17
  "finalhandler": "^1.2.0",
18
18
  "formidable": "^1.2.6",
19
+ "fresh": "^0.5.2",
20
+ "http-errors": "^2.0.0",
19
21
  "inflection": "^2.0.1",
20
22
  "proxy-addr": "^2.0.7",
21
23
  "qs": "^6.11.0",
24
+ "range-parser": "^1.2.1",
25
+ "send": "^0.18.0",
22
26
  "sequelize": "^6.6.5",
23
- "serve-static": "^1.15.0",
24
- "slugify": "^1.6.5",
25
27
  "type-is": "^1.6.18",
26
28
  "vary": "^1.1.2"
27
29
  },
@@ -0,0 +1,15 @@
1
+
2
+ module.exports = function OrdersQueryPreprocessor(opts={}) {
3
+ return handle.bind(this);
4
+ }
5
+
6
+ async function handle(nquery, req, res) {
7
+ console.log("was called", { nquery });
8
+
9
+ // Get role or set "visitor".
10
+ // const _role = typeof role === 'string' && role.length > 1 ? role : VISITOR;
11
+
12
+ // const policy = this.policies[_role];
13
+
14
+ // const resultQuery = await traverse(nquery, policy, this.model);
15
+ }
@@ -0,0 +1,23 @@
1
+ 'use strict'
2
+
3
+ const Router = require('nodester/router');
4
+ // Preprocessors:
5
+ const preprocessOrdersQuery = require('./preprocessors/queries/orders.queries');
6
+ // Utils.
7
+ const Path = require('path');
8
+
9
+
10
+ module.exports = function initRouter() {
11
+ const controllersPath = Path.join(__dirname, 'controllers');
12
+ const router = new Router({ controllersPath });
13
+
14
+ // router.add.route('get /orders', async (req, res) => {
15
+ // res.json({ route: 'orders' });
16
+ // });
17
+
18
+ router.add.route('get /orders', { before: preprocessOrdersQuery(), controlledBy: 'orders.getMany' });
19
+ router.add.route('get /orders/*', { controlledBy: 'orders.getMany' });
20
+ router.add.route('get /orders/:id', { controlledBy: 'orders.getOne' });
21
+
22
+ return router.handle.bind(router);
23
+ }