@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.
package/init.js ADDED
@@ -0,0 +1,254 @@
1
+ /**
2
+ * Bootstrap.js
3
+ *
4
+ */
5
+
6
+ const dotenv = require('dotenv');
7
+ const path = require('path');
8
+ const moment = require('moment');
9
+ const merge = require('deepmerge');
10
+ const _ = require('underscore');
11
+ const Promise = require('bluebird');
12
+ const v8 = require('v8');
13
+ const fs = require('fs');
14
+
15
+ global.app = {};
16
+ global._ = _;
17
+ global.Promise = Promise;
18
+
19
+ if (!global.ABS_PATH) {
20
+ global.ABS_PATH = path.resolve(__dirname, '');
21
+ }
22
+
23
+ if (!global.APP_PATH) {
24
+ global.APP_PATH = path.join(__dirname, '../app');
25
+ }
26
+
27
+ if (!global.PUBLIC_PATH) {
28
+ global.PUBLIC_PATH = path.join(__dirname, '../public');
29
+ }
30
+
31
+ global.CORE_PATH = path.join(__dirname, '');
32
+
33
+ if (!fs.existsSync(APP_PATH)) {
34
+ console.log('the global var APP_PATH or directory not found');
35
+ global.APP_PATH = path.resolve(__dirname, '');
36
+ }
37
+
38
+ if (!fs.existsSync(PUBLIC_PATH)) {
39
+ console.log('the global var PUBLIC_PATH or directory not found');
40
+ global.PUBLIC_PATH = path.resolve(__dirname, '');
41
+ }
42
+
43
+ // Read Dontenv config
44
+ dotenv.config();
45
+
46
+ // Include all api config
47
+ const config = require('include-all')({
48
+ dirname: `${APP_PATH}/config`,
49
+ filter: /(.+)\.js$/,
50
+ optional: true
51
+ });
52
+
53
+ // Get package.json information
54
+ const pkg = require(`${CORE_PATH}/package.json`);
55
+ const appPkg = require(`${ABS_PATH}/package.json`);
56
+
57
+ // Environment
58
+ const NODE_ENV = (process.env.NODE_ENV || 'development').toLowerCase();
59
+
60
+ app.PRODUCTION = NODE_ENV === 'production' ? true : false;
61
+
62
+ const {
63
+ views,
64
+ local,
65
+ env
66
+ } = config || {};
67
+
68
+ // NODE_ENV
69
+ const environmentConfig = env ? env[NODE_ENV] || {} : {};
70
+
71
+ // Merge Settings
72
+ const settings = {
73
+ ...config.settings,
74
+ views: views?.config || ''
75
+ };
76
+
77
+ // All config merged (default, NODE_ENV (folder env), local.js file)
78
+ const allConfig = merge.all([
79
+ // General Config
80
+ config || {},
81
+
82
+ // Settings Config
83
+ { settings },
84
+
85
+ // Environment Config
86
+ environmentConfig,
87
+
88
+ // Local Config
89
+ local || {}
90
+ ]);
91
+
92
+ delete allConfig.env;
93
+ delete allConfig.local;
94
+
95
+ // General Settings
96
+ app.config = allConfig;
97
+
98
+ // Package Config
99
+ app.pkg = pkg;
100
+
101
+ // Include all components
102
+ require('./bootstrap/services')();
103
+ require('./database/mongodb')();
104
+
105
+ const controllers = require('./controllers/controllers')();
106
+ const server = require('./bootstrap/server');
107
+
108
+ const colors = {
109
+ reset: '\x1b[0m',
110
+ bright: '\x1b[1m',
111
+ dim: '\x1b[2m',
112
+ underscore: '\x1b[4m',
113
+ blink: '\x1b[5m',
114
+ reverse: '\x1b[7m',
115
+ hidden: '\x1b[8m',
116
+ fg: {
117
+ black: '\x1b[30m',
118
+ red: '\x1b[31m',
119
+ green: '\x1b[32m',
120
+ yellow: '\x1b[33m',
121
+ blue: '\x1b[34m',
122
+ magenta: '\x1b[35m',
123
+ cyan: '\x1b[36m',
124
+ white: '\x1b[37m',
125
+ crimson: '\x1b[38m' // Scarlet
126
+ },
127
+ bg: {
128
+ black: '\x1b[40m',
129
+ red: '\x1b[41m',
130
+ green: '\x1b[42m',
131
+ yellow: '\x1b[43m',
132
+ blue: '\x1b[44m',
133
+ magenta: '\x1b[45m',
134
+ cyan: '\x1b[46m',
135
+ white: '\x1b[47m',
136
+ crimson: '\x1b[48m'
137
+ }
138
+ };
139
+
140
+ function startVulkano() {
141
+
142
+ console.log('');
143
+ console.log('');
144
+ console.log(`${colors.fg.magenta}------------------------------------------`, colors.reset);
145
+ console.log('');
146
+ console.log(colors.fg.cyan, ' 🌋', colors.reset);
147
+ console.log(colors.fg.cyan, ` APP VERSION ${appPkg.version}`, colors.reset);
148
+ console.log(colors.fg.cyan, ` VULKANO ${pkg.version}`, colors.reset);
149
+ console.log('');
150
+ console.log(colors.fg.blue, '🔗 https://github.com/vulkanojs/vulkano', colors.reset);
151
+ console.log(colors.fg.cyan, '☕ https://buymeacoffee.com/argordmel', colors.reset);
152
+ console.log('');
153
+ console.log(`${colors.fg.magenta}------------------------------------------`, colors.reset);
154
+
155
+ // Routes
156
+ app.routes = controllers;
157
+
158
+ // Server Config
159
+ app.server = {
160
+ ...server,
161
+ ...app.config.settings
162
+ };
163
+
164
+ // Server Routes
165
+ app.server.routes = {
166
+ ...app.config.routes
167
+ };
168
+
169
+ const {
170
+ bootstrap
171
+ } = config;
172
+
173
+ if (!bootstrap || typeof bootstrap !== 'function') {
174
+ console.log('Missing the boostrap file to start app: app/config/bootstrap.js');
175
+ return;
176
+ }
177
+
178
+ bootstrap( (callbackAfterInitVulkano) => {
179
+
180
+ // Start Express
181
+ app.server.start( () => {
182
+
183
+ const {
184
+ sockets,
185
+ settings: configSettings,
186
+ redis
187
+ } = app.config || {};
188
+
189
+ const {
190
+ database
191
+ } = configSettings || {};
192
+
193
+ const {
194
+ connection
195
+ } = database || {};
196
+
197
+ const connectionToShow = connection && process.env.MONGO_URI ? 'MONGO_URI' : connection;
198
+
199
+ const serverConfig = [];
200
+
201
+ const nodeVersion = process.version.match(/^v(\d+\.\d+\.\d+)/)[1];
202
+ const portText = String(app.server.get('port') || 8000).padEnd(nodeVersion.length, ' ');
203
+ const socketText = (sockets.enabled ? 'YES' : 'NO').padEnd(nodeVersion.length - 3, ' ');
204
+
205
+ serverConfig.push(` PORT: ${colors.fg.green}${portText}${colors.reset}`);
206
+ serverConfig.push(' | ');
207
+ serverConfig.push(` ENV: ${app.PRODUCTION ? colors.fg.red : colors.fg.green}${env}${colors.reset}`);
208
+
209
+ console.log(serverConfig.join(''));
210
+
211
+ const totalHeapSize = v8.getHeapStatistics().total_available_size;
212
+ const totalHeapSizeGb = (totalHeapSize / 1024 / 1024 / 1024).toFixed(2);
213
+
214
+ const nodeConfig = [];
215
+ nodeConfig.push(` NODE: ${colors.fg.green}${nodeVersion}${colors.reset}`);
216
+ nodeConfig.push(' | ');
217
+ nodeConfig.push(' MAX MEM: ', `${colors.fg.green}${totalHeapSizeGb} GB${colors.reset}`);
218
+ console.log(nodeConfig.join(''));
219
+
220
+ const startUpConfig = [];
221
+ if (sockets.redis && redis && redis.enabled) {
222
+ startUpConfig.push(' SOCKETS: ', `${colors.fg.green}${socketText}${colors.reset}`);
223
+ } else {
224
+ startUpConfig.push(' SOCKETS: ', `${colors.fg.green}${socketText}${colors.reset}`);
225
+ }
226
+ startUpConfig.push(' | ');
227
+ startUpConfig.push(` STARTUP: ${colors.fg.green}${moment(moment().diff(global.START_TIME)).format('ss.SSS')} sec${colors.reset}`);
228
+ console.log(startUpConfig.join(''));
229
+
230
+ const dbConfig = [];
231
+ if (redis && redis.enabled) {
232
+ dbConfig.push(' REDIS: ', `${colors.fg.green}YES ${colors.reset}`);
233
+ } else {
234
+ dbConfig.push(' REDIS: ', `${colors.fg.green}NO ${colors.reset}`);
235
+ }
236
+
237
+ dbConfig.push(' | ');
238
+ dbConfig.push(' DB: ', connection ? `${colors.fg.green}${connectionToShow}${colors.reset}` : `${colors.fg.blue}The connection is empty${colors.reset}`);
239
+ console.log(dbConfig.join(''));
240
+
241
+ console.log(`${colors.fg.magenta}--------------------------------------`, colors.reset);
242
+
243
+ // Run custom callback after init vulkano
244
+ if (callbackAfterInitVulkano && typeof callbackAfterInitVulkano === 'function') {
245
+ callbackAfterInitVulkano();
246
+ }
247
+
248
+ });
249
+
250
+ });
251
+
252
+ };
253
+
254
+ module.exports = startVulkano;
@@ -0,0 +1,19 @@
1
+ const Cron = require('cron').CronJob;
2
+
3
+ module.exports = {
4
+
5
+ schedule(start, task, end, timeZone) {
6
+
7
+ const config = {
8
+ cronTime: start,
9
+ onTick: task || ( () => {} ),
10
+ onComplete: end || ( () => {} ),
11
+ timeZone: timeZone || 'America/New_York',
12
+ start: true
13
+ };
14
+
15
+ return new Cron(config);
16
+
17
+ }
18
+
19
+ };
@@ -0,0 +1,45 @@
1
+ const crypto = require('crypto');
2
+
3
+ class Encrypter {
4
+
5
+ constructor(encryptionKey) {
6
+
7
+ this.algorithm = 'aes-256-cbc';
8
+ this.key = crypto.scryptSync(encryptionKey, 'salt', 32);
9
+
10
+ }
11
+
12
+ encrypt(clearText) {
13
+
14
+ const iv = crypto.randomBytes(16);
15
+ const cipher = crypto.createCipheriv(this.algorithm, this.key, iv);
16
+ const encrypted = cipher.update(clearText, 'utf8', 'hex');
17
+
18
+ return [
19
+ encrypted + cipher.final('hex'),
20
+ Buffer.from(iv).toString('hex'),
21
+ ].join('|');
22
+
23
+ }
24
+
25
+ dencrypt(encryptedText) {
26
+
27
+ const [encrypted, iv] = encryptedText.split('|');
28
+
29
+ if (!iv) {
30
+ throw new VSError('IV not found', 500);
31
+ }
32
+
33
+ const decipher = crypto.createDecipheriv(
34
+ this.algorithm,
35
+ this.key,
36
+ Buffer.from(iv, 'hex')
37
+ );
38
+
39
+ return decipher.update(encrypted, 'hex', 'utf8') + decipher.final('utf8');
40
+
41
+ }
42
+
43
+ }
44
+
45
+ module.exports = Encrypter;
package/libs/Filter.js ADDED
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Filter
3
+ *
4
+ * Filter.get(' custom string', 'trim');
5
+ * return 'custom
6
+ *
7
+ */
8
+ const path = require('path');
9
+
10
+ // Include all api controllers
11
+ const coreFilters = require('include-all')({
12
+ dirname: path.join(CORE_PATH, '/libs/filters'),
13
+ filter: /(.+)\.js$/,
14
+ optional: true
15
+ });
16
+
17
+ const appFilters = require('include-all')({
18
+ dirname: path.join(APP_PATH, '/services/filters'),
19
+ filter: /(.+)\.js$/,
20
+ optional: true
21
+ });
22
+
23
+ const allFilters = { ...coreFilters, ...appFilters };
24
+
25
+ module.exports = {
26
+
27
+ get(str, filters, opts) {
28
+
29
+ let result = null;
30
+
31
+ if (Array.isArray(filters)) {
32
+ filters.forEach((filter) => {
33
+ const f = Filter.load(filter);
34
+ result = (!f) ? '' : f.exec(str, opts);
35
+ });
36
+ return result;
37
+ }
38
+
39
+ const f = Filter.load(filters);
40
+ return (!f) ? '' : f.exec(str, opts);
41
+
42
+ },
43
+
44
+ load(filter) {
45
+
46
+ if (!allFilters[filter]) {
47
+ console.error('FILTER', filter, 'NOT FOUND INTO /app/services/filters');
48
+ return false;
49
+ }
50
+
51
+ return allFilters[filter];
52
+
53
+ }
54
+
55
+ };
package/libs/Jwt.js ADDED
@@ -0,0 +1,220 @@
1
+ const { expressjwt: JWT } = require('express-jwt');
2
+ const jwtSimple = require('jwt-simple');
3
+ const moment = require('moment');
4
+
5
+ module.exports = {
6
+
7
+ /**
8
+ * Get JWT config
9
+ *
10
+ * @returns {Object}
11
+ */
12
+ getConfig() {
13
+
14
+ const {
15
+ jwt,
16
+ // Express config folder in app/confg/express
17
+ express
18
+ } = app.config || {};
19
+
20
+ const {
21
+ jwt: expressJwt,
22
+ } = express || {};
23
+
24
+ return jwt || expressJwt || {};
25
+
26
+ },
27
+
28
+ /**
29
+ * Init JWT for Express
30
+ *
31
+ * @param {Object} opts
32
+ * @returns
33
+ */
34
+ init(opts) {
35
+
36
+ const {
37
+ key,
38
+ algorithms
39
+ } = this.getConfig();
40
+
41
+ const config = {
42
+
43
+ algorithms: algorithms || ['HS256'],
44
+
45
+ secret: key,
46
+
47
+ getToken: (req) => this.getToken(req)
48
+
49
+ };
50
+
51
+ return JWT({ ...config, ...opts });
52
+
53
+ },
54
+
55
+ /**
56
+ * Get token from request
57
+ *
58
+ * @param {Express} req
59
+ * @returns {String}
60
+ */
61
+ getToken(req) {
62
+
63
+ const {
64
+ header,
65
+ queryParameter,
66
+ cookieName
67
+ } = this.getConfig();
68
+
69
+ // Get Token via HTTP header
70
+ const headerToken = req.headers[header] || req.headers[header.toUpperCase()] || null;
71
+
72
+ // Get Token via Cookie
73
+ const cookieToken = req.cookies && req.cookies[cookieName]
74
+ ? req.cookies[cookieName]
75
+ : null;
76
+
77
+ // Get Token via Query Parameter
78
+ const queryToken = req.query && req.query[queryParameter]
79
+ ? req.query[queryParameter]
80
+ : null;
81
+
82
+ // Current Token
83
+ const token = headerToken || cookieToken || queryToken || null;
84
+
85
+ // Decode Token
86
+ const hasData = this.decode(token);
87
+
88
+ // Return only if token is valid
89
+ return hasData ? token : null;
90
+
91
+ },
92
+
93
+ /**
94
+ * Encode token
95
+ *
96
+ * @param {String} data
97
+ * @returns {Object}
98
+ */
99
+ encode(data) {
100
+
101
+ const {
102
+ key
103
+ } = this.getConfig();
104
+
105
+ const Encrypt = new Encrypter(`${key}-JWT`);
106
+ const payload = Encrypt.encrypt(JSON.stringify({ data }));
107
+
108
+ return jwtSimple.encode(payload, key);
109
+
110
+ },
111
+
112
+ /**
113
+ * Decode token
114
+ *
115
+ * @param {String} token
116
+ * @param {String} customKey Optional Key
117
+ * @returns {Object}
118
+ */
119
+ decode(token, customKey) {
120
+
121
+ const {
122
+ key
123
+ } = this.getConfig();
124
+
125
+ let data = {};
126
+ try {
127
+
128
+ const payload = jwtSimple.decode(token, customKey || key);
129
+ data = this.decrypt(payload);
130
+
131
+ } catch (e) {
132
+ console.log('Invalid Token');
133
+ }
134
+
135
+ const {
136
+ expiration
137
+ } = data || {};
138
+
139
+ const now = moment().format('x');
140
+
141
+ // Token expired
142
+ if (expiration && ( Number(now) > Number(expiration) )) {
143
+ return null;
144
+ }
145
+
146
+ // Expiration must be required
147
+ if (!expiration) {
148
+ console.log('JWT Without expiration date');
149
+ return null;
150
+ }
151
+
152
+ return data;
153
+
154
+ },
155
+
156
+ /**
157
+ * Decryp Token
158
+ *
159
+ * @param {String} str
160
+ * @returns {String}
161
+ */
162
+ decrypt(str) {
163
+
164
+ const {
165
+ key
166
+ } = this.getConfig();
167
+
168
+ const Encrypt = new Encrypter(`${key}-JWT`);
169
+
170
+ let data = null;
171
+
172
+ try {
173
+
174
+ const r = JSON.parse(Encrypt.dencrypt(str));
175
+
176
+ const {
177
+ data: result
178
+ } = r || {};
179
+
180
+ data = result;
181
+
182
+ } catch (e) {
183
+ data = null;
184
+ }
185
+
186
+ return data;
187
+
188
+ },
189
+
190
+ /**
191
+ * Decode token from SocketIO
192
+ *
193
+ * @param {Socket} socket
194
+ * @returns {Object}
195
+ */
196
+ socket(socket) {
197
+
198
+ const {
199
+ token
200
+ } = socket.handshake.auth || {};
201
+
202
+ if (token === null || typeof token === 'undefined' || !token) {
203
+ return false;
204
+ }
205
+
206
+ const data = this.decode(token);
207
+
208
+ const {
209
+ _id
210
+ } = data || {};
211
+
212
+ if (!_id) {
213
+ return false;
214
+ }
215
+
216
+ return data;
217
+
218
+ }
219
+
220
+ };
@@ -0,0 +1,33 @@
1
+ const Promise = require('bluebird');
2
+
3
+ function VSError(msg, code, props) {
4
+
5
+ Error.captureStackTrace(this, this.constructor);
6
+
7
+ const {
8
+ stack
9
+ } = props || {};
10
+
11
+ this.message = msg;
12
+ this.statusCode = code || 500;
13
+ this.customProps = props || {};
14
+
15
+ if (app.PRODUCTION || stack === false ) {
16
+ delete this.stack;
17
+ }
18
+
19
+ }
20
+
21
+ // Not Found Object
22
+ VSError.notFound = (n) => {
23
+ const name = n || 'Object';
24
+ return Promise.reject(new VSError(`${name} Not Found`, 404));
25
+ };
26
+
27
+ // Reject request
28
+ VSError.reject = (text, status, props) => Promise.reject(new VSError(text, status, props));
29
+
30
+ // Extending of native error object
31
+ require('util').inherits(VSError, Error);
32
+
33
+ module.exports = VSError;
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Filter ltrim
3
+ *
4
+ * Filter.get('custom string', 'ltrim', 'cus');
5
+ * return 'tom string'
6
+ *
7
+ */
8
+ module.exports = {
9
+
10
+ exec: (_str, opt) => {
11
+ let str = _str || '';
12
+ if (opt) {
13
+ while (str.charAt(0) === opt) {
14
+ str = str.substr(1, str.length - 1);
15
+ }
16
+ } else {
17
+ while (str.charAt(0) === ' ') {
18
+ str = str.substr(1, str.length - 1);
19
+ }
20
+ }
21
+ return str;
22
+ }
23
+
24
+ };
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Filter number
3
+ *
4
+ * Filter.get('cu570m 5tr1ng', 'number');
5
+ * return '57051'
6
+ *
7
+ */
8
+ module.exports = {
9
+
10
+ exec: (_str) => {
11
+ return String(_str || '').replace( /\D+/g, '');
12
+ }
13
+
14
+ };
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Filter Object ID
3
+ *
4
+ * Filter.get('new ObjectId("aiuijdñjñ8987987")', 'objectId');
5
+ * return 'aiuijdñjñ8987987'
6
+ *
7
+ */
8
+ module.exports = {
9
+
10
+ exec: (_id) => {
11
+ return String(_id || '').replace(/ObjectId\("(.*)"\)/, '$1');
12
+ }
13
+
14
+ };
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Filter prefix
3
+ *
4
+ * Filter.get('custom string', 'prefix', '/');
5
+ * return '/custom string'
6
+ *
7
+ */
8
+ module.exports = {
9
+
10
+ exec: (_str, opt) => {
11
+
12
+ const str = _str || '';
13
+
14
+ if (str.indexOf(opt) === 0) {
15
+ return str;
16
+ }
17
+
18
+ return opt + str;
19
+
20
+ }
21
+
22
+ };