@vulkano/core 1.17.4 → 1.18.1

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 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
@@ -1,4 +1,5 @@
1
1
  /* eslint-disable import/no-dynamic-require */
2
+ /* global Vite */
2
3
 
3
4
  /**
4
5
  * Bootstrap.js
@@ -80,11 +81,7 @@ const NODE_ENV = (process.env.NODE_ENV || 'development').toLowerCase();
80
81
 
81
82
  app.PRODUCTION = NODE_ENV === 'production' ? true : false;
82
83
 
83
- const {
84
- views,
85
- local,
86
- env
87
- } = config || {};
84
+ const { views, local, env } = config || {};
88
85
 
89
86
  // NODE_ENV
90
87
  const environmentConfig = env ? env[NODE_ENV] || {} : {};
@@ -120,12 +117,7 @@ app.config = allConfig;
120
117
  app.pkg = appPkg;
121
118
 
122
119
  // Include all components
123
- const {
124
- lineWidth,
125
- colors,
126
- showCenteredText,
127
- showColumn
128
- } = require('./bootstrap/logger');
120
+ const { lineWidth, colors, showCenteredText, showColumn } = require('./bootstrap/logger');
129
121
 
130
122
  // Include all components
131
123
  const loadDatabase = require('./database/mongodb');
@@ -134,7 +126,6 @@ const loadControllers = require('./controllers/controllers');
134
126
  const loadServer = require('./bootstrap/server');
135
127
 
136
128
  async function startVulkano() {
137
-
138
129
  // Load Services
139
130
  loadServices();
140
131
 
@@ -154,17 +145,17 @@ async function startVulkano() {
154
145
  const cutLine = '-'.padEnd(lineWidth, '-');
155
146
 
156
147
  console.log('');
157
- console.log(`${colors.fg.magenta}${cutLine}`, colors.reset);
148
+ console.log(`${colors.fg.magenta}${cutLine}${colors.reset}`);
158
149
  console.log('');
159
- console.log(colors.fg.cyan, showCenteredText('🌋'), colors.reset);
160
- console.log(colors.fg.cyan, showCenteredText(`${appName} ${appVersion}`), colors.reset);
161
- console.log(colors.fg.cyan, showCenteredText(`${pkg.name} ${pkg.version}`.toUpperCase()), colors.reset);
150
+ console.log(`${colors.fg.cyan}${showCenteredText('🌋')}${colors.reset}`);
151
+ console.log(`${colors.fg.cyan}${showCenteredText(`${appName} ${appVersion}`)}${colors.reset}`);
152
+ console.log(`${colors.fg.cyan}${showCenteredText(`${pkg.name} ${pkg.version}`.toUpperCase())}${colors.reset}`);
162
153
  console.log('');
163
- console.log(colors.fg.blue, '🔗 github.com/vulkanojs/vulkano', colors.reset);
164
- console.log(colors.fg.cyan, '☕ buymeacoffee.com/argordmel', colors.reset);
154
+ console.log(`${colors.fg.blue}🔗 github.com/vulkanojs/vulkano${colors.reset}`);
155
+ console.log(`${colors.fg.cyan}☕ buymeacoffee.com/argordmel${colors.reset}`);
165
156
  console.log('');
166
157
  console.log(` Author: ${colors.fg.green}${author}${colors.reset}`);
167
- console.log(`${colors.fg.magenta}${cutLine}`, colors.reset);
158
+ console.log(`${colors.fg.magenta}${cutLine}${colors.reset}`);
168
159
 
169
160
  // Routes
170
161
  app.routes = controllers;
@@ -180,32 +171,21 @@ async function startVulkano() {
180
171
  ...app.config.routes
181
172
  };
182
173
 
183
- const {
184
- bootstrap
185
- } = config;
174
+ const { bootstrap } = config;
186
175
 
187
176
  if (!bootstrap || typeof bootstrap !== 'function') {
188
177
  console.log('Missing the boostrap file to start app: app/config/bootstrap.js');
189
178
  return;
190
179
  }
191
180
 
192
- bootstrap( (callbackAfterInitVulkano) => {
193
-
181
+ bootstrap((callbackAfterInitVulkano) => {
194
182
  // Start Express
195
- app.server.start( () => {
196
-
197
- const {
198
- sockets,
199
- settings: configSettings
200
- } = app.config || {};
183
+ app.server.start(() => {
184
+ const { sockets, settings: configSettings, vite } = app.config || {};
201
185
 
202
- const {
203
- database
204
- } = configSettings || {};
186
+ const { database } = configSettings || {};
205
187
 
206
- const {
207
- connection
208
- } = database || {};
188
+ const { connection } = database || {};
209
189
 
210
190
  const connectionToShow = connection && process.env.MONGO_URI ? 'MONGO_URI' : connection;
211
191
 
@@ -213,12 +193,15 @@ async function startVulkano() {
213
193
 
214
194
  const nodeVersion = process.version.match(/^v(\d+\.\d+\.\d+)/)[1];
215
195
  const portText = String(app.vulkano.get('port') || 8000);
216
- const socketText = sockets.enabled ? 'YES' : 'NO';
217
- const adapterText = sockets.enabled ? String(sockets.adapter || 'memory').toUpperCase() : 'NO';
196
+ const socketText = sockets.enabled
197
+ ? String(sockets.adapter || 'memory').toUpperCase()
198
+ : 'NO';
218
199
 
219
- serverConfig.push(` PORT: ${colors.fg.green}${showColumn(portText, 7)}${colors.reset}`);
200
+ serverConfig.push(`🚀 PORT: ${colors.fg.green}${showColumn(portText, 7)}${colors.reset}`);
220
201
  serverConfig.push(' | ');
221
- serverConfig.push(` ENV: ${app.PRODUCTION ? colors.fg.red : colors.fg.green}${showColumn(NODE_ENV, 0)}${colors.reset}`);
202
+ serverConfig.push(
203
+ `🌿 ENV: ${app.PRODUCTION ? colors.fg.red : colors.fg.green}${showColumn(NODE_ENV, 0)}${colors.reset}`
204
+ );
222
205
 
223
206
  console.log(serverConfig.join(''));
224
207
 
@@ -226,34 +209,48 @@ async function startVulkano() {
226
209
  const totalHeapSizeGb = (totalHeapSize / 1024 / 1024 / 1024).toFixed(2);
227
210
 
228
211
  const nodeConfig = [];
229
- nodeConfig.push(` NODE: ${colors.fg.green}${showColumn(nodeVersion, 7)}${colors.reset}`);
212
+ nodeConfig.push(`📦 NODE: ${colors.fg.green}${showColumn(nodeVersion, 7)}${colors.reset}`);
230
213
  nodeConfig.push(' | ');
231
- nodeConfig.push(' MAX MEM: ', `${colors.fg.green}${totalHeapSizeGb} GB${colors.reset}`);
214
+ nodeConfig.push(`🧠 MAX MEM: `, `${colors.fg.green}${totalHeapSizeGb} GB${colors.reset}`);
232
215
  console.log(nodeConfig.join(''));
233
216
 
234
217
  const startUpConfig = [];
235
- startUpConfig.push(' SOCKETS: ', `${colors.fg.green}${showColumn(socketText, 10)}${colors.reset}`);
218
+ startUpConfig.push(
219
+ `🔌 SOCKETS: `,
220
+ `${sockets.enabled ? colors.fg.green : colors.fg.blue}${showColumn(socketText, 10)}${colors.reset}`
221
+ );
236
222
  startUpConfig.push(' | ');
237
- startUpConfig.push(` STARTUP: ${colors.fg.green}${((Date.now() - global.START_TIME) / 1000).toFixed(3)}s${colors.reset}`);
223
+ startUpConfig.push(
224
+ `🍃 DB: `,
225
+ connection
226
+ ? `${colors.fg.green}${connectionToShow}${colors.reset}`
227
+ : `${colors.fg.blue}NO DATABASE${colors.reset}`
228
+ );
238
229
  console.log(startUpConfig.join(''));
239
230
 
240
- const dbConfig = [];
241
- dbConfig.push(' ADAPTER: ', `${colors.fg.green}${showColumn(adapterText, 10)}${colors.reset}`);
242
- dbConfig.push(' | ');
243
- dbConfig.push(' DB: ', connection ? `${colors.fg.green}${connectionToShow}${colors.reset}` : `${colors.fg.blue}NO DATABASE${colors.reset}`);
244
- console.log(dbConfig.join(''));
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
+ }
245
238
 
246
- console.log(`${colors.fg.magenta}${cutLine}`, colors.reset);
239
+ const startupMs = ((Date.now() - global.START_TIME) / 1000).toFixed(3);
240
+ console.log(`${colors.fg.magenta}${cutLine}${colors.reset}`);
241
+ console.log(`${colors.bright}${colors.fg.cyan}${showCenteredText(`⚡ Ready in ${startupMs}s`)}${colors.reset}`);
242
+ console.log(`${colors.fg.magenta}${cutLine}${colors.reset}`);
243
+
244
+ if (vite?.enabled) {
245
+ app.vite = Vite.init(vite.buildPath || 'public/.vite');
246
+ }
247
247
 
248
248
  // Run custom callback after init vulkano
249
249
  if (callbackAfterInitVulkano && typeof callbackAfterInitVulkano === 'function') {
250
250
  callbackAfterInitVulkano();
251
251
  }
252
-
253
252
  });
254
-
255
253
  });
256
-
257
254
  }
258
255
 
259
256
  module.exports = startVulkano;
package/bin/vulkano.js ADDED
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env node
2
+ /* eslint-disable global-require */
3
+ /* eslint-disable import/extensions */
4
+
5
+ const [,, command] = process.argv;
6
+
7
+ switch (command) {
8
+ case 'init':
9
+ require('./setup.js');
10
+ break;
11
+ default:
12
+ console.log([
13
+ '',
14
+ ' Usage: vulkano <command>',
15
+ '',
16
+ ' Commands:',
17
+ ' init Scaffold a new Vulkano project in the current directory',
18
+ '',
19
+ ].join('\n'));
20
+ process.exit(0);
21
+ }
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
+ }
@@ -1,6 +1,6 @@
1
1
  const logger = {
2
2
 
3
- lineWidth: 39,
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 = (logger.lineWidth / 2) - 3;
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;
@@ -15,6 +15,12 @@ const appFilters = require('include-all')({
15
15
  });
16
16
 
17
17
  // Include all helpers
18
+ const coreHelpers = require('include-all')({
19
+ dirname: path.join(CORE_PATH, 'views/helpers'),
20
+ filter: /(.+)\.js$/,
21
+ optional: true
22
+ });
23
+
18
24
  const appHelpers = require('include-all')({
19
25
  dirname: path.join(APP_PATH, 'config/views/helpers'),
20
26
  filter: /(.+)\.js$/,
@@ -32,6 +38,6 @@ module.exports = {
32
38
  appFilters || {}
33
39
  ],
34
40
 
35
- helpers: [appHelpers || {}]
41
+ helpers: [coreHelpers || {}, appHelpers || {}]
36
42
 
37
43
  };
package/libs/Vite.js ADDED
@@ -0,0 +1,71 @@
1
+ const fs = require('fs');
2
+
3
+ module.exports = {
4
+
5
+ init(buildPath) {
6
+
7
+ // we must have a manifest file...
8
+ let manifestPath = null;
9
+
10
+ const viteFolder = [
11
+ ABS_PATH,
12
+ (buildPath || 'public/.vite')
13
+ ].join('/');
14
+
15
+ const env = String(process.env.NODE_ENV || 'development').toLowerCase();
16
+
17
+ const isProd = env === 'production' ? true : false;
18
+
19
+ // Get the main manifest file
20
+ if (fs.existsSync(`${viteFolder}/manifest.json`)) {
21
+ manifestPath = fs.readFileSync(`${viteFolder}/manifest.json`, 'utf8');
22
+ }
23
+
24
+ // if in dev, try to get the env specific manifest file
25
+ if (!isProd) {
26
+ if (fs.existsSync(`${viteFolder}/manifest.${env}.json`)) {
27
+ manifestPath = fs.readFileSync(`${viteFolder}/manifest.${env}.json`, 'utf8');
28
+ } else if (manifestPath) {
29
+ console.log(`No Vite Manifest for env: ${env} exists. Fallback: manifest.json.`);
30
+ }
31
+ }
32
+
33
+ // Show warning if no manifest found
34
+ if (!manifestPath) {
35
+ if (isProd) {
36
+ console.log(`No Vite Manifest exists. Path: ${viteFolder}/manifest.json. Should hot server be running?`);
37
+ } else {
38
+ console.log(`No Vite Manifest exists. Path: ${viteFolder}/manifest.${env}.json. Should hot server be running?`);
39
+ }
40
+ }
41
+
42
+ const manifest = JSON.parse(manifestPath || '{}');
43
+
44
+ const {
45
+ url
46
+ } = manifest || {};
47
+
48
+ if (!url) {
49
+
50
+ return {
51
+ env,
52
+ url: '',
53
+ inputs: manifest || {}
54
+ };
55
+
56
+ }
57
+
58
+ return {
59
+ env,
60
+ ...manifest
61
+ };
62
+
63
+ },
64
+
65
+ buildFolder() {
66
+
67
+ return [ABS_PATH, this.buildPath].join('/');
68
+
69
+ }
70
+
71
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vulkano/core",
3
- "version": "1.17.4",
3
+ "version": "1.18.1",
4
4
  "description": "A MVC framework using Express 4",
5
5
  "license": "MIT",
6
6
  "author": "Vulkano Team",
@@ -8,11 +8,16 @@
8
8
  "node": ">=20"
9
9
  },
10
10
  "main": "app.js",
11
+ "bin": {
12
+ "vulkano": "./bin/vulkano.js"
13
+ },
11
14
  "scripts": {
15
+ "format": "biome format --write .",
16
+ "lint": "oxlint . && biome check .",
12
17
  "test": "jest",
13
18
  "test:watch": "jest --watch",
14
19
  "test:coverage": "jest --coverage",
15
- "postinstall": "node bin/postinstall.js"
20
+ "init": "node bin/setup.js"
16
21
  },
17
22
  "preferGlobal": true,
18
23
  "homepage": "https://github.com/vulkanojs/vulkano-core",
@@ -58,21 +63,9 @@
58
63
  "undici": "^6.25.0"
59
64
  },
60
65
  "devDependencies": {
61
- "@babel/core": "^7.26.9",
62
- "@babel/eslint-parser": "^7.26.8",
63
- "@babel/plugin-syntax-dynamic-import": "^7.8.3",
64
- "@babel/plugin-syntax-jsx": "^7.25.9",
65
- "@babel/preset-env": "^7.26.9",
66
- "@babel/preset-react": "^7.26.3",
67
- "@babel/preset-stage-1": "^7.8.3",
68
- "eslint": "^8.57.0",
69
- "eslint-config-airbnb": "^19.0.4",
70
- "eslint-import-resolver-alias": "^1.1.2",
71
- "eslint-plugin-import": "^2.31.0",
72
- "eslint-plugin-jsx-a11y": "^6.10.2",
73
- "eslint-plugin-react": "^7.37.4",
74
- "eslint-plugin-react-hooks": "^4.6.2",
66
+ "@biomejs/biome": "^2.4.15",
75
67
  "jest": "^29.7.0",
76
- "nodemon": "^3.1.14"
68
+ "nodemon": "^3.1.14",
69
+ "oxlint": "^1.64.0"
77
70
  }
78
- }
71
+ }
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Custom backend integration for Vite asset injection.
3
+ * Reads the Vite manifest (dev or production) from `app.vite` to dynamically
4
+ * inject the correct <script> or <link> tags into Nunjucks templates.
5
+ * Supports two asset types via the `type` param: "script" and "style(s)".
6
+ * In development, it emits the Vite HMR client + module entry; in production
7
+ * it resolves the hashed filenames from the manifest and appends a cache-bust
8
+ * query string using the app version.
9
+ *
10
+ * In your template, you can define the CSS and JS entries like this:
11
+ *
12
+ * CSS: {{ vite({ entry: 'app', type: 'style' }) | safe }}
13
+ * JS: {{ vite({ entry: 'app', type: 'script' }) | safe }}
14
+ *
15
+ */
16
+ module.exports = (props) => {
17
+
18
+ const {
19
+ vite
20
+ } = app.config || {};
21
+
22
+ if (!vite || (vite && !vite.enabled) ) {
23
+ return '<!-- Vite support not enabled. Enable it in your config/vite.js -->';
24
+ }
25
+
26
+ const {
27
+ entry,
28
+ type
29
+ } = props || {};
30
+
31
+ const {
32
+ url,
33
+ inputs
34
+ } = app.vite || {};
35
+
36
+ const {
37
+ version
38
+ } = app.pkg || {};
39
+
40
+ const validEntry = Object.keys(inputs).find( (k) => k.indexOf(entry) >= 0 );
41
+
42
+ if (!validEntry) {
43
+ return `<!-- Invalid Entry ${entry} -->`;
44
+ }
45
+
46
+ const currentEntry = inputs[validEntry];
47
+
48
+ const {
49
+ file,
50
+ css
51
+ } = currentEntry || {};
52
+
53
+ if (type === 'styles' || type === 'style') {
54
+ return (css || []).map( (s) => `<link rel="stylesheet" href="${url || '/'}${s}?v=${version}">`).join('\n');
55
+ }
56
+
57
+ if (type === 'script') {
58
+
59
+ // Development
60
+ if (typeof currentEntry === 'string') {
61
+ return [
62
+ '<!-- development -->',
63
+ `<script type="module" src="${url}@vite/client"></script>`,
64
+ `<script type="module" src="${url || '/'}${currentEntry}"></script>`
65
+ ].join('\n');
66
+ }
67
+
68
+ // Production
69
+ return `<script type="module" src="${url || '/'}${file}?v=${version}"></script>`;
70
+
71
+ }
72
+
73
+ return '';
74
+
75
+ };
File without changes