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
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
const ResponseFormats = require('nodester/constants/ResponseFormats');
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
module.exports = class APIResponseFactory {
|
|
5
|
-
constructor() {}
|
|
6
|
-
|
|
7
|
-
/*
|
|
8
|
-
Format for all API responses will be JSON
|
|
9
|
-
{
|
|
10
|
-
content: {...}
|
|
11
|
-
error: {...}
|
|
12
|
-
}
|
|
13
|
-
Status code is sent in header.
|
|
14
|
-
|
|
15
|
-
If error is not present, error should be null.
|
|
16
|
-
If error is present, content can be null (But it's not required).
|
|
17
|
-
*/
|
|
18
|
-
createGenericResponse(
|
|
19
|
-
options = {
|
|
20
|
-
res: null,
|
|
21
|
-
status: 200,
|
|
22
|
-
content: {},
|
|
23
|
-
error: null,
|
|
24
|
-
format: ResponseFormats.JSON
|
|
25
|
-
}
|
|
26
|
-
) {
|
|
27
|
-
try {
|
|
28
|
-
const data = {
|
|
29
|
-
content: options?.content ?? null,
|
|
30
|
-
error: options?.error ?? null
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
switch(options?.format) {
|
|
34
|
-
case ResponseFormats.JSON:
|
|
35
|
-
return options?.res.status(options?.status).json(data);
|
|
36
|
-
case ResponseFormats.XML:
|
|
37
|
-
break;
|
|
38
|
-
default: {
|
|
39
|
-
const err = new Error("No response format specified.");
|
|
40
|
-
throw err;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
catch(error) {
|
|
45
|
-
const err = new Error(`Could not create generic response: ${error.message}`);
|
|
46
|
-
err.name = error?.name;
|
|
47
|
-
err.code = error?.code;
|
|
48
|
-
|
|
49
|
-
console.error(err);
|
|
50
|
-
|
|
51
|
-
throw err;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Sends response with status code 200.
|
|
57
|
-
* Should be called on all successful respones.
|
|
58
|
-
*
|
|
59
|
-
* @param <Object> res
|
|
60
|
-
* @param <Object> content
|
|
61
|
-
* @param <String> format
|
|
62
|
-
*/
|
|
63
|
-
createOKResponse(options) {
|
|
64
|
-
|
|
65
|
-
return this.createGenericResponse({
|
|
66
|
-
...options,
|
|
67
|
-
status: 200,
|
|
68
|
-
format: options?.format ?? ResponseFormats.JSON
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* Sends response with provided error code.
|
|
74
|
-
* Should be called on all failed respones.
|
|
75
|
-
*
|
|
76
|
-
* @param <Object> res
|
|
77
|
-
* @param <Object> error
|
|
78
|
-
* @param <Object> content (optional)
|
|
79
|
-
* @param <Int> status
|
|
80
|
-
* @param <String> format
|
|
81
|
-
*/
|
|
82
|
-
createErrorResponse(options) {
|
|
83
|
-
|
|
84
|
-
return this.createGenericResponse({
|
|
85
|
-
...options,
|
|
86
|
-
status: options?.status ?? 500,
|
|
87
|
-
format: options?.format ?? ResponseFormats.JSON
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
}
|
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
const Layer = require('./layer');
|
|
2
|
-
|
|
3
|
-
// Utils:
|
|
4
|
-
const { getType } = require('../../utils/types.util');
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
module.exports = function NodesterDefaultRouter(app=null) {
|
|
8
|
-
this.markers = {};
|
|
9
|
-
this.layer = new Layer();
|
|
10
|
-
|
|
11
|
-
if (!!app) {
|
|
12
|
-
this.app = app
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
// Expose methods:
|
|
16
|
-
// Markers:
|
|
17
|
-
this.addMarker = _addMarker;
|
|
18
|
-
this.getMarker = _getMarker;
|
|
19
|
-
|
|
20
|
-
// Routing:
|
|
21
|
-
this.handle = _handle;
|
|
22
|
-
this.only = _only;
|
|
23
|
-
this.route = _route;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Adds marker to the stack.
|
|
28
|
-
* Returns itself for chaining.
|
|
29
|
-
* @return {NodesterDefaultRouter}
|
|
30
|
-
*
|
|
31
|
-
* @alias addMarker
|
|
32
|
-
* @public
|
|
33
|
-
*/
|
|
34
|
-
function _addMarker(nameOrSymbol='', fn=()=>{}) {
|
|
35
|
-
if (typeof fn !== 'function') {
|
|
36
|
-
const err = new TypeError(`Router.addMarker() requires a middleware function but got a ${ getType(fn) }`);
|
|
37
|
-
throw err;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const marker = this.getMarker(nameOrSymbol);
|
|
41
|
-
if (marker.marker.index > -1) {
|
|
42
|
-
const err = new TypeError(`Marker with key ${ nameOrSymbol } is already set.`);
|
|
43
|
-
throw err;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
this.markers[nameOrSymbol] = fn;
|
|
47
|
-
|
|
48
|
-
return this;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Tries to find marker's data by provided key.
|
|
54
|
-
* @return {Object}
|
|
55
|
-
*
|
|
56
|
-
* @alias getMarker
|
|
57
|
-
* @public
|
|
58
|
-
*/
|
|
59
|
-
function _getMarker(nameOrSymbol='') {
|
|
60
|
-
const result = {
|
|
61
|
-
marker: {
|
|
62
|
-
key: nameOrSymbol,
|
|
63
|
-
index: -1,
|
|
64
|
-
},
|
|
65
|
-
middleware: undefined
|
|
66
|
-
}
|
|
67
|
-
try {
|
|
68
|
-
const keys = Object.keys(this.markers);
|
|
69
|
-
|
|
70
|
-
const index = keys.indexOf(nameOrSymbol);
|
|
71
|
-
if (keys.indexOf(nameOrSymbol) === -1) {
|
|
72
|
-
const err = new Error('NotFound');
|
|
73
|
-
throw err;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// Marker found:
|
|
77
|
-
result.marker.index = index;
|
|
78
|
-
result.middleware = this.markers[nameOrSymbol];
|
|
79
|
-
}
|
|
80
|
-
catch(error) {
|
|
81
|
-
result.marker.index = -1;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
return result;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Start routes pipeline processing.
|
|
89
|
-
*
|
|
90
|
-
* If no callback is provided, then default error handlers will respond
|
|
91
|
-
* in the event of an error bubbling through the stack.
|
|
92
|
-
*
|
|
93
|
-
* @alias handle
|
|
94
|
-
* @public
|
|
95
|
-
*/
|
|
96
|
-
function _handle(req, res, callback) {
|
|
97
|
-
const method = req.method;
|
|
98
|
-
const requestPath = req.url;
|
|
99
|
-
|
|
100
|
-
console.log(method, requestPath);
|
|
101
|
-
|
|
102
|
-
let markerName = null;
|
|
103
|
-
|
|
104
|
-
// Check if this request satisfies any markers:
|
|
105
|
-
const markers = Object.entries(this.markers);
|
|
106
|
-
console.log({ markers });
|
|
107
|
-
|
|
108
|
-
for (const [marker, fn] of markers) {
|
|
109
|
-
const result = fn(req, res, callback);
|
|
110
|
-
console.log(result);
|
|
111
|
-
|
|
112
|
-
if (result === true) {
|
|
113
|
-
markerName = marker;
|
|
114
|
-
break;
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
console.log({ markerName });
|
|
119
|
-
|
|
120
|
-
return res.send(markerName ?? 'Hi!');
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
/**
|
|
125
|
-
*
|
|
126
|
-
* @alias only
|
|
127
|
-
* @public
|
|
128
|
-
*/
|
|
129
|
-
function _only(condition) {
|
|
130
|
-
this.layer.push('condition', condition);
|
|
131
|
-
// Return layer for chaining.
|
|
132
|
-
return this.layer;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
*
|
|
138
|
-
* @alias route
|
|
139
|
-
* @public
|
|
140
|
-
*/
|
|
141
|
-
function _route() {
|
|
142
|
-
|
|
143
|
-
}
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
module.exports = function NodesterDefaultRouterLayer() {
|
|
3
|
-
this.conditions = [];
|
|
4
|
-
this.routesList = {};
|
|
5
|
-
|
|
6
|
-
this.push = _push;
|
|
7
|
-
this.route = _route;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
*
|
|
13
|
-
* @alias push
|
|
14
|
-
* @public
|
|
15
|
-
*/
|
|
16
|
-
function _push(key='condition') {
|
|
17
|
-
let args = [...arguments].shift();
|
|
18
|
-
|
|
19
|
-
switch(key) {
|
|
20
|
-
case 'condition':
|
|
21
|
-
// this.conditions[]
|
|
22
|
-
break;
|
|
23
|
-
case 'route':
|
|
24
|
-
const route = args.shift();
|
|
25
|
-
this.routesList[route] = args;
|
|
26
|
-
break;
|
|
27
|
-
break;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
return this;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
*
|
|
36
|
-
* @alias route
|
|
37
|
-
* @public
|
|
38
|
-
*/
|
|
39
|
-
function _route(path='/') {
|
|
40
|
-
const middlewares = [...arguments].shift();
|
|
41
|
-
|
|
42
|
-
console.log({ path });
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
*
|
|
48
|
-
* @alias push
|
|
49
|
-
* @public
|
|
50
|
-
*/
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
const express = require('express');
|
|
2
|
-
// Utils:
|
|
3
|
-
const cwd = process.cwd();
|
|
4
|
-
const Path = require('path');
|
|
5
|
-
// Custom error.
|
|
6
|
-
const { Err } = require('nodester/factories/errors');
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
class RolesRouter extends express.Router {
|
|
10
|
-
constructor(
|
|
11
|
-
rolesToRoutesMap={},
|
|
12
|
-
pathToControllers=null
|
|
13
|
-
) {
|
|
14
|
-
super();
|
|
15
|
-
|
|
16
|
-
// rolesToRoutesMap is a map of role -> route -> controller:
|
|
17
|
-
if (!rolesToRoutesMap) {
|
|
18
|
-
const err = new Err('"rolesToRoutesMap" argument is required.');
|
|
19
|
-
throw err;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
if (!pathToControllers) {
|
|
23
|
-
const err = new Err('"pathToControllers" argument is required.');
|
|
24
|
-
throw err;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// Extract all available roles.
|
|
28
|
-
const roles = Object.keys(rolesToRoutesMap);
|
|
29
|
-
|
|
30
|
-
// Flip map (Make it route -> role -> controller):
|
|
31
|
-
const routesToRolesMap = {};
|
|
32
|
-
for (const role of roles) {
|
|
33
|
-
const roleRoutes = rolesToRoutesMap[role]
|
|
34
|
-
|
|
35
|
-
for (const route in roleRoutes) {
|
|
36
|
-
// If this route is set:
|
|
37
|
-
if (!!routesToRolesMap[route]) {
|
|
38
|
-
// Add role to set.
|
|
39
|
-
routesToRolesMap[route][role] = roleRoutes[route];
|
|
40
|
-
}
|
|
41
|
-
else {
|
|
42
|
-
// Create set for this role.
|
|
43
|
-
routesToRolesMap[route] = { [role]: roleRoutes[route] };
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// At this point we have a map of route -> role -> controller.
|
|
49
|
-
// Let's now set these routes to this Router:
|
|
50
|
-
for (const route in routesToRolesMap) {
|
|
51
|
-
const rolesAndControllersMap = routesToRolesMap[route];
|
|
52
|
-
|
|
53
|
-
// Split route by space, as it has structure [<Rest method> <Route>]
|
|
54
|
-
const routeParts = route.split(/\s+/);
|
|
55
|
-
const routeMethod = routeParts[0].toLocaleLowerCase();
|
|
56
|
-
const routePath = routeParts[1].replace(/\s\s+/g, ' ');
|
|
57
|
-
|
|
58
|
-
// Set up this route:
|
|
59
|
-
this.route(routePath)[routeMethod]((req, res, next) => {
|
|
60
|
-
// Extract role:
|
|
61
|
-
const role = req?.user?.role ?? 'visitor';
|
|
62
|
-
|
|
63
|
-
// If no handler for this role-route, skip:
|
|
64
|
-
if (!rolesAndControllersMap[role]) {
|
|
65
|
-
return next();
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const controllerAndMethod = rolesAndControllersMap[role].split('.');
|
|
69
|
-
const controllerName = controllerAndMethod[0];
|
|
70
|
-
const controllerMethod = controllerAndMethod[1];
|
|
71
|
-
|
|
72
|
-
// Get controller from path.
|
|
73
|
-
const controller = require(Path.join(cwd, pathToControllers, controllerName));
|
|
74
|
-
|
|
75
|
-
return controller[controllerMethod](req, res, next);
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
module.exports = RolesRouter;
|
package/lib/utils/params.util.js
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
module.exports = Params;
|
|
3
|
-
|
|
4
|
-
function Params(
|
|
5
|
-
sourceObject={},
|
|
6
|
-
defaultValuesList={}
|
|
7
|
-
) {
|
|
8
|
-
const result = {};
|
|
9
|
-
|
|
10
|
-
const keys = Object.keys(defaultValuesList);
|
|
11
|
-
for (const key of keys) {
|
|
12
|
-
result[key] = typeof sourceObject[key] !== 'boolean' && !sourceObject[key] ?
|
|
13
|
-
defaultValuesList[key]
|
|
14
|
-
:
|
|
15
|
-
sourceObject[key];
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
return result;
|
|
19
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|