nodester 0.1.5 → 0.2.0
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 +16 -55
- package/lib/application/index.js +174 -63
- package/lib/body/extract.js +15 -4
- package/lib/constants/Bounds.js +15 -0
- package/lib/constants/Clauses.js +13 -0
- package/lib/constants/ResponseFormats.js +2 -2
- package/lib/controllers/methods/index.js +7 -0
- package/lib/controllers/mixins/index.js +36 -36
- package/lib/database/connection.js +6 -0
- package/lib/database/migration.js +14 -4
- package/lib/facades/methods/index.js +10 -9
- package/lib/facades/mixins/index.js +67 -13
- package/lib/factories/responses/rest.js +25 -13
- package/lib/http/{request.js → request/index.js} +53 -75
- package/lib/http/request/utils.js +27 -0
- package/lib/http/response/headers.js +138 -0
- package/lib/http/response/index.js +248 -0
- package/lib/http/response/utils.js +38 -0
- package/lib/middlewares/SearchParams/index.js +25 -0
- package/lib/middlewares/cookies/index.js +44 -0
- package/lib/middlewares/etag/index.js +32 -15
- package/lib/middlewares/formidable/index.js +30 -25
- package/lib/middlewares/ql/sequelize/index.js +11 -2
- package/lib/middlewares/ql/sequelize/interpreter/QueryLexer.js +2 -1
- package/lib/middlewares/render/index.js +62 -0
- package/lib/models/associate.js +25 -1
- package/lib/models/define.js +19 -15
- package/lib/models/mixins.js +7 -0
- package/lib/query/traverse.js +96 -63
- package/lib/router/handlers.util.js +1 -0
- package/lib/router/index.js +193 -98
- package/lib/router/markers.js +7 -0
- package/lib/router/route.js +5 -0
- package/lib/router/routes.util.js +12 -14
- package/lib/router/utils.js +7 -0
- package/lib/stacks/MarkersStack.js +41 -3
- package/lib/stacks/MiddlewaresStack.js +200 -0
- package/lib/structures/Enum.js +46 -0
- package/lib/structures/Filter.js +156 -0
- package/lib/structures/Params.js +55 -0
- package/lib/tools/sql.tool.js +7 -0
- package/lib/utils/objects.util.js +31 -24
- package/lib/utils/sanitizations.util.js +10 -4
- package/lib/validators/arguments.js +68 -0
- package/lib/validators/dates.js +7 -0
- package/lib/validators/numbers.js +7 -0
- package/package.json +11 -8
- package/lib/database/utils.js +0 -19
- package/lib/enums/Enum.js +0 -16
- package/lib/filters/Filter.js +0 -109
- package/lib/http/response.js +0 -1074
- package/lib/http/utils.js +0 -254
- package/lib/params/Params.js +0 -37
- package/lib/policies/Role.js +0 -77
- package/lib/policies/RoleExtracting.js +0 -97
- package/lib/services/includes.service.js +0 -79
- package/lib/services/jwt.service.js +0 -147
- package/lib/stacks/MiddlewareStack.js +0 -159
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* /nodester
|
|
3
|
+
* MIT Licensed
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
1
8
|
const {
|
|
2
9
|
NODESTER_QUERY_ERROR,
|
|
3
10
|
UNAUTHORIZED_ERROR,
|
|
@@ -16,6 +23,9 @@ const {
|
|
|
16
23
|
deleteOne
|
|
17
24
|
} = require('../methods');
|
|
18
25
|
|
|
26
|
+
// Arguments validator.
|
|
27
|
+
const { ensure } = require('../../validators/arguments');
|
|
28
|
+
|
|
19
29
|
|
|
20
30
|
module.exports = {
|
|
21
31
|
withDefaultCRUD: _withDefaultCRUD,
|
|
@@ -30,29 +40,27 @@ module.exports = {
|
|
|
30
40
|
* Sets one of or all of CRUD methods to Controller.
|
|
31
41
|
*
|
|
32
42
|
* @param {Function|Object} controller
|
|
33
|
-
* @param {Object}
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
43
|
+
* @param {Object} options
|
|
44
|
+
* @param {Function|Object} options.facade
|
|
45
|
+
* @param {String} options.name
|
|
46
|
+
* @param {Array} options.only
|
|
37
47
|
*
|
|
38
48
|
* @return {Function|Object} controller
|
|
39
49
|
*
|
|
40
50
|
* @api public
|
|
41
51
|
* @alias withDefaultCRUD
|
|
42
52
|
*/
|
|
43
|
-
function _withDefaultCRUD(controller,
|
|
53
|
+
function _withDefaultCRUD(controller, options={}) {
|
|
54
|
+
ensure(controller, 'function|object,required', 'controller');
|
|
55
|
+
ensure(options, 'object,required', 'options');
|
|
56
|
+
|
|
44
57
|
const {
|
|
45
58
|
facade,
|
|
46
59
|
|
|
47
60
|
// Optional:
|
|
48
61
|
name,
|
|
49
62
|
only
|
|
50
|
-
} =
|
|
51
|
-
|
|
52
|
-
if (!controller) {
|
|
53
|
-
const err = new TypeError(`'controller' argument is not provided.`);
|
|
54
|
-
throw err;
|
|
55
|
-
}
|
|
63
|
+
} = options;
|
|
56
64
|
|
|
57
65
|
_setFacade(controller, facade);
|
|
58
66
|
|
|
@@ -60,7 +68,7 @@ function _withDefaultCRUD(controller, opts={}) {
|
|
|
60
68
|
const model = facade.model;
|
|
61
69
|
// Extract plural name of this model.
|
|
62
70
|
const modelPluralName = model?.options?.name?.plural;
|
|
63
|
-
// Set name of this controller:
|
|
71
|
+
// Set read-only name of this controller:
|
|
64
72
|
Object.defineProperty(controller, 'name', {
|
|
65
73
|
value: name ?? `${ modelPluralName ?? controller.name }Controller`,
|
|
66
74
|
writable: false
|
|
@@ -120,18 +128,15 @@ function _withDefaultCRUD(controller, opts={}) {
|
|
|
120
128
|
* Sets default error responses to Controller.
|
|
121
129
|
*
|
|
122
130
|
* @param {Function|Object} controller
|
|
123
|
-
* @param {Object}
|
|
131
|
+
* @param {Object} options
|
|
124
132
|
*
|
|
125
133
|
* @return {Function|Object} controller
|
|
126
134
|
*
|
|
127
135
|
* @api public
|
|
128
136
|
* @alias withDefaultErrorProcessing
|
|
129
137
|
*/
|
|
130
|
-
function _withDefaultErrorProcessing(controller,
|
|
131
|
-
|
|
132
|
-
const err = new TypeError(`'controller' argument is not provided.`);
|
|
133
|
-
throw err;
|
|
134
|
-
}
|
|
138
|
+
function _withDefaultErrorProcessing(controller, options={}) {
|
|
139
|
+
ensure(controller, 'function|object,required', 'controller');
|
|
135
140
|
|
|
136
141
|
// Set processError:
|
|
137
142
|
controller.processError = function (error, req, res) {
|
|
@@ -220,15 +225,8 @@ function _withDefaultErrorProcessing(controller, opts={}) {
|
|
|
220
225
|
* @alias setFacade
|
|
221
226
|
*/
|
|
222
227
|
function _setFacade(controller, facade, facadeName=null) {
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
throw err;
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
if (!facade) {
|
|
229
|
-
const err = new TypeError(`'facade' argument is invalid.`);
|
|
230
|
-
throw err;
|
|
231
|
-
}
|
|
228
|
+
ensure(controller, 'function|object,required', 'controller');
|
|
229
|
+
ensure(facade, 'function|object,required', 'facade');
|
|
232
230
|
|
|
233
231
|
// Set main facade:
|
|
234
232
|
if (facade.constructor.name === 'Function') {
|
|
@@ -237,25 +235,27 @@ function _setFacade(controller, facade, facadeName=null) {
|
|
|
237
235
|
else {
|
|
238
236
|
controller[facadeName ?? 'facade'] = facade;
|
|
239
237
|
}
|
|
238
|
+
|
|
239
|
+
return controller;
|
|
240
240
|
}
|
|
241
241
|
|
|
242
242
|
|
|
243
243
|
/**
|
|
244
244
|
* Sets one of CRUD methods to Controller.
|
|
245
245
|
*
|
|
246
|
-
* @param {
|
|
247
|
-
* @param {
|
|
246
|
+
* @param {Controller} controller
|
|
247
|
+
* @param {Function} fn
|
|
248
248
|
*
|
|
249
|
-
* @return {
|
|
249
|
+
* @return {Controller} controller
|
|
250
250
|
*
|
|
251
251
|
* @api public
|
|
252
|
-
* @alias
|
|
252
|
+
* @alias setMethod
|
|
253
253
|
*/
|
|
254
|
-
function _setMethod(controller,) {
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
throw err;
|
|
258
|
-
}
|
|
254
|
+
function _setMethod(controller, fn) {
|
|
255
|
+
ensure(controller, 'function|object,required', 'controller');
|
|
256
|
+
ensure(fn, 'function,required', 'fn');
|
|
259
257
|
|
|
258
|
+
controller[fn] = fn.bind(controller);
|
|
260
259
|
|
|
260
|
+
return controller;
|
|
261
261
|
}
|
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
|
|
1
|
+
/*!
|
|
2
|
+
* /nodester
|
|
3
|
+
* MIT Licensed
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
const { associateModels } = require('nodester/models/associate');
|
|
2
9
|
|
|
3
10
|
|
|
4
11
|
module.exports = {
|
|
@@ -19,10 +26,13 @@ async function _migrate(databaseConnection, force=false) {
|
|
|
19
26
|
|
|
20
27
|
const models = databaseConnection.models;
|
|
21
28
|
const modelNames = Object.keys(models);
|
|
22
|
-
|
|
29
|
+
|
|
30
|
+
console.info('Models list:', ...modelNames.map(name => `\n • ${ name }`), '\n');
|
|
31
|
+
|
|
23
32
|
console.info('Forcefully?', force);
|
|
24
33
|
console.info('Syncing...\n');
|
|
25
|
-
|
|
34
|
+
|
|
35
|
+
await associateModels(databaseConnection);
|
|
26
36
|
await databaseConnection.sync({ force });
|
|
27
37
|
console.info('Successful migration!');
|
|
28
38
|
|
|
@@ -34,7 +44,7 @@ async function _migrate(databaseConnection, force=false) {
|
|
|
34
44
|
return Promise.resolve(output);
|
|
35
45
|
}
|
|
36
46
|
catch(error) {
|
|
37
|
-
console.error('Migration failed!');
|
|
47
|
+
console.error(' Migration failed!');
|
|
38
48
|
console.error(error);
|
|
39
49
|
return Promise.reject(error);
|
|
40
50
|
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* /nodester
|
|
3
3
|
* MIT Licensed
|
|
4
4
|
*/
|
|
5
|
+
|
|
5
6
|
'use strict';
|
|
6
7
|
|
|
7
8
|
const Params = require('nodester/params');
|
|
@@ -36,13 +37,13 @@ async function _getOne(params) {
|
|
|
36
37
|
const instance = await this.model.findOne(query);
|
|
37
38
|
|
|
38
39
|
const result = {
|
|
39
|
-
[this.
|
|
40
|
+
[this.outputName.singular]: instance,
|
|
40
41
|
count: 0 + (instance !== null)
|
|
41
42
|
}
|
|
42
43
|
return Promise.resolve(result);
|
|
43
44
|
}
|
|
44
45
|
catch(error) {
|
|
45
|
-
log.error(`${
|
|
46
|
+
log.error(`${ this.name }.getOne error:`, error);
|
|
46
47
|
return Promise.reject(error);
|
|
47
48
|
}
|
|
48
49
|
}
|
|
@@ -66,13 +67,13 @@ async function _getMany(params) {
|
|
|
66
67
|
const instances = await this.model.findAll(query);
|
|
67
68
|
|
|
68
69
|
const result = {
|
|
69
|
-
[this.
|
|
70
|
+
[this.outputName.plural]: instances,
|
|
70
71
|
count: instances.length
|
|
71
72
|
}
|
|
72
73
|
return Promise.resolve(result);
|
|
73
74
|
}
|
|
74
75
|
catch(error) {
|
|
75
|
-
log.error(`${
|
|
76
|
+
log.error(`${ this.name }.getMany error:`, error);
|
|
76
77
|
return Promise.reject(error);
|
|
77
78
|
}
|
|
78
79
|
}
|
|
@@ -98,7 +99,7 @@ async function _createOne(params) {
|
|
|
98
99
|
});
|
|
99
100
|
|
|
100
101
|
const result = {
|
|
101
|
-
[this.
|
|
102
|
+
[this.outputName.singular]: instance,
|
|
102
103
|
count: 0 + (instance !== null)
|
|
103
104
|
}
|
|
104
105
|
|
|
@@ -108,7 +109,7 @@ async function _createOne(params) {
|
|
|
108
109
|
return Promise.resolve(result);
|
|
109
110
|
}
|
|
110
111
|
catch(error) {
|
|
111
|
-
log.error(`${
|
|
112
|
+
log.error(`${ this.name }.createOne error:`, error);
|
|
112
113
|
return Promise.reject(error);
|
|
113
114
|
}
|
|
114
115
|
}
|
|
@@ -137,13 +138,13 @@ async function _updateOne(params) {
|
|
|
137
138
|
|
|
138
139
|
const result = {
|
|
139
140
|
success: isNewRecord === false,
|
|
140
|
-
[this.
|
|
141
|
+
[this.outputName.singular]: instance,
|
|
141
142
|
count: 0 + (instance !== null)
|
|
142
143
|
}
|
|
143
144
|
return Promise.resolve(result);
|
|
144
145
|
}
|
|
145
146
|
catch(error) {
|
|
146
|
-
log.error(`${
|
|
147
|
+
log.error(`${ this.name }.updateOne error:`, error);
|
|
147
148
|
return Promise.reject(error);
|
|
148
149
|
}
|
|
149
150
|
}
|
|
@@ -173,7 +174,7 @@ async function _deleteOne(params) {
|
|
|
173
174
|
return Promise.resolve(result);
|
|
174
175
|
}
|
|
175
176
|
catch(error) {
|
|
176
|
-
log.error(`${
|
|
177
|
+
log.error(`${ this.name }.deleteOne error:`, error);
|
|
177
178
|
return Promise.reject(error);
|
|
178
179
|
}
|
|
179
180
|
}
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* /nodester
|
|
3
|
+
* MIT Licensed
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
1
8
|
const {
|
|
2
9
|
getOne,
|
|
3
10
|
getMany,
|
|
@@ -5,41 +12,47 @@ const {
|
|
|
5
12
|
updateOne,
|
|
6
13
|
deleteOne
|
|
7
14
|
} = require('../methods');
|
|
8
|
-
|
|
15
|
+
|
|
16
|
+
// Utils:
|
|
17
|
+
const { Sequelize } = require('sequelize');
|
|
9
18
|
const { lowerCaseFirstLetter } = require('nodester/utils/strings');
|
|
10
19
|
|
|
20
|
+
// Arguments validator.
|
|
21
|
+
const { ensure } = require('../../validators/arguments');
|
|
22
|
+
|
|
11
23
|
|
|
12
24
|
module.exports = {
|
|
13
25
|
withDefaultCRUD: _withDefaultCRUD,
|
|
26
|
+
|
|
27
|
+
setMethod: _setMethod
|
|
14
28
|
}
|
|
15
29
|
|
|
16
30
|
/**
|
|
17
31
|
* Sets one of or all of CRUD methods to Facade.
|
|
18
32
|
*
|
|
19
33
|
* @param {Function|Object} facade
|
|
20
|
-
* @param {Object}
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
34
|
+
* @param {Object} options
|
|
35
|
+
* @param {Function|Object} options.model
|
|
36
|
+
* @param {String} options.name
|
|
37
|
+
* @param {Array} options.only
|
|
24
38
|
*
|
|
25
39
|
* @return {Function|Object} facade
|
|
26
40
|
*
|
|
27
41
|
* @api public
|
|
28
42
|
* @alias withDefaultCRUD
|
|
29
43
|
*/
|
|
30
|
-
function _withDefaultCRUD(facade,
|
|
44
|
+
function _withDefaultCRUD(facade, options={}) {
|
|
45
|
+
ensure(facade, 'function|object,required', 'facade');
|
|
46
|
+
ensure(options, 'object,required', 'options');
|
|
47
|
+
ensure(options.model, 'function|object,required', 'options.model');
|
|
48
|
+
|
|
31
49
|
const {
|
|
32
50
|
model,
|
|
33
51
|
|
|
34
52
|
// Optional:
|
|
35
53
|
name,
|
|
36
54
|
only
|
|
37
|
-
} =
|
|
38
|
-
|
|
39
|
-
if (!facade) {
|
|
40
|
-
const err = new TypeError(`'facade' argument is not provided.`);
|
|
41
|
-
throw err;
|
|
42
|
-
}
|
|
55
|
+
} = options;
|
|
43
56
|
|
|
44
57
|
// Set model info:
|
|
45
58
|
// Set model:
|
|
@@ -58,7 +71,6 @@ function _withDefaultCRUD(facade, opts={}) {
|
|
|
58
71
|
writable: false
|
|
59
72
|
});
|
|
60
73
|
|
|
61
|
-
|
|
62
74
|
// Set name of this facade:
|
|
63
75
|
Object.defineProperty(facade, 'name', {
|
|
64
76
|
value: name ?? `${ modelName.plural ?? facade.name }Facade`,
|
|
@@ -66,6 +78,28 @@ function _withDefaultCRUD(facade, opts={}) {
|
|
|
66
78
|
});
|
|
67
79
|
|
|
68
80
|
|
|
81
|
+
// Set the name of the output:
|
|
82
|
+
const outputName = {
|
|
83
|
+
singular: Sequelize.Utils.underscore(modelName.singular),
|
|
84
|
+
plural: Sequelize.Utils.underscore(modelName.plural)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
switch (model.options.nodester.output) {
|
|
88
|
+
case 'camelcased':
|
|
89
|
+
outputName.singular = this.modelName.singular;
|
|
90
|
+
outputName.plural = this.modelName.plural;
|
|
91
|
+
break;
|
|
92
|
+
case 'underscored':
|
|
93
|
+
default:
|
|
94
|
+
break;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
Object.defineProperty(facade, 'outputName', {
|
|
98
|
+
value: outputName,
|
|
99
|
+
writable: false
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
|
|
69
103
|
// If only certain methods should be set:
|
|
70
104
|
if (!!only) {
|
|
71
105
|
for (const selectedMethod of only) {
|
|
@@ -109,3 +143,23 @@ function _withDefaultCRUD(facade, opts={}) {
|
|
|
109
143
|
|
|
110
144
|
return facade;
|
|
111
145
|
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Sets one of CRUD methods to Facade.
|
|
149
|
+
*
|
|
150
|
+
* @param {Facade} facade
|
|
151
|
+
* @param {Function} fn
|
|
152
|
+
*
|
|
153
|
+
* @return {Facade} facade
|
|
154
|
+
*
|
|
155
|
+
* @api public
|
|
156
|
+
* @alias setMethod
|
|
157
|
+
*/
|
|
158
|
+
function _setMethod(facade, fn) {
|
|
159
|
+
ensure(facade, 'function|object,required', 'facade');
|
|
160
|
+
ensure(fn, 'function,required', 'fn');
|
|
161
|
+
|
|
162
|
+
facade[fn] = fn.bind(facade);
|
|
163
|
+
|
|
164
|
+
return facade;
|
|
165
|
+
}
|
|
@@ -1,5 +1,12 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* /nodester
|
|
3
|
+
* MIT Licensed
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
1
8
|
/*
|
|
2
|
-
*
|
|
9
|
+
* REST response factory.
|
|
3
10
|
*/
|
|
4
11
|
|
|
5
12
|
const ResponseFormats = require('../../constants/ResponseFormats');
|
|
@@ -11,7 +18,6 @@ module.exports = {
|
|
|
11
18
|
createErrorResponse: _createErrorResponse,
|
|
12
19
|
}
|
|
13
20
|
|
|
14
|
-
|
|
15
21
|
/*
|
|
16
22
|
* Format for all API responses will be JSON
|
|
17
23
|
* {
|
|
@@ -25,6 +31,10 @@ module.exports = {
|
|
|
25
31
|
*
|
|
26
32
|
* @param {ServerResponse} res
|
|
27
33
|
* @param {Object} options
|
|
34
|
+
* @param {Object} options.error
|
|
35
|
+
* @param {Object} options.content (optional)
|
|
36
|
+
* @param {Int} options.status
|
|
37
|
+
* @param {String} options.format
|
|
28
38
|
*
|
|
29
39
|
* @alias createGenericResponse
|
|
30
40
|
* @api public
|
|
@@ -45,12 +55,13 @@ function _createGenericResponse(
|
|
|
45
55
|
};
|
|
46
56
|
|
|
47
57
|
switch(options?.format) {
|
|
48
|
-
case ResponseFormats.JSON:
|
|
49
|
-
return
|
|
50
|
-
|
|
58
|
+
case ResponseFormats.JSON: {
|
|
59
|
+
return res.json(data);
|
|
60
|
+
}
|
|
61
|
+
case ResponseFormats.XML: {
|
|
51
62
|
// TODO: format data into XML.
|
|
52
|
-
return
|
|
53
|
-
|
|
63
|
+
return res.send(data);
|
|
64
|
+
}
|
|
54
65
|
default: {
|
|
55
66
|
const err = new TypeError("No format specified.");
|
|
56
67
|
throw err;
|
|
@@ -71,8 +82,8 @@ function _createGenericResponse(
|
|
|
71
82
|
* Should be called on all successful respones.
|
|
72
83
|
*
|
|
73
84
|
* @param {ServerResponse} res
|
|
74
|
-
* @param
|
|
75
|
-
* @param
|
|
85
|
+
* @param {Object} options.content (optional)
|
|
86
|
+
* @param {String} options.format
|
|
76
87
|
*
|
|
77
88
|
* @alias createOKResponse
|
|
78
89
|
* @api public
|
|
@@ -92,10 +103,11 @@ function _createOKResponse(res, options={}) {
|
|
|
92
103
|
* Should be called on all failed respones.
|
|
93
104
|
*
|
|
94
105
|
* @param {ServerResponse} res
|
|
95
|
-
* @param
|
|
96
|
-
* @param
|
|
97
|
-
* @param
|
|
98
|
-
* @param
|
|
106
|
+
* @param {Object} options
|
|
107
|
+
* @param {Object} options.error
|
|
108
|
+
* @param {Object} options.content (optional)
|
|
109
|
+
* @param {Int} options.status
|
|
110
|
+
* @param {String} options.format
|
|
99
111
|
*
|
|
100
112
|
* @alias createErrorResponse
|
|
101
113
|
* @api public
|