@vulkano/core 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.
@@ -0,0 +1,108 @@
1
+ module.exports = (modelName) => {
2
+
3
+ const {
4
+ config
5
+ } = app;
6
+
7
+ const {
8
+ settings
9
+ } = config;
10
+
11
+ const {
12
+ database
13
+ } = settings;
14
+
15
+ const {
16
+ connection
17
+ } = database || {};
18
+
19
+ if (!connection && !process.env.MONGO_URI) {
20
+ return {};
21
+ }
22
+
23
+ if (!modelName) {
24
+ console.log(`Invalid Model name ${modelName} to the Scaffold Controller`);
25
+ return {};
26
+ }
27
+
28
+ const {
29
+ create,
30
+ update
31
+ } = global[modelName] || {};
32
+
33
+ const getAllModelName = `getAll${modelName}`;
34
+ const getModelName = `get${modelName}`;
35
+
36
+ if (!create || !update) {
37
+
38
+ const invalid = [];
39
+
40
+ if (!create) {
41
+ invalid.push('create');
42
+ }
43
+
44
+ if (!update) {
45
+ invalid.push('update');
46
+ }
47
+
48
+ console.log(`Invalid Model method(s) ${invalid.join(', ')} to the model ${modelName} to the Scaffold Controller. Please verify the connection and try again.`);
49
+
50
+ return {};
51
+
52
+ }
53
+
54
+ return {
55
+
56
+ get(req, res) {
57
+
58
+ res.vsr(global[modelName][getAllModelName](req.query || {}));
59
+
60
+ },
61
+
62
+ 'get :id': function onGetRecord(req, res) {
63
+
64
+ const {
65
+ id
66
+ } = req.params || {};
67
+
68
+ res.vsr(global[modelName][getModelName](id) );
69
+
70
+ },
71
+
72
+ post: function onCreateRecord(req, res) {
73
+
74
+ const {
75
+ body
76
+ } = req || {};
77
+
78
+ res.vsr(global[modelName].create(body), 201);
79
+
80
+ },
81
+
82
+ 'put :id': function onPutRecord(req, res) {
83
+
84
+ const {
85
+ id
86
+ } = req.params || {};
87
+
88
+ const {
89
+ body
90
+ } = req || {};
91
+
92
+ res.vsr(global[modelName].update(id, body), 202);
93
+
94
+ },
95
+
96
+ 'delete :id': function onDeleteRecord(req, res) {
97
+
98
+ const {
99
+ id
100
+ } = req.params || {};
101
+
102
+ res.vsr(global[modelName].delete(id), 204);
103
+
104
+ }
105
+
106
+ };
107
+
108
+ };
@@ -0,0 +1,149 @@
1
+ /**
2
+ * Controllers
3
+ */
4
+
5
+ // Include all api controllers
6
+ const AllControllers = require('include-all')({
7
+ dirname: `${APP_PATH}/controllers`,
8
+ filter: /(.+Controller)\.js$/,
9
+ optional: true
10
+ });
11
+
12
+ const scaffoldController = require('./ScaffoldController');
13
+
14
+ module.exports = function loadControllersApplication() {
15
+
16
+ const routes = {};
17
+
18
+ Object.keys(AllControllers).forEach( (controller) => {
19
+
20
+ const methods = ['get', 'post', 'put', 'delete'];
21
+ const current = AllControllers[controller];
22
+
23
+ const {
24
+ scaffold,
25
+ model
26
+ } = current;
27
+
28
+ if (scaffold && model) {
29
+
30
+ const scaffoldingCurrent = scaffoldController(model);
31
+
32
+ Object.keys(scaffoldingCurrent).forEach( (m) => {
33
+
34
+ if (!current[m]) {
35
+ current[m] = scaffoldingCurrent[m];
36
+ }
37
+
38
+ });
39
+
40
+ }
41
+
42
+ let controllerName = controller.replace('Controller', '').toLowerCase();
43
+
44
+ let parts = [];
45
+ let method = 'get';
46
+ let pathToRun = '';
47
+ let moduleName = '';
48
+
49
+ Object.keys(current || []).forEach( (route) => {
50
+
51
+ // Is a submodule (like api/TestController)
52
+ if (route.split('Controller').length > 1) {
53
+
54
+ moduleName = controllerName;
55
+ const submodules = AllControllers[moduleName];
56
+
57
+ Object.keys(submodules || []).forEach( (subcontroller) => {
58
+
59
+ controllerName = subcontroller.replace('Controller', '').toLowerCase();
60
+ const subcurrent = submodules[subcontroller];
61
+
62
+ const {
63
+ scaffold: subcurrentScaffold,
64
+ model: subcurrentModel
65
+ } = subcurrent || {};
66
+
67
+ if (subcurrentScaffold && subcurrentModel) {
68
+
69
+ const scaffoldingSubcurrent = scaffoldController(subcurrentModel);
70
+
71
+ Object.keys(scaffoldingSubcurrent).forEach( (m) => {
72
+
73
+ if (!subcurrent[m]) {
74
+ subcurrent[m] = scaffoldingSubcurrent[m];
75
+ }
76
+
77
+ });
78
+
79
+ }
80
+
81
+ Object.keys(subcurrent || []).forEach( (subroute) => {
82
+
83
+ parts = subroute.split(' ');
84
+
85
+ const [tmpMethod, tmpPath] = parts;
86
+
87
+ if (tmpPath) {
88
+ method = tmpMethod.toLowerCase();
89
+ pathToRun = tmpPath;
90
+ } else {
91
+ pathToRun = tmpMethod;
92
+ }
93
+
94
+ const isAbsolute = (pathToRun.substring(0, 1) === '/') ? true : false;
95
+
96
+ if (!isAbsolute) {
97
+
98
+ if (methods.indexOf(pathToRun.toLowerCase()) >= 0) {
99
+ method = pathToRun.toLowerCase();
100
+ pathToRun = `/${moduleName}/${controllerName}/`;
101
+ } else {
102
+ pathToRun = `/${moduleName}/${controllerName}/${pathToRun.replace(/GET|POST|DELETE|PUT/i, '')}`;
103
+ }
104
+
105
+ }
106
+
107
+ if (typeof subcurrent[subroute] === 'function') {
108
+ routes[`${method} ${pathToRun}`] = subcurrent[subroute];
109
+ }
110
+
111
+ });
112
+ });
113
+
114
+ } else {
115
+
116
+ parts = route.split(' ');
117
+ const [tmpMethod, tmpPath] = parts;
118
+
119
+ if (tmpPath) {
120
+ method = tmpMethod.toLowerCase();
121
+ pathToRun = tmpPath;
122
+ } else {
123
+ pathToRun = tmpMethod;
124
+ }
125
+
126
+ const isAbsolute = (pathToRun.substring(0, 1) === '/') ? true : false;
127
+
128
+ if (!isAbsolute) {
129
+ if (methods.indexOf(pathToRun.toLowerCase()) >= 0) {
130
+ method = pathToRun.toLowerCase();
131
+ pathToRun = `/${controllerName}/`;
132
+ } else {
133
+ pathToRun = `/${controllerName}/${pathToRun.replace(/GET|POST|DELETE|PUT/i, '')}`;
134
+ }
135
+ }
136
+
137
+ if (typeof current[route] === 'function') {
138
+ routes[`${method} ${pathToRun}`] = current[route];
139
+ }
140
+
141
+ }
142
+
143
+ });
144
+
145
+ });
146
+
147
+ return routes;
148
+
149
+ };
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Models
3
+ */
4
+
5
+ // Include all app models
6
+ const AllModels = require('include-all')({
7
+ dirname: `${APP_PATH}/models`,
8
+ filter: /(.+)\.js$/,
9
+ excludeDirs: /^\.(git|svn)$/,
10
+ optional: true
11
+ });
12
+
13
+ const scaffold = require('./scaffold');
14
+
15
+ const Callbacks = {
16
+
17
+ beforeSave: (next) => {
18
+ next();
19
+ },
20
+
21
+ beforeUpdate: (next) => {
22
+ next();
23
+ },
24
+
25
+ beforeRemove: (next) => {
26
+ next();
27
+ },
28
+
29
+ beforeValidate: (next) => {
30
+ next();
31
+ },
32
+
33
+ afterSave: () => {
34
+
35
+ },
36
+
37
+ afterUpdate: () => {
38
+
39
+ },
40
+
41
+ afterRemove: () => {
42
+
43
+ },
44
+
45
+ afterValidate: () => {
46
+
47
+ },
48
+
49
+ beforeFindOneAndUpdate: (next) => {
50
+ next();
51
+ }
52
+
53
+ };
54
+
55
+ module.exports = function loadModelsApplication() {
56
+
57
+ const models = {};
58
+
59
+ Object.keys(AllModels).forEach((i) => {
60
+
61
+ const Current = AllModels[i];
62
+
63
+ const getAll = `getAll${i}`;
64
+ const getModelName = `get${i}`;
65
+
66
+ const custom = {
67
+
68
+ [getAll](props) {
69
+ return global[i].getAll(props);
70
+ },
71
+
72
+ [getModelName](id) {
73
+ return global[i].getByField(id);
74
+ }
75
+
76
+ };
77
+
78
+ models[i] = {
79
+ ...Callbacks,
80
+ ...scaffold,
81
+ ...custom,
82
+ ...ActiveRecord,
83
+ ...Current
84
+ };
85
+
86
+ });
87
+
88
+ return models;
89
+
90
+ };
@@ -0,0 +1,232 @@
1
+ /**
2
+ * Database connection
3
+ */
4
+
5
+ const Promise = require('bluebird');
6
+ const paginate = require('mongoose-paginate');
7
+ const merge = require('deepmerge');
8
+
9
+ const mongoose = require('mongoose');
10
+
11
+ mongoose.Promise = Promise;
12
+
13
+ global.mongoose = mongoose;
14
+ global.Virtual = 'Virtual';
15
+ global.Mixed = mongoose.Schema.Types.Mixed;
16
+
17
+ const AllModels = require('./models')();
18
+
19
+ module.exports = function loadDatabaseApplication() {
20
+
21
+ const {
22
+ config
23
+ } = app;
24
+
25
+ const {
26
+ connections,
27
+ settings
28
+ } = config || {};
29
+
30
+ const {
31
+ database
32
+ } = settings || {};
33
+
34
+ const {
35
+ connection,
36
+ settings: dbSettings
37
+ } = database || {};
38
+
39
+ if (!connection) {
40
+ return;
41
+ }
42
+
43
+ const toConnect = connection in connections
44
+ ? connections[connection]
45
+ : (connection || null);
46
+
47
+ if (!toConnect) {
48
+ throw `Invalid conection to user MongoDB with source ${connection}`;
49
+ }
50
+
51
+ const defaultProps = {
52
+ useNewUrlParser: true,
53
+ useUnifiedTopology: true,
54
+ family: 4
55
+ };
56
+
57
+ const connectionProps = merge.all([
58
+ defaultProps,
59
+ (database ? database.config || {} : {})
60
+ ]);
61
+
62
+ if (dbSettings) {
63
+ Object.keys(dbSettings).forEach( (s) => {
64
+ mongoose.set(s, dbSettings[s]);
65
+ });
66
+ }
67
+
68
+ if (!mongoose.connection.readyState) {
69
+ mongoose.connect(toConnect, connectionProps);
70
+ }
71
+
72
+ const db = mongoose.connection;
73
+
74
+ // Each Model
75
+ Object.keys(AllModels).forEach((model) => {
76
+
77
+ const current = AllModels[model];
78
+ if (!current.attributes) {
79
+ global[model] = current;
80
+ } else {
81
+
82
+ // Allow trim all attributes
83
+ const attributes = {};
84
+ const virtuals = {};
85
+
86
+ Object.keys(current.attributes).forEach( (attr) => {
87
+
88
+ const currentAttr = current.attributes[attr];
89
+ const type = currentAttr.type || '';
90
+
91
+ if ( type !== Boolean) {
92
+ if (currentAttr.trim !== false) {
93
+ currentAttr.trim = true;
94
+ }
95
+ }
96
+
97
+ if ( String(type).toLowerCase() === 'virtual' ) {
98
+ virtuals[attr] = currentAttr;
99
+ delete attributes[attr];
100
+ } else {
101
+ attributes[attr] = currentAttr;
102
+ }
103
+
104
+ });
105
+
106
+ if (!attributes.active) {
107
+ attributes.active = {
108
+ type: Boolean,
109
+ default: true
110
+ };
111
+ }
112
+
113
+ if (!attributes.createdAt) {
114
+ attributes.createdAt = {
115
+ type: Date,
116
+ default: Date.now
117
+ };
118
+ }
119
+
120
+ if (!attributes.updatedAt) {
121
+ attributes.updatedAt = {
122
+ type: Date
123
+ };
124
+ }
125
+
126
+ const schema = mongoose.Schema(attributes);
127
+
128
+ Object.keys(virtuals).forEach( (v) => {
129
+
130
+ const currentVirtual = virtuals[v];
131
+
132
+ const {
133
+ get: getVirtual
134
+ } = currentVirtual || {};
135
+
136
+ if (getVirtual) {
137
+ schema.virtual(v, currentVirtual).get(getVirtual);
138
+ } else {
139
+ schema.virtual(v, currentVirtual);
140
+ }
141
+
142
+ });
143
+
144
+ schema.set('toObject', { virtuals: true, getters: true, setters: true });
145
+ schema.set('toJSON', { virtuals: true, getters: true, setters: true });
146
+
147
+ delete current.attributes;
148
+ schema.statics = { ...current };
149
+ schema.plugin(paginate);
150
+
151
+ // Indexes
152
+ if (current.indexes !== undefined) {
153
+ if (Array.isArray(current.indexes)) {
154
+ const tmp = current.indexes;
155
+ Object.keys(tmp).forEach( (index) => schema.index(tmp[index]));
156
+ } else if (typeof current.indexes === 'object') {
157
+ schema.index(current.indexes);
158
+ }
159
+ }
160
+
161
+ // Plugins
162
+ if (current.plugins !== undefined) {
163
+ if (Array.isArray(current.plugins)) {
164
+ const tmp = current.plugins;
165
+ Object.keys(tmp).forEach( (plugin) => schema.plugin(tmp[plugin]));
166
+ } else if (typeof current.plugins === 'object') {
167
+ schema.plugin(current.plugins);
168
+ }
169
+ }
170
+
171
+ //
172
+ // Callbacks
173
+ //
174
+
175
+ // Save
176
+ if (current.beforeSave) {
177
+ schema.pre('save', current.beforeSave);
178
+ delete schema.statics.beforeSave;
179
+ }
180
+ if (current.afterSave) {
181
+ schema.post('save', current.afterSave);
182
+ delete schema.statics.afterSave;
183
+ }
184
+
185
+ // Update
186
+ if (current.beforeUpdate) {
187
+ schema.pre('update', current.beforeUpdate);
188
+ delete schema.statics.beforeUpdate;
189
+ }
190
+ if (current.afterUpdate) {
191
+ schema.post('update', current.afterUpdate);
192
+ delete schema.statics.afterUpdate;
193
+ }
194
+
195
+ // findOneAndUpdate
196
+ if (current.beforeFindOneAndUpdate) {
197
+ schema.pre('findOneAndUpdate', current.beforeFindOneAndUpdate);
198
+ delete schema.statics.beforeFindOneAndUpdate;
199
+ }
200
+ if (current.afterFindOneAndUpdate) {
201
+ schema.post('findOneAndUpdate', current.afterFindOneAndUpdate);
202
+ delete schema.statics.afterFindOneAndUpdate;
203
+ }
204
+
205
+ // Remove
206
+ if (current.beforeRemove) {
207
+ schema.pre('remove', current.beforeRemove);
208
+ delete schema.statics.beforeRemove;
209
+ }
210
+ if (current.afterRemove) {
211
+ schema.post('remove', current.afterRemove);
212
+ delete schema.statics.afterRemove;
213
+ }
214
+
215
+ // Validation
216
+ if (current.beforeValidate) {
217
+ schema.pre('validate', current.beforeValidate);
218
+ delete schema.statics.beforeValidate;
219
+ }
220
+ if (current.afterValidate) {
221
+ schema.post('validate', current.afterValidate);
222
+ delete schema.statics.afterValidate;
223
+ }
224
+
225
+ global[model] = db.model(model, schema, model.toLowerCase());
226
+ global[model].attributes = attributes;
227
+
228
+ }
229
+
230
+ });
231
+
232
+ };
@@ -0,0 +1,118 @@
1
+ module.exports = {
2
+
3
+ /**
4
+ * Method to get all records by page
5
+ *
6
+ * @param {Object} props (page, perPage, search, sort)
7
+ * @returns {Promise}
8
+ */
9
+ getAll(props) {
10
+
11
+ // Props to Query
12
+ const defaultProps = {
13
+ sort: 'createdAt|DESC',
14
+ searchBy: [],
15
+ filter: {
16
+ active: true
17
+ },
18
+ };
19
+
20
+ // Query to Run
21
+ const query = Paginate.serializeQuery(defaultProps, props);
22
+
23
+ // Pagination
24
+ return Paginate.get(this, query);
25
+
26
+ },
27
+
28
+ /**
29
+ * Method to get a record by id
30
+ *
31
+ * @param {ObjectID} id
32
+ * @returns {Promise}
33
+ */
34
+ getByField(value, field) {
35
+
36
+ // This is to prevent error while run the findOne
37
+ if (!(/^[a-fA-F0-9]{24}$/).test(value) && !field) {
38
+ return VSError.reject('Invalid ID. Record not found.', 404);
39
+ }
40
+
41
+ const toSearch = { active: true };
42
+ toSearch[field || '_id'] = value;
43
+
44
+ return this.findOne(toSearch)
45
+ .then( (r) => {
46
+
47
+ if (!r) {
48
+ return VSError.notFound();
49
+ }
50
+
51
+ return r.toObject({ transform: true });
52
+
53
+ });
54
+
55
+ },
56
+
57
+ /**
58
+ * Method to create a new record
59
+ * @param {Promise} data
60
+ */
61
+ create(data) {
62
+
63
+ const obj = new this(data);
64
+
65
+ if (obj._id) {
66
+ delete obj._id;
67
+ }
68
+
69
+ return obj.save();
70
+
71
+ },
72
+
73
+ /**
74
+ * Method to update a record
75
+ * @param {ObjectID} id
76
+ * @param {Object} data
77
+ * @returns {Promise}
78
+ */
79
+ update(_id, data) {
80
+
81
+ return this.getByField(_id)
82
+ .then( (record) => {
83
+
84
+ // Merge current info with incoming values
85
+ const merged = {
86
+ ...record,
87
+ ...data,
88
+ updatedAt: Date.now()
89
+ };
90
+
91
+ return this.findOneAndUpdate({ _id }, merged, { new: true })
92
+ .then( (r) => {
93
+
94
+ const tmp = r.toObject({ transform: true });
95
+ return tmp;
96
+
97
+ });
98
+
99
+ });
100
+
101
+ },
102
+
103
+ /**
104
+ * Method to delete a record
105
+ * @param {ObjectID} id
106
+ * @returns {Promise}
107
+ */
108
+ delete(id) {
109
+
110
+ // Scaffold Model
111
+ // const Model = global[modelName];
112
+
113
+ // Soft delete
114
+ return this.update(id, { active: false });
115
+
116
+ }
117
+
118
+ };