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.
Files changed (58) hide show
  1. package/Readme.md +16 -55
  2. package/lib/application/index.js +174 -63
  3. package/lib/body/extract.js +15 -4
  4. package/lib/constants/Bounds.js +15 -0
  5. package/lib/constants/Clauses.js +13 -0
  6. package/lib/constants/ResponseFormats.js +2 -2
  7. package/lib/controllers/methods/index.js +7 -0
  8. package/lib/controllers/mixins/index.js +36 -36
  9. package/lib/database/connection.js +6 -0
  10. package/lib/database/migration.js +14 -4
  11. package/lib/facades/methods/index.js +10 -9
  12. package/lib/facades/mixins/index.js +67 -13
  13. package/lib/factories/responses/rest.js +25 -13
  14. package/lib/http/{request.js → request/index.js} +53 -75
  15. package/lib/http/request/utils.js +27 -0
  16. package/lib/http/response/headers.js +138 -0
  17. package/lib/http/response/index.js +248 -0
  18. package/lib/http/response/utils.js +38 -0
  19. package/lib/middlewares/SearchParams/index.js +25 -0
  20. package/lib/middlewares/cookies/index.js +44 -0
  21. package/lib/middlewares/etag/index.js +32 -15
  22. package/lib/middlewares/formidable/index.js +30 -25
  23. package/lib/middlewares/ql/sequelize/index.js +11 -2
  24. package/lib/middlewares/ql/sequelize/interpreter/QueryLexer.js +2 -1
  25. package/lib/middlewares/render/index.js +62 -0
  26. package/lib/models/associate.js +25 -1
  27. package/lib/models/define.js +19 -15
  28. package/lib/models/mixins.js +7 -0
  29. package/lib/query/traverse.js +96 -63
  30. package/lib/router/handlers.util.js +1 -0
  31. package/lib/router/index.js +193 -98
  32. package/lib/router/markers.js +7 -0
  33. package/lib/router/route.js +5 -0
  34. package/lib/router/routes.util.js +12 -14
  35. package/lib/router/utils.js +7 -0
  36. package/lib/stacks/MarkersStack.js +41 -3
  37. package/lib/stacks/MiddlewaresStack.js +200 -0
  38. package/lib/structures/Enum.js +46 -0
  39. package/lib/structures/Filter.js +156 -0
  40. package/lib/structures/Params.js +55 -0
  41. package/lib/tools/sql.tool.js +7 -0
  42. package/lib/utils/objects.util.js +31 -24
  43. package/lib/utils/sanitizations.util.js +10 -4
  44. package/lib/validators/arguments.js +68 -0
  45. package/lib/validators/dates.js +7 -0
  46. package/lib/validators/numbers.js +7 -0
  47. package/package.json +11 -8
  48. package/lib/database/utils.js +0 -19
  49. package/lib/enums/Enum.js +0 -16
  50. package/lib/filters/Filter.js +0 -109
  51. package/lib/http/response.js +0 -1074
  52. package/lib/http/utils.js +0 -254
  53. package/lib/params/Params.js +0 -37
  54. package/lib/policies/Role.js +0 -77
  55. package/lib/policies/RoleExtracting.js +0 -97
  56. package/lib/services/includes.service.js +0 -79
  57. package/lib/services/jwt.service.js +0 -147
  58. 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} opts
34
- * - @param {Function|Object} facade
35
- * - @param {String} name
36
- * - @param {Array} only
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, opts={}) {
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
- } = opts;
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} opts
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, opts={}) {
131
- if (!controller) {
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
- if (!controller) {
224
- const err = new TypeError(`'controller' argument is not provided.`);
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 {Function|Object} controller
247
- * @param {Object} opts
246
+ * @param {Controller} controller
247
+ * @param {Function} fn
248
248
  *
249
- * @return {Function|Object} controller
249
+ * @return {Controller} controller
250
250
  *
251
251
  * @api public
252
- * @alias withDefaultCRUD
252
+ * @alias setMethod
253
253
  */
254
- function _setMethod(controller,) {
255
- if (!controller) {
256
- const err = new TypeError(`'controller' argument is not provided.`);
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,3 +1,9 @@
1
+ /*!
2
+ * /nodester
3
+ * MIT Licensed
4
+ */
5
+ 'use strict';
6
+
1
7
  // ORM.
2
8
  const Sequelize = require('sequelize');
3
9
 
@@ -1,4 +1,11 @@
1
- const { associateModels } = require('./utils');
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
- console.info('Models to sync:', modelNames);
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
- await associateModels(models);
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.modelName.singular]: instance,
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(`${ [this.modelName.singular] }Facade.getOne error:`, 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.modelName.plural]: instances,
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(`${ [this.modelName.singular] }Facade.getMany error:`, 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.modelName.singular]: instance,
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(`${ [this.modelName.singular] }Facade.createOne error:`, 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.modelName.singular]: instance,
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(`${ [this.modelName.singular] }Facade.updateOne error:`, 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(`${ [this.modelName.singular] }Facade.deleteOne error:`, 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
- // Utils,
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} opts
21
- * - @param {Function|Object} model
22
- * - @param {String} name
23
- * - @param {Array} only
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, opts={}) {
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
- } = opts;
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
- * Rest response factory.
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 options?.res.status(options?.status).json(data);
50
- case ResponseFormats.XML:
58
+ case ResponseFormats.JSON: {
59
+ return res.json(data);
60
+ }
61
+ case ResponseFormats.XML: {
51
62
  // TODO: format data into XML.
52
- return options?.res.status(options?.status).send(data);
53
- break;
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 <Object> content
75
- * @param <String> format
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 <Object> error
96
- * @param <Object> content (optional)
97
- * @param <Int> status
98
- * @param <String> format
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