@vulkano/core 1.4.0 → 1.5.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/app.js +26 -62
- package/bootstrap/express.js +38 -4
- package/bootstrap/logger.js +59 -0
- package/bootstrap/server.js +525 -426
- package/database/mongodb.js +2 -2
- package/libs/Crontab.js +13 -5
- package/package.json +2 -1
- package/bun.lockb +0 -0
package/bootstrap/server.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
/* global mongoose */
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Server.js
|
|
3
5
|
*/
|
|
@@ -13,8 +15,10 @@ const helmet = require('helmet');
|
|
|
13
15
|
const timeout = require('connect-timeout');
|
|
14
16
|
const useragent = require('express-useragent');
|
|
15
17
|
const cookieParser = require('cookie-parser');
|
|
16
|
-
const { createClient } = require('redis');
|
|
17
|
-
const
|
|
18
|
+
const { createClient: socketRedis } = require('redis');
|
|
19
|
+
const socketMongoose = require('mongoose');
|
|
20
|
+
const { createAdapter: socketRedisAdapter } = require('@socket.io/redis-adapter');
|
|
21
|
+
const { createAdapter: socketMongoAdapter } = require('@socket.io/mongo-adapter');
|
|
18
22
|
|
|
19
23
|
// Include all api controllers
|
|
20
24
|
const AllControllers = require('include-all')({
|
|
@@ -35,568 +39,663 @@ const expressConfig = require('./express')();
|
|
|
35
39
|
// Express Responses
|
|
36
40
|
const responses = require('./responses');
|
|
37
41
|
|
|
38
|
-
module.exports = {
|
|
42
|
+
module.exports = function loadServer() {
|
|
39
43
|
|
|
40
|
-
|
|
44
|
+
return {
|
|
41
45
|
|
|
42
|
-
|
|
46
|
+
routes: {},
|
|
43
47
|
|
|
44
|
-
|
|
45
|
-
const {
|
|
46
|
-
JWT_SECRET_KEY,
|
|
47
|
-
COOKIES_SECRET_KEY
|
|
48
|
-
} = process.env || {};
|
|
48
|
+
start: async function startServerApplication(cb) {
|
|
49
49
|
|
|
50
|
-
|
|
50
|
+
// Get ENV Vars
|
|
51
|
+
const {
|
|
52
|
+
JWT_SECRET_KEY,
|
|
53
|
+
COOKIES_SECRET_KEY
|
|
54
|
+
} = process.env || {};
|
|
51
55
|
|
|
52
|
-
|
|
53
|
-
vulkano.enable('trust proxy');
|
|
56
|
+
const vulkano = express();
|
|
54
57
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
// ---------------
|
|
58
|
-
vulkano.set('port', expressConfig.port);
|
|
58
|
+
// Settings
|
|
59
|
+
vulkano.enable('trust proxy');
|
|
59
60
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
61
|
+
// ---------------
|
|
62
|
+
// PORT - File: app/config/express/settings.js
|
|
63
|
+
// ---------------
|
|
64
|
+
vulkano.set('port', expressConfig.port);
|
|
64
65
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
66
|
+
// ---------------
|
|
67
|
+
// MULTER - File: app/config/express/multer.js
|
|
68
|
+
// ---------------
|
|
69
|
+
const upload = multer(expressConfig.multer);
|
|
69
70
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
71
|
+
// ---------------
|
|
72
|
+
// MORGAN - File: app/config/express/morgan.js
|
|
73
|
+
// ---------------
|
|
74
|
+
vulkano.use(morgan(expressConfig.morgan.format, expressConfig.morgan));
|
|
74
75
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
76
|
+
// ---------------
|
|
77
|
+
// USER AGENT
|
|
78
|
+
// ---------------
|
|
79
|
+
vulkano.use(useragent.express());
|
|
79
80
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
const cookiesSecretKey = COOKIES_SECRET_KEY || expressConfig.cookies.key || expressConfig.cookies.secret || '';
|
|
85
|
-
if (!cookiesSecretKey) {
|
|
86
|
-
console.log(' \x1b[33mWARNING\x1b[0m: Set the secret key in the config/express/cookie.js file or COOKIES_SECRET_KEY in the .env file.');
|
|
87
|
-
}
|
|
88
|
-
vulkano.use(cookieParser(cookiesSecretKey));
|
|
89
|
-
}
|
|
81
|
+
// ---------------
|
|
82
|
+
// COMPRESSION - File: app/config/express/compression.js
|
|
83
|
+
// ---------------
|
|
84
|
+
vulkano.use(compression( expressConfig.compression || {} ));
|
|
90
85
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
// ---------------
|
|
102
|
-
// HELMET - File: app/config/express/helmet.js
|
|
103
|
-
// ---------------
|
|
104
|
-
vulkano.use(helmet(expressConfig.helmet));
|
|
105
|
-
|
|
106
|
-
// ---------------
|
|
107
|
-
// RESPONSES
|
|
108
|
-
// ---------------
|
|
109
|
-
vulkano.use(responses);
|
|
110
|
-
|
|
111
|
-
// ---------------
|
|
112
|
-
// FRAMEGUARD - File: app/config/express/frameguard.js
|
|
113
|
-
// ---------------
|
|
114
|
-
if (expressConfig.frameguard) {
|
|
115
|
-
if (Array.isArray(expressConfig.frameguard)) {
|
|
116
|
-
expressConfig.frameguard.forEach( (frame) => {
|
|
117
|
-
vulkano.use(frameguard(frame));
|
|
118
|
-
});
|
|
119
|
-
} else {
|
|
120
|
-
vulkano.use(frameguard(expressConfig.frameguard));
|
|
86
|
+
// ---------------
|
|
87
|
+
// COOKIES - File: app/config/express/cookies.js
|
|
88
|
+
// ---------------
|
|
89
|
+
if (expressConfig.cookies && expressConfig.cookies.enabled) {
|
|
90
|
+
const cookiesSecretKey = COOKIES_SECRET_KEY || expressConfig.cookies.key || expressConfig.cookies.secret || '';
|
|
91
|
+
if (!cookiesSecretKey) {
|
|
92
|
+
console.log(' \x1b[33mWARNING\x1b[0m: Set the secret key in the config/express/cookie.js file or COOKIES_SECRET_KEY in the .env file.');
|
|
93
|
+
}
|
|
94
|
+
vulkano.use(cookieParser(cookiesSecretKey));
|
|
121
95
|
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
// ---------------
|
|
125
|
-
// PROTOCOL & POWERED BY - File: app/config/settings.js
|
|
126
|
-
// ---------------
|
|
127
|
-
vulkano.use( (req, res, next) => {
|
|
128
96
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
if (expressConfig.poweredBy) {
|
|
135
|
-
res.setHeader('X-Powered-By', expressConfig.poweredBy);
|
|
136
|
-
}
|
|
97
|
+
// ---------------
|
|
98
|
+
// EXPRESS JSON - File: app/config/express/json.js
|
|
99
|
+
// ---------------
|
|
100
|
+
vulkano.use(express.json(expressConfig.json));
|
|
137
101
|
|
|
138
|
-
|
|
102
|
+
// ---------------
|
|
103
|
+
// EXPRESS FORM DATA - File: app/config/express/urlencoded.js
|
|
104
|
+
// ---------------
|
|
105
|
+
vulkano.use(express.urlencoded(expressConfig.urlencoded));
|
|
139
106
|
|
|
140
|
-
|
|
107
|
+
// ---------------
|
|
108
|
+
// HELMET - File: app/config/express/helmet.js
|
|
109
|
+
// ---------------
|
|
110
|
+
vulkano.use(helmet(expressConfig.helmet));
|
|
141
111
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
112
|
+
// ---------------
|
|
113
|
+
// RESPONSES
|
|
114
|
+
// ---------------
|
|
115
|
+
vulkano.use(responses);
|
|
146
116
|
|
|
147
117
|
// ---------------
|
|
148
|
-
//
|
|
118
|
+
// FRAMEGUARD - File: app/config/express/frameguard.js
|
|
149
119
|
// ---------------
|
|
150
|
-
if (expressConfig.
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
120
|
+
if (expressConfig.frameguard) {
|
|
121
|
+
if (Array.isArray(expressConfig.frameguard)) {
|
|
122
|
+
expressConfig.frameguard.forEach( (frame) => {
|
|
123
|
+
vulkano.use(frameguard(frame));
|
|
124
|
+
});
|
|
125
|
+
} else {
|
|
126
|
+
vulkano.use(frameguard(expressConfig.frameguard));
|
|
127
|
+
}
|
|
158
128
|
}
|
|
159
|
-
res.header('Allow', 'GET,PUT,POST,DELETE,OPTIONS');
|
|
160
|
-
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
|
|
161
129
|
|
|
162
|
-
|
|
130
|
+
// ---------------
|
|
131
|
+
// PROTOCOL & POWERED BY - File: app/config/settings.js
|
|
132
|
+
// ---------------
|
|
133
|
+
vulkano.use( (req, res, next) => {
|
|
163
134
|
|
|
164
|
-
|
|
135
|
+
const proto = req.secure ? 'https' : 'http';
|
|
136
|
+
const forwarded = req.headers['x-forwaded-proto'] || null;
|
|
137
|
+
const currentProtocol = (forwarded || proto).split('://')[0];
|
|
138
|
+
req.protocol = currentProtocol;
|
|
165
139
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
vulkano.use(timeout( expressConfig.timeout || 120000 ));
|
|
140
|
+
if (expressConfig.poweredBy) {
|
|
141
|
+
res.setHeader('X-Powered-By', expressConfig.poweredBy);
|
|
142
|
+
}
|
|
170
143
|
|
|
171
|
-
vulkano.use( (req, res, next) => {
|
|
172
|
-
if (!req.timedout) {
|
|
173
144
|
next();
|
|
174
|
-
}
|
|
175
|
-
});
|
|
176
145
|
|
|
177
|
-
|
|
178
|
-
// JWT - File: app/config/express/jwt.js
|
|
179
|
-
// ---------------
|
|
180
|
-
if (expressConfig.jwt && expressConfig.jwt.enabled) {
|
|
146
|
+
});
|
|
181
147
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
148
|
+
// ---------------
|
|
149
|
+
// REQUEST OPTIONS - File: app/config/express/cors.js
|
|
150
|
+
// ---------------
|
|
151
|
+
vulkano.options('*', (req, res) => {
|
|
152
|
+
|
|
153
|
+
// ---------------
|
|
154
|
+
// CORS
|
|
155
|
+
// ---------------
|
|
156
|
+
if (expressConfig.cors && expressConfig.cors.enabled) {
|
|
157
|
+
let tmpCustomHeaders = ['X-Requested-With', 'X-HTTP-Method-Override', 'Content-Type', 'Accept'];
|
|
158
|
+
tmpCustomHeaders = tmpCustomHeaders.concat(expressConfig.cors.headers || []);
|
|
159
|
+
res.header('Access-Control-Allow-Origin', expressConfig.cors.origin);
|
|
160
|
+
res.header('Access-Control-Allow-Headers', tmpCustomHeaders.join(', '));
|
|
161
|
+
} else {
|
|
162
|
+
res.header('Access-Control-Allow-Origin', '*');
|
|
163
|
+
res.header('Access-Control-Allow-Headers', 'X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept');
|
|
164
|
+
}
|
|
165
|
+
res.header('Allow', 'GET,PUT,POST,DELETE,OPTIONS');
|
|
166
|
+
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
|
|
187
167
|
|
|
188
|
-
|
|
189
|
-
vulkano.use(expressConfig.jwt.path || '*', jwtMiddleware.init().unless({
|
|
190
|
-
path: expressConfig.jwt.ignore || []
|
|
191
|
-
}));
|
|
168
|
+
res.status(200).end();
|
|
192
169
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
// ---------------
|
|
173
|
+
// TIMEOUT - File: app/config/settings.js
|
|
174
|
+
// ---------------
|
|
175
|
+
vulkano.use(timeout( expressConfig.timeout || 120000 ));
|
|
176
|
+
|
|
177
|
+
vulkano.use( (req, res, next) => {
|
|
178
|
+
if (!req.timedout) {
|
|
198
179
|
next();
|
|
199
180
|
}
|
|
200
181
|
});
|
|
201
182
|
|
|
202
|
-
|
|
183
|
+
// ---------------
|
|
184
|
+
// JWT - File: app/config/express/jwt.js
|
|
185
|
+
// ---------------
|
|
186
|
+
if (expressConfig.jwt && expressConfig.jwt.enabled) {
|
|
203
187
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
188
|
+
const jwtSecretKey = JWT_SECRET_KEY || expressConfig.jwt.key || expressConfig.jwt.secret || '';
|
|
189
|
+
if (!jwtSecretKey) {
|
|
190
|
+
console.log(' \x1b[41mERROR\x1b[0m: Can not get key in config/express/jwt.js file or JWT_SECRET_KEY in .env file');
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
208
193
|
|
|
209
|
-
|
|
194
|
+
// JWT (secret key)
|
|
195
|
+
vulkano.use(expressConfig.jwt.path || '*', jwtMiddleware.init().unless({
|
|
196
|
+
path: expressConfig.jwt.ignore || []
|
|
197
|
+
}));
|
|
198
|
+
|
|
199
|
+
// JWT Handler error
|
|
200
|
+
vulkano.use((err, req, res, next) => {
|
|
201
|
+
if (err && err.name === 'UnauthorizedError') {
|
|
202
|
+
res.status(401).jsonp({ success: false, error: 'Invalid token' });
|
|
203
|
+
} else {
|
|
204
|
+
next();
|
|
205
|
+
}
|
|
206
|
+
});
|
|
210
207
|
|
|
211
|
-
|
|
212
|
-
let tmpCorsHeaders = ['X-Requested-With', 'X-HTTP-Method-Override', 'Content-Type', 'Accept'];
|
|
213
|
-
tmpCorsHeaders = tmpCorsHeaders.concat(expressConfig.cors.headers || []);
|
|
208
|
+
}
|
|
214
209
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
210
|
+
// ---------------
|
|
211
|
+
// CORS - File: app/config/express/cors.js
|
|
212
|
+
// ---------------
|
|
213
|
+
if (expressConfig.cors && expressConfig.cors.enabled) {
|
|
218
214
|
|
|
219
|
-
|
|
220
|
-
res.header('Cache-Control', 'no-cache, no-store, must-revalidate'); // HTTP 1.1.
|
|
221
|
-
res.header('Pragma', 'no-cache'); // HTTP 1.0.
|
|
222
|
-
res.header('Expires', '0'); // Proxies.
|
|
215
|
+
vulkano.use(expressConfig.cors.path, (req, res, next) => {
|
|
223
216
|
|
|
224
|
-
|
|
217
|
+
// Enable CORS.
|
|
218
|
+
let tmpCorsHeaders = ['X-Requested-With', 'X-HTTP-Method-Override', 'Content-Type', 'Accept'];
|
|
219
|
+
tmpCorsHeaders = tmpCorsHeaders.concat(expressConfig.cors.headers || []);
|
|
225
220
|
|
|
226
|
-
|
|
227
|
-
|
|
221
|
+
res.header('Access-Control-Allow-Origin', expressConfig.cors.origin);
|
|
222
|
+
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
|
|
223
|
+
res.header('Access-Control-Allow-Headers', tmpCorsHeaders.join(', '));
|
|
224
|
+
|
|
225
|
+
// Disable CACHE in API resources.
|
|
226
|
+
res.header('Cache-Control', 'no-cache, no-store, must-revalidate'); // HTTP 1.1.
|
|
227
|
+
res.header('Pragma', 'no-cache'); // HTTP 1.0.
|
|
228
|
+
res.header('Expires', '0'); // Proxies.
|
|
229
|
+
|
|
230
|
+
next();
|
|
231
|
+
|
|
232
|
+
});
|
|
233
|
+
}
|
|
228
234
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
235
|
+
// ---------------
|
|
236
|
+
// VIEWS
|
|
237
|
+
// ---------------
|
|
232
238
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
239
|
+
const views = {
|
|
240
|
+
...viewsConfig,
|
|
241
|
+
...(app.server.views || {})
|
|
242
|
+
};
|
|
237
243
|
|
|
238
|
-
|
|
244
|
+
vulkano.set('views', views.path);
|
|
239
245
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
246
|
+
const {
|
|
247
|
+
settings: nunjucksSettingsUser
|
|
248
|
+
} = views || {};
|
|
243
249
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
+
const nunjucksSettings = {
|
|
251
|
+
autoescape: true,
|
|
252
|
+
watch: !app.PRODUCTION,
|
|
253
|
+
...(nunjucksSettingsUser || {}),
|
|
254
|
+
express: vulkano
|
|
255
|
+
};
|
|
250
256
|
|
|
251
|
-
|
|
257
|
+
const envNunjucks = nunjucks.configure(views.path, nunjucksSettings);
|
|
252
258
|
|
|
253
|
-
|
|
259
|
+
app.server.views._engine = envNunjucks;
|
|
254
260
|
|
|
255
|
-
|
|
261
|
+
envNunjucks.addGlobal('app', app);
|
|
256
262
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
263
|
+
if (views.globals && Array.isArray(views.globals)) {
|
|
264
|
+
views.globals.forEach((global) => {
|
|
265
|
+
Object.keys(global || []).forEach((i) => {
|
|
266
|
+
envNunjucks.addGlobal(i, global[i]);
|
|
267
|
+
});
|
|
261
268
|
});
|
|
262
|
-
}
|
|
263
|
-
}
|
|
269
|
+
}
|
|
264
270
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
271
|
+
if (views.helpers && Array.isArray(views.helpers)) {
|
|
272
|
+
views.helpers.forEach((helper) => {
|
|
273
|
+
Object.keys(helper || []).forEach((i) => {
|
|
274
|
+
envNunjucks.addGlobal(i, helper[i]);
|
|
275
|
+
});
|
|
269
276
|
});
|
|
270
|
-
}
|
|
271
|
-
}
|
|
277
|
+
}
|
|
272
278
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
279
|
+
if (views.filters && Array.isArray(views.filters)) {
|
|
280
|
+
views.filters.forEach((filter) => {
|
|
281
|
+
Object.keys(filter || []).forEach((i) => {
|
|
282
|
+
envNunjucks.addFilter(i, filter[i]);
|
|
283
|
+
});
|
|
277
284
|
});
|
|
278
|
-
}
|
|
279
|
-
}
|
|
285
|
+
}
|
|
280
286
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
287
|
+
if (views.extensions && Array.isArray(views.extensions)) {
|
|
288
|
+
views.extensions.forEach((extension) => {
|
|
289
|
+
Object.keys(extension || []).forEach((i) => {
|
|
290
|
+
envNunjucks.addExtension(i, extension[i]);
|
|
291
|
+
});
|
|
285
292
|
});
|
|
286
|
-
}
|
|
287
|
-
}
|
|
293
|
+
}
|
|
288
294
|
|
|
289
|
-
|
|
295
|
+
app.nunjucks = nunjucks;
|
|
296
|
+
|
|
297
|
+
// ---------------
|
|
298
|
+
// Middlewares
|
|
299
|
+
// ---------------
|
|
290
300
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
301
|
+
// Middleware File (compatibility)
|
|
302
|
+
const middleware = app.config.middleware || ((req, res, next) => {
|
|
303
|
+
next();
|
|
304
|
+
});
|
|
294
305
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
next();
|
|
298
|
-
});
|
|
306
|
+
// Middleware Folder
|
|
307
|
+
const middlewares = app.config.middlewares || {};
|
|
299
308
|
|
|
300
|
-
|
|
301
|
-
|
|
309
|
+
Object.keys(middlewares).forEach( (item) => {
|
|
310
|
+
const middlewareFunction = middlewares[item];
|
|
311
|
+
if (typeof middlewareFunction === 'function') {
|
|
312
|
+
vulkano.use(middlewareFunction);
|
|
313
|
+
}
|
|
314
|
+
});
|
|
302
315
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
316
|
+
// ---------------
|
|
317
|
+
// PUBLIC PATH - File: app/config/settings.js
|
|
318
|
+
// (if are using Vite)
|
|
319
|
+
// ---------------
|
|
320
|
+
if (!app.viteProxy) {
|
|
321
|
+
vulkano.use(express.static(PUBLIC_PATH));
|
|
307
322
|
}
|
|
308
|
-
});
|
|
309
|
-
|
|
310
|
-
// ---------------
|
|
311
|
-
// PUBLIC PATH - File: app/config/settings.js
|
|
312
|
-
// (if are using Vite)
|
|
313
|
-
// ---------------
|
|
314
|
-
if (!app.viteProxy) {
|
|
315
|
-
vulkano.use(express.static(PUBLIC_PATH));
|
|
316
|
-
}
|
|
317
323
|
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
324
|
+
// ---------------
|
|
325
|
+
// ROUTES
|
|
326
|
+
// ---------------
|
|
321
327
|
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
328
|
+
const {
|
|
329
|
+
routes
|
|
330
|
+
} = app;
|
|
325
331
|
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
332
|
+
let method;
|
|
333
|
+
let pathToRoute;
|
|
334
|
+
let handler;
|
|
329
335
|
|
|
330
|
-
|
|
336
|
+
Object.keys(routes).forEach((route) => {
|
|
331
337
|
|
|
332
|
-
|
|
338
|
+
const parts = route.split(' ');
|
|
333
339
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
340
|
+
const [
|
|
341
|
+
methodToRun,
|
|
342
|
+
pathToRun
|
|
343
|
+
] = parts;
|
|
338
344
|
|
|
339
|
-
|
|
345
|
+
method = methodToRun;
|
|
340
346
|
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
347
|
+
if (pathToRun) {
|
|
348
|
+
pathToRoute = pathToRun;
|
|
349
|
+
}
|
|
344
350
|
|
|
345
|
-
|
|
351
|
+
handler = routes[route];
|
|
346
352
|
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
353
|
+
if (method === 'post') {
|
|
354
|
+
vulkano[method](pathToRoute, upload.any(), middleware, handler);
|
|
355
|
+
} else {
|
|
356
|
+
vulkano[method](pathToRoute, middleware, handler);
|
|
357
|
+
}
|
|
352
358
|
|
|
353
|
-
|
|
359
|
+
});
|
|
354
360
|
|
|
355
|
-
|
|
361
|
+
Object.keys(this.routes || {}).forEach((i) => {
|
|
356
362
|
|
|
357
|
-
|
|
363
|
+
const fullPath = this.routes[i].split('.');
|
|
358
364
|
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
365
|
+
const [
|
|
366
|
+
moduleToRun,
|
|
367
|
+
controllerToRun,
|
|
368
|
+
actionToRun
|
|
369
|
+
] = fullPath;
|
|
364
370
|
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
371
|
+
let module;
|
|
372
|
+
let controller;
|
|
373
|
+
let action;
|
|
368
374
|
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
375
|
+
if (actionToRun) { // Has folder
|
|
376
|
+
module = moduleToRun;
|
|
377
|
+
controller = controllerToRun;
|
|
378
|
+
action = actionToRun;
|
|
379
|
+
} else {
|
|
380
|
+
module = null;
|
|
381
|
+
controller = moduleToRun;
|
|
382
|
+
action = controllerToRun;
|
|
383
|
+
}
|
|
378
384
|
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
+
const parts = i.split(' ');
|
|
386
|
+
const pathToRun = parts.pop();
|
|
387
|
+
let option = (parts[0] !== undefined) ? parts[0].toLowerCase() : 'get';
|
|
388
|
+
if (option !== 'get' && option !== 'post' && option !== 'put' && option !== 'delete') {
|
|
389
|
+
option = 'get';
|
|
390
|
+
}
|
|
385
391
|
|
|
386
|
-
|
|
392
|
+
let toExecute = null;
|
|
387
393
|
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
394
|
+
try {
|
|
395
|
+
toExecute = module
|
|
396
|
+
? (AllControllers[module][controller][action])
|
|
397
|
+
: AllControllers[controller][action];
|
|
398
|
+
} catch (e) {
|
|
399
|
+
toExecute = null;
|
|
400
|
+
}
|
|
395
401
|
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
402
|
+
if (toExecute) {
|
|
403
|
+
if (option === 'post') {
|
|
404
|
+
vulkano[option](pathToRun || '/', upload.any(), middleware, toExecute);
|
|
405
|
+
} else {
|
|
406
|
+
vulkano[option](pathToRun || '/', middleware, toExecute);
|
|
407
|
+
}
|
|
399
408
|
} else {
|
|
400
|
-
|
|
409
|
+
console.error('\x1b[31mError:', 'Controller not found in', (module) ? `${module}.${controller}.${action}` : `${controller}.${action}`, '\x1b[0m');
|
|
401
410
|
}
|
|
402
|
-
} else {
|
|
403
|
-
console.error('\x1b[31mError:', 'Controller not found in', (module) ? `${module}.${controller}.${action}` : `${controller}.${action}`, '\x1b[0m');
|
|
404
|
-
}
|
|
405
411
|
|
|
406
|
-
|
|
412
|
+
});
|
|
413
|
+
|
|
414
|
+
const server = await vulkano.listen(expressConfig.port);
|
|
407
415
|
|
|
408
|
-
|
|
416
|
+
// ---------------
|
|
417
|
+
// ERROR 404
|
|
418
|
+
// ---------------
|
|
419
|
+
vulkano.use((req, res) => {
|
|
420
|
+
if (+res.statusCode >= 500 && +res.statusCode < 600) {
|
|
421
|
+
throw new Error();
|
|
422
|
+
}
|
|
423
|
+
res.status(404).render(`${views.path}/_shared/errors/404.html`);
|
|
424
|
+
});
|
|
409
425
|
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
// ---------------
|
|
423
|
-
vulkano.use((err, req, res) => {
|
|
424
|
-
const status = err.status || res.statusCode || 500;
|
|
425
|
-
res.status(status);
|
|
426
|
-
if (!res.xhr) {
|
|
427
|
-
if (+status > 400 && +status < 500) {
|
|
428
|
-
res.render(`${vulkano.get('views')}/_shared/errors/404.html`, { content: err.stack });
|
|
426
|
+
// ---------------
|
|
427
|
+
// ERROR 5XX
|
|
428
|
+
// ---------------
|
|
429
|
+
vulkano.use((err, req, res) => {
|
|
430
|
+
const status = err.status || res.statusCode || 500;
|
|
431
|
+
res.status(status);
|
|
432
|
+
if (!res.xhr) {
|
|
433
|
+
if (+status > 400 && +status < 500) {
|
|
434
|
+
res.render(`${vulkano.get('views')}/_shared/errors/404.html`, { content: err.stack });
|
|
435
|
+
} else {
|
|
436
|
+
res.render(`${vulkano.get('views')}/_shared/errors/500.html`, { content: err.stack });
|
|
437
|
+
}
|
|
429
438
|
} else {
|
|
430
|
-
res.
|
|
439
|
+
res.jsonp({
|
|
440
|
+
success: false,
|
|
441
|
+
error: err.message || err.error || err.invalidAttributes || err.toString() || 'Object Not Found',
|
|
442
|
+
data: (app.PRODUCTION) ? {} : (err.stack || {})
|
|
443
|
+
});
|
|
431
444
|
}
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
445
|
+
});
|
|
446
|
+
|
|
447
|
+
// ---------------
|
|
448
|
+
// PUBLIC PATH
|
|
449
|
+
// (if not are using Vite)
|
|
450
|
+
// ---------------
|
|
451
|
+
if (app.viteProxy) {
|
|
452
|
+
vulkano.use(express.static(PUBLIC_PATH));
|
|
438
453
|
}
|
|
439
|
-
});
|
|
440
|
-
|
|
441
|
-
// ---------------
|
|
442
|
-
// PUBLIC PATH
|
|
443
|
-
// (if not are using Vite)
|
|
444
|
-
// ---------------
|
|
445
|
-
if (app.viteProxy) {
|
|
446
|
-
vulkano.use(express.static(PUBLIC_PATH));
|
|
447
|
-
}
|
|
448
454
|
|
|
449
|
-
|
|
450
|
-
|
|
455
|
+
app.vulkano = vulkano;
|
|
456
|
+
app.server = server;
|
|
451
457
|
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
} = expressConfig || {};
|
|
458
|
+
// ---------------
|
|
459
|
+
// SOCKETS
|
|
460
|
+
// ---------------
|
|
461
|
+
const {
|
|
462
|
+
sockets
|
|
463
|
+
} = expressConfig || {};
|
|
459
464
|
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
465
|
+
if (!sockets || (sockets && !sockets.enabled)) {
|
|
466
|
+
cb();
|
|
467
|
+
return;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
const {
|
|
471
|
+
config: socketsConfig
|
|
472
|
+
} = sockets;
|
|
473
|
+
|
|
474
|
+
const socketProps = {
|
|
475
|
+
...(socketsConfig || {}),
|
|
476
|
+
pingTimeout: +socketsConfig.timeout || 4000,
|
|
477
|
+
pingInterval: +socketsConfig.interval || 2000,
|
|
478
|
+
transports: socketsConfig.transports || ['websocket', 'polling']
|
|
479
|
+
};
|
|
464
480
|
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
if (sockets.cors) {
|
|
472
|
-
if (typeof sockets.cors === 'function') {
|
|
473
|
-
socketProps.allowRequest = sockets.cors;
|
|
474
|
-
} else if (typeof sockets.cors === 'string') {
|
|
475
|
-
socketProps.cors = sockets.cors || '';
|
|
481
|
+
if (sockets.cors) {
|
|
482
|
+
if (typeof sockets.cors === 'function') {
|
|
483
|
+
socketProps.allowRequest = sockets.cors;
|
|
484
|
+
} else if (typeof sockets.cors === 'string') {
|
|
485
|
+
socketProps.cors = sockets.cors || '';
|
|
486
|
+
}
|
|
476
487
|
}
|
|
477
|
-
}
|
|
478
488
|
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
489
|
+
const {
|
|
490
|
+
adapter
|
|
491
|
+
} = sockets;
|
|
482
492
|
|
|
483
|
-
|
|
493
|
+
const {
|
|
494
|
+
redis: redisAdapter,
|
|
495
|
+
mongodb: mongodbAdapter
|
|
496
|
+
} = sockets.adapters || {};
|
|
484
497
|
|
|
485
|
-
|
|
486
|
-
let subClient = null;
|
|
498
|
+
if ( String(adapter).toLocaleLowerCase() === 'redis') {
|
|
487
499
|
|
|
488
|
-
|
|
500
|
+
const {
|
|
501
|
+
host,
|
|
502
|
+
port
|
|
503
|
+
} = redisAdapter || {};
|
|
489
504
|
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
505
|
+
if (!host || !port) {
|
|
506
|
+
throw new Error('Unable to connect to Redis. File: "app/config/sockets/adapters/redis.js" to connect the sockets');
|
|
507
|
+
}
|
|
493
508
|
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
509
|
+
if (socketProps.transports.includes('polling')) {
|
|
510
|
+
throw new Error('To enable Sockets with Redis support, the transports must be set ¨websocket¨ only');
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
} else if ( String(adapter).toLocaleLowerCase() === 'mongodb') {
|
|
514
|
+
|
|
515
|
+
// if (socketProps.transports.includes('polling')) {
|
|
516
|
+
// eslint-disable-next-line max-len
|
|
517
|
+
// console.log('To enable Sockets with MongoDB support the transports must be set to ["websocket"] only');
|
|
518
|
+
// }
|
|
498
519
|
|
|
499
|
-
if (redis.password) {
|
|
500
|
-
propsToRedis.password = redis.password;
|
|
501
520
|
}
|
|
502
521
|
|
|
503
|
-
|
|
504
|
-
subClient = pubClient.duplicate();
|
|
522
|
+
const io = new Server(server, socketProps);
|
|
505
523
|
|
|
506
|
-
|
|
524
|
+
let pubClient = null;
|
|
525
|
+
let subClient = null;
|
|
507
526
|
|
|
508
|
-
|
|
527
|
+
if ( String(adapter).toLocaleLowerCase() === 'redis') {
|
|
528
|
+
|
|
529
|
+
const propsToRedis = {
|
|
530
|
+
host: redisAdapter.host,
|
|
531
|
+
port: redisAdapter.port
|
|
532
|
+
};
|
|
533
|
+
|
|
534
|
+
if (redisAdapter.password) {
|
|
535
|
+
propsToRedis.password = redisAdapter.password;
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
pubClient = socketRedis(propsToRedis);
|
|
539
|
+
subClient = pubClient.duplicate();
|
|
540
|
+
|
|
541
|
+
io.adapter(socketRedisAdapter(pubClient, subClient));
|
|
542
|
+
|
|
543
|
+
} else if ( String(adapter).toLocaleLowerCase() === 'mongodb') {
|
|
544
|
+
|
|
545
|
+
const {
|
|
546
|
+
settings: socketsMongoSettings
|
|
547
|
+
} = mongodbAdapter || {};
|
|
548
|
+
|
|
549
|
+
const socketsConnection = String(process.env.SOCKETS_MONGO_URI || mongodbAdapter.connection || '').trim();
|
|
550
|
+
let socketsDatabase = String(process.env.SOCKETS_MONGO_DATABASE || mongodbAdapter.database || '').trim();
|
|
551
|
+
const socketsCollection = String(process.env.SOCKETS_MONGO_COLLECTION || mongodbAdapter.collection || 'socket.io-adapter-events').trim();
|
|
552
|
+
|
|
553
|
+
let socketsMongoCollection = null;
|
|
509
554
|
|
|
510
|
-
|
|
511
|
-
.all([
|
|
512
|
-
(sockets.redis ? pubClient.connect() : null),
|
|
513
|
-
(sockets.redis ? subClient.connect() : null)
|
|
514
|
-
])
|
|
515
|
-
.then(() => {
|
|
555
|
+
try {
|
|
516
556
|
|
|
517
|
-
|
|
557
|
+
let mongoClientDB = null;
|
|
558
|
+
|
|
559
|
+
// if not has a mongo conection try to create it
|
|
560
|
+
if (!mongoose.connection.readyState) {
|
|
561
|
+
|
|
562
|
+
if (!socketsConnection) {
|
|
563
|
+
throw new Error('Unable to connecto to the database for SocketIO. Please check the env var SOCKETS_MONGO_URI and try again.');
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
const socketMongooseConnection = await socketMongoose.connect(socketsConnection);
|
|
567
|
+
mongoClientDB = socketMongooseConnection.connection.getClient();
|
|
568
|
+
|
|
569
|
+
} else {
|
|
570
|
+
|
|
571
|
+
// Get current connection
|
|
572
|
+
mongoClientDB = mongoose.connection.getClient();
|
|
573
|
+
socketsDatabase = mongoose.connection.db.s.namespace.db;
|
|
574
|
+
|
|
575
|
+
// SOCKETS_MONGO_URI
|
|
576
|
+
if (socketsConnection !== mongoClientDB.s.url) {
|
|
577
|
+
|
|
578
|
+
const socketMongoInstance = new socketMongoose.Mongoose();
|
|
579
|
+
|
|
580
|
+
const socketMongooseConnection = await socketMongoInstance.connect(socketsConnection);
|
|
581
|
+
mongoClientDB = socketMongooseConnection.connection.getClient();
|
|
582
|
+
socketsDatabase = socketMongoInstance.connection.db.s.namespace.db;
|
|
583
|
+
|
|
584
|
+
}
|
|
518
585
|
|
|
519
|
-
if ( typeof sockets.onConnect === 'function') {
|
|
520
|
-
sockets.onConnect(socket);
|
|
521
586
|
}
|
|
522
587
|
|
|
523
|
-
|
|
588
|
+
socketsMongoCollection = mongoClientDB.db(socketsDatabase).collection(socketsCollection);
|
|
524
589
|
|
|
525
|
-
|
|
590
|
+
const propsToMongoCollection = {
|
|
591
|
+
expireAfterSeconds: 3600,
|
|
592
|
+
background: true,
|
|
593
|
+
...(socketsMongoSettings || {})
|
|
594
|
+
};
|
|
526
595
|
|
|
527
|
-
|
|
596
|
+
socketsMongoCollection.createIndex({ createdAt: 1 }, propsToMongoCollection);
|
|
528
597
|
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
598
|
+
} catch (err) {
|
|
599
|
+
console.log(err);
|
|
600
|
+
throw new Error('To enable Sockets with MongoDB support. Check the connection.');
|
|
601
|
+
}
|
|
533
602
|
|
|
534
|
-
|
|
603
|
+
io.adapter(socketMongoAdapter(socketsMongoCollection, { addCreatedAtField: true }));
|
|
535
604
|
|
|
536
|
-
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
Promise
|
|
608
|
+
.all([
|
|
609
|
+
(sockets.redis ? pubClient.connect() : null),
|
|
610
|
+
(sockets.redis ? subClient.connect() : null)
|
|
611
|
+
])
|
|
612
|
+
.then(() => {
|
|
613
|
+
|
|
614
|
+
io.on('connection', (socket) => {
|
|
615
|
+
|
|
616
|
+
if ( typeof sockets.onConnect === 'function') {
|
|
617
|
+
sockets.onConnect(socket);
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
const socketEvents = sockets.events || sockets.routes || {};
|
|
537
621
|
|
|
538
|
-
|
|
622
|
+
Object.keys(socketEvents).forEach( (i) => {
|
|
539
623
|
|
|
540
|
-
const
|
|
624
|
+
const checkPath = socketEvents[i] || '';
|
|
541
625
|
|
|
542
|
-
|
|
626
|
+
let toExecute = null;
|
|
627
|
+
let module = null;
|
|
628
|
+
let controller = null;
|
|
629
|
+
let action = null;
|
|
543
630
|
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
action
|
|
548
|
-
] = fullPath;
|
|
631
|
+
if (typeof checkPath === 'function') {
|
|
632
|
+
|
|
633
|
+
toExecute = checkPath;
|
|
549
634
|
|
|
550
635
|
} else {
|
|
551
636
|
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
637
|
+
const fullPath = checkPath.split('.');
|
|
638
|
+
|
|
639
|
+
if (fullPath.length > 2) { // Has folder
|
|
640
|
+
|
|
641
|
+
[
|
|
642
|
+
module,
|
|
643
|
+
controller,
|
|
644
|
+
action
|
|
645
|
+
] = fullPath;
|
|
646
|
+
|
|
647
|
+
} else {
|
|
648
|
+
|
|
649
|
+
[
|
|
650
|
+
controller,
|
|
651
|
+
action
|
|
652
|
+
] = fullPath;
|
|
653
|
+
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
try {
|
|
657
|
+
toExecute = module
|
|
658
|
+
? (AllControllers[module][controller][action])
|
|
659
|
+
: AllControllers[controller][action];
|
|
660
|
+
} catch (e) {
|
|
661
|
+
toExecute = null;
|
|
662
|
+
}
|
|
556
663
|
|
|
557
664
|
}
|
|
558
665
|
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
}
|
|
564
|
-
|
|
666
|
+
if (toExecute) {
|
|
667
|
+
socket.on(i, (body) => {
|
|
668
|
+
toExecute({ socket, body: body || {} });
|
|
669
|
+
});
|
|
670
|
+
} else {
|
|
671
|
+
console.error('\x1b[31mError:', 'Controller not found in', (module) ? `${module}.${controller}.${action}` : `${controller}.${action}`, '\x1b[0m', 'to socket event', i);
|
|
565
672
|
}
|
|
566
673
|
|
|
567
|
-
}
|
|
674
|
+
});
|
|
568
675
|
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
toExecute({ socket, body: body || {} });
|
|
572
|
-
});
|
|
573
|
-
} else {
|
|
574
|
-
console.error('\x1b[31mError:', 'Controller not found in', (module) ? `${module}.${controller}.${action}` : `${controller}.${action}`, '\x1b[0m', 'to socket event', i);
|
|
575
|
-
}
|
|
676
|
+
vulkano.set('socket', socket);
|
|
677
|
+
app.socket = socket;
|
|
576
678
|
|
|
577
679
|
});
|
|
578
680
|
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
});
|
|
681
|
+
// next line is the money
|
|
682
|
+
global.io = io;
|
|
683
|
+
vulkano.set('socketio', io);
|
|
583
684
|
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
685
|
+
// middleware
|
|
686
|
+
if (sockets.middleware && typeof sockets.middleware === 'function') {
|
|
687
|
+
io.use(sockets.middleware);
|
|
688
|
+
}
|
|
587
689
|
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
io.use(sockets.middleware);
|
|
591
|
-
}
|
|
690
|
+
// override vulkano
|
|
691
|
+
app.vulkano = vulkano;
|
|
592
692
|
|
|
593
|
-
|
|
594
|
-
app.vulkano = vulkano;
|
|
693
|
+
cb();
|
|
595
694
|
|
|
596
|
-
|
|
695
|
+
});
|
|
597
696
|
|
|
598
|
-
|
|
697
|
+
}
|
|
599
698
|
|
|
600
|
-
}
|
|
699
|
+
};
|
|
601
700
|
|
|
602
701
|
};
|