@vulkano/core 1.18.0 → 1.19.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/.oxlintrc.json +42 -0
- package/.vscode/settings.json +14 -0
- package/app.js +51 -58
- package/bin/setup.js +3 -3
- package/biome.json +31 -0
- package/bootstrap/engines/handlebars.js +55 -0
- package/bootstrap/engines/index.js +31 -0
- package/bootstrap/engines/nunjucks.js +33 -0
- package/bootstrap/express.js +1 -1
- package/bootstrap/logger.js +2 -2
- package/bootstrap/responses.js +1 -1
- package/bootstrap/server.js +163 -289
- package/bootstrap/services.js +1 -1
- package/bootstrap/views.js +4 -7
- package/libs/Download.js +3 -3
- package/libs/Encrypter.js +1 -1
- package/libs/Filter.js +1 -1
- package/libs/VSError.js +1 -1
- package/libs/Vite.js +1 -1
- package/package.json +8 -17
- package/views/errors/handlebars/exception.html +48 -0
- package/views/errors/handlebars/no_action.html +63 -0
- package/views/errors/handlebars/no_controller.html +65 -0
- package/views/errors/handlebars/no_view.html +57 -0
package/.oxlintrc.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"env": {
|
|
3
|
+
"node": true,
|
|
4
|
+
"browser": true,
|
|
5
|
+
"es6": true
|
|
6
|
+
},
|
|
7
|
+
"globals": {
|
|
8
|
+
"app": "readonly",
|
|
9
|
+
"io": "readonly",
|
|
10
|
+
"ApiClient": "readonly",
|
|
11
|
+
"Download": "readonly",
|
|
12
|
+
"Paginate": "readonly",
|
|
13
|
+
"Mixed": "readonly",
|
|
14
|
+
"Crontab": "readonly",
|
|
15
|
+
"Encrypter": "readonly",
|
|
16
|
+
"Filter": "readonly",
|
|
17
|
+
"i18n": "readonly",
|
|
18
|
+
"Jwt": "readonly",
|
|
19
|
+
"VSError": "readonly",
|
|
20
|
+
"ABS_PATH": "readonly",
|
|
21
|
+
"APP_PATH": "readonly",
|
|
22
|
+
"CORE_PATH": "readonly",
|
|
23
|
+
"PUBLIC_PATH": "readonly"
|
|
24
|
+
},
|
|
25
|
+
"rules": {
|
|
26
|
+
"curly": "error",
|
|
27
|
+
"no-console": "off",
|
|
28
|
+
"no-underscore-dangle": "off",
|
|
29
|
+
"no-throw-literal": "off",
|
|
30
|
+
"no-unneeded-ternary": "off",
|
|
31
|
+
"guard-for-in": "off"
|
|
32
|
+
},
|
|
33
|
+
"ignorePatterns": [
|
|
34
|
+
"node_modules",
|
|
35
|
+
"test",
|
|
36
|
+
"bundle",
|
|
37
|
+
"tasks",
|
|
38
|
+
"docs",
|
|
39
|
+
"public",
|
|
40
|
+
"setup"
|
|
41
|
+
]
|
|
42
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"oxc.enable": true,
|
|
3
|
+
"oxc.configPath": ".oxlintrc.json",
|
|
4
|
+
"editor.defaultFormatter": "biomejs.biome",
|
|
5
|
+
"editor.formatOnSave": true,
|
|
6
|
+
"javascript.format.enable": false,
|
|
7
|
+
"typescript.format.enable": false,
|
|
8
|
+
"[javascript]": {
|
|
9
|
+
"editor.defaultFormatter": "biomejs.biome"
|
|
10
|
+
},
|
|
11
|
+
"[javascriptreact]": {
|
|
12
|
+
"editor.defaultFormatter": "biomejs.biome"
|
|
13
|
+
}
|
|
14
|
+
}
|
package/app.js
CHANGED
|
@@ -10,9 +10,9 @@
|
|
|
10
10
|
global.START_TIME = Date.now();
|
|
11
11
|
|
|
12
12
|
const dotenv = require('dotenv');
|
|
13
|
-
const path = require('path');
|
|
14
|
-
const v8 = require('v8');
|
|
15
|
-
const fs = require('fs');
|
|
13
|
+
const path = require('node:path');
|
|
14
|
+
const v8 = require('node:v8');
|
|
15
|
+
const fs = require('node:fs');
|
|
16
16
|
|
|
17
17
|
global.app = {};
|
|
18
18
|
|
|
@@ -81,11 +81,7 @@ const NODE_ENV = (process.env.NODE_ENV || 'development').toLowerCase();
|
|
|
81
81
|
|
|
82
82
|
app.PRODUCTION = NODE_ENV === 'production' ? true : false;
|
|
83
83
|
|
|
84
|
-
const {
|
|
85
|
-
views,
|
|
86
|
-
local,
|
|
87
|
-
env
|
|
88
|
-
} = config || {};
|
|
84
|
+
const { views, local, env } = config || {};
|
|
89
85
|
|
|
90
86
|
// NODE_ENV
|
|
91
87
|
const environmentConfig = env ? env[NODE_ENV] || {} : {};
|
|
@@ -121,12 +117,7 @@ app.config = allConfig;
|
|
|
121
117
|
app.pkg = appPkg;
|
|
122
118
|
|
|
123
119
|
// Include all components
|
|
124
|
-
const {
|
|
125
|
-
lineWidth,
|
|
126
|
-
colors,
|
|
127
|
-
showCenteredText,
|
|
128
|
-
showColumn
|
|
129
|
-
} = require('./bootstrap/logger');
|
|
120
|
+
const { lineWidth, colors, showCenteredText, showColumn } = require('./bootstrap/logger');
|
|
130
121
|
|
|
131
122
|
// Include all components
|
|
132
123
|
const loadDatabase = require('./database/mongodb');
|
|
@@ -135,7 +126,6 @@ const loadControllers = require('./controllers/controllers');
|
|
|
135
126
|
const loadServer = require('./bootstrap/server');
|
|
136
127
|
|
|
137
128
|
async function startVulkano() {
|
|
138
|
-
|
|
139
129
|
// Load Services
|
|
140
130
|
loadServices();
|
|
141
131
|
|
|
@@ -155,17 +145,19 @@ async function startVulkano() {
|
|
|
155
145
|
const cutLine = '-'.padEnd(lineWidth, '-');
|
|
156
146
|
|
|
157
147
|
console.log('');
|
|
158
|
-
console.log(`${colors.fg.magenta}${cutLine}
|
|
148
|
+
console.log(`${colors.fg.magenta}${cutLine}${colors.reset}`);
|
|
159
149
|
console.log('');
|
|
160
|
-
console.log(colors.fg.cyan
|
|
161
|
-
console.log(colors.fg.cyan
|
|
162
|
-
console.log(
|
|
150
|
+
console.log(`${colors.fg.cyan}${showCenteredText('🌋')}${colors.reset}`);
|
|
151
|
+
console.log(`${colors.fg.cyan}${showCenteredText(`${appName} ${appVersion}`)}${colors.reset}`);
|
|
152
|
+
console.log(
|
|
153
|
+
`${colors.fg.cyan}${showCenteredText(`${pkg.name} ${pkg.version}`.toUpperCase())}${colors.reset}`
|
|
154
|
+
);
|
|
163
155
|
console.log('');
|
|
164
|
-
console.log(colors.fg.blue
|
|
165
|
-
console.log(colors.fg.cyan
|
|
156
|
+
console.log(`${colors.fg.blue}🔗 github.com/vulkanojs/vulkano${colors.reset}`);
|
|
157
|
+
console.log(`${colors.fg.cyan}☕ buymeacoffee.com/argordmel${colors.reset}`);
|
|
166
158
|
console.log('');
|
|
167
159
|
console.log(` Author: ${colors.fg.green}${author}${colors.reset}`);
|
|
168
|
-
console.log(`${colors.fg.magenta}${cutLine}
|
|
160
|
+
console.log(`${colors.fg.magenta}${cutLine}${colors.reset}`);
|
|
169
161
|
|
|
170
162
|
// Routes
|
|
171
163
|
app.routes = controllers;
|
|
@@ -181,33 +173,21 @@ async function startVulkano() {
|
|
|
181
173
|
...app.config.routes
|
|
182
174
|
};
|
|
183
175
|
|
|
184
|
-
const {
|
|
185
|
-
bootstrap
|
|
186
|
-
} = config;
|
|
176
|
+
const { bootstrap } = config;
|
|
187
177
|
|
|
188
178
|
if (!bootstrap || typeof bootstrap !== 'function') {
|
|
189
179
|
console.log('Missing the boostrap file to start app: app/config/bootstrap.js');
|
|
190
180
|
return;
|
|
191
181
|
}
|
|
192
182
|
|
|
193
|
-
bootstrap(
|
|
194
|
-
|
|
183
|
+
bootstrap((callbackAfterInitVulkano) => {
|
|
195
184
|
// Start Express
|
|
196
|
-
app.server.start(
|
|
185
|
+
app.server.start(() => {
|
|
186
|
+
const { sockets, settings: configSettings, vite } = app.config || {};
|
|
197
187
|
|
|
198
|
-
const {
|
|
199
|
-
sockets,
|
|
200
|
-
settings: configSettings,
|
|
201
|
-
vite
|
|
202
|
-
} = app.config || {};
|
|
188
|
+
const { database } = configSettings || {};
|
|
203
189
|
|
|
204
|
-
const {
|
|
205
|
-
database
|
|
206
|
-
} = configSettings || {};
|
|
207
|
-
|
|
208
|
-
const {
|
|
209
|
-
connection
|
|
210
|
-
} = database || {};
|
|
190
|
+
const { connection } = database || {};
|
|
211
191
|
|
|
212
192
|
const connectionToShow = connection && process.env.MONGO_URI ? 'MONGO_URI' : connection;
|
|
213
193
|
|
|
@@ -215,12 +195,13 @@ async function startVulkano() {
|
|
|
215
195
|
|
|
216
196
|
const nodeVersion = process.version.match(/^v(\d+\.\d+\.\d+)/)[1];
|
|
217
197
|
const portText = String(app.vulkano.get('port') || 8000);
|
|
218
|
-
const socketText = sockets.enabled ? '
|
|
219
|
-
const adapterText = sockets.enabled ? String(sockets.adapter || 'memory').toUpperCase() : 'NO';
|
|
198
|
+
const socketText = sockets.enabled ? String(sockets.adapter || 'memory').toUpperCase() : 'NO';
|
|
220
199
|
|
|
221
|
-
serverConfig.push(
|
|
200
|
+
serverConfig.push(`🚀 PORT: ${colors.fg.green}${showColumn(portText, 7)}${colors.reset}`);
|
|
222
201
|
serverConfig.push(' | ');
|
|
223
|
-
serverConfig.push(
|
|
202
|
+
serverConfig.push(
|
|
203
|
+
`🌿 ENV: ${app.PRODUCTION ? colors.fg.red : colors.fg.green}${showColumn(NODE_ENV, 0)}${colors.reset}`
|
|
204
|
+
);
|
|
224
205
|
|
|
225
206
|
console.log(serverConfig.join(''));
|
|
226
207
|
|
|
@@ -228,26 +209,41 @@ async function startVulkano() {
|
|
|
228
209
|
const totalHeapSizeGb = (totalHeapSize / 1024 / 1024 / 1024).toFixed(2);
|
|
229
210
|
|
|
230
211
|
const nodeConfig = [];
|
|
231
|
-
nodeConfig.push(
|
|
212
|
+
nodeConfig.push(`📦 NODE: ${colors.fg.green}${showColumn(nodeVersion, 7)}${colors.reset}`);
|
|
232
213
|
nodeConfig.push(' | ');
|
|
233
|
-
nodeConfig.push(
|
|
214
|
+
nodeConfig.push(`🧠 MAX MEM: `, `${colors.fg.green}${totalHeapSizeGb} GB${colors.reset}`);
|
|
234
215
|
console.log(nodeConfig.join(''));
|
|
235
216
|
|
|
236
217
|
const startUpConfig = [];
|
|
237
|
-
startUpConfig.push(
|
|
218
|
+
startUpConfig.push(
|
|
219
|
+
`🔌 SOCKETS: `,
|
|
220
|
+
`${sockets.enabled ? colors.fg.green : colors.fg.blue}${showColumn(socketText, 10)}${colors.reset}`
|
|
221
|
+
);
|
|
238
222
|
startUpConfig.push(' | ');
|
|
239
|
-
startUpConfig.push(
|
|
223
|
+
startUpConfig.push(
|
|
224
|
+
`🍃 DB: `,
|
|
225
|
+
connection
|
|
226
|
+
? `${colors.fg.green}${connectionToShow}${colors.reset}`
|
|
227
|
+
: `${colors.fg.blue}NO DATABASE${colors.reset}`
|
|
228
|
+
);
|
|
240
229
|
console.log(startUpConfig.join(''));
|
|
241
230
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
231
|
+
if (vite?.enabled) {
|
|
232
|
+
console.log(
|
|
233
|
+
`${colors.fg.yellow}⚡ VITE${colors.reset}`,
|
|
234
|
+
`${colors.fg.green}${showColumn('ENABLED', 5)}${colors.reset}`,
|
|
235
|
+
`${colors.dim}${vite.buildPath || 'public/.vite'}${colors.reset}`
|
|
236
|
+
);
|
|
237
|
+
}
|
|
247
238
|
|
|
248
|
-
|
|
239
|
+
const startupMs = ((Date.now() - global.START_TIME) / 1000).toFixed(3);
|
|
240
|
+
console.log(`${colors.fg.magenta}${cutLine}${colors.reset}`);
|
|
241
|
+
console.log(
|
|
242
|
+
`${colors.bright}${colors.fg.cyan}${showCenteredText(`⚡ Ready in ${startupMs}s`)}${colors.reset}`
|
|
243
|
+
);
|
|
244
|
+
console.log(`${colors.fg.magenta}${cutLine}${colors.reset}`);
|
|
249
245
|
|
|
250
|
-
if (vite
|
|
246
|
+
if (vite?.enabled) {
|
|
251
247
|
app.vite = Vite.init(vite.buildPath || 'public/.vite');
|
|
252
248
|
}
|
|
253
249
|
|
|
@@ -255,11 +251,8 @@ async function startVulkano() {
|
|
|
255
251
|
if (callbackAfterInitVulkano && typeof callbackAfterInitVulkano === 'function') {
|
|
256
252
|
callbackAfterInitVulkano();
|
|
257
253
|
}
|
|
258
|
-
|
|
259
254
|
});
|
|
260
|
-
|
|
261
255
|
});
|
|
262
|
-
|
|
263
256
|
}
|
|
264
257
|
|
|
265
258
|
module.exports = startVulkano;
|
package/bin/setup.js
CHANGED
|
@@ -7,9 +7,9 @@
|
|
|
7
7
|
* creates the minimal folder structure and config files needed to start.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
const fs = require('fs');
|
|
11
|
-
const path = require('path');
|
|
12
|
-
const readline = require('readline');
|
|
10
|
+
const fs = require('node:fs');
|
|
11
|
+
const path = require('node:path');
|
|
12
|
+
const readline = require('node:readline');
|
|
13
13
|
|
|
14
14
|
// npm sets INIT_CWD to the directory where `npm install` was invoked.
|
|
15
15
|
// npm_config_local_prefix is the project root (directory containing node_modules).
|
package/biome.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://biomejs.dev/schemas/2.4.15/schema.json",
|
|
3
|
+
"files": {
|
|
4
|
+
"includes": [
|
|
5
|
+
"**",
|
|
6
|
+
"!node_modules",
|
|
7
|
+
"!test",
|
|
8
|
+
"!bundle",
|
|
9
|
+
"!tasks",
|
|
10
|
+
"!docs",
|
|
11
|
+
"!public",
|
|
12
|
+
"!setup"
|
|
13
|
+
]
|
|
14
|
+
},
|
|
15
|
+
"formatter": {
|
|
16
|
+
"enabled": true,
|
|
17
|
+
"indentStyle": "space",
|
|
18
|
+
"indentWidth": 2,
|
|
19
|
+
"lineWidth": 100
|
|
20
|
+
},
|
|
21
|
+
"linter": {
|
|
22
|
+
"enabled": true
|
|
23
|
+
},
|
|
24
|
+
"javascript": {
|
|
25
|
+
"formatter": {
|
|
26
|
+
"quoteStyle": "single",
|
|
27
|
+
"trailingCommas": "none",
|
|
28
|
+
"semicolons": "always"
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
const { create: hbsCreate } = require('express-handlebars');
|
|
2
|
+
|
|
3
|
+
// Wraps a Nunjucks-style function so it works as a Handlebars helper:
|
|
4
|
+
// Hash params → {{{helper key=val}}} calls fn({ key: val })
|
|
5
|
+
// Positional → {{helper value}} calls fn(value)
|
|
6
|
+
// String output is wrapped in SafeString to prevent double-escaping
|
|
7
|
+
function wrapHelper(hbs, fn) {
|
|
8
|
+
return function hbsHelper(...args) {
|
|
9
|
+
const hbsOpts = args[args.length - 1];
|
|
10
|
+
const isHbsOptions = hbsOpts && typeof hbsOpts === 'object' && 'hash' in hbsOpts;
|
|
11
|
+
let result;
|
|
12
|
+
if (isHbsOptions) {
|
|
13
|
+
const positional = args.slice(0, -1);
|
|
14
|
+
result = positional.length === 0 ? fn(hbsOpts.hash) : fn(...positional);
|
|
15
|
+
} else {
|
|
16
|
+
result = fn(...args);
|
|
17
|
+
}
|
|
18
|
+
return typeof result === 'string' ? new hbs.handlebars.SafeString(result) : result;
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function registerGroup(hbs, groups, method) {
|
|
23
|
+
(groups || []).forEach((group) => {
|
|
24
|
+
Object.keys(group || {}).forEach((key) => {
|
|
25
|
+
hbs.handlebars[method](key, wrapHelper(hbs, group[key]));
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
module.exports = function setupHandlebars(vulkano, views, viewsExt) {
|
|
31
|
+
const hbs = hbsCreate({
|
|
32
|
+
extname: viewsExt,
|
|
33
|
+
defaultLayout: views.defaultLayout !== undefined ? views.defaultLayout : 'default',
|
|
34
|
+
layoutsDir: views.layoutsDir || `${views.path}/_shared/templates`,
|
|
35
|
+
partialsDir: views.partialsDir || `${views.path}/_shared/partials`,
|
|
36
|
+
...(views.settings || {})
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
registerGroup(hbs, views.filters, 'registerHelper');
|
|
40
|
+
registerGroup(hbs, views.helpers, 'registerHelper');
|
|
41
|
+
|
|
42
|
+
vulkano.use((_req, res, next) => {
|
|
43
|
+
(views.globals || []).forEach((group) => {
|
|
44
|
+
Object.assign(res.locals, group || {});
|
|
45
|
+
});
|
|
46
|
+
res.locals.app = app;
|
|
47
|
+
next();
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
vulkano.engine(viewsExt, hbs.engine);
|
|
51
|
+
vulkano.set('view engine', viewsExt);
|
|
52
|
+
|
|
53
|
+
app.server.views._engine = hbs;
|
|
54
|
+
app.handlebars = hbs;
|
|
55
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
const viewsConfig = require('../views');
|
|
2
|
+
|
|
3
|
+
const SUPPORTED_ENGINES = ['nunjucks', 'handlebars'];
|
|
4
|
+
|
|
5
|
+
module.exports = function setupViewEngine(vulkano) {
|
|
6
|
+
const views = {
|
|
7
|
+
ext: '.html',
|
|
8
|
+
...viewsConfig,
|
|
9
|
+
...(app.server.views || {})
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const engine = views.engine || 'nunjucks';
|
|
13
|
+
const ext = views.ext || '.html';
|
|
14
|
+
|
|
15
|
+
if (!SUPPORTED_ENGINES.includes(engine)) {
|
|
16
|
+
throw new Error(
|
|
17
|
+
`Vulkano: unsupported view engine "${engine}". Supported engines: ${SUPPORTED_ENGINES.join(', ')}.`
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
vulkano.set('views', views.path);
|
|
22
|
+
|
|
23
|
+
if (engine === 'handlebars') {
|
|
24
|
+
require('./handlebars')(vulkano, views, ext);
|
|
25
|
+
} else {
|
|
26
|
+
require('./nunjucks')(vulkano, views);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Error view subfolder depends on engine (core dev-mode error templates)
|
|
30
|
+
return engine;
|
|
31
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
const nunjucks = require('nunjucks');
|
|
2
|
+
|
|
3
|
+
module.exports = function setupNunjucks(vulkano, views) {
|
|
4
|
+
const settings = {
|
|
5
|
+
autoescape: true,
|
|
6
|
+
watch: !app.PRODUCTION,
|
|
7
|
+
...(views.settings || {}),
|
|
8
|
+
express: vulkano
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const env = nunjucks.configure([views.path, CORE_PATH], settings);
|
|
12
|
+
|
|
13
|
+
env.addGlobal('app', app);
|
|
14
|
+
|
|
15
|
+
(views.globals || []).forEach((group) => {
|
|
16
|
+
Object.keys(group || {}).forEach((key) => env.addGlobal(key, group[key]));
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
(views.helpers || []).forEach((group) => {
|
|
20
|
+
Object.keys(group || {}).forEach((key) => env.addGlobal(key, group[key]));
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
(views.filters || []).forEach((group) => {
|
|
24
|
+
Object.keys(group || {}).forEach((key) => env.addFilter(key, group[key]));
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
(views.extensions || []).forEach((group) => {
|
|
28
|
+
Object.keys(group || {}).forEach((key) => env.addExtension(key, group[key]));
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
app.server.views._engine = env;
|
|
32
|
+
app.nunjucks = nunjucks;
|
|
33
|
+
};
|
package/bootstrap/express.js
CHANGED
package/bootstrap/logger.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const logger = {
|
|
2
2
|
|
|
3
|
-
lineWidth:
|
|
3
|
+
lineWidth: 41,
|
|
4
4
|
|
|
5
5
|
colors: {
|
|
6
6
|
reset: '\x1b[0m',
|
|
@@ -36,7 +36,7 @@ const logger = {
|
|
|
36
36
|
|
|
37
37
|
showCenteredText(text) {
|
|
38
38
|
|
|
39
|
-
const colSize =
|
|
39
|
+
const colSize = logger.lineWidth / 2;
|
|
40
40
|
const textLength = (text || '').length;
|
|
41
41
|
const textLeftSize = Math.trunc(textLength / 2);
|
|
42
42
|
const textRightSize = textLength - textLeftSize;
|
package/bootstrap/responses.js
CHANGED