vako 1.3.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/CHANGELOG.md +63 -0
- package/README.md +1944 -0
- package/bin/commands/quick-setup.js +111 -0
- package/bin/commands/setup-executor.js +203 -0
- package/bin/commands/setup.js +737 -0
- package/bin/create-veko-app.js +75 -0
- package/bin/veko-update.js +205 -0
- package/bin/veko.js +188 -0
- package/error/error.ejs +382 -0
- package/index.js +36 -0
- package/lib/adapters/nextjs-adapter.js +241 -0
- package/lib/app.js +749 -0
- package/lib/core/auth-manager.js +1353 -0
- package/lib/core/auto-updater.js +1118 -0
- package/lib/core/logger.js +97 -0
- package/lib/core/module-installer.js +86 -0
- package/lib/dev/dev-server.js +292 -0
- package/lib/layout/layout-manager.js +834 -0
- package/lib/plugin-manager.js +1795 -0
- package/lib/routing/route-manager.js +1000 -0
- package/package.json +231 -0
- package/templates/public/css/style.css +2 -0
- package/templates/public/js/main.js +1 -0
- package/tsconfig.json +50 -0
- package/types/index.d.ts +238 -0
package/README.md
ADDED
|
@@ -0,0 +1,1944 @@
|
|
|
1
|
+
# 🚀 Veko.js
|
|
2
|
+
|
|
3
|
+
An **ultra-modern** and **intelligent** web framework for Node.js with Express and EJS, designed for rapid and efficient development with **intelligent hot reload**, **beautiful logging**, **extensible plugin system**, and **revolutionary auto-updater**.
|
|
4
|
+
|
|
5
|
+
# 🚀 Veko.js v1.2.0
|
|
6
|
+
|
|
7
|
+
An **ultra-modern** and **intelligent** web framework for Node.js with Express and EJS, designed for rapid and efficient development with **intelligent hot reload**, **beautiful logging**, **extensible plugin system**, **advanced code verification**, and the **most advanced auto-updater** in the Node.js ecosystem.
|
|
8
|
+
|
|
9
|
+
## ✨ Features
|
|
10
|
+
|
|
11
|
+
- 🔥 **Intelligent Hot Reload** - Selective reloading of modified routes
|
|
12
|
+
- 🎨 **Beautiful Logging** - Colorful logging system with icons and timestamps
|
|
13
|
+
- ⚡ **Integrated WebSocket** - Real-time communication for development
|
|
14
|
+
- 📁 **Auto-loading** - Routes, views, and middleware auto-configured
|
|
15
|
+
- 🛠️ **Development Mode** - Advanced file monitoring
|
|
16
|
+
- 🌐 **Smart Prefetching** - Route caching and prefetching
|
|
17
|
+
- 🔌 **Plugin System** - Extensible architecture with hooks and complete API
|
|
18
|
+
- 🛣️ **Dynamic Route Management** - Create/delete routes on-the-fly
|
|
19
|
+
- 🎨 **Advanced Layout System** - Powerful templating with sections and helpers
|
|
20
|
+
- 📦 **Auto Module Installation** - Automatic dependency management
|
|
21
|
+
- 🔬 **Advanced Code Verification** - Comprehensive code quality analysis
|
|
22
|
+
- 📊 **HTML Reports** - Beautiful verification reports with interactive dashboard
|
|
23
|
+
- 🔒 **Security Auditing** - Advanced security vulnerability detection
|
|
24
|
+
- 🧮 **Complexity Analysis** - Cyclomatic complexity and performance metrics
|
|
25
|
+
- 🔄 **Revolutionary Auto-Updater** - The most advanced auto-updater in Node.js ecosystem
|
|
26
|
+
- 🛡️ **Security-First Updates** - Automatic critical security updates with rollback protection
|
|
27
|
+
- 💾 **Intelligent Backup System** - Smart backups with one-click rollback
|
|
28
|
+
- 🎯 **Multi-Channel Updates** - Support for stable, beta, and alpha channels
|
|
29
|
+
- 🎨 **Interactive CLI** - Beautiful command-line interface with auto-completion
|
|
30
|
+
|
|
31
|
+
## 📋 Changelog
|
|
32
|
+
|
|
33
|
+
### 🎉 Version 1.2.0 (Latest) - December 2024
|
|
34
|
+
|
|
35
|
+
#### 🆕 Revolutionary Auto-Updater System
|
|
36
|
+
|
|
37
|
+
- **🔄 Advanced Auto-Updater**
|
|
38
|
+
- Automatic version checking with intelligent scheduling
|
|
39
|
+
- Multi-channel support (stable, beta, alpha, custom registries)
|
|
40
|
+
- Security-first approach with cryptographic validation
|
|
41
|
+
- Interactive CLI with beautiful colored interface
|
|
42
|
+
- Real-time notifications and progress indicators
|
|
43
|
+
- Seamless integration with existing applications
|
|
44
|
+
|
|
45
|
+
- **🔒 Security-First Architecture**
|
|
46
|
+
- SHA512 integrity verification for all packages
|
|
47
|
+
- Automatic security updates with priority handling
|
|
48
|
+
- Rollback protection against failed updates
|
|
49
|
+
- Vulnerability scanning before installation
|
|
50
|
+
- Secure communication protocols
|
|
51
|
+
- Audit trail for all operations
|
|
52
|
+
|
|
53
|
+
- **💾 Smart Backup & Rollback System**
|
|
54
|
+
- Automatic backup before every update
|
|
55
|
+
- Configurable backup retention (1-10 backups)
|
|
56
|
+
- Instant rollback in case of failure
|
|
57
|
+
- Backup size optimization and integrity verification
|
|
58
|
+
- Selective file backup with smart exclusions
|
|
59
|
+
- Emergency rollback functionality
|
|
60
|
+
|
|
61
|
+
- **🎨 Interactive CLI Experience**
|
|
62
|
+
- Beautiful colored interface with emojis and animations
|
|
63
|
+
- Auto-completion for all commands
|
|
64
|
+
- Interactive configuration wizard
|
|
65
|
+
- Real-time progress bars and status indicators
|
|
66
|
+
- Comprehensive help system with examples
|
|
67
|
+
- Menu-driven navigation
|
|
68
|
+
|
|
69
|
+
- **📊 Advanced Monitoring & Statistics**
|
|
70
|
+
- Update history tracking with detailed logs
|
|
71
|
+
- Performance metrics and success rates
|
|
72
|
+
- Rollback statistics and failure analysis
|
|
73
|
+
- Update channel analytics
|
|
74
|
+
- System health monitoring
|
|
75
|
+
- Historical trend analysis
|
|
76
|
+
|
|
77
|
+
#### 🔄 Auto-Updater Quick Start
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
# Installation globale recommandée
|
|
81
|
+
npm install -g veko
|
|
82
|
+
|
|
83
|
+
# Commandes disponibles
|
|
84
|
+
veko update # Lancer le gestionnaire de mises à jour interactif
|
|
85
|
+
veko update check # Vérifier les mises à jour
|
|
86
|
+
veko update config # Configurer l'auto-updater
|
|
87
|
+
veko update fix # Réparer l'auto-updater en cas de problème
|
|
88
|
+
|
|
89
|
+
# Alternative sans installation globale
|
|
90
|
+
npx veko update # Utiliser veko update sans installation globale
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
#### 🔄 Auto-Updater Simplifié
|
|
94
|
+
|
|
95
|
+
L'auto-updater de Veko a été simplifié pour plus de stabilité et d'efficacité. Il se concentre maintenant sur les commandes essentielles et évite les interfaces interactives qui pourraient interférer avec le fonctionnement de l'application.
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
# Vérifier les mises à jour
|
|
99
|
+
veko update check
|
|
100
|
+
|
|
101
|
+
# Installer une mise à jour
|
|
102
|
+
veko update update
|
|
103
|
+
|
|
104
|
+
# Afficher la configuration
|
|
105
|
+
veko update config
|
|
106
|
+
|
|
107
|
+
# Modifier un paramètre de configuration
|
|
108
|
+
veko update config autoUpdate true
|
|
109
|
+
|
|
110
|
+
# Afficher les statistiques
|
|
111
|
+
veko update stats
|
|
112
|
+
|
|
113
|
+
# Restaurer une version précédente
|
|
114
|
+
veko update rollback
|
|
115
|
+
|
|
116
|
+
# Réparer l'auto-updater
|
|
117
|
+
veko update fix
|
|
118
|
+
|
|
119
|
+
# Afficher l'aide et les commandes disponibles
|
|
120
|
+
veko update help
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
#### 🔧 Auto-Updater Robuste
|
|
124
|
+
|
|
125
|
+
L'auto-updater a été conçu pour être stable et ne jamais interférer avec le fonctionnement de l'application principale. Il offre :
|
|
126
|
+
|
|
127
|
+
- ✅ **Installation non-bloquante** - Aucun risque de ralentissement de votre application
|
|
128
|
+
- ✅ **Mises à jour automatisées** - Programmez des vérifications régulières
|
|
129
|
+
- ✅ **Gestion des erreurs avancée** - Restauration automatique en cas d'échec
|
|
130
|
+
- ✅ **Système de backup** - Avant toute mise à jour
|
|
131
|
+
- ✅ **Configuration simple** - Via la ligne de commande
|
|
132
|
+
|
|
133
|
+
#### 🔧 Auto-Updater Integration
|
|
134
|
+
|
|
135
|
+
```javascript
|
|
136
|
+
const { App } = require('veko');
|
|
137
|
+
|
|
138
|
+
const app = new App({
|
|
139
|
+
// Auto-updater configuration optimisée
|
|
140
|
+
autoUpdater: {
|
|
141
|
+
enabled: true, // Activer l'auto-updater
|
|
142
|
+
checkOnStart: true, // Vérifier au démarrage
|
|
143
|
+
autoUpdate: false, // Mode manuel (recommandé)
|
|
144
|
+
updateChannel: 'stable', // stable | beta | alpha
|
|
145
|
+
securityUpdates: true, // Auto-installer les mises à jour de sécurité
|
|
146
|
+
backupCount: 5, // Nombre de backups à conserver
|
|
147
|
+
checkInterval: 3600000, // Vérifier chaque heure (en millisecondes)
|
|
148
|
+
rollbackOnFailure: true // Restauration automatique en cas d'échec
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
app.listen();
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
#### 🌐 RESTful Auto-Updater API
|
|
156
|
+
|
|
157
|
+
Built-in API endpoints for remote management:
|
|
158
|
+
|
|
159
|
+
```javascript
|
|
160
|
+
// Check for updates programmatically
|
|
161
|
+
const updateInfo = await app.checkForUpdates();
|
|
162
|
+
console.log(updateInfo); // { hasUpdate: true, currentVersion: '1.0.0', latestVersion: '2.0.0' }
|
|
163
|
+
|
|
164
|
+
// Perform update
|
|
165
|
+
if (updateInfo.hasUpdate) {
|
|
166
|
+
const success = await app.performUpdate(updateInfo);
|
|
167
|
+
console.log('Update successful:', success);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Rollback if needed
|
|
171
|
+
await app.rollbackUpdate();
|
|
172
|
+
|
|
173
|
+
// Get auto-updater status
|
|
174
|
+
const status = app.getAutoUpdaterInfo();
|
|
175
|
+
console.log(status); // { active: true, currentVersion: '2.0.0', config: {...}, stats: {...} }
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
#### 🛡️ RESTful Endpoints
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
# Check for updates via HTTP
|
|
182
|
+
GET http://localhost:3000/_veko/updates/check
|
|
183
|
+
|
|
184
|
+
# Trigger update via HTTP
|
|
185
|
+
POST http://localhost:3000/_veko/updates/perform
|
|
186
|
+
|
|
187
|
+
# Get statistics via HTTP
|
|
188
|
+
GET http://localhost:3000/_veko/updates/stats
|
|
189
|
+
|
|
190
|
+
# Perform rollback via HTTP
|
|
191
|
+
POST http://localhost:3000/_veko/updates/rollback
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
#### 🎯 Update Channels
|
|
195
|
+
|
|
196
|
+
**Stable Channel (Production)**
|
|
197
|
+
```bash
|
|
198
|
+
npx veko-update config
|
|
199
|
+
# Select "Update Channel" -> "stable"
|
|
200
|
+
```
|
|
201
|
+
- ✅ Production-ready releases
|
|
202
|
+
- ✅ Thoroughly tested and stable
|
|
203
|
+
- ✅ Backward compatibility guaranteed
|
|
204
|
+
- ✅ Recommended for production environments
|
|
205
|
+
|
|
206
|
+
**Beta Channel (Testing)**
|
|
207
|
+
```bash
|
|
208
|
+
npx veko-update config
|
|
209
|
+
# Select "Update Channel" -> "beta"
|
|
210
|
+
```
|
|
211
|
+
- ✅ Pre-release versions with new features
|
|
212
|
+
- ✅ Stability testing phase
|
|
213
|
+
- ⚠️ May contain minor issues
|
|
214
|
+
- 🎯 Perfect for testing environments
|
|
215
|
+
|
|
216
|
+
**Alpha Channel (Development)**
|
|
217
|
+
```bash
|
|
218
|
+
npx veko-update config
|
|
219
|
+
# Select "Update Channel" -> "alpha"
|
|
220
|
+
```
|
|
221
|
+
- ✅ Cutting-edge features and improvements
|
|
222
|
+
- ✅ Immediate access to latest developments
|
|
223
|
+
- ⚠️ Experimental features included
|
|
224
|
+
- 🚧 Development and testing use only
|
|
225
|
+
|
|
226
|
+
#### 📊 Statistics Dashboard
|
|
227
|
+
|
|
228
|
+
```bash
|
|
229
|
+
npx veko-update stats
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
Comprehensive statistics including:
|
|
233
|
+
- 📈 Total updates performed
|
|
234
|
+
- ✅ Success/failure rates
|
|
235
|
+
- 🔄 Rollback history and frequency
|
|
236
|
+
- 📢 Update channel distribution
|
|
237
|
+
- ⚡ Performance metrics and timing
|
|
238
|
+
- 🔒 Security update history
|
|
239
|
+
- 📅 Last check/update timestamps
|
|
240
|
+
|
|
241
|
+
### 📜 Previous Versions
|
|
242
|
+
|
|
243
|
+
#### Version 1.1.0
|
|
244
|
+
- Initial plugin system implementation
|
|
245
|
+
- Basic layout system with EJS integration
|
|
246
|
+
- Hot reload functionality with WebSocket
|
|
247
|
+
- CLI commands (dev, setup, build, start)
|
|
248
|
+
- Basic logging system with colors
|
|
249
|
+
- Auto-loading for routes and middleware
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
## ✨ Features
|
|
253
|
+
|
|
254
|
+
- 🔥 **Intelligent Hot Reload** - Selective reloading of modified routes
|
|
255
|
+
- 🎨 **Beautiful Logging** - Colorful logging system with icons and timestamps
|
|
256
|
+
- ⚡ **Integrated WebSocket** - Real-time communication for development
|
|
257
|
+
- 📁 **Auto-loading** - Routes, views, and middleware auto-configured
|
|
258
|
+
- 🛠️ **Development Mode** - Advanced file monitoring
|
|
259
|
+
- 🌐 **Smart Prefetching** - Route caching and prefetching
|
|
260
|
+
- 🔌 **Plugin System** - Extensible architecture with hooks and complete API
|
|
261
|
+
- 🛣️ **Dynamic Route Management** - Create/delete routes on-the-fly
|
|
262
|
+
- 🎨 **Advanced Layout System** - Powerful templating with sections and helpers
|
|
263
|
+
- 📦 **Auto Module Installation** - Automatic dependency management
|
|
264
|
+
|
|
265
|
+
## 🚀 Installation
|
|
266
|
+
|
|
267
|
+
### Global Installation (CLI)
|
|
268
|
+
|
|
269
|
+
```bash
|
|
270
|
+
npm install -g veko
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
### Project Installation
|
|
274
|
+
|
|
275
|
+
```bash
|
|
276
|
+
npm install veko
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
## 📦 Quick Start
|
|
280
|
+
|
|
281
|
+
### 1. Create a New Project
|
|
282
|
+
|
|
283
|
+
```bash
|
|
284
|
+
# Create a new project
|
|
285
|
+
veko setup my-app
|
|
286
|
+
|
|
287
|
+
# With options
|
|
288
|
+
veko setup --name my-blog --template blog --git
|
|
289
|
+
|
|
290
|
+
# Available templates: default, api, blog, admin
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
### 2. Basic Application
|
|
294
|
+
|
|
295
|
+
```javascript
|
|
296
|
+
const { App } = require('veko');
|
|
297
|
+
|
|
298
|
+
const app = new App({
|
|
299
|
+
port: 3000,
|
|
300
|
+
viewsDir: 'views',
|
|
301
|
+
staticDir: 'public',
|
|
302
|
+
routesDir: 'routes',
|
|
303
|
+
layouts: {
|
|
304
|
+
enabled: true,
|
|
305
|
+
defaultLayout: 'main'
|
|
306
|
+
},
|
|
307
|
+
plugins: {
|
|
308
|
+
enabled: true,
|
|
309
|
+
autoLoad: true,
|
|
310
|
+
pluginsDir: 'plugins'
|
|
311
|
+
}
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
app.loadRoutes() // Automatically load all routes
|
|
315
|
+
.listen();
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
### 3. Ultra-Modern Development Mode
|
|
319
|
+
|
|
320
|
+
```javascript
|
|
321
|
+
const { startDev } = require('veko');
|
|
322
|
+
|
|
323
|
+
// Simple dev startup
|
|
324
|
+
startDev({ port: 3000 });
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
Or directly with the App class:
|
|
328
|
+
|
|
329
|
+
```javascript
|
|
330
|
+
const { App } = require('veko');
|
|
331
|
+
|
|
332
|
+
const app = new App({
|
|
333
|
+
port: 3000,
|
|
334
|
+
isDev: true, // Enable development mode
|
|
335
|
+
wsPort: 3008, // WebSocket port for hot reload
|
|
336
|
+
watchDirs: ['views', 'routes', 'public'], // Watched directories
|
|
337
|
+
layouts: {
|
|
338
|
+
enabled: true,
|
|
339
|
+
defaultLayout: 'main'
|
|
340
|
+
},
|
|
341
|
+
plugins: {
|
|
342
|
+
enabled: true,
|
|
343
|
+
autoLoad: true,
|
|
344
|
+
pluginsDir: 'plugins'
|
|
345
|
+
}
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
app.loadRoutes().listen();
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
### 4. CLI Commands
|
|
352
|
+
|
|
353
|
+
```bash
|
|
354
|
+
# Start development server
|
|
355
|
+
veko dev
|
|
356
|
+
|
|
357
|
+
# Start with custom port
|
|
358
|
+
veko dev --port 8080
|
|
359
|
+
|
|
360
|
+
# Create new project
|
|
361
|
+
veko setup my-project
|
|
362
|
+
|
|
363
|
+
# Create API project
|
|
364
|
+
veko setup --template api --name my-api
|
|
365
|
+
|
|
366
|
+
# Create blog project
|
|
367
|
+
veko setup --template blog --name my-blog
|
|
368
|
+
|
|
369
|
+
# Create admin project
|
|
370
|
+
veko setup --template admin --name admin-panel
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
## 🎨 Advanced Layout System
|
|
374
|
+
|
|
375
|
+
Veko.js includes a powerful layout system that automatically wraps your views with layouts, providing sections, helpers, and dynamic content injection.
|
|
376
|
+
|
|
377
|
+
### Layout Configuration
|
|
378
|
+
|
|
379
|
+
```javascript
|
|
380
|
+
const app = new App({
|
|
381
|
+
layouts: {
|
|
382
|
+
enabled: true, // Enable layout system
|
|
383
|
+
layoutsDir: 'views/layouts', // Layout directory
|
|
384
|
+
defaultLayout: 'main', // Default layout name
|
|
385
|
+
extension: '.ejs', // Layout file extension
|
|
386
|
+
sections: ['head', 'header', 'content', 'footer', 'scripts'],
|
|
387
|
+
cache: true // Cache layouts in production
|
|
388
|
+
}
|
|
389
|
+
});
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
### Creating Layouts
|
|
393
|
+
|
|
394
|
+
**views/layouts/main.ejs:**
|
|
395
|
+
|
|
396
|
+
```html
|
|
397
|
+
<!DOCTYPE html>
|
|
398
|
+
<html lang="en">
|
|
399
|
+
<head>
|
|
400
|
+
<meta charset="UTF-8">
|
|
401
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
402
|
+
<title><%= meta.title || 'Veko.js App' %></title>
|
|
403
|
+
|
|
404
|
+
<% if (meta.description) { %>
|
|
405
|
+
<meta name="description" content="<%= meta.description %>">
|
|
406
|
+
<% } %>
|
|
407
|
+
|
|
408
|
+
<!-- Default CSS -->
|
|
409
|
+
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
|
410
|
+
|
|
411
|
+
<!-- Custom CSS -->
|
|
412
|
+
<% if (layout && layout.css) { %>
|
|
413
|
+
<% layout.css.forEach(href => { %>
|
|
414
|
+
<link rel="stylesheet" href="<%= href %>">
|
|
415
|
+
<% }); %>
|
|
416
|
+
<% } %>
|
|
417
|
+
|
|
418
|
+
<!-- Custom head section -->
|
|
419
|
+
<% if (sections && sections.head) { %>
|
|
420
|
+
<%- sections.head %>
|
|
421
|
+
<% } %>
|
|
422
|
+
</head>
|
|
423
|
+
<body class="<%= layout && layout.bodyClass || '' %>">
|
|
424
|
+
<!-- Navigation -->
|
|
425
|
+
<nav class="navbar navbar-expand-lg navbar-dark bg-primary">
|
|
426
|
+
<div class="container">
|
|
427
|
+
<a class="navbar-brand" href="/">🚀 Veko.js</a>
|
|
428
|
+
<div class="navbar-nav ms-auto">
|
|
429
|
+
<a class="nav-link" href="/">Home</a>
|
|
430
|
+
<a class="nav-link" href="/about">About</a>
|
|
431
|
+
<a class="nav-link" href="/contact">Contact</a>
|
|
432
|
+
</div>
|
|
433
|
+
</div>
|
|
434
|
+
</nav>
|
|
435
|
+
|
|
436
|
+
<!-- Custom header -->
|
|
437
|
+
<% if (sections && sections.header) { %>
|
|
438
|
+
<header>
|
|
439
|
+
<%- sections.header %>
|
|
440
|
+
</header>
|
|
441
|
+
<% } %>
|
|
442
|
+
|
|
443
|
+
<!-- Main content -->
|
|
444
|
+
<main class="container my-4">
|
|
445
|
+
<%- sections.content %>
|
|
446
|
+
</main>
|
|
447
|
+
|
|
448
|
+
<!-- Footer -->
|
|
449
|
+
<footer class="bg-dark text-light py-4 mt-5">
|
|
450
|
+
<div class="container">
|
|
451
|
+
<% if (sections && sections.footer) { %>
|
|
452
|
+
<%- sections.footer %>
|
|
453
|
+
<% } else { %>
|
|
454
|
+
<p>© <%= new Date().getFullYear() %> - Powered by Veko.js ⚡</p>
|
|
455
|
+
<% } %>
|
|
456
|
+
</div>
|
|
457
|
+
</footer>
|
|
458
|
+
|
|
459
|
+
<!-- JavaScript -->
|
|
460
|
+
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
|
461
|
+
|
|
462
|
+
<!-- Custom JS -->
|
|
463
|
+
<% if (layout && layout.js) { %>
|
|
464
|
+
<% layout.js.forEach(src => { %>
|
|
465
|
+
<script src="<%= src %>"></script>
|
|
466
|
+
<% }); %>
|
|
467
|
+
<% } %>
|
|
468
|
+
|
|
469
|
+
<!-- Custom scripts section -->
|
|
470
|
+
<% if (sections && sections.scripts) { %>
|
|
471
|
+
<%- sections.scripts %>
|
|
472
|
+
<% } %>
|
|
473
|
+
</body>
|
|
474
|
+
</html>
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
### Using Layouts in Views
|
|
478
|
+
|
|
479
|
+
**views/home.ejs:**
|
|
480
|
+
|
|
481
|
+
```html
|
|
482
|
+
<% layout.title('Home - My App') %>
|
|
483
|
+
<% layout.meta('description', 'Welcome to my Veko.js application') %>
|
|
484
|
+
<% layout.css('/css/home.css') %>
|
|
485
|
+
|
|
486
|
+
<% layout.section('header', `
|
|
487
|
+
<div class="jumbotron bg-gradient text-center text-white p-5">
|
|
488
|
+
<h1>🎉 Welcome to Veko.js</h1>
|
|
489
|
+
<p>Ultra-modern Node.js framework</p>
|
|
490
|
+
</div>
|
|
491
|
+
`) %>
|
|
492
|
+
|
|
493
|
+
<div class="row">
|
|
494
|
+
<div class="col-md-4">
|
|
495
|
+
<div class="card">
|
|
496
|
+
<div class="card-body">
|
|
497
|
+
<h3>🚀 Fast</h3>
|
|
498
|
+
<p>Optimized performance and ultra-fast loading times.</p>
|
|
499
|
+
</div>
|
|
500
|
+
</div>
|
|
501
|
+
</div>
|
|
502
|
+
<div class="col-md-4">
|
|
503
|
+
<div class="card">
|
|
504
|
+
<div class="card-body">
|
|
505
|
+
<h3>💎 Modern</h3>
|
|
506
|
+
<p>Cutting-edge technologies and modern architecture.</p>
|
|
507
|
+
</div>
|
|
508
|
+
</div>
|
|
509
|
+
</div>
|
|
510
|
+
<div class="col-md-4">
|
|
511
|
+
<div class="card">
|
|
512
|
+
<div class="card-body">
|
|
513
|
+
<h3>🎨 Flexible</h3>
|
|
514
|
+
<p>Advanced layout system and reusable components.</p>
|
|
515
|
+
</div>
|
|
516
|
+
</div>
|
|
517
|
+
</div>
|
|
518
|
+
</div>
|
|
519
|
+
|
|
520
|
+
<% layout.section('scripts', `
|
|
521
|
+
<script>
|
|
522
|
+
console.log('✨ Page loaded with Veko.js!');
|
|
523
|
+
|
|
524
|
+
// Card hover animations
|
|
525
|
+
document.querySelectorAll('.card').forEach(card => {
|
|
526
|
+
card.addEventListener('mouseenter', function() {
|
|
527
|
+
this.style.transform = 'translateY(-5px)';
|
|
528
|
+
this.style.transition = 'transform 0.3s ease';
|
|
529
|
+
});
|
|
530
|
+
|
|
531
|
+
card.addEventListener('mouseleave', function() {
|
|
532
|
+
this.style.transform = 'translateY(0)';
|
|
533
|
+
});
|
|
534
|
+
});
|
|
535
|
+
</script>
|
|
536
|
+
`) %>
|
|
537
|
+
```
|
|
538
|
+
|
|
539
|
+
### Layout Helpers
|
|
540
|
+
|
|
541
|
+
Available helpers in your views:
|
|
542
|
+
|
|
543
|
+
```javascript
|
|
544
|
+
// Set page title
|
|
545
|
+
<% layout.title('My Page Title') %>
|
|
546
|
+
|
|
547
|
+
// Add meta tags
|
|
548
|
+
<% layout.meta('description', 'Page description') %>
|
|
549
|
+
<% layout.meta('keywords', 'veko, nodejs, framework') %>
|
|
550
|
+
|
|
551
|
+
// Add CSS files
|
|
552
|
+
<% layout.css('/css/custom.css') %>
|
|
553
|
+
<% layout.css('https://cdn.example.com/lib.css') %>
|
|
554
|
+
|
|
555
|
+
// Add JavaScript files
|
|
556
|
+
<% layout.js('/js/custom.js') %>
|
|
557
|
+
<% layout.js('https://cdn.example.com/lib.js') %>
|
|
558
|
+
|
|
559
|
+
// Define sections
|
|
560
|
+
<% layout.section('sectionName', 'content') %>
|
|
561
|
+
<% layout.section('header', `
|
|
562
|
+
<div class="custom-header">
|
|
563
|
+
<h1>Custom Header</h1>
|
|
564
|
+
</div>
|
|
565
|
+
`) %>
|
|
566
|
+
```
|
|
567
|
+
|
|
568
|
+
### Layout Management API
|
|
569
|
+
|
|
570
|
+
```javascript
|
|
571
|
+
// Create a new layout
|
|
572
|
+
app.createLayout('admin', customLayoutContent);
|
|
573
|
+
|
|
574
|
+
// Delete a layout
|
|
575
|
+
app.deleteLayout('admin');
|
|
576
|
+
|
|
577
|
+
// List all available layouts
|
|
578
|
+
const layouts = app.listLayouts();
|
|
579
|
+
|
|
580
|
+
// Reload layouts in development mode
|
|
581
|
+
app.reloadLayouts();
|
|
582
|
+
|
|
583
|
+
// Render with specific layout
|
|
584
|
+
app.renderWithCustomLayout(res, 'view', 'admin', data);
|
|
585
|
+
|
|
586
|
+
// Render without layout
|
|
587
|
+
app.renderWithoutLayout(res, 'view', data);
|
|
588
|
+
```
|
|
589
|
+
|
|
590
|
+
## 🔌 Plugin System
|
|
591
|
+
|
|
592
|
+
Veko.js includes a powerful and extensible plugin system that allows adding functionality without modifying the framework core.
|
|
593
|
+
|
|
594
|
+
### Plugin Configuration
|
|
595
|
+
|
|
596
|
+
```javascript
|
|
597
|
+
const app = new App({
|
|
598
|
+
plugins: {
|
|
599
|
+
enabled: true, // Enable plugin system
|
|
600
|
+
autoLoad: true, // Automatic plugin loading
|
|
601
|
+
pluginsDir: 'plugins' // Plugin directory
|
|
602
|
+
}
|
|
603
|
+
});
|
|
604
|
+
```
|
|
605
|
+
|
|
606
|
+
### Plugin Structure
|
|
607
|
+
|
|
608
|
+
```javascript
|
|
609
|
+
// plugins/my-plugin.js
|
|
610
|
+
module.exports = {
|
|
611
|
+
name: 'my-plugin',
|
|
612
|
+
version: '1.0.0',
|
|
613
|
+
description: 'Description of my plugin',
|
|
614
|
+
author: 'My Name',
|
|
615
|
+
|
|
616
|
+
// Dependencies (other required plugins)
|
|
617
|
+
dependencies: ['other-plugin'],
|
|
618
|
+
|
|
619
|
+
// Default configuration
|
|
620
|
+
defaultConfig: {
|
|
621
|
+
enabled: true,
|
|
622
|
+
option1: 'value'
|
|
623
|
+
},
|
|
624
|
+
|
|
625
|
+
// Method called during loading
|
|
626
|
+
async load(app, config, context) {
|
|
627
|
+
// Your initialization code
|
|
628
|
+
context.log('success', 'Plugin loaded!');
|
|
629
|
+
|
|
630
|
+
// Add a route
|
|
631
|
+
context.addRoute('get', '/my-plugin', (req, res) => {
|
|
632
|
+
res.json({ message: 'Hello from plugin!' });
|
|
633
|
+
});
|
|
634
|
+
|
|
635
|
+
// Add middleware
|
|
636
|
+
context.addMiddleware((req, res, next) => {
|
|
637
|
+
req.pluginData = { source: 'my-plugin' };
|
|
638
|
+
next();
|
|
639
|
+
});
|
|
640
|
+
|
|
641
|
+
// Add hooks
|
|
642
|
+
context.hook('route:create', (method, path) => {
|
|
643
|
+
context.log('info', `Route created: ${method} ${path}`);
|
|
644
|
+
});
|
|
645
|
+
},
|
|
646
|
+
|
|
647
|
+
// Method called during unloading
|
|
648
|
+
async unload(app, config) {
|
|
649
|
+
console.log('Plugin unloaded');
|
|
650
|
+
},
|
|
651
|
+
|
|
652
|
+
// Activation/deactivation
|
|
653
|
+
async activate(app, config) {
|
|
654
|
+
console.log('Plugin activated');
|
|
655
|
+
},
|
|
656
|
+
|
|
657
|
+
async deactivate(app, config) {
|
|
658
|
+
console.log('Plugin deactivated');
|
|
659
|
+
}
|
|
660
|
+
};
|
|
661
|
+
```
|
|
662
|
+
|
|
663
|
+
### Plugin Context API
|
|
664
|
+
|
|
665
|
+
Each plugin receives a rich context with numerous functionalities:
|
|
666
|
+
|
|
667
|
+
```javascript
|
|
668
|
+
async load(app, config, context) {
|
|
669
|
+
// === HOOKS ===
|
|
670
|
+
// Add a hook
|
|
671
|
+
context.hook('hookName', callback);
|
|
672
|
+
context.removeHook('hookName', callback);
|
|
673
|
+
|
|
674
|
+
// === ROUTES AND MIDDLEWARE ===
|
|
675
|
+
// Add a route
|
|
676
|
+
context.addRoute('get', '/path', handler);
|
|
677
|
+
|
|
678
|
+
// Add middleware
|
|
679
|
+
context.addMiddleware(middlewareFunction);
|
|
680
|
+
|
|
681
|
+
// Add CLI command
|
|
682
|
+
context.addCommand('name', handler, 'description');
|
|
683
|
+
|
|
684
|
+
// === LOGGING ===
|
|
685
|
+
// Log with automatic plugin name
|
|
686
|
+
context.log('success', 'Message', 'details');
|
|
687
|
+
|
|
688
|
+
// === ACCESS TO OTHER PLUGINS ===
|
|
689
|
+
// Get another plugin
|
|
690
|
+
const otherPlugin = context.getPlugin('other-plugin');
|
|
691
|
+
|
|
692
|
+
// List all plugins
|
|
693
|
+
const plugins = context.listPlugins();
|
|
694
|
+
|
|
695
|
+
// === CONFIGURATION ===
|
|
696
|
+
// Read config
|
|
697
|
+
const config = context.getConfig();
|
|
698
|
+
|
|
699
|
+
// Modify config
|
|
700
|
+
context.updateConfig({ newOption: 'value' });
|
|
701
|
+
|
|
702
|
+
// === PERSISTENT STORAGE ===
|
|
703
|
+
// Save data
|
|
704
|
+
context.storage.set('key', 'value');
|
|
705
|
+
context.storage.set({ key1: 'value1', key2: 'value2' });
|
|
706
|
+
|
|
707
|
+
// Read data
|
|
708
|
+
const value = context.storage.get('key', 'defaultValue');
|
|
709
|
+
const allData = context.storage.get();
|
|
710
|
+
|
|
711
|
+
// Delete data
|
|
712
|
+
context.storage.delete('key');
|
|
713
|
+
context.storage.clear();
|
|
714
|
+
}
|
|
715
|
+
```
|
|
716
|
+
|
|
717
|
+
### Plugin Management
|
|
718
|
+
|
|
719
|
+
```javascript
|
|
720
|
+
// Load plugin manually
|
|
721
|
+
await app.loadPlugin('plugin-name', { option: 'value' });
|
|
722
|
+
|
|
723
|
+
// Unload plugin
|
|
724
|
+
await app.unloadPlugin('plugin-name');
|
|
725
|
+
|
|
726
|
+
// Reload plugin
|
|
727
|
+
await app.reloadPlugin('plugin-name', { newConfig: true });
|
|
728
|
+
|
|
729
|
+
// List plugins
|
|
730
|
+
const plugins = app.listPlugins();
|
|
731
|
+
|
|
732
|
+
// Enable/disable plugin
|
|
733
|
+
await app.plugins.togglePlugin('plugin-name', true);
|
|
734
|
+
|
|
735
|
+
// Statistics
|
|
736
|
+
const stats = app.plugins.getStats();
|
|
737
|
+
console.log(`${stats.active}/${stats.total} plugins active`);
|
|
738
|
+
```
|
|
739
|
+
|
|
740
|
+
### Available Hooks
|
|
741
|
+
|
|
742
|
+
The plugin system provides numerous built-in hooks:
|
|
743
|
+
|
|
744
|
+
```javascript
|
|
745
|
+
// Application hooks
|
|
746
|
+
app:init // Application initialization
|
|
747
|
+
app:start // Server startup
|
|
748
|
+
app:stop // Server shutdown
|
|
749
|
+
|
|
750
|
+
// Route hooks
|
|
751
|
+
route:load // Route loading
|
|
752
|
+
route:create // Route creation
|
|
753
|
+
route:created // Route created (after)
|
|
754
|
+
route:delete // Route deletion
|
|
755
|
+
|
|
756
|
+
// Request hooks
|
|
757
|
+
request:start // Request start
|
|
758
|
+
request:end // Request end
|
|
759
|
+
|
|
760
|
+
// WebSocket hooks
|
|
761
|
+
websocket:connect // WebSocket connection
|
|
762
|
+
websocket:disconnect // WebSocket disconnection
|
|
763
|
+
|
|
764
|
+
// File hooks
|
|
765
|
+
file:change // File modification
|
|
766
|
+
|
|
767
|
+
// Plugin hooks
|
|
768
|
+
plugin:load // Plugin loading
|
|
769
|
+
plugin:unload // Plugin unloading
|
|
770
|
+
|
|
771
|
+
// Error hooks
|
|
772
|
+
error:handle // Error handling
|
|
773
|
+
```
|
|
774
|
+
|
|
775
|
+
### Plugin Examples
|
|
776
|
+
|
|
777
|
+
#### Database Plugin
|
|
778
|
+
|
|
779
|
+
```javascript
|
|
780
|
+
// plugins/database.js
|
|
781
|
+
const mongoose = require('mongoose');
|
|
782
|
+
|
|
783
|
+
module.exports = {
|
|
784
|
+
name: 'database',
|
|
785
|
+
version: '1.0.0',
|
|
786
|
+
description: 'MongoDB connection plugin',
|
|
787
|
+
|
|
788
|
+
defaultConfig: {
|
|
789
|
+
uri: 'mongodb://localhost:27017/myapp',
|
|
790
|
+
options: {
|
|
791
|
+
useNewUrlParser: true,
|
|
792
|
+
useUnifiedTopology: true
|
|
793
|
+
}
|
|
794
|
+
},
|
|
795
|
+
|
|
796
|
+
async load(app, config, context) {
|
|
797
|
+
try {
|
|
798
|
+
await mongoose.connect(config.uri, config.options);
|
|
799
|
+
context.log('success', 'MongoDB connection established');
|
|
800
|
+
|
|
801
|
+
// Expose mongoose in app
|
|
802
|
+
app.db = mongoose;
|
|
803
|
+
|
|
804
|
+
// Shutdown hook
|
|
805
|
+
context.hook('app:stop', async () => {
|
|
806
|
+
await mongoose.disconnect();
|
|
807
|
+
context.log('info', 'MongoDB connection closed');
|
|
808
|
+
});
|
|
809
|
+
|
|
810
|
+
} catch (error) {
|
|
811
|
+
context.log('error', 'MongoDB connection error', error.message);
|
|
812
|
+
throw error;
|
|
813
|
+
}
|
|
814
|
+
},
|
|
815
|
+
|
|
816
|
+
async unload() {
|
|
817
|
+
await mongoose.disconnect();
|
|
818
|
+
}
|
|
819
|
+
};
|
|
820
|
+
```
|
|
821
|
+
|
|
822
|
+
#### Authentication Plugin
|
|
823
|
+
|
|
824
|
+
```javascript
|
|
825
|
+
// plugins/auth.js
|
|
826
|
+
const jwt = require('jsonwebtoken');
|
|
827
|
+
|
|
828
|
+
module.exports = {
|
|
829
|
+
name: 'auth',
|
|
830
|
+
version: '1.0.0',
|
|
831
|
+
description: 'JWT authentication plugin',
|
|
832
|
+
dependencies: ['database'],
|
|
833
|
+
|
|
834
|
+
defaultConfig: {
|
|
835
|
+
secret: 'your-secret-key',
|
|
836
|
+
expiresIn: '24h'
|
|
837
|
+
},
|
|
838
|
+
|
|
839
|
+
async load(app, config, context) {
|
|
840
|
+
// Authentication middleware
|
|
841
|
+
const authMiddleware = (req, res, next) => {
|
|
842
|
+
const token = req.headers.authorization?.split(' ')[1];
|
|
843
|
+
|
|
844
|
+
if (!token) {
|
|
845
|
+
return res.status(401).json({ error: 'Missing token' });
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
try {
|
|
849
|
+
const decoded = jwt.verify(token, config.secret);
|
|
850
|
+
req.user = decoded;
|
|
851
|
+
next();
|
|
852
|
+
} catch (error) {
|
|
853
|
+
res.status(401).json({ error: 'Invalid token' });
|
|
854
|
+
}
|
|
855
|
+
};
|
|
856
|
+
|
|
857
|
+
// Authentication routes
|
|
858
|
+
context.addRoute('post', '/auth/login', async (req, res) => {
|
|
859
|
+
const { email, password } = req.body;
|
|
860
|
+
|
|
861
|
+
// User validation (example)
|
|
862
|
+
const user = await validateUser(email, password);
|
|
863
|
+
|
|
864
|
+
if (user) {
|
|
865
|
+
const token = jwt.sign(
|
|
866
|
+
{ id: user.id, email: user.email },
|
|
867
|
+
config.secret,
|
|
868
|
+
{ expiresIn: config.expiresIn }
|
|
869
|
+
);
|
|
870
|
+
|
|
871
|
+
res.json({ token, user });
|
|
872
|
+
} else {
|
|
873
|
+
res.status(401).json({ error: 'Invalid credentials' });
|
|
874
|
+
}
|
|
875
|
+
});
|
|
876
|
+
|
|
877
|
+
context.addRoute('get', '/auth/profile', authMiddleware, (req, res) => {
|
|
878
|
+
res.json({ user: req.user });
|
|
879
|
+
});
|
|
880
|
+
|
|
881
|
+
// Expose middleware in app
|
|
882
|
+
app.authMiddleware = authMiddleware;
|
|
883
|
+
|
|
884
|
+
context.log('success', 'Authentication plugin loaded');
|
|
885
|
+
}
|
|
886
|
+
};
|
|
887
|
+
```
|
|
888
|
+
|
|
889
|
+
#### Cache Plugin
|
|
890
|
+
|
|
891
|
+
```javascript
|
|
892
|
+
// plugins/cache.js
|
|
893
|
+
const NodeCache = require('node-cache');
|
|
894
|
+
|
|
895
|
+
module.exports = {
|
|
896
|
+
name: 'cache',
|
|
897
|
+
version: '1.0.0',
|
|
898
|
+
description: 'In-memory cache plugin',
|
|
899
|
+
|
|
900
|
+
defaultConfig: {
|
|
901
|
+
stdTTL: 600, // 10 minutes
|
|
902
|
+
checkperiod: 120
|
|
903
|
+
},
|
|
904
|
+
|
|
905
|
+
async load(app, config, context) {
|
|
906
|
+
const cache = new NodeCache(config);
|
|
907
|
+
|
|
908
|
+
// Cache middleware
|
|
909
|
+
const cacheMiddleware = (duration = 300) => {
|
|
910
|
+
return (req, res, next) => {
|
|
911
|
+
const key = req.originalUrl;
|
|
912
|
+
const cached = cache.get(key);
|
|
913
|
+
|
|
914
|
+
if (cached) {
|
|
915
|
+
context.log('info', 'Cache hit', key);
|
|
916
|
+
return res.json(cached);
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
const originalSend = res.json;
|
|
920
|
+
res.json = function(data) {
|
|
921
|
+
cache.set(key, data, duration);
|
|
922
|
+
context.log('info', 'Cache set', key);
|
|
923
|
+
return originalSend.call(this, data);
|
|
924
|
+
};
|
|
925
|
+
|
|
926
|
+
next();
|
|
927
|
+
};
|
|
928
|
+
};
|
|
929
|
+
|
|
930
|
+
// Cache API
|
|
931
|
+
app.cache = {
|
|
932
|
+
get: (key) => cache.get(key),
|
|
933
|
+
set: (key, value, ttl) => cache.set(key, value, ttl),
|
|
934
|
+
del: (key) => cache.del(key),
|
|
935
|
+
flush: () => cache.flushAll(),
|
|
936
|
+
middleware: cacheMiddleware,
|
|
937
|
+
stats: () => cache.getStats()
|
|
938
|
+
};
|
|
939
|
+
|
|
940
|
+
// Stats route
|
|
941
|
+
context.addRoute('get', '/cache/stats', (req, res) => {
|
|
942
|
+
res.json(cache.getStats());
|
|
943
|
+
});
|
|
944
|
+
|
|
945
|
+
context.log('success', 'Cache plugin loaded');
|
|
946
|
+
}
|
|
947
|
+
};
|
|
948
|
+
```
|
|
949
|
+
|
|
950
|
+
### Inline Plugin Creation
|
|
951
|
+
|
|
952
|
+
```javascript
|
|
953
|
+
// Create a simple plugin directly in code
|
|
954
|
+
const simplePlugin = app.plugins.createSimplePlugin(
|
|
955
|
+
'logger-plugin',
|
|
956
|
+
(app, config, context) => {
|
|
957
|
+
// Hook to log all requests
|
|
958
|
+
context.hook('request:start', (req) => {
|
|
959
|
+
context.log('info', `${req.method} ${req.url}`);
|
|
960
|
+
});
|
|
961
|
+
|
|
962
|
+
// Debug route
|
|
963
|
+
context.addRoute('get', '/debug/logs', (req, res) => {
|
|
964
|
+
res.json({
|
|
965
|
+
plugin: 'logger-plugin',
|
|
966
|
+
requests: context.storage.get('requestCount', 0)
|
|
967
|
+
});
|
|
968
|
+
});
|
|
969
|
+
},
|
|
970
|
+
{
|
|
971
|
+
version: '1.0.0',
|
|
972
|
+
description: 'Request logging plugin'
|
|
973
|
+
}
|
|
974
|
+
);
|
|
975
|
+
|
|
976
|
+
await app.loadPlugin(simplePlugin);
|
|
977
|
+
```
|
|
978
|
+
|
|
979
|
+
## 🛣️ Dynamic Route Management
|
|
980
|
+
|
|
981
|
+
Veko.js allows creating, modifying, and deleting routes dynamically during runtime.
|
|
982
|
+
|
|
983
|
+
### Dynamic Route Creation
|
|
984
|
+
|
|
985
|
+
```javascript
|
|
986
|
+
// Create route on-the-fly
|
|
987
|
+
app.createRoute('get', '/api/dynamic', (req, res) => {
|
|
988
|
+
res.json({ message: 'Route created dynamically!' });
|
|
989
|
+
});
|
|
990
|
+
|
|
991
|
+
// With middleware
|
|
992
|
+
app.createRoute('post', '/api/secure', [
|
|
993
|
+
authMiddleware,
|
|
994
|
+
validationMiddleware,
|
|
995
|
+
(req, res) => {
|
|
996
|
+
res.json({ success: true });
|
|
997
|
+
}
|
|
998
|
+
]);
|
|
999
|
+
|
|
1000
|
+
// Update existing route
|
|
1001
|
+
app.updateRoute('get', '/api/dynamic', (req, res) => {
|
|
1002
|
+
res.json({ message: 'Route updated!' });
|
|
1003
|
+
});
|
|
1004
|
+
|
|
1005
|
+
// Delete route
|
|
1006
|
+
app.deleteRoute('get', '/api/dynamic');
|
|
1007
|
+
```
|
|
1008
|
+
|
|
1009
|
+
### Creating Route Files
|
|
1010
|
+
|
|
1011
|
+
```javascript
|
|
1012
|
+
// Create physical route file
|
|
1013
|
+
app.createRouteFile('/users/profile', {
|
|
1014
|
+
get: (req, res) => {
|
|
1015
|
+
res.render('profile', { user: req.user });
|
|
1016
|
+
},
|
|
1017
|
+
post: (req, res) => {
|
|
1018
|
+
// Profile update
|
|
1019
|
+
res.json({ updated: true });
|
|
1020
|
+
}
|
|
1021
|
+
}, {
|
|
1022
|
+
description: 'User profile management',
|
|
1023
|
+
middleware: [authMiddleware]
|
|
1024
|
+
});
|
|
1025
|
+
|
|
1026
|
+
// Delete route file
|
|
1027
|
+
app.deleteRouteFile('/users/profile');
|
|
1028
|
+
|
|
1029
|
+
// List all routes
|
|
1030
|
+
const routes = app.listRoutes();
|
|
1031
|
+
console.log(routes);
|
|
1032
|
+
```
|
|
1033
|
+
|
|
1034
|
+
## 🎨 Beautiful Logging
|
|
1035
|
+
|
|
1036
|
+
Veko.js offers a revolutionary logging system with:
|
|
1037
|
+
|
|
1038
|
+
- 🕒 **Formatted timestamps**
|
|
1039
|
+
- 🎯 **Colored badges** with Unicode icons
|
|
1040
|
+
- 📊 **Specialized log types**
|
|
1041
|
+
- 🌈 **Optimized ANSI colors**
|
|
1042
|
+
|
|
1043
|
+
### Available Log Types
|
|
1044
|
+
|
|
1045
|
+
```javascript
|
|
1046
|
+
app.log('success', 'Operation successful', '✅ Additional details');
|
|
1047
|
+
app.log('error', 'Critical error', '❌ Error message');
|
|
1048
|
+
app.log('warning', 'Warning', '⚠️ Warning message');
|
|
1049
|
+
app.log('info', 'Information', 'ℹ️ General info');
|
|
1050
|
+
app.log('server', 'Server', '🚀 Server startup');
|
|
1051
|
+
app.log('route', 'Route', '🌐 New route');
|
|
1052
|
+
app.log('dev', 'Development', '🛠️ Dev mode');
|
|
1053
|
+
app.log('file', 'File', '📁 File modification');
|
|
1054
|
+
app.log('reload', 'Reload', '🔄 Hot reload');
|
|
1055
|
+
app.log('create', 'Creation', '➕ Element created');
|
|
1056
|
+
app.log('delete', 'Deletion', '🗑️ Element deleted');
|
|
1057
|
+
app.log('install', 'Installation', '📦 Module installed');
|
|
1058
|
+
```
|
|
1059
|
+
|
|
1060
|
+
### Console Output Example
|
|
1061
|
+
|
|
1062
|
+
```
|
|
1063
|
+
[2:32:15 PM] ✨ Server started successfully 🌐 http://localhost:3000
|
|
1064
|
+
[2:32:16 PM] 🛠️ Development mode active 🔥 Intelligent hot reload on port 3008
|
|
1065
|
+
[2:32:16 PM] 🔌 Plugin database loaded database v1.0.0
|
|
1066
|
+
[2:32:16 PM] 🔌 Plugin auth loaded auth v1.0.0
|
|
1067
|
+
[2:32:17 PM] 💎 Plugin system 🔌 2/2 plugins active
|
|
1068
|
+
[2:32:17 PM] 🌐 Route loaded index.js → /
|
|
1069
|
+
[2:32:18 PM] ➕ Route created dynamically GET /api/users
|
|
1070
|
+
[2:32:19 PM] 📁 File modified 📝 routes/users.js
|
|
1071
|
+
[2:32:19 PM] 🔄 Route reloaded 🔄 routes/users.js
|
|
1072
|
+
```
|
|
1073
|
+
|
|
1074
|
+
## 🔥 Intelligent Hot Reload
|
|
1075
|
+
|
|
1076
|
+
### Selective Reload by File Type
|
|
1077
|
+
|
|
1078
|
+
- **Modified routes** → Route-only reload
|
|
1079
|
+
- **Modified views** → Light template reload
|
|
1080
|
+
- **Static files** → Full browser reload
|
|
1081
|
+
- **Modified plugins** → Specific plugin reload
|
|
1082
|
+
- **Modified layouts** → Layout cache clear and reload
|
|
1083
|
+
|
|
1084
|
+
### Hot Reload Configuration
|
|
1085
|
+
|
|
1086
|
+
```javascript
|
|
1087
|
+
const app = new App({
|
|
1088
|
+
isDev: true,
|
|
1089
|
+
wsPort: 3008, // WebSocket port
|
|
1090
|
+
watchDirs: ['views', 'routes', 'public', 'src', 'plugins'], // Watched directories
|
|
1091
|
+
prefetch: {
|
|
1092
|
+
enabled: true,
|
|
1093
|
+
maxConcurrent: 3,
|
|
1094
|
+
notifyUser: true,
|
|
1095
|
+
cacheRoutes: true,
|
|
1096
|
+
prefetchDelay: 1000
|
|
1097
|
+
}
|
|
1098
|
+
});
|
|
1099
|
+
```
|
|
1100
|
+
|
|
1101
|
+
### Automatic Client Script
|
|
1102
|
+
|
|
1103
|
+
The hot reload script is automatically injected into your pages:
|
|
1104
|
+
|
|
1105
|
+
```javascript
|
|
1106
|
+
// Automatically injected before </body>
|
|
1107
|
+
<script>
|
|
1108
|
+
(function() {
|
|
1109
|
+
const ws = new WebSocket('ws://localhost:3008');
|
|
1110
|
+
|
|
1111
|
+
ws.onopen = () => console.log('🔗 Veko.js connected');
|
|
1112
|
+
ws.onmessage = (event) => {
|
|
1113
|
+
const data = JSON.parse(event.data);
|
|
1114
|
+
|
|
1115
|
+
switch(data.type) {
|
|
1116
|
+
case 'reload':
|
|
1117
|
+
console.log('🔄 Full reload...');
|
|
1118
|
+
setTimeout(() => window.location.reload(), 300);
|
|
1119
|
+
break;
|
|
1120
|
+
|
|
1121
|
+
case 'route-reload':
|
|
1122
|
+
console.log('🔄 Route reloaded:', data.route);
|
|
1123
|
+
if (window.location.pathname === data.route) {
|
|
1124
|
+
setTimeout(() => window.location.reload(), 300);
|
|
1125
|
+
}
|
|
1126
|
+
break;
|
|
1127
|
+
|
|
1128
|
+
case 'route-created':
|
|
1129
|
+
console.log('➕ Route created:', data.method, data.path);
|
|
1130
|
+
break;
|
|
1131
|
+
|
|
1132
|
+
case 'route-deleted':
|
|
1133
|
+
console.log('🗑️ Route deleted:', data.method, data.path);
|
|
1134
|
+
break;
|
|
1135
|
+
|
|
1136
|
+
case 'view-reload':
|
|
1137
|
+
console.log('🎨 View reloaded:', data.file);
|
|
1138
|
+
setTimeout(() => window.location.reload(), 300);
|
|
1139
|
+
break;
|
|
1140
|
+
|
|
1141
|
+
case 'layout-reload':
|
|
1142
|
+
console.log('🎨 Layout reloaded:', data.file);
|
|
1143
|
+
setTimeout(() => window.location.reload(), 300);
|
|
1144
|
+
break;
|
|
1145
|
+
|
|
1146
|
+
case 'plugin-reload':
|
|
1147
|
+
console.log('🔌 Plugin reloaded:', data.plugin);
|
|
1148
|
+
break;
|
|
1149
|
+
}
|
|
1150
|
+
};
|
|
1151
|
+
})();
|
|
1152
|
+
</script>
|
|
1153
|
+
```
|
|
1154
|
+
|
|
1155
|
+
## 📁 Project Structure
|
|
1156
|
+
|
|
1157
|
+
```
|
|
1158
|
+
my-project/
|
|
1159
|
+
├── routes/
|
|
1160
|
+
│ ├── index.js # Route: /
|
|
1161
|
+
│ ├── about.js # Route: /about
|
|
1162
|
+
│ ├── users/
|
|
1163
|
+
│ │ ├── index.js # Route: /users
|
|
1164
|
+
│ │ └── [id].js # Route: /users/:id
|
|
1165
|
+
│ └── api/
|
|
1166
|
+
│ └── products.js # Route: /api/products
|
|
1167
|
+
├── views/
|
|
1168
|
+
│ ├── layouts/ # Layout templates
|
|
1169
|
+
│ │ ├── main.ejs # Main layout
|
|
1170
|
+
│ │ └── admin.ejs # Admin layout
|
|
1171
|
+
│ ├── partials/ # Reusable components
|
|
1172
|
+
│ ├── index.ejs
|
|
1173
|
+
│ └── about.ejs
|
|
1174
|
+
├── public/
|
|
1175
|
+
│ ├── css/
|
|
1176
|
+
│ ├── js/
|
|
1177
|
+
│ └── images/
|
|
1178
|
+
├── plugins/ # Custom plugins
|
|
1179
|
+
│ ├── database.js
|
|
1180
|
+
│ ├── auth.js
|
|
1181
|
+
│ └── cache.js
|
|
1182
|
+
├── data/ # Plugin data
|
|
1183
|
+
│ └── plugins/
|
|
1184
|
+
│ ├── database.json
|
|
1185
|
+
│ └── auth.json
|
|
1186
|
+
├── config/ # Configuration files
|
|
1187
|
+
│ └── app.js
|
|
1188
|
+
├── middleware/ # Custom middleware
|
|
1189
|
+
└── package.json
|
|
1190
|
+
```
|
|
1191
|
+
|
|
1192
|
+
## 🛣️ Route System
|
|
1193
|
+
|
|
1194
|
+
### Automatic Routes
|
|
1195
|
+
|
|
1196
|
+
Veko.js automatically loads all routes from the `routes/` folder. The filename determines the URL:
|
|
1197
|
+
|
|
1198
|
+
- `routes/index.js` → `/`
|
|
1199
|
+
- `routes/about.js` → `/about`
|
|
1200
|
+
- `routes/users/profile.js` → `/users/profile`
|
|
1201
|
+
- `routes/api/users.js` → `/api/users`
|
|
1202
|
+
|
|
1203
|
+
### Dynamic Parameters
|
|
1204
|
+
|
|
1205
|
+
Use brackets for parameters:
|
|
1206
|
+
- `routes/users/[id].js` → `/users/:id`
|
|
1207
|
+
- `routes/posts/[slug]/comments.js` → `/posts/:slug/comments`
|
|
1208
|
+
|
|
1209
|
+
### Route File Formats
|
|
1210
|
+
|
|
1211
|
+
#### HTTP Methods (Recommended)
|
|
1212
|
+
|
|
1213
|
+
```javascript
|
|
1214
|
+
// routes/users.js
|
|
1215
|
+
module.exports = {
|
|
1216
|
+
// GET /users
|
|
1217
|
+
get: (req, res) => {
|
|
1218
|
+
res.render('users', { users: [] });
|
|
1219
|
+
},
|
|
1220
|
+
|
|
1221
|
+
// POST /users
|
|
1222
|
+
post: (req, res) => {
|
|
1223
|
+
const newUser = req.body;
|
|
1224
|
+
res.status(201).json({ user: newUser });
|
|
1225
|
+
},
|
|
1226
|
+
|
|
1227
|
+
// PUT /users
|
|
1228
|
+
put: (req, res) => {
|
|
1229
|
+
res.json({ message: 'User updated' });
|
|
1230
|
+
},
|
|
1231
|
+
|
|
1232
|
+
// DELETE /users
|
|
1233
|
+
delete: (req, res) => {
|
|
1234
|
+
res.json({ message: 'User deleted' });
|
|
1235
|
+
}
|
|
1236
|
+
};
|
|
1237
|
+
```
|
|
1238
|
+
|
|
1239
|
+
#### Custom Function
|
|
1240
|
+
|
|
1241
|
+
```javascript
|
|
1242
|
+
// routes/custom.js
|
|
1243
|
+
module.exports = (app) => {
|
|
1244
|
+
app.get('/custom', (req, res) => {
|
|
1245
|
+
res.json({ message: 'Custom route' });
|
|
1246
|
+
});
|
|
1247
|
+
|
|
1248
|
+
app.post('/custom/:action', middleware, (req, res) => {
|
|
1249
|
+
res.json({ action: req.params.action });
|
|
1250
|
+
});
|
|
1251
|
+
};
|
|
1252
|
+
```
|
|
1253
|
+
|
|
1254
|
+
## ⚡ Ultra-Modern Development Mode
|
|
1255
|
+
|
|
1256
|
+
Development mode includes:
|
|
1257
|
+
|
|
1258
|
+
- 🔥 **Intelligent Hot Reload** - Selective reload by file type
|
|
1259
|
+
- 📡 **WebSocket** - Real-time server ↔ client communication
|
|
1260
|
+
- 🎨 **Colorful Logs** - Logging system with badges and icons
|
|
1261
|
+
- 🔍 **Advanced Monitoring** - File monitoring with chokidar
|
|
1262
|
+
- ⚡ **Performance** - Reload only modified parts
|
|
1263
|
+
- 🛠️ **Debugging** - Detailed error messages with stack traces
|
|
1264
|
+
- 🔌 **Hot Plugin Reload** - Real-time plugin reloading
|
|
1265
|
+
|
|
1266
|
+
### Complete Configuration
|
|
1267
|
+
|
|
1268
|
+
```javascript
|
|
1269
|
+
const app = new App({
|
|
1270
|
+
port: 3000,
|
|
1271
|
+
wsPort: 3008,
|
|
1272
|
+
viewsDir: 'views',
|
|
1273
|
+
staticDir: 'public',
|
|
1274
|
+
routesDir: 'routes',
|
|
1275
|
+
isDev: true,
|
|
1276
|
+
watchDirs: ['views', 'routes', 'public', 'src', 'plugins'],
|
|
1277
|
+
errorLog: 'error.log',
|
|
1278
|
+
showStack: true,
|
|
1279
|
+
autoInstall: true,
|
|
1280
|
+
layouts: {
|
|
1281
|
+
enabled: true,
|
|
1282
|
+
defaultLayout: 'main',
|
|
1283
|
+
layoutsDir: 'views/layouts',
|
|
1284
|
+
cache: false // Disable cache in dev mode
|
|
1285
|
+
},
|
|
1286
|
+
plugins: {
|
|
1287
|
+
enabled: true,
|
|
1288
|
+
autoLoad: true,
|
|
1289
|
+
pluginsDir: 'plugins'
|
|
1290
|
+
},
|
|
1291
|
+
prefetch: {
|
|
1292
|
+
enabled: true,
|
|
1293
|
+
maxConcurrent: 3,
|
|
1294
|
+
notifyUser: true,
|
|
1295
|
+
cacheRoutes: true,
|
|
1296
|
+
prefetchDelay: 1000
|
|
1297
|
+
}
|
|
1298
|
+
});
|
|
1299
|
+
```
|
|
1300
|
+
|
|
1301
|
+
### Advanced Error Handling
|
|
1302
|
+
|
|
1303
|
+
```javascript
|
|
1304
|
+
// Automatic handling of uncaught errors
|
|
1305
|
+
process.on('uncaughtException', (error) => {
|
|
1306
|
+
app.log('error', 'Uncaught exception', error.message);
|
|
1307
|
+
// Automatic WebSocket notification to clients
|
|
1308
|
+
});
|
|
1309
|
+
|
|
1310
|
+
process.on('unhandledRejection', (reason) => {
|
|
1311
|
+
app.log('error', 'Promise rejected', reason.toString());
|
|
1312
|
+
// Automatic error broadcast
|
|
1313
|
+
});
|
|
1314
|
+
```
|
|
1315
|
+
|
|
1316
|
+
## 🎨 Views with EJS
|
|
1317
|
+
|
|
1318
|
+
Veko.js uses EJS as the default template engine with advanced configuration.
|
|
1319
|
+
|
|
1320
|
+
### View Configuration
|
|
1321
|
+
|
|
1322
|
+
```javascript
|
|
1323
|
+
// Automatic view directory configuration
|
|
1324
|
+
this.express.set('view engine', 'ejs');
|
|
1325
|
+
this.express.set('views', [
|
|
1326
|
+
path.join(process.cwd(), this.options.viewsDir), // Project directory
|
|
1327
|
+
path.join(process.cwd(), this.options.layouts.layoutsDir), // Layouts directory
|
|
1328
|
+
path.join(__dirname, '..', 'views'), // Veko.js views
|
|
1329
|
+
path.join(__dirname, '..', 'error') // Error pages
|
|
1330
|
+
]);
|
|
1331
|
+
```
|
|
1332
|
+
|
|
1333
|
+
### Modern View Example
|
|
1334
|
+
|
|
1335
|
+
```html
|
|
1336
|
+
<!-- views/index.ejs -->
|
|
1337
|
+
<!DOCTYPE html>
|
|
1338
|
+
<html>
|
|
1339
|
+
<head>
|
|
1340
|
+
<title><%= title %></title>
|
|
1341
|
+
<link rel="stylesheet" href="/css/style.css">
|
|
1342
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
1343
|
+
</head>
|
|
1344
|
+
<body>
|
|
1345
|
+
<header>
|
|
1346
|
+
<h1><%= message %></h1>
|
|
1347
|
+
</header>
|
|
1348
|
+
|
|
1349
|
+
<main>
|
|
1350
|
+
<% if (users && users.length > 0) { %>
|
|
1351
|
+
<section class="users">
|
|
1352
|
+
<% users.forEach(user => { %>
|
|
1353
|
+
<article class="user-card">
|
|
1354
|
+
<h3><%= user.name %></h3>
|
|
1355
|
+
<p><%= user.email %></p>
|
|
1356
|
+
</article>
|
|
1357
|
+
<% }); %>
|
|
1358
|
+
</section>
|
|
1359
|
+
<% } else { %>
|
|
1360
|
+
<p>No users found.</p>
|
|
1361
|
+
<% } %>
|
|
1362
|
+
</main>
|
|
1363
|
+
|
|
1364
|
+
<!-- Hot reload script automatically injected in dev mode -->
|
|
1365
|
+
</body>
|
|
1366
|
+
</html>
|
|
1367
|
+
```
|
|
1368
|
+
|
|
1369
|
+
## 📦 Auto Module Installation
|
|
1370
|
+
|
|
1371
|
+
Veko.js automatically installs missing dependencies during initialization.
|
|
1372
|
+
|
|
1373
|
+
### Module Installation Configuration
|
|
1374
|
+
|
|
1375
|
+
```javascript
|
|
1376
|
+
const app = new App({
|
|
1377
|
+
autoInstall: true // Enable automatic installation (default: true)
|
|
1378
|
+
});
|
|
1379
|
+
|
|
1380
|
+
// Check if module is available
|
|
1381
|
+
if (app.isModuleAvailable('express')) {
|
|
1382
|
+
console.log('Express is available');
|
|
1383
|
+
}
|
|
1384
|
+
|
|
1385
|
+
// Install module on-the-fly
|
|
1386
|
+
await app.installModule('lodash', '4.17.21');
|
|
1387
|
+
|
|
1388
|
+
// Require module with auto-installation
|
|
1389
|
+
const lodash = await app.requireModule('lodash');
|
|
1390
|
+
```
|
|
1391
|
+
|
|
1392
|
+
### Required Modules
|
|
1393
|
+
|
|
1394
|
+
Veko.js automatically manages these dependencies:
|
|
1395
|
+
|
|
1396
|
+
```javascript
|
|
1397
|
+
const requiredModules = {
|
|
1398
|
+
'express': '^4.18.2',
|
|
1399
|
+
'ejs': '^3.1.9',
|
|
1400
|
+
'ws': '^8.14.2',
|
|
1401
|
+
'chokidar': '^3.5.3',
|
|
1402
|
+
'chalk': '^4.1.2',
|
|
1403
|
+
'commander': '^11.1.0'
|
|
1404
|
+
};
|
|
1405
|
+
```
|
|
1406
|
+
|
|
1407
|
+
## 🔧 Complete API
|
|
1408
|
+
|
|
1409
|
+
### App Class
|
|
1410
|
+
|
|
1411
|
+
#### Constructor
|
|
1412
|
+
|
|
1413
|
+
```javascript
|
|
1414
|
+
const app = new App({
|
|
1415
|
+
port: 3000, // Listening port
|
|
1416
|
+
wsPort: 3008, // WebSocket port (dev mode)
|
|
1417
|
+
viewsDir: 'views', // Views directory
|
|
1418
|
+
staticDir: 'public', // Static directory
|
|
1419
|
+
routesDir: 'routes', // Routes directory
|
|
1420
|
+
isDev: false, // Development mode
|
|
1421
|
+
watchDirs: ['views', 'routes', 'public'], // Watched directories
|
|
1422
|
+
errorLog: 'error.log', // Error log file
|
|
1423
|
+
showStack: true, // Show stack trace
|
|
1424
|
+
autoInstall: true, // Auto module installation
|
|
1425
|
+
layouts: { // Layout configuration
|
|
1426
|
+
enabled: true,
|
|
1427
|
+
defaultLayout: 'main',
|
|
1428
|
+
layoutsDir: 'views/layouts',
|
|
1429
|
+
extension: '.ejs',
|
|
1430
|
+
cache: true
|
|
1431
|
+
},
|
|
1432
|
+
plugins: { // Plugin configuration
|
|
1433
|
+
enabled: true,
|
|
1434
|
+
autoLoad: true,
|
|
1435
|
+
pluginsDir: 'plugins'
|
|
1436
|
+
},
|
|
1437
|
+
prefetch: { // Prefetch configuration
|
|
1438
|
+
enabled: true,
|
|
1439
|
+
maxConcurrent: 3,
|
|
1440
|
+
notifyUser: true,
|
|
1441
|
+
cacheRoutes: true,
|
|
1442
|
+
prefetchDelay: 1000
|
|
1443
|
+
}
|
|
1444
|
+
});
|
|
1445
|
+
```
|
|
1446
|
+
|
|
1447
|
+
#### Main Methods
|
|
1448
|
+
|
|
1449
|
+
```javascript
|
|
1450
|
+
// Loading and startup
|
|
1451
|
+
app.loadRoutes(routesDir) // Load routes automatically
|
|
1452
|
+
app.listen(port) // Start server
|
|
1453
|
+
app.startDev(port) // Start in development mode
|
|
1454
|
+
app.stop() // Stop server
|
|
1455
|
+
|
|
1456
|
+
// Middleware and configuration
|
|
1457
|
+
app.use(middleware) // Add middleware
|
|
1458
|
+
app.setupExpress() // Configure Express
|
|
1459
|
+
app.setupDevMode() // Enable development mode
|
|
1460
|
+
|
|
1461
|
+
// Beautiful logging
|
|
1462
|
+
app.log(type, message, details) // Advanced logging system
|
|
1463
|
+
|
|
1464
|
+
// Dynamic route management
|
|
1465
|
+
app.createRoute(method, path, handler, options) // Create route dynamically
|
|
1466
|
+
app.deleteRoute(method, path) // Delete route
|
|
1467
|
+
app.updateRoute(method, path, newHandler) // Update route
|
|
1468
|
+
app.createRouteFile(routePath, handlers, options) // Create route file
|
|
1469
|
+
app.deleteRouteFile(routePath) // Delete route file
|
|
1470
|
+
app.listRoutes() // List all routes
|
|
1471
|
+
|
|
1472
|
+
// Layout management
|
|
1473
|
+
app.createLayout(name, content) // Create layout
|
|
1474
|
+
app.deleteLayout(name) // Delete layout
|
|
1475
|
+
app.listLayouts() // List layouts
|
|
1476
|
+
app.reloadLayouts() // Reload layouts
|
|
1477
|
+
app.renderWithCustomLayout(res, view, layout, data) // Render with specific layout
|
|
1478
|
+
app.renderWithoutLayout(res, view, data) // Render without layout
|
|
1479
|
+
|
|
1480
|
+
// Module management
|
|
1481
|
+
app.installModule(name, version) // Install module
|
|
1482
|
+
app.isModuleAvailable(name) // Check module availability
|
|
1483
|
+
app.requireModule(name, version) // Require with auto-install
|
|
1484
|
+
|
|
1485
|
+
// Route management (internal)
|
|
1486
|
+
app.reloadSpecificRoute(filePath) // Reload specific route
|
|
1487
|
+
app.removeRoute(filePath) // Remove route
|
|
1488
|
+
app.filePathToRoute(filePath) // Convert path → route
|
|
1489
|
+
|
|
1490
|
+
// WebSocket and broadcast
|
|
1491
|
+
app.broadcast(data) // Broadcast WebSocket message
|
|
1492
|
+
app.sendAvailableRoutes(ws) // Send available routes
|
|
1493
|
+
|
|
1494
|
+
// Plugin management
|
|
1495
|
+
app.loadPlugin(plugin, config) // Load plugin
|
|
1496
|
+
app.unloadPlugin(pluginName) // Unload plugin
|
|
1497
|
+
app.reloadPlugin(pluginName, config) // Reload plugin
|
|
1498
|
+
app.listPlugins() // List plugins
|
|
1499
|
+
app.executeHook(hookName, ...args) // Execute hook
|
|
1500
|
+
```
|
|
1501
|
+
|
|
1502
|
+
### Utility Functions
|
|
1503
|
+
|
|
1504
|
+
```javascript
|
|
1505
|
+
const { createApp, startDev, start } = require('veko');
|
|
1506
|
+
|
|
1507
|
+
// Quick app creation
|
|
1508
|
+
const app = createApp({ port: 3000 });
|
|
1509
|
+
|
|
1510
|
+
// Development startup
|
|
1511
|
+
startDev({ port: 3000, watchDirs: ['src'] });
|
|
1512
|
+
|
|
1513
|
+
// Production startup
|
|
1514
|
+
start({ port: 8080 });
|
|
1515
|
+
```
|
|
1516
|
+
|
|
1517
|
+
## 🔍 Advanced Examples
|
|
1518
|
+
|
|
1519
|
+
### Complete Application with Plugins
|
|
1520
|
+
|
|
1521
|
+
```javascript
|
|
1522
|
+
const { App } = require('veko');
|
|
1523
|
+
|
|
1524
|
+
const app = new App({
|
|
1525
|
+
port: 3000,
|
|
1526
|
+
isDev: process.env.NODE_ENV === 'development',
|
|
1527
|
+
layouts: {
|
|
1528
|
+
enabled: true,
|
|
1529
|
+
defaultLayout: 'main'
|
|
1530
|
+
},
|
|
1531
|
+
plugins: {
|
|
1532
|
+
enabled: true,
|
|
1533
|
+
autoLoad: true,
|
|
1534
|
+
pluginsDir: 'plugins'
|
|
1535
|
+
}
|
|
1536
|
+
});
|
|
1537
|
+
|
|
1538
|
+
// Load plugins with specific configuration
|
|
1539
|
+
await app.loadPlugin('database', {
|
|
1540
|
+
uri: process.env.MONGODB_URI || 'mongodb://localhost:27017/myapp'
|
|
1541
|
+
});
|
|
1542
|
+
|
|
1543
|
+
await app.loadPlugin('auth', {
|
|
1544
|
+
secret: process.env.JWT_SECRET || 'development-secret',
|
|
1545
|
+
expiresIn: '7d'
|
|
1546
|
+
});
|
|
1547
|
+
|
|
1548
|
+
await app.loadPlugin('cache', {
|
|
1549
|
+
stdTTL: 3600 // 1 hour
|
|
1550
|
+
});
|
|
1551
|
+
|
|
1552
|
+
// Add global hooks
|
|
1553
|
+
app.plugins.addHook('request:start', (req) => {
|
|
1554
|
+
app.log('info', `${req.method} ${req.url}`, `IP: ${req.ip}`);
|
|
1555
|
+
});
|
|
1556
|
+
|
|
1557
|
+
app.plugins.addHook('error:handle', (error, req) => {
|
|
1558
|
+
app.log('error', 'Application error', `${error.message} - ${req.url}`);
|
|
1559
|
+
});
|
|
1560
|
+
|
|
1561
|
+
app.loadRoutes().listen();
|
|
1562
|
+
```
|
|
1563
|
+
|
|
1564
|
+
### Modern REST API with Error Handling
|
|
1565
|
+
|
|
1566
|
+
```javascript
|
|
1567
|
+
// routes/api/users.js
|
|
1568
|
+
const users = [];
|
|
1569
|
+
|
|
1570
|
+
module.exports = {
|
|
1571
|
+
get: async (req, res) => {
|
|
1572
|
+
try {
|
|
1573
|
+
// Use plugin cache
|
|
1574
|
+
const cacheKey = `users:${JSON.stringify(req.query)}`;
|
|
1575
|
+
const cached = req.app.cache?.get(cacheKey);
|
|
1576
|
+
|
|
1577
|
+
if (cached) {
|
|
1578
|
+
return res.json(cached);
|
|
1579
|
+
}
|
|
1580
|
+
|
|
1581
|
+
// Database simulation
|
|
1582
|
+
const page = parseInt(req.query.page) || 1;
|
|
1583
|
+
const limit = parseInt(req.query.limit) || 10;
|
|
1584
|
+
const start = (page - 1) * limit;
|
|
1585
|
+
const end = start + limit;
|
|
1586
|
+
|
|
1587
|
+
const paginatedUsers = users.slice(start, end);
|
|
1588
|
+
|
|
1589
|
+
const result = {
|
|
1590
|
+
users: paginatedUsers,
|
|
1591
|
+
pagination: {
|
|
1592
|
+
page,
|
|
1593
|
+
limit,
|
|
1594
|
+
total: users.length,
|
|
1595
|
+
pages: Math.ceil(users.length / limit)
|
|
1596
|
+
}
|
|
1597
|
+
};
|
|
1598
|
+
|
|
1599
|
+
// Cache result
|
|
1600
|
+
req.app.cache?.set(cacheKey, result, 300);
|
|
1601
|
+
|
|
1602
|
+
res.json(result);
|
|
1603
|
+
} catch (error) {
|
|
1604
|
+
res.status(500).json({ error: 'Server error' });
|
|
1605
|
+
}
|
|
1606
|
+
},
|
|
1607
|
+
|
|
1608
|
+
post: [
|
|
1609
|
+
// Use auth middleware from plugin
|
|
1610
|
+
(req, res, next) => req.app.authMiddleware?.(req, res, next) || next(),
|
|
1611
|
+
|
|
1612
|
+
async (req, res) => {
|
|
1613
|
+
try {
|
|
1614
|
+
const { name, email } = req.body;
|
|
1615
|
+
|
|
1616
|
+
if (!name || !email) {
|
|
1617
|
+
return res.status(400).json({
|
|
1618
|
+
error: 'Name and email required'
|
|
1619
|
+
});
|
|
1620
|
+
}
|
|
1621
|
+
|
|
1622
|
+
const newUser = {
|
|
1623
|
+
id: users.length + 1,
|
|
1624
|
+
name,
|
|
1625
|
+
email,
|
|
1626
|
+
createdAt: new Date().toISOString()
|
|
1627
|
+
};
|
|
1628
|
+
|
|
1629
|
+
users.push(newUser);
|
|
1630
|
+
|
|
1631
|
+
// Invalidate cache
|
|
1632
|
+
req.app.cache?.del('users:*');
|
|
1633
|
+
|
|
1634
|
+
res.status(201).json({
|
|
1635
|
+
message: 'User created',
|
|
1636
|
+
user: newUser
|
|
1637
|
+
});
|
|
1638
|
+
} catch (error) {
|
|
1639
|
+
res.status(500).json({ error: 'Server error' });
|
|
1640
|
+
}
|
|
1641
|
+
}
|
|
1642
|
+
]
|
|
1643
|
+
};
|
|
1644
|
+
```
|
|
1645
|
+
|
|
1646
|
+
### Advanced Plugin with CLI
|
|
1647
|
+
|
|
1648
|
+
```javascript
|
|
1649
|
+
// plugins/admin.js
|
|
1650
|
+
module.exports = {
|
|
1651
|
+
name: 'admin',
|
|
1652
|
+
version: '2.0.0',
|
|
1653
|
+
description: 'Advanced administration plugin',
|
|
1654
|
+
dependencies: ['database', 'auth'],
|
|
1655
|
+
|
|
1656
|
+
defaultConfig: {
|
|
1657
|
+
adminPath: '/admin',
|
|
1658
|
+
secretKey: 'admin-secret'
|
|
1659
|
+
},
|
|
1660
|
+
|
|
1661
|
+
async load(app, config, context) {
|
|
1662
|
+
// Admin-only middleware
|
|
1663
|
+
const adminMiddleware = (req, res, next) => {
|
|
1664
|
+
if (!req.user || req.user.role !== 'admin') {
|
|
1665
|
+
return res.status(403).json({ error: 'Access denied' });
|
|
1666
|
+
}
|
|
1667
|
+
next();
|
|
1668
|
+
};
|
|
1669
|
+
|
|
1670
|
+
// Administration routes
|
|
1671
|
+
context.addRoute('get', `${config.adminPath}/dashboard`, [
|
|
1672
|
+
app.authMiddleware,
|
|
1673
|
+
adminMiddleware,
|
|
1674
|
+
(req, res) => {
|
|
1675
|
+
res.render('admin/dashboard', {
|
|
1676
|
+
layout: 'admin',
|
|
1677
|
+
stats: context.storage.get('stats', {}),
|
|
1678
|
+
plugins: context.listPlugins()
|
|
1679
|
+
});
|
|
1680
|
+
}
|
|
1681
|
+
]);
|
|
1682
|
+
|
|
1683
|
+
// Plugin management API
|
|
1684
|
+
context.addRoute('post', `${config.adminPath}/plugins/:name/toggle`, [
|
|
1685
|
+
app.authMiddleware,
|
|
1686
|
+
adminMiddleware,
|
|
1687
|
+
async (req, res) => {
|
|
1688
|
+
try {
|
|
1689
|
+
const { name } = req.params;
|
|
1690
|
+
const result = await context.getPlugin('plugins')?.togglePlugin(name);
|
|
1691
|
+
res.json({ success: true, active: result });
|
|
1692
|
+
} catch (error) {
|
|
1693
|
+
res.status(500).json({ error: error.message });
|
|
1694
|
+
}
|
|
1695
|
+
}
|
|
1696
|
+
]);
|
|
1697
|
+
|
|
1698
|
+
// CLI commands
|
|
1699
|
+
context.addCommand('admin:stats', () => {
|
|
1700
|
+
console.log('=== Admin Statistics ===');
|
|
1701
|
+
console.log('Plugins:', context.listPlugins().length);
|
|
1702
|
+
console.log('Stats:', context.storage.get('stats', {}));
|
|
1703
|
+
}, 'Display administration statistics');
|
|
1704
|
+
|
|
1705
|
+
context.addCommand('admin:reset', () => {
|
|
1706
|
+
context.storage.clear();
|
|
1707
|
+
console.log('Admin data reset');
|
|
1708
|
+
}, 'Reset administration data');
|
|
1709
|
+
|
|
1710
|
+
// Hook to collect stats
|
|
1711
|
+
context.hook('request:end', (req, res) => {
|
|
1712
|
+
const stats = context.storage.get('stats', { requests: 0, errors: 0 });
|
|
1713
|
+
stats.requests++;
|
|
1714
|
+
|
|
1715
|
+
if (res.statusCode >= 400) {
|
|
1716
|
+
stats.errors++;
|
|
1717
|
+
}
|
|
1718
|
+
|
|
1719
|
+
context.storage.set('stats', stats);
|
|
1720
|
+
});
|
|
1721
|
+
|
|
1722
|
+
context.log('success', 'Admin plugin loaded', `Interface: ${config.adminPath}`);
|
|
1723
|
+
}
|
|
1724
|
+
};
|
|
1725
|
+
```
|
|
1726
|
+
|
|
1727
|
+
## 🚀 Deployment
|
|
1728
|
+
|
|
1729
|
+
### Production Mode
|
|
1730
|
+
|
|
1731
|
+
```javascript
|
|
1732
|
+
// app.js
|
|
1733
|
+
const { App } = require('veko');
|
|
1734
|
+
|
|
1735
|
+
const app = new App({
|
|
1736
|
+
port: process.env.PORT || 3000,
|
|
1737
|
+
isDev: false, // Disable development mode
|
|
1738
|
+
errorLog: 'logs/error.log',
|
|
1739
|
+
showStack: false, // Hide stack traces in production
|
|
1740
|
+
autoInstall: false, // Disable auto-installation in production
|
|
1741
|
+
layouts: {
|
|
1742
|
+
enabled: true,
|
|
1743
|
+
cache: true // Enable layout caching
|
|
1744
|
+
},
|
|
1745
|
+
plugins: {
|
|
1746
|
+
enabled: true,
|
|
1747
|
+
autoLoad: true,
|
|
1748
|
+
pluginsDir: 'plugins'
|
|
1749
|
+
}
|
|
1750
|
+
});
|
|
1751
|
+
|
|
1752
|
+
app.loadRoutes().listen();
|
|
1753
|
+
```
|
|
1754
|
+
|
|
1755
|
+
### Environment Variables
|
|
1756
|
+
|
|
1757
|
+
```bash
|
|
1758
|
+
# .env
|
|
1759
|
+
NODE_ENV=production
|
|
1760
|
+
PORT=8080
|
|
1761
|
+
LOG_LEVEL=info
|
|
1762
|
+
MONGODB_URI=mongodb://prod-server:27017/myapp
|
|
1763
|
+
JWT_SECRET=super-secret-production-key
|
|
1764
|
+
```
|
|
1765
|
+
|
|
1766
|
+
### Docker
|
|
1767
|
+
|
|
1768
|
+
```dockerfile
|
|
1769
|
+
FROM node:18-alpine
|
|
1770
|
+
|
|
1771
|
+
WORKDIR /app
|
|
1772
|
+
|
|
1773
|
+
COPY package*.json ./
|
|
1774
|
+
RUN npm ci --only=production
|
|
1775
|
+
|
|
1776
|
+
COPY . .
|
|
1777
|
+
|
|
1778
|
+
EXPOSE 3000
|
|
1779
|
+
|
|
1780
|
+
CMD ["node", "app.js"]
|
|
1781
|
+
```
|
|
1782
|
+
|
|
1783
|
+
## 📊 Performance and Optimization
|
|
1784
|
+
|
|
1785
|
+
### Smart Prefetching
|
|
1786
|
+
|
|
1787
|
+
```javascript
|
|
1788
|
+
const app = new App({
|
|
1789
|
+
prefetch: {
|
|
1790
|
+
enabled: true, // Enable prefetching
|
|
1791
|
+
maxConcurrent: 3, // Max simultaneous requests
|
|
1792
|
+
notifyUser: true, // Notify user
|
|
1793
|
+
cacheRoutes: true, // Route caching
|
|
1794
|
+
prefetchDelay: 1000 // Delay before prefetching
|
|
1795
|
+
}
|
|
1796
|
+
});
|
|
1797
|
+
```
|
|
1798
|
+
|
|
1799
|
+
### Performance Monitoring
|
|
1800
|
+
|
|
1801
|
+
```javascript
|
|
1802
|
+
// Monitoring plugin
|
|
1803
|
+
const monitoringPlugin = {
|
|
1804
|
+
name: 'monitoring',
|
|
1805
|
+
|
|
1806
|
+
async load(app, config, context) {
|
|
1807
|
+
context.hook('request:start', (req) => {
|
|
1808
|
+
req.startTime = process.hrtime.bigint();
|
|
1809
|
+
});
|
|
1810
|
+
|
|
1811
|
+
context.hook('request:end', (req, res) => {
|
|
1812
|
+
const duration = Number(process.hrtime.bigint() - req.startTime) / 1000000;
|
|
1813
|
+
|
|
1814
|
+
if (duration > 100) {
|
|
1815
|
+
context.log('warning', 'Slow request detected',
|
|
1816
|
+
`${req.method} ${req.url} - ${duration.toFixed(2)}ms`);
|
|
1817
|
+
}
|
|
1818
|
+
|
|
1819
|
+
// Store metrics
|
|
1820
|
+
const metrics = context.storage.get('metrics', { slow: 0, total: 0 });
|
|
1821
|
+
metrics.total++;
|
|
1822
|
+
if (duration > 100) metrics.slow++;
|
|
1823
|
+
context.storage.set('metrics', metrics);
|
|
1824
|
+
});
|
|
1825
|
+
}
|
|
1826
|
+
};
|
|
1827
|
+
|
|
1828
|
+
app.loadPlugin(monitoringPlugin);
|
|
1829
|
+
```
|
|
1830
|
+
|
|
1831
|
+
## 🛠️ CLI Commands
|
|
1832
|
+
|
|
1833
|
+
### Setup Commands
|
|
1834
|
+
|
|
1835
|
+
```bash
|
|
1836
|
+
# Create new project with default template
|
|
1837
|
+
veko setup my-app
|
|
1838
|
+
|
|
1839
|
+
# Create with specific template
|
|
1840
|
+
veko setup --template api --name my-api
|
|
1841
|
+
veko setup --template blog --name my-blog
|
|
1842
|
+
veko setup --template admin --name admin-panel
|
|
1843
|
+
|
|
1844
|
+
# Setup with options
|
|
1845
|
+
veko setup my-app --git --skip-install
|
|
1846
|
+
veko setup --name my-app --dir ./projects/my-app
|
|
1847
|
+
```
|
|
1848
|
+
|
|
1849
|
+
### Development Commands
|
|
1850
|
+
|
|
1851
|
+
```bash
|
|
1852
|
+
# Start development server
|
|
1853
|
+
veko dev
|
|
1854
|
+
|
|
1855
|
+
# Start with custom port
|
|
1856
|
+
veko dev --port 8080
|
|
1857
|
+
|
|
1858
|
+
# Start with custom watch directories
|
|
1859
|
+
veko dev --watch "src,views,routes"
|
|
1860
|
+
|
|
1861
|
+
# Start with custom entry file
|
|
1862
|
+
veko dev --file ./src/server.js
|
|
1863
|
+
```
|
|
1864
|
+
|
|
1865
|
+
### Build Commands
|
|
1866
|
+
|
|
1867
|
+
```bash
|
|
1868
|
+
# Build for production
|
|
1869
|
+
veko build
|
|
1870
|
+
|
|
1871
|
+
# Start production server
|
|
1872
|
+
veko start
|
|
1873
|
+
```
|
|
1874
|
+
|
|
1875
|
+
## 🤝 Contributing
|
|
1876
|
+
|
|
1877
|
+
Contributions are welcome!
|
|
1878
|
+
|
|
1879
|
+
### Local Development
|
|
1880
|
+
|
|
1881
|
+
```bash
|
|
1882
|
+
git clone https://github.com/username/veko.js.git
|
|
1883
|
+
cd veko.js
|
|
1884
|
+
npm install
|
|
1885
|
+
npm run dev
|
|
1886
|
+
```
|
|
1887
|
+
|
|
1888
|
+
### Testing
|
|
1889
|
+
|
|
1890
|
+
```bash
|
|
1891
|
+
npm test
|
|
1892
|
+
npm run test:watch
|
|
1893
|
+
npm run test:coverage
|
|
1894
|
+
```
|
|
1895
|
+
|
|
1896
|
+
### Creating a Plugin
|
|
1897
|
+
|
|
1898
|
+
1. Create a file in `plugins/`
|
|
1899
|
+
2. Follow the documented plugin structure
|
|
1900
|
+
3. Test in development mode
|
|
1901
|
+
4. Submit a PR
|
|
1902
|
+
|
|
1903
|
+
### Code Style
|
|
1904
|
+
|
|
1905
|
+
- Use ES6+ features
|
|
1906
|
+
- Follow JSDoc comments
|
|
1907
|
+
- Use meaningful variable names
|
|
1908
|
+
- Add unit tests for new features
|
|
1909
|
+
|
|
1910
|
+
## 📄 License
|
|
1911
|
+
|
|
1912
|
+
MIT License - see LICENSE file for details.
|
|
1913
|
+
|
|
1914
|
+
---
|
|
1915
|
+
|
|
1916
|
+
**Veko.js v2.0** - Ultra-modern web framework with the most advanced auto-updater in the Node.js ecosystem 🚀🔄
|
|
1917
|
+
|
|
1918
|
+
### Quick Auto-Updater Commands
|
|
1919
|
+
|
|
1920
|
+
```bash
|
|
1921
|
+
veko update # 🎨 Menu interactif
|
|
1922
|
+
veko update check # 🔍 Vérification des mises à jour
|
|
1923
|
+
veko update update # ⚡ Mettre à jour maintenant
|
|
1924
|
+
veko update status # 📊 Afficher le statut
|
|
1925
|
+
veko update daemon # 👾 Mode arrière-plan
|
|
1926
|
+
veko update --help # ❓ Aide complète
|
|
1927
|
+
```
|
|
1928
|
+
|
|
1929
|
+
### Quick Links
|
|
1930
|
+
|
|
1931
|
+
- [🏠 Home](/)
|
|
1932
|
+
- [📚 Documentation](/docs)
|
|
1933
|
+
- [🔄 Auto-Updater Guide](/docs/auto-updater)
|
|
1934
|
+
- [🔌 Plugins](/plugins)
|
|
1935
|
+
- [🛠️ CLI](/cli)
|
|
1936
|
+
- [💡 Examples](/examples)
|
|
1937
|
+
- [🐛 Issues](https://github.com/username/veko.js/issues)
|
|
1938
|
+
- [💬 Discussions](https://github.com/username/veko.js/discussions)
|
|
1939
|
+
|
|
1940
|
+
Built with ❤️ by the Veko.js team
|
|
1941
|
+
|
|
1942
|
+
**Experience the future of Node.js development with Veko.js 2.0! 🚀✨**# vako
|
|
1943
|
+
# vako
|
|
1944
|
+
|