nodester 0.0.8 → 0.1.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 +18 -59
- package/lib/application/index.js +28 -7
- package/lib/controllers/methods/index.js +34 -10
- package/lib/controllers/mixins/index.js +14 -5
- package/lib/database/connection.js +34 -0
- package/lib/database/migration.js +42 -0
- package/lib/database/utils.js +19 -0
- package/lib/facades/methods/index.js +173 -0
- package/lib/facades/mixins/index.js +111 -0
- package/lib/middlewares/formidable/index.js +37 -0
- package/lib/middlewares/ql/sequelize/interpreter/ModelsTree.js +2 -2
- package/lib/middlewares/ql/sequelize/interpreter/QueryLexer.js +3 -3
- package/lib/models/associate.js +17 -0
- package/lib/models/define.js +50 -1
- package/lib/models/mixins.js +81 -72
- package/lib/params/Params.js +10 -7
- package/lib/queries/Colander.js +84 -0
- package/lib/queries/traverse.js +311 -0
- package/lib/router/handlers.util.js +22 -2
- package/lib/router/index.js +96 -75
- package/lib/router/markers.js +78 -0
- package/lib/router/route.js +4 -4
- package/lib/router/routes.util.js +35 -5
- package/lib/router/utils.js +30 -0
- package/package.json +20 -7
- package/tests/nql.test.js +3 -3
- package/lib/_/n_controllers/Controller.js +0 -474
- package/lib/_/n_controllers/JWTController.js +0 -240
- package/lib/_/n_controllers/ServiceController.js +0 -109
- package/lib/_/n_controllers/WebController.js +0 -75
- package/lib/_facades/Facade.js +0 -388
- package/lib/_facades/FacadeParams.js +0 -11
- package/lib/_facades/ServiceFacade.js +0 -17
- package/lib/_facades/jwt.facade.js +0 -273
- package/lib/models/DisabledRefreshToken.js +0 -68
- package/lib/models/Extractor.js +0 -320
- package/lib/utils/forms.util.js +0 -22
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
const {
|
|
2
|
+
getOne,
|
|
3
|
+
getMany,
|
|
4
|
+
createOne,
|
|
5
|
+
updateOne,
|
|
6
|
+
deleteOne
|
|
7
|
+
} = require('../methods');
|
|
8
|
+
// Utils,
|
|
9
|
+
const { lowerCaseFirstLetter } = require('nodester/utils/strings');
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
module.exports = {
|
|
13
|
+
withDefaultCRUD: _withDefaultCRUD,
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Sets one of or all of CRUD methods to Facade.
|
|
18
|
+
*
|
|
19
|
+
* @param {Function|Object} facade
|
|
20
|
+
* @param {Object} opts
|
|
21
|
+
* - @param {Function|Object} model
|
|
22
|
+
* - @param {String} name
|
|
23
|
+
* - @param {Array} only
|
|
24
|
+
*
|
|
25
|
+
* @return {Function|Object} facade
|
|
26
|
+
*
|
|
27
|
+
* @api public
|
|
28
|
+
* @alias withDefaultCRUD
|
|
29
|
+
*/
|
|
30
|
+
function _withDefaultCRUD(facade, opts={}) {
|
|
31
|
+
const {
|
|
32
|
+
model,
|
|
33
|
+
|
|
34
|
+
// Optional:
|
|
35
|
+
name,
|
|
36
|
+
only
|
|
37
|
+
} = opts;
|
|
38
|
+
|
|
39
|
+
if (!facade) {
|
|
40
|
+
const err = new TypeError(`'facade' argument is not provided.`);
|
|
41
|
+
throw err;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Set model info:
|
|
45
|
+
// Set model:
|
|
46
|
+
Object.defineProperty(facade, 'model', {
|
|
47
|
+
value: model,
|
|
48
|
+
writable: false
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
// Model name:
|
|
52
|
+
const modelName = model.options.name;
|
|
53
|
+
Object.defineProperty(facade, 'modelName', {
|
|
54
|
+
value: {
|
|
55
|
+
singular: lowerCaseFirstLetter(modelName.singular),
|
|
56
|
+
plural: lowerCaseFirstLetter(modelName.plural)
|
|
57
|
+
},
|
|
58
|
+
writable: false
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
// Set name of this facade:
|
|
63
|
+
Object.defineProperty(facade, 'name', {
|
|
64
|
+
value: name ?? `${ modelName.plural ?? facade.name }Facade`,
|
|
65
|
+
writable: false
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
// If only certain methods should be set:
|
|
70
|
+
if (!!only) {
|
|
71
|
+
for (const selectedMethod of only) {
|
|
72
|
+
switch(selectedMethod) {
|
|
73
|
+
case 'getOne':
|
|
74
|
+
facade.getOne = getOne.bind(facade);
|
|
75
|
+
break;
|
|
76
|
+
case 'getMany':
|
|
77
|
+
facade.getMany = getMany.bind(facade);
|
|
78
|
+
break;
|
|
79
|
+
case 'createOne':
|
|
80
|
+
facade.createOne = createOne.bind(facade);
|
|
81
|
+
break;
|
|
82
|
+
case 'updateOne':
|
|
83
|
+
facade.updateOne = updateOne.bind(facade);
|
|
84
|
+
break;
|
|
85
|
+
case 'deleteOne':
|
|
86
|
+
facade.deleteOne = deleteOne.bind(facade);
|
|
87
|
+
break;
|
|
88
|
+
|
|
89
|
+
default:
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
// Or set all methods:
|
|
95
|
+
else {
|
|
96
|
+
facade.getOne = getOne.bind(facade);
|
|
97
|
+
facade.getMany = getMany.bind(facade);
|
|
98
|
+
facade.createOne = createOne.bind(facade);
|
|
99
|
+
facade.updateOne = updateOne.bind(facade);
|
|
100
|
+
facade.deleteOne = deleteOne.bind(facade);
|
|
101
|
+
|
|
102
|
+
// Set empty hooks:
|
|
103
|
+
facade.afterGetOne = async () => {};
|
|
104
|
+
facade.afterGetMany = async () => {};
|
|
105
|
+
facade.afterCreateOne = async () => {};
|
|
106
|
+
facade.afterUpdateOne = async () => {};
|
|
107
|
+
facade.afterDeleteOe = async () => {};
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return facade;
|
|
111
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* /nodester
|
|
3
|
+
* MIT Licensed
|
|
4
|
+
*/
|
|
5
|
+
'use strict';
|
|
6
|
+
|
|
7
|
+
const { formidable } = require('formidable');
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
module.exports = function FormidableMiddleware(formidableOptions={}) {
|
|
11
|
+
return async function(req, res, next) {
|
|
12
|
+
try {
|
|
13
|
+
const form = formidable(formidableOptions);
|
|
14
|
+
const [fields, files] = await form.parse(req);
|
|
15
|
+
|
|
16
|
+
// Add to request:
|
|
17
|
+
req.form = {
|
|
18
|
+
fields,
|
|
19
|
+
files
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
next();
|
|
23
|
+
}
|
|
24
|
+
catch(error) {
|
|
25
|
+
const statusCode = error.status || 406;
|
|
26
|
+
res.status(statusCode);
|
|
27
|
+
res.json({
|
|
28
|
+
error: {
|
|
29
|
+
message: error.message,
|
|
30
|
+
code: statusCode
|
|
31
|
+
},
|
|
32
|
+
status: statusCode
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
|
|
@@ -16,7 +16,7 @@ class ModelsTreeNode {
|
|
|
16
16
|
|
|
17
17
|
this.includes = opts.includes ?? [];
|
|
18
18
|
this.order = opts.order ?? 'asc';
|
|
19
|
-
this.
|
|
19
|
+
this.order_by = opts.order_by ?? 'id';
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
get hasParent() {
|
|
@@ -64,7 +64,7 @@ class ModelsTreeNode {
|
|
|
64
64
|
skip: this.skip,
|
|
65
65
|
limit: this.limit,
|
|
66
66
|
order: this.order,
|
|
67
|
-
|
|
67
|
+
order_by: this.order_by,
|
|
68
68
|
|
|
69
69
|
fields: this.fields,
|
|
70
70
|
|
|
@@ -378,7 +378,7 @@ module.exports = class QueryLexer {
|
|
|
378
378
|
return 'order';
|
|
379
379
|
case 'order_by':
|
|
380
380
|
case 'o_by':
|
|
381
|
-
return '
|
|
381
|
+
return 'order_by';
|
|
382
382
|
case 'fields':
|
|
383
383
|
case 'f':
|
|
384
384
|
return 'fields';
|
|
@@ -406,8 +406,8 @@ module.exports = class QueryLexer {
|
|
|
406
406
|
case 'order':
|
|
407
407
|
treeNode.order = token;
|
|
408
408
|
break;
|
|
409
|
-
case '
|
|
410
|
-
treeNode.
|
|
409
|
+
case 'order_by':
|
|
410
|
+
treeNode.order_by = token;
|
|
411
411
|
break;
|
|
412
412
|
case 'fields':
|
|
413
413
|
if (token)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
|
|
2
|
+
module.exports = async function associateModels(databaseConnection) {
|
|
3
|
+
try {
|
|
4
|
+
const models = databaseConnection.models;
|
|
5
|
+
|
|
6
|
+
const modelNames = Object.keys(models);
|
|
7
|
+
|
|
8
|
+
for (let modelName of modelNames) {
|
|
9
|
+
await models[modelName].associate(models);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
return Promise.resolve(models);
|
|
13
|
+
}
|
|
14
|
+
catch(error) {
|
|
15
|
+
return Promise.reject(error);
|
|
16
|
+
}
|
|
17
|
+
}
|
package/lib/models/define.js
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
const { implementsCRUD } = require('./mixins');
|
|
3
3
|
// ORM.
|
|
4
4
|
const { DataTypes } = require('sequelize');
|
|
5
|
+
// NQL.
|
|
6
|
+
const Colander = require('../queries/Colander');
|
|
5
7
|
|
|
6
8
|
|
|
7
9
|
module.exports = defineModel;
|
|
@@ -37,13 +39,23 @@ function defineModel(
|
|
|
37
39
|
// Add user-defined options (they can override upper ones).
|
|
38
40
|
...options
|
|
39
41
|
};
|
|
42
|
+
|
|
40
43
|
const model = databaseConnection.define(modelName, definitionObject, _options);
|
|
41
44
|
|
|
42
45
|
if (options.noCRUD !== true) {
|
|
43
|
-
// Add
|
|
46
|
+
// Add:
|
|
47
|
+
// - createWithIncludes;
|
|
48
|
+
// - findById;
|
|
49
|
+
// - updateById;
|
|
50
|
+
// - deleteById;
|
|
51
|
+
// - etc.
|
|
44
52
|
implementsCRUD(model);
|
|
45
53
|
}
|
|
46
54
|
|
|
55
|
+
// Association helpers:
|
|
56
|
+
model.associate = (models) => {};
|
|
57
|
+
model.getIncludesList = _getIncludesList.bind(model);
|
|
58
|
+
|
|
47
59
|
// Instance methods:
|
|
48
60
|
model.prototype.toJSON = function() {
|
|
49
61
|
const values = { ...this.get() };
|
|
@@ -53,3 +65,40 @@ function defineModel(
|
|
|
53
65
|
|
|
54
66
|
return model;
|
|
55
67
|
}
|
|
68
|
+
|
|
69
|
+
/* Association mixins: */
|
|
70
|
+
function _getIncludesList(facadeData=null) {
|
|
71
|
+
const result = [];
|
|
72
|
+
|
|
73
|
+
const associations = this.associations;
|
|
74
|
+
const associationEntries = Object.entries(associations);
|
|
75
|
+
|
|
76
|
+
associationEntries.forEach(([
|
|
77
|
+
associationName,
|
|
78
|
+
associationDefinition
|
|
79
|
+
]) => {
|
|
80
|
+
const a = { association: associationName };
|
|
81
|
+
|
|
82
|
+
if (!!facadeData) {
|
|
83
|
+
// If facade data is set, go deeper:
|
|
84
|
+
const keys = Object.keys( facadeData );
|
|
85
|
+
if (keys.indexOf(associationName) > 0) {
|
|
86
|
+
const associationModel = associationDefinition.target;
|
|
87
|
+
|
|
88
|
+
const a = { association: associationName };
|
|
89
|
+
if (Object.entries(associationModel.associations).length > 0) {
|
|
90
|
+
const deepData = facadeData[ associationName ];
|
|
91
|
+
a.include = associationModel.getIncludesList(Array.isArray(deepData) ? deepData[0] : deepData);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
result.push( a );
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
result.push( a );
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
return result;
|
|
103
|
+
}
|
|
104
|
+
/* Association mixins\ */
|
package/lib/models/mixins.js
CHANGED
|
@@ -6,7 +6,11 @@ const {
|
|
|
6
6
|
modelHasAssociations,
|
|
7
7
|
getModelAssociationProps,
|
|
8
8
|
compileModelAssociationData,
|
|
9
|
-
} = require('
|
|
9
|
+
} = require('../utils/modelAssociations.util');
|
|
10
|
+
|
|
11
|
+
// Nodester query:
|
|
12
|
+
const NQLexer = require('../middlewares/ql/sequelize/interpreter/QueryLexer');
|
|
13
|
+
const traverseNQuery = require('../queries/traverse');
|
|
10
14
|
|
|
11
15
|
|
|
12
16
|
module.exports = {
|
|
@@ -17,15 +21,15 @@ module.exports = {
|
|
|
17
21
|
/**
|
|
18
22
|
* Sets all of CRUD methods to Model.
|
|
19
23
|
*
|
|
20
|
-
* @param {Object}
|
|
24
|
+
* @param {Object} modelDefinition
|
|
21
25
|
*
|
|
22
26
|
*
|
|
23
27
|
* @api public
|
|
24
28
|
* @alias implementsCRUD
|
|
25
29
|
*/
|
|
26
|
-
function _implementsCRUD(
|
|
27
|
-
if (!
|
|
28
|
-
const err = new TypeError(`
|
|
30
|
+
function _implementsCRUD(modelDefinition) {
|
|
31
|
+
if (!modelDefinition) {
|
|
32
|
+
const err = new TypeError(`"modelDefinition" argument is not provided.`);
|
|
29
33
|
throw err;
|
|
30
34
|
}
|
|
31
35
|
|
|
@@ -34,17 +38,15 @@ function _implementsCRUD(model) {
|
|
|
34
38
|
|
|
35
39
|
// Read:
|
|
36
40
|
modelDefinition.findById = _findById.bind(modelDefinition);
|
|
37
|
-
modelDefinition.
|
|
41
|
+
modelDefinition.findMany = _findMany.bind(modelDefinition);
|
|
38
42
|
|
|
39
43
|
// Update:
|
|
40
44
|
modelDefinition.updateOne = _updateOne.bind(modelDefinition);
|
|
41
45
|
modelDefinition.updateById = _updateById.bind(modelDefinition);
|
|
42
46
|
|
|
43
|
-
// Delete
|
|
47
|
+
// Delete:
|
|
48
|
+
modelDefinition.deleteOne = _deleteOne.bind(modelDefinition);
|
|
44
49
|
modelDefinition.deleteById = _deleteById.bind(modelDefinition);
|
|
45
|
-
|
|
46
|
-
// Associations:
|
|
47
|
-
modelDefinition.getIncludesList = _getIncludesList.bind(modelDefinition);
|
|
48
50
|
}
|
|
49
51
|
|
|
50
52
|
|
|
@@ -114,37 +116,76 @@ async function _createWithIncludes(
|
|
|
114
116
|
|
|
115
117
|
function _findById(
|
|
116
118
|
id=null,
|
|
117
|
-
|
|
118
|
-
paranoid=true
|
|
119
|
+
opts={}
|
|
119
120
|
) {
|
|
120
|
-
const query =
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
121
|
+
const { query } = opts;
|
|
122
|
+
|
|
123
|
+
let _query = {};
|
|
124
|
+
|
|
125
|
+
if (typeof query === 'string') {
|
|
126
|
+
const lexer = new NQLexer(query);
|
|
127
|
+
const nquery = lexer.query;
|
|
128
|
+
_query = traverseNQuery(nquery, null, this);
|
|
129
|
+
_query.where = {
|
|
130
|
+
..._query.where,
|
|
131
|
+
id: id
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
const {
|
|
136
|
+
include,
|
|
137
|
+
paranoid
|
|
138
|
+
} = opts;
|
|
139
|
+
|
|
140
|
+
_query = {
|
|
141
|
+
where: { id },
|
|
142
|
+
include: include,
|
|
143
|
+
paranoid: !!paranoid
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
return this.findOne(_query);
|
|
126
148
|
}
|
|
127
149
|
|
|
128
|
-
function
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
150
|
+
function _findMany(opts={}) {
|
|
151
|
+
const { query } = opts;
|
|
152
|
+
|
|
153
|
+
let _query = {};
|
|
154
|
+
|
|
155
|
+
if (typeof query === 'string') {
|
|
156
|
+
const lexer = new NQLexer(query);
|
|
157
|
+
const nquery = lexer.query;
|
|
158
|
+
_query = traverseNQuery(nquery, null, this);
|
|
159
|
+
_query.where = {
|
|
160
|
+
..._query.where,
|
|
161
|
+
id: id
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
const {
|
|
166
|
+
include,
|
|
167
|
+
paranoid
|
|
168
|
+
} = opts;
|
|
169
|
+
|
|
170
|
+
_query = {
|
|
171
|
+
where: { id },
|
|
172
|
+
include: include,
|
|
173
|
+
paranoid: !!paranoid
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
return this.findAll(_query);
|
|
139
179
|
}
|
|
140
180
|
|
|
181
|
+
|
|
141
182
|
async function _updateOne(
|
|
142
183
|
where,
|
|
143
184
|
data,
|
|
144
185
|
include=[]
|
|
145
186
|
) {
|
|
146
187
|
try {
|
|
147
|
-
const instance = await this.
|
|
188
|
+
const instance = await this.findOne({ where, include });
|
|
148
189
|
|
|
149
190
|
if (!instance) {
|
|
150
191
|
const err = new Error(`Model not found`);
|
|
@@ -201,7 +242,7 @@ async function _updateOne(
|
|
|
201
242
|
|
|
202
243
|
// Select this instance again, if includes was set:
|
|
203
244
|
if (include?.length > 0) {
|
|
204
|
-
const updatedInstance = await this.
|
|
245
|
+
const updatedInstance = await this.findOne({ where, include });
|
|
205
246
|
fullInstanceData = updatedInstance.toJSON();
|
|
206
247
|
}
|
|
207
248
|
|
|
@@ -225,6 +266,15 @@ async function _updateById(
|
|
|
225
266
|
);
|
|
226
267
|
}
|
|
227
268
|
|
|
269
|
+
|
|
270
|
+
function _deleteOne(query={}) {
|
|
271
|
+
const _query = {
|
|
272
|
+
...query,
|
|
273
|
+
limit: 1
|
|
274
|
+
}
|
|
275
|
+
return this.destroy(_query);
|
|
276
|
+
}
|
|
277
|
+
|
|
228
278
|
function _deleteById(
|
|
229
279
|
id=null
|
|
230
280
|
) {
|
|
@@ -235,47 +285,6 @@ function _deleteById(
|
|
|
235
285
|
}
|
|
236
286
|
/* Main mixinis\ */
|
|
237
287
|
|
|
238
|
-
/* Association mixins: */
|
|
239
|
-
function _getIncludesList(facadeData=null) {
|
|
240
|
-
// console.log({ facadeData, model: this });
|
|
241
|
-
|
|
242
|
-
const result = [];
|
|
243
|
-
|
|
244
|
-
const associations = this.associations;
|
|
245
|
-
const associationEntries = Object.entries(associations);
|
|
246
|
-
|
|
247
|
-
associationEntries.forEach(([
|
|
248
|
-
associationName,
|
|
249
|
-
associationDefinition
|
|
250
|
-
]) => {
|
|
251
|
-
const a = { association: associationName };
|
|
252
|
-
|
|
253
|
-
if (!!facadeData) {
|
|
254
|
-
// If facade data is set, go deeper:
|
|
255
|
-
const keys = Object.keys( facadeData );
|
|
256
|
-
if (keys.indexOf(associationName) > 0) {
|
|
257
|
-
const associationModel = associationDefinition.target;
|
|
258
|
-
|
|
259
|
-
const a = { association: associationName };
|
|
260
|
-
if (Object.entries(associationModel.associations).length > 0) {
|
|
261
|
-
const deepData = facadeData[ associationName ];
|
|
262
|
-
a.include = associationModel.getIncludesList(Array.isArray(deepData) ? deepData[0] : deepData);
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
result.push( a );
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
else {
|
|
269
|
-
result.push( a );
|
|
270
|
-
}
|
|
271
|
-
});
|
|
272
|
-
|
|
273
|
-
// console.log('getIncludesList', result);
|
|
274
|
-
|
|
275
|
-
return result;
|
|
276
|
-
}
|
|
277
|
-
/* Association mixins\ */
|
|
278
|
-
|
|
279
288
|
/* Subfunctions: */
|
|
280
289
|
async function _updateOrCreateOrDelete(
|
|
281
290
|
modelDefinition,
|
package/lib/params/Params.js
CHANGED
|
@@ -10,10 +10,9 @@ module.exports = Params;
|
|
|
10
10
|
* @param {Object} sourceObj
|
|
11
11
|
* @param {Object} defaultValuesList
|
|
12
12
|
*
|
|
13
|
-
* @return {
|
|
13
|
+
* @return {Object} result
|
|
14
14
|
*
|
|
15
15
|
* @api public
|
|
16
|
-
* @alias withDefaultCRUD
|
|
17
16
|
*/
|
|
18
17
|
function Params(
|
|
19
18
|
sourceObj={},
|
|
@@ -23,11 +22,15 @@ function Params(
|
|
|
23
22
|
|
|
24
23
|
const keys = Object.keys(defaultValuesList);
|
|
25
24
|
for (const key of keys) {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
25
|
+
|
|
26
|
+
// If value is not set,
|
|
27
|
+
// use default one from 'defaultValuesList':
|
|
28
|
+
if (sourceObj[key] === undefined) {
|
|
29
|
+
result[key] = defaultValuesList[key];
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
result[key] = sourceObj[key];
|
|
31
34
|
}
|
|
32
35
|
|
|
33
36
|
return result;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
const CLAUSES = ['limit', 'skip', 'order', 'order_by'];
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
module.exports = class Colander {
|
|
5
|
+
|
|
6
|
+
/*
|
|
7
|
+
*
|
|
8
|
+
* @param {Object|Model} optsOrModelDefinition
|
|
9
|
+
* - @param {Array} fields
|
|
10
|
+
* - @param {Array} clauses
|
|
11
|
+
* - @param {Object} includes
|
|
12
|
+
* - @param {Object} statics
|
|
13
|
+
* -- @param {Object} attributes
|
|
14
|
+
* -- @param {Object} clauses
|
|
15
|
+
*
|
|
16
|
+
*/
|
|
17
|
+
constructor(optsOrModelDefinition) {
|
|
18
|
+
this._fields = [];
|
|
19
|
+
this._clauses = [];
|
|
20
|
+
this._includes = {};
|
|
21
|
+
|
|
22
|
+
this._statics = {
|
|
23
|
+
attributes: {},
|
|
24
|
+
clauses: {
|
|
25
|
+
limit: 3
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// If model:
|
|
30
|
+
if (!!optsOrModelDefinition.tableName && typeof optsOrModelDefinition._schema === 'object') {
|
|
31
|
+
this._fields = Object.keys(optsOrModelDefinition.tableAttributes);
|
|
32
|
+
this._clauses = CLAUSES;
|
|
33
|
+
}
|
|
34
|
+
// If options:
|
|
35
|
+
else {
|
|
36
|
+
const {
|
|
37
|
+
fields,
|
|
38
|
+
clauses,
|
|
39
|
+
includes,
|
|
40
|
+
statics,
|
|
41
|
+
} = optsOrModelDefinition;
|
|
42
|
+
|
|
43
|
+
if (Array.isArray(fields)) {
|
|
44
|
+
this._fields = fields;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (Array.isArray(clauses)) {
|
|
48
|
+
this._clauses = clauses;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (typeof includes === 'object') {
|
|
52
|
+
this._includes = includes;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (typeof statics === 'object') {
|
|
56
|
+
if (typeof statics.attributes === 'object') {
|
|
57
|
+
this._statics.attributes = statics.attributes;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (typeof statics.clauses === 'object') {
|
|
61
|
+
this._statics.clauses = statics.clauses;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Getters:
|
|
68
|
+
get fields() {
|
|
69
|
+
return this._fields;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
get clauses() {
|
|
73
|
+
return this._clauses;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
get includes() {
|
|
77
|
+
return this._includes;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
get statics() {
|
|
81
|
+
return this._statics;
|
|
82
|
+
}
|
|
83
|
+
// Getters\
|
|
84
|
+
}
|