voltjs-framework 1.0.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.
Files changed (60) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1265 -0
  3. package/bin/volt.js +139 -0
  4. package/package.json +56 -0
  5. package/src/api/graphql.js +399 -0
  6. package/src/api/rest.js +204 -0
  7. package/src/api/websocket.js +285 -0
  8. package/src/cli/build.js +111 -0
  9. package/src/cli/create.js +371 -0
  10. package/src/cli/db.js +106 -0
  11. package/src/cli/dev.js +114 -0
  12. package/src/cli/generate.js +278 -0
  13. package/src/cli/lint.js +172 -0
  14. package/src/cli/routes.js +118 -0
  15. package/src/cli/start.js +42 -0
  16. package/src/cli/test.js +138 -0
  17. package/src/core/app.js +701 -0
  18. package/src/core/config.js +232 -0
  19. package/src/core/middleware.js +133 -0
  20. package/src/core/plugins.js +88 -0
  21. package/src/core/react-renderer.js +244 -0
  22. package/src/core/renderer.js +337 -0
  23. package/src/core/router.js +183 -0
  24. package/src/database/index.js +461 -0
  25. package/src/database/migration.js +192 -0
  26. package/src/database/model.js +285 -0
  27. package/src/database/query.js +394 -0
  28. package/src/database/seeder.js +89 -0
  29. package/src/index.js +156 -0
  30. package/src/security/auth.js +425 -0
  31. package/src/security/cors.js +80 -0
  32. package/src/security/csrf.js +125 -0
  33. package/src/security/encryption.js +110 -0
  34. package/src/security/helmet.js +103 -0
  35. package/src/security/index.js +75 -0
  36. package/src/security/rateLimit.js +119 -0
  37. package/src/security/sanitizer.js +113 -0
  38. package/src/security/xss.js +110 -0
  39. package/src/ui/component.js +224 -0
  40. package/src/ui/reactive.js +503 -0
  41. package/src/ui/template.js +448 -0
  42. package/src/utils/cache.js +216 -0
  43. package/src/utils/collection.js +772 -0
  44. package/src/utils/cron.js +213 -0
  45. package/src/utils/date.js +223 -0
  46. package/src/utils/events.js +181 -0
  47. package/src/utils/excel.js +482 -0
  48. package/src/utils/form.js +547 -0
  49. package/src/utils/hash.js +121 -0
  50. package/src/utils/http.js +461 -0
  51. package/src/utils/logger.js +186 -0
  52. package/src/utils/mail.js +347 -0
  53. package/src/utils/paginator.js +179 -0
  54. package/src/utils/pdf.js +417 -0
  55. package/src/utils/queue.js +199 -0
  56. package/src/utils/schema.js +985 -0
  57. package/src/utils/sms.js +243 -0
  58. package/src/utils/storage.js +348 -0
  59. package/src/utils/string.js +236 -0
  60. package/src/utils/validation.js +318 -0
package/README.md ADDED
@@ -0,0 +1,1265 @@
1
+ # âš¡ VoltJS
2
+
3
+ **The batteries-included, security-first JavaScript framework.**
4
+
5
+ Zero boilerplate. Zero config. Everything you need — out of the box.
6
+
7
+ ```bash
8
+ npx voltjs create my-app
9
+ cd my-app
10
+ npm install
11
+ npm run dev
12
+ ```
13
+
14
+ ---
15
+
16
+ ## Why VoltJS?
17
+
18
+ | Problem | VoltJS Solution |
19
+ |---------|----------------|
20
+ | Express needs 20+ packages to be production-ready | **Everything built-in** — security, ORM, mail, PDF, Excel, SMS, caching, queues |
21
+ | CSRF, XSS, CORS require manual setup | **All security ON by default** — zero-config protection |
22
+ | Next.js / Nuxt are heavy and opinionated | **Lightweight & flexible** — use what you need |
23
+ | Setting up auth takes hours | **Auth in 2 lines** — JWT, sessions, API keys, RBAC, 2FA |
24
+ | Need separate packages for email, PDF, Excel | **Built-in utilities** — no extra dependencies |
25
+ | File-based routing OR programmatic? | **Both** — choose your style |
26
+
27
+ ### Single Import, Everything Available
28
+
29
+ ```js
30
+ const {
31
+ Volt, Router, Auth, Mail, Excel, PDF, SMS,
32
+ Database, Model, Cache, Queue, Cron, Logger,
33
+ Validator, HttpClient, Storage, Hash, EventBus,
34
+ Component, Reactive, RestAPI, WebSocketServer, GraphQLHandler,
35
+ Form, Schema, _, Collection,
36
+ } = require('voltjs-framework');
37
+ ```
38
+
39
+ ---
40
+
41
+ ## Table of Contents
42
+
43
+ - [Quick Start](#quick-start)
44
+ - [Routing](#routing)
45
+ - [Security](#security)
46
+ - [Database & ORM](#database--orm)
47
+ - [Authentication](#authentication)
48
+ - [Validation](#validation)
49
+ - [Email](#email)
50
+ - [SMS](#sms)
51
+ - [Excel Import/Export](#excel-importexport)
52
+ - [PDF Generation](#pdf-generation)
53
+ - [File Storage](#file-storage)
54
+ - [Caching](#caching)
55
+ - [Job Queues](#job-queues)
56
+ - [Scheduled Tasks (Cron)](#scheduled-tasks-cron)
57
+ - [WebSockets](#websockets)
58
+ - [GraphQL](#graphql)
59
+ - [REST API Builder](#rest-api-builder)
60
+ - [Reactive State](#reactive-state)
61
+ - [Components](#components)
62
+ - [Template Engine](#template-engine)
63
+ - [Form Handling](#form-handling)
64
+ - [Schema Validation (Zod)](#schema-validation-zod)
65
+ - [Collection Utilities (Lodash)](#collection-utilities-lodash)
66
+ - [classNames / clsx](#classnames--clsx)
67
+ - [Logging](#logging)
68
+ - [HTTP Client](#http-client)
69
+ - [CLI Commands](#cli-commands)
70
+ - [Configuration](#configuration)
71
+ - [Project Structure](#project-structure)
72
+
73
+ ---
74
+
75
+ ## Quick Start
76
+
77
+ ### Create a New Project
78
+
79
+ ```bash
80
+ npx voltjs create my-app
81
+ cd my-app
82
+ npm install
83
+ npm run dev
84
+ ```
85
+
86
+ ### Minimal App (2 files)
87
+
88
+ **app.js:**
89
+ ```js
90
+ const { Volt } = require('voltjs-framework');
91
+ const app = new Volt();
92
+
93
+ app.get('/', (req, res) => {
94
+ res.json({ message: 'Hello VoltJS! âš¡' });
95
+ });
96
+
97
+ app.listen(3000);
98
+ ```
99
+
100
+ **That's it.** CSRF, XSS protection, CORS, rate limiting, and security headers are all active.
101
+
102
+ ### What's Built In (No Extra Packages Needed)
103
+
104
+ | Category | Replaces | VoltJS Module |
105
+ |----------|----------|---------------|
106
+ | State Management | Redux, Zustand, MobX | `Reactive.createStore()` — signals, actions, undo/redo, persist |
107
+ | HTTP Client | Axios, Fetch wrappers | `HttpClient` — interceptors, retries, gzip |
108
+ | Data Fetching | SWR, React Query | `HttpClient.swr()` — stale-while-revalidate, dedup, polling |
109
+ | Routing | Express Router, Next.js | `Router` — file-based + programmatic, groups, params |
110
+ | Form Handling | React Hook Form, Formik | `Form` — dirty/touched, field errors, arrays, submit |
111
+ | Schema Validation | Zod, Yup, Joi | `Schema` — chainable types, transforms, coercion, unions |
112
+ | String Validation | Validator.js | `Validator` — 25+ rules, middleware, static checks |
113
+ | Utilities | Lodash, Underscore | `_` — chunk, debounce, groupBy, merge, cloneDeep, 80+ utils |
114
+ | Date Utils | Moment.js, Day.js, date-fns | `DateHelper` — format, ago, add, diff, range |
115
+ | UUID | uuid, nanoid | `Hash.uuid()` — crypto.randomUUID |
116
+ | CSS Classes | classnames, clsx | `_.classNames()` — conditional class merging |
117
+ | Email | Nodemailer | `Mail` — raw SMTP, attachments, templates |
118
+ | PDF | PDFKit, jsPDF | `PDF` — raw PDF generation |
119
+ | Excel | ExcelJS, SheetJS | `Excel` — CSV/XLSX read/write |
120
+ | Caching | node-cache, ioredis | `Cache` — LRU, TTL, middleware |
121
+ | Job Queues | Bull, BullMQ | `Queue` — retries, priorities, concurrency |
122
+
123
+ ---
124
+
125
+ ## Routing
126
+
127
+ ### Programmatic Routes
128
+
129
+ ```js
130
+ app.get('/users', listUsers);
131
+ app.post('/users', createUser);
132
+ app.get('/users/:id', showUser);
133
+ app.put('/users/:id', updateUser);
134
+ app.delete('/users/:id', deleteUser);
135
+
136
+ // Resource routes (auto CRUD)
137
+ app.resource('/api/posts', {
138
+ index: listPosts,
139
+ show: showPost,
140
+ store: createPost,
141
+ update: updatePost,
142
+ destroy: deletePost,
143
+ });
144
+
145
+ // Route groups
146
+ app.group('/admin', [authMiddleware], (group) => {
147
+ group.get('/dashboard', dashboard);
148
+ group.get('/settings', settings);
149
+ });
150
+ ```
151
+
152
+ ### File-Based Routing
153
+
154
+ ```
155
+ pages/
156
+ ├── index.js → GET /
157
+ ├── about.js → GET /about
158
+ ├── blog/
159
+ │ ├── index.js → GET /blog
160
+ │ └── [id].js → GET /blog/:id
161
+ api/
162
+ ├── users.js → GET/POST /api/users
163
+ └── users/
164
+ └── [id].js → GET/PUT/DELETE /api/users/:id
165
+ ```
166
+
167
+ **pages/about.js:**
168
+ ```js
169
+ module.exports = {
170
+ get(req, res) {
171
+ res.render('about', { title: 'About Us' });
172
+ },
173
+ };
174
+ ```
175
+
176
+ ---
177
+
178
+ ## Security
179
+
180
+ All protections are **enabled by default**. No setup required.
181
+
182
+ ```js
183
+ const { Volt } = require('voltjs-framework');
184
+ const app = new Volt();
185
+ // ✅ CSRF protection — active
186
+ // ✅ XSS sanitization — active
187
+ // ✅ CORS handling — active
188
+ // ✅ Rate limiting — active
189
+ // ✅ Security headers (helmet) — active
190
+ // ✅ Input sanitization — active
191
+ ```
192
+
193
+ ### Customize Security
194
+
195
+ ```js
196
+ // volt.config.js
197
+ module.exports = {
198
+ security: {
199
+ csrf: true,
200
+ cors: { origin: 'https://mysite.com', credentials: true },
201
+ rateLimit: { windowMs: 15 * 60 * 1000, max: 100 },
202
+ helmet: true,
203
+ },
204
+ };
205
+ ```
206
+
207
+ ### Manual Security Usage
208
+
209
+ ```js
210
+ const { CSRF, XSS, CORS, RateLimiter, Encryption } = require('voltjs-framework');
211
+
212
+ // Encrypt/decrypt data
213
+ const encrypted = Encryption.encrypt('sensitive data', 'secret-key');
214
+ const decrypted = Encryption.decrypt(encrypted, 'secret-key');
215
+
216
+ // Hash comparison (timing-safe)
217
+ Encryption.timingSafeCompare(hash1, hash2);
218
+
219
+ // Generate OTP
220
+ const otp = Encryption.generateOTP(6); // "482916"
221
+ ```
222
+
223
+ ---
224
+
225
+ ## Database & ORM
226
+
227
+ ### Quick Setup (In-Memory — Zero Config)
228
+
229
+ ```js
230
+ const { Database, Model } = require('voltjs-framework');
231
+
232
+ const db = new Database(); // In-memory by default
233
+ await db.connect();
234
+ ```
235
+
236
+ ### Adapters
237
+
238
+ ```js
239
+ // SQLite
240
+ const db = new Database({ driver: 'sqlite', database: './app.db' });
241
+
242
+ // MySQL
243
+ const db = new Database({ driver: 'mysql', host: 'localhost', database: 'myapp', user: 'root' });
244
+
245
+ // PostgreSQL
246
+ const db = new Database({ driver: 'postgres', host: 'localhost', database: 'myapp', user: 'postgres' });
247
+ ```
248
+
249
+ ### Active Record ORM
250
+
251
+ ```js
252
+ class User extends Model {
253
+ static table = 'users';
254
+ static schema = {
255
+ name: { type: 'string', required: true, maxLength: 100 },
256
+ email: { type: 'string', required: true },
257
+ age: { type: 'number', min: 0 },
258
+ };
259
+ }
260
+
261
+ // CRUD
262
+ const user = await User.create({ name: 'Jane', email: 'jane@example.com' });
263
+ const users = await User.all();
264
+ const found = await User.find(1);
265
+ const filtered = await User.where({ age: 25 });
266
+ await User.updateById(1, { name: 'Jane Doe' });
267
+ await User.deleteById(1);
268
+
269
+ // Pagination
270
+ const page = await User.paginate(1, 20); // { data: [...], meta: { ... } }
271
+ ```
272
+
273
+ ### Fluent Query Builder
274
+
275
+ ```js
276
+ const { QueryBuilder } = require('voltjs-framework');
277
+
278
+ const results = await new QueryBuilder(db)
279
+ .table('users')
280
+ .select('name', 'email')
281
+ .where('age', '>', 18)
282
+ .whereLike('name', '%john%')
283
+ .orderBy('created_at', 'DESC')
284
+ .limit(10)
285
+ .get();
286
+ ```
287
+
288
+ ### Migrations
289
+
290
+ ```bash
291
+ volt generate migration create_users_table
292
+ volt db:migrate
293
+ volt db:rollback
294
+ ```
295
+
296
+ ---
297
+
298
+ ## Authentication
299
+
300
+ ```js
301
+ const { Auth } = require('voltjs-framework');
302
+
303
+ // JWT
304
+ const token = Auth.generateToken({ userId: 1 }, 'secret', '24h');
305
+ const payload = Auth.verifyToken(token, 'secret');
306
+ const { accessToken, refreshToken } = Auth.generateTokenPair({ userId: 1 }, 'secret');
307
+
308
+ // Password hashing
309
+ const hash = await Auth.hashPassword('mypassword');
310
+ const valid = await Auth.verifyPassword('mypassword', hash);
311
+
312
+ // Middleware
313
+ app.get('/protected', Auth.requireAuth('secret'), handler);
314
+ app.get('/admin', Auth.requireRole('admin'), adminHandler);
315
+
316
+ // Sessions
317
+ const sessionId = Auth.createSession({ userId: 1, role: 'admin' });
318
+ const session = Auth.getSession(sessionId);
319
+
320
+ // API Keys
321
+ const key = Auth.generateApiKey();
322
+ app.get('/api/data', Auth.requireApiKey(['key1', 'key2']), handler);
323
+
324
+ // 2FA (TOTP)
325
+ const { secret, uri } = Auth.generateTOTPSecret('MyApp', 'user@email.com');
326
+ const isValid = Auth.verifyTOTP('123456', secret);
327
+
328
+ // RBAC
329
+ Auth.defineRole('editor', ['posts:read', 'posts:write', 'posts:delete']);
330
+ app.post('/posts', Auth.requirePermission('posts:write'), createPost);
331
+ ```
332
+
333
+ ---
334
+
335
+ ## Validation
336
+
337
+ ```js
338
+ const { Validator } = require('voltjs-framework');
339
+
340
+ const result = Validator.validate(req.body, {
341
+ name: 'required|string|min:2|max:50',
342
+ email: 'required|email',
343
+ age: 'required|integer|min:18|max:120',
344
+ password: 'required|min:8|strongPassword',
345
+ website: 'url',
346
+ role: 'in:admin,user,editor',
347
+ phone: 'phone',
348
+ tags: 'array',
349
+ });
350
+
351
+ if (!result.valid) {
352
+ console.log(result.errors);
353
+ // { email: ['email must be a valid email'], age: ['age must be at least 18'] }
354
+ }
355
+
356
+ // As middleware
357
+ app.post('/register', Validator.body({
358
+ name: 'required|string|min:2',
359
+ email: 'required|email',
360
+ password: 'required|min:8|strongPassword',
361
+ }), registerHandler);
362
+
363
+ // Individual validators
364
+ Validator.isEmail('test@example.com'); // true
365
+ Validator.isURL('https://example.com'); // true
366
+ Validator.isCreditCard('4111111111111111'); // true
367
+ Validator.isStrongPassword('Abc123!@#'); // true
368
+ Validator.isUUID('550e8400-e29b-41d4-a716-446655440000'); // true
369
+ ```
370
+
371
+ ---
372
+
373
+ ## Email
374
+
375
+ ```js
376
+ const { Mail } = require('voltjs-framework');
377
+
378
+ const mail = new Mail({
379
+ host: 'smtp.gmail.com',
380
+ port: 587,
381
+ user: 'you@gmail.com',
382
+ pass: 'app-password',
383
+ });
384
+
385
+ // Send email
386
+ await mail.send({
387
+ to: 'user@example.com',
388
+ subject: 'Welcome!',
389
+ html: '<h1>Hello {{name}}</h1>',
390
+ data: { name: 'John' },
391
+ });
392
+
393
+ // With attachments
394
+ await mail.send({
395
+ to: 'user@example.com',
396
+ subject: 'Report',
397
+ text: 'Please find attached.',
398
+ attachments: [
399
+ { filename: 'report.pdf', content: pdfBuffer },
400
+ ],
401
+ });
402
+
403
+ // Quick send (static)
404
+ await Mail.quickSend(config, { to, subject, html });
405
+ ```
406
+
407
+ ---
408
+
409
+ ## SMS
410
+
411
+ ```js
412
+ const { SMS } = require('voltjs-framework');
413
+
414
+ const sms = new SMS({
415
+ provider: 'twilio',
416
+ accountSid: process.env.TWILIO_SID,
417
+ authToken: process.env.TWILIO_TOKEN,
418
+ from: '+1234567890',
419
+ });
420
+
421
+ await sms.send('+1987654321', 'Hello from VoltJS!');
422
+
423
+ // Send OTP
424
+ await sms.sendOTP('+1987654321', '5829');
425
+
426
+ // Bulk send
427
+ await sms.sendBulk(['+111111', '+222222'], 'Announcement!');
428
+ ```
429
+
430
+ ---
431
+
432
+ ## Excel Import/Export
433
+
434
+ ```js
435
+ const { Excel } = require('voltjs-framework');
436
+
437
+ // Export to CSV
438
+ Excel.writeCSV('users.csv', [
439
+ { name: 'John', email: 'john@example.com', age: 30 },
440
+ { name: 'Jane', email: 'jane@example.com', age: 25 },
441
+ ]);
442
+
443
+ // Import from CSV
444
+ const data = Excel.readCSV('users.csv');
445
+
446
+ // Export to XLSX (real Excel file, zero dependencies!)
447
+ Excel.writeXLSX('report.xlsx', data, { sheetName: 'Users' });
448
+
449
+ // Import from XLSX
450
+ const xlsxData = Excel.readXLSX('report.xlsx');
451
+
452
+ // JSON import/export
453
+ Excel.writeJSON('data.json', data);
454
+ const jsonData = Excel.readJSON('data.json');
455
+ ```
456
+
457
+ ---
458
+
459
+ ## PDF Generation
460
+
461
+ ```js
462
+ const { PDF } = require('voltjs-framework');
463
+
464
+ const pdf = new PDF();
465
+ pdf.addPage();
466
+ pdf.setFont('Helvetica', 24);
467
+ pdf.text(50, 50, 'Hello VoltJS!');
468
+ pdf.setFont('Helvetica', 12);
469
+ pdf.paragraph(50, 100, 'This PDF was generated from scratch with zero dependencies.', 500);
470
+
471
+ // Tables
472
+ pdf.table(50, 200, {
473
+ headers: ['Name', 'Email', 'Role'],
474
+ rows: [
475
+ ['John Doe', 'john@example.com', 'Admin'],
476
+ ['Jane Smith', 'jane@example.com', 'User'],
477
+ ],
478
+ columnWidths: [150, 200, 100],
479
+ });
480
+
481
+ pdf.save('output.pdf');
482
+
483
+ // Quick report from data
484
+ PDF.fromData('Report Title', columns, rows).save('report.pdf');
485
+
486
+ // Generate invoice
487
+ PDF.invoice({ company, customer, items, tax }).save('invoice.pdf');
488
+ ```
489
+
490
+ ---
491
+
492
+ ## File Storage
493
+
494
+ ```js
495
+ const { Storage } = require('voltjs-framework');
496
+
497
+ const storage = new Storage({ root: './uploads' });
498
+
499
+ await storage.put('avatars/user1.png', imageBuffer);
500
+ const file = await storage.get('avatars/user1.png');
501
+ const exists = await storage.exists('avatars/user1.png');
502
+ await storage.delete('avatars/user1.png');
503
+ const url = storage.url('avatars/user1.png');
504
+
505
+ // S3-compatible storage
506
+ const s3 = new Storage({
507
+ driver: 's3',
508
+ bucket: 'my-bucket',
509
+ region: 'us-east-1',
510
+ accessKey: process.env.S3_ACCESS_KEY,
511
+ secretKey: process.env.S3_SECRET_KEY,
512
+ });
513
+
514
+ // Upload middleware
515
+ app.post('/upload', Storage.upload({
516
+ dest: 'uploads',
517
+ maxSize: 5 * 1024 * 1024, // 5MB
518
+ allowedTypes: ['image/png', 'image/jpeg'],
519
+ }), handler);
520
+ ```
521
+
522
+ ---
523
+
524
+ ## Caching
525
+
526
+ ```js
527
+ const { Cache } = require('voltjs-framework');
528
+
529
+ const cache = new Cache({ maxSize: 10000, defaultTTL: 300 });
530
+
531
+ cache.set('user:1', userData, 60); // 60 second TTL
532
+ const user = cache.get('user:1');
533
+
534
+ // Get-or-set pattern
535
+ const data = await cache.getOrSet('expensive-query', async () => {
536
+ return await db.query('SELECT ...');
537
+ }, 120);
538
+
539
+ // Response caching middleware
540
+ app.get('/api/data', Cache.middleware(60), handler);
541
+
542
+ // Stats
543
+ cache.stats(); // { size: 42, hits: 150, misses: 12, hitRate: '92.6%' }
544
+ ```
545
+
546
+ ---
547
+
548
+ ## Job Queues
549
+
550
+ ```js
551
+ const { Queue } = require('voltjs-framework');
552
+
553
+ const emailQueue = new Queue('emails', { concurrency: 3, retries: 3 });
554
+
555
+ emailQueue.process(async (job) => {
556
+ await sendEmail(job.data);
557
+ });
558
+
559
+ emailQueue.add({ to: 'user@example.com', subject: 'Hello' });
560
+ emailQueue.add(urgentJob, { priority: 'high', delay: 5000 });
561
+
562
+ emailQueue.on('completed', (job) => console.log(`Done: ${job.id}`));
563
+ emailQueue.on('failed', (job, err) => console.error(`Failed: ${err.message}`));
564
+ ```
565
+
566
+ ---
567
+
568
+ ## Scheduled Tasks (Cron)
569
+
570
+ ```js
571
+ const { Cron } = require('voltjs-framework');
572
+
573
+ const cron = new Cron();
574
+
575
+ cron.schedule('cleanup', '0 * * * *', cleanupOldFiles); // Every hour
576
+ cron.schedule('report', '0 9 * * 1', sendWeeklyReport); // Monday 9am
577
+ cron.schedule('backup', '0 2 * * *', backupDatabase); // Daily 2am
578
+
579
+ // Convenience methods
580
+ cron.everyMinute('health-check', checkHealth);
581
+ cron.daily('cleanup', cleanupTask);
582
+ cron.weekly('report', generateReport);
583
+
584
+ cron.start();
585
+ ```
586
+
587
+ ---
588
+
589
+ ## WebSockets
590
+
591
+ ```js
592
+ const { Volt, WebSocketServer } = require('voltjs-framework');
593
+ const app = new Volt();
594
+
595
+ const wss = new WebSocketServer(app, { path: '/ws' });
596
+
597
+ wss.on('connection', (client) => {
598
+ console.log(`Client connected: ${client.id}`);
599
+ client.join('lobby');
600
+
601
+ client.on('chat', (data) => {
602
+ wss.to('lobby').emit('chat', {
603
+ user: client.id,
604
+ message: data.message,
605
+ });
606
+ });
607
+ });
608
+
609
+ wss.requireAuth(async (req, client) => {
610
+ const token = req.headers['authorization'];
611
+ return Auth.verifyToken(token, 'secret');
612
+ });
613
+
614
+ app.listen(3000);
615
+ ```
616
+
617
+ ---
618
+
619
+ ## GraphQL
620
+
621
+ ```js
622
+ const { GraphQLHandler } = require('voltjs-framework');
623
+
624
+ const gql = new GraphQLHandler();
625
+
626
+ gql.type('User', {
627
+ id: 'ID!',
628
+ name: 'String!',
629
+ email: 'String',
630
+ });
631
+
632
+ gql.query('users', {}, async () => await User.all());
633
+ gql.query('user', { id: 'ID!' }, async ({ id }) => await User.find(id));
634
+
635
+ gql.mutation('createUser', { name: 'String!', email: 'String!' }, async (args) => {
636
+ return await User.create(args);
637
+ });
638
+
639
+ app.post('/graphql', gql.middleware());
640
+ ```
641
+
642
+ ---
643
+
644
+ ## REST API Builder
645
+
646
+ ```js
647
+ const { RestAPI } = require('voltjs-framework');
648
+
649
+ const api = new RestAPI(app, { prefix: '/api/v1' });
650
+
651
+ api.resource('users', {
652
+ async index(req, res) { return await User.all(); },
653
+ async show(req, res) { return await User.find(req.params.id); },
654
+ async store(req, res) { return await User.create(req.body); },
655
+ async update(req, res) { return await User.updateById(req.params.id, req.body); },
656
+ async destroy(req, res) { await User.deleteById(req.params.id); res.noContent(); },
657
+ });
658
+
659
+ // Versioned API groups
660
+ api.version(2, (v2) => {
661
+ v2.get('/status', (req, res) => res.json({ version: 2, status: 'ok' }));
662
+ });
663
+ ```
664
+
665
+ ---
666
+
667
+ ## Reactive State
668
+
669
+ ```js
670
+ const { Reactive } = require('voltjs-framework');
671
+
672
+ const count = Reactive.signal(0);
673
+ const doubled = Reactive.computed(() => count.value * 2);
674
+
675
+ Reactive.effect(() => {
676
+ console.log(`Count: ${count.value}, Doubled: ${doubled.value}`);
677
+ });
678
+
679
+ count.value = 5; // Logs: "Count: 5, Doubled: 10"
680
+
681
+ // Reactive store
682
+ const store = Reactive.store({
683
+ user: null,
684
+ theme: 'dark',
685
+ count: 0,
686
+ });
687
+
688
+ store.$watch('count', (val) => console.log('Count changed:', val));
689
+ store.count = 42;
690
+
691
+ // Batch updates
692
+ Reactive.batch(() => {
693
+ store.count = 1;
694
+ store.theme = 'light';
695
+ }); // Single re-render
696
+ ```
697
+
698
+ ### Advanced Store (Redux-like Actions, Undo/Redo, Persist)
699
+
700
+ ```js
701
+ const counter = Reactive.createStore({
702
+ state: { count: 0, todos: [] },
703
+ actions: {
704
+ increment(state) { state.count++; },
705
+ add(state, amount) { state.count += amount; },
706
+ addTodo(state, text) { state.todos = [...state.todos, text]; },
707
+ },
708
+ middleware: [Reactive.loggerMiddleware],
709
+ persist: { storage: 'file', path: './.store.json' },
710
+ history: true,
711
+ });
712
+
713
+ counter.dispatch('increment');
714
+ counter.dispatch('add', 5);
715
+
716
+ // Memoized selectors
717
+ const total = counter.select(s => s.count);
718
+ console.log(total.value); // 6
719
+
720
+ // Undo / Redo
721
+ counter.$undo();
722
+ console.log(counter.count); // 1
723
+ counter.$redo();
724
+ console.log(counter.count); // 6
725
+
726
+ // Subscribe to all changes
727
+ counter.$subscribe((key, value, snapshot) => {
728
+ console.log(`${key} changed to`, value);
729
+ });
730
+ ```
731
+
732
+ ---
733
+
734
+ ## Components
735
+
736
+ ```js
737
+ const { Component } = require('voltjs-framework');
738
+
739
+ class Card extends Component {
740
+ setup() {
741
+ this.state = { likes: 0 };
742
+ }
743
+
744
+ render() {
745
+ return `
746
+ <div class="${this.$class({ card: true, featured: this.props.featured })}">
747
+ <h3>${this.$escape(this.props.title)}</h3>
748
+ <p>${this.$escape(this.props.body)}</p>
749
+ <span>Likes: ${this.state.likes}</span>
750
+ </div>
751
+ `;
752
+ }
753
+ }
754
+
755
+ // Usage in route
756
+ app.get('/cards', (req, res) => {
757
+ const html = Component.render(Card, { title: 'Hello', body: 'World' });
758
+ res.html(html);
759
+ });
760
+ ```
761
+
762
+ ---
763
+
764
+ ## Template Engine
765
+
766
+ VoltJS includes a Mustache-like template engine with layouts, partials, loops, and conditionals.
767
+
768
+ ```html
769
+ <!-- views/layouts/main.volt -->
770
+ <!DOCTYPE html>
771
+ <html>
772
+ <head><title>{{ title }}</title></head>
773
+ <body>
774
+ {> header}
775
+ <main>{#slot content}</main>
776
+ {> footer}
777
+ </body>
778
+ </html>
779
+
780
+ <!-- views/index.volt -->
781
+ {#layout layouts/main}
782
+
783
+ {#block content}
784
+ <h1>{{ title }}</h1>
785
+
786
+ {#if user}
787
+ <p>Welcome, {{ user.name }}!</p>
788
+ {#else}
789
+ <p>Please log in.</p>
790
+ {/if}
791
+
792
+ <ul>
793
+ {#each items as item}
794
+ <li>{{ item.name }} - ${{ item.price }}</li>
795
+ {/each}
796
+ </ul>
797
+ {/block}
798
+ ```
799
+
800
+ ```js
801
+ app.get('/', (req, res) => {
802
+ res.render('index', { title: 'Home', user, items });
803
+ });
804
+ ```
805
+
806
+ ---
807
+
808
+ ## Form Handling
809
+
810
+ Built-in form state management — like **React Hook Form** with dirty/touched tracking,
811
+ field-level errors, array fields, watchers, and submission handling.
812
+
813
+ ```js
814
+ const { Form } = require('voltjs-framework');
815
+
816
+ const form = new Form({
817
+ defaults: { name: '', email: '', tags: [] },
818
+ rules: {
819
+ name: 'required|string|min:2',
820
+ email: 'required|email',
821
+ },
822
+ validateOn: 'change', // 'change' | 'blur' | 'submit'
823
+ onSubmit: async (data) => await User.create(data),
824
+ });
825
+
826
+ form.set('name', 'John');
827
+ form.set('email', 'john@example.com');
828
+
829
+ // State tracking
830
+ form.isDirty; // true
831
+ form.isFieldDirty('name'); // true
832
+ form.isFieldTouched('name'); // false
833
+ form.touch('name'); // mark as touched
834
+ form.dirtyValues; // { name: 'John', email: 'john@example.com' }
835
+
836
+ // Array fields
837
+ form.append('tags', 'javascript');
838
+ form.append('tags', 'nodejs');
839
+ form.remove('tags', 0);
840
+ form.move('tags', 0, 1);
841
+
842
+ // Nested fields (dot notation)
843
+ form.set('address.city', 'NYC');
844
+ form.get('address.city'); // 'NYC'
845
+
846
+ // Watch field changes
847
+ form.watch('email', (newVal, oldVal) => console.log('Email changed'));
848
+
849
+ // Submit
850
+ const result = await form.submit();
851
+ // { success: true, data: { ... } } or { success: false, errors: { ... } }
852
+
853
+ // Reset
854
+ form.reset();
855
+
856
+ // As middleware
857
+ app.post('/register', Form.handle({
858
+ rules: { name: 'required', email: 'required|email' },
859
+ onSubmit: (data) => User.create(data),
860
+ }), (req, res) => {
861
+ res.json(req.formResult);
862
+ });
863
+ ```
864
+
865
+ ---
866
+
867
+ ## Schema Validation (Zod)
868
+
869
+ Type-safe, chainable schema builder — like **Zod/Yup** with transforms, coercion,
870
+ nested objects, arrays, unions, and enums.
871
+
872
+ ```js
873
+ const { Schema } = require('voltjs-framework');
874
+
875
+ const userSchema = Schema.object({
876
+ name: Schema.string().min(2).max(50).trim().required(),
877
+ email: Schema.string().email().toLowerCase().required(),
878
+ age: Schema.number().int().min(18).max(120).optional(),
879
+ role: Schema.enum(['admin', 'user', 'editor']).default('user'),
880
+ tags: Schema.array(Schema.string()).min(1).unique(),
881
+ website: Schema.string().url().optional(),
882
+ address: Schema.object({
883
+ street: Schema.string(),
884
+ city: Schema.string().required(),
885
+ zip: Schema.string().regex(/^\d{5}$/),
886
+ }).optional(),
887
+ });
888
+
889
+ // Validate (returns result)
890
+ const result = userSchema.validate(data);
891
+ if (!result.valid) console.log(result.errors);
892
+
893
+ // Parse (throws on invalid)
894
+ const parsed = userSchema.parse(data);
895
+
896
+ // Safe parse (never throws)
897
+ const safe = userSchema.safeParse(data);
898
+
899
+ // Schema composition
900
+ const updateSchema = userSchema.partial(); // All fields optional
901
+ const loginSchema = userSchema.pick(['email']); // Only email
902
+ const publicSchema = userSchema.omit(['age']); // Remove age
903
+
904
+ // Coercion (auto-convert types)
905
+ const configSchema = Schema.object({
906
+ port: Schema.number().coerce().int().min(0).max(65535),
907
+ debug: Schema.boolean().coerce(),
908
+ });
909
+ configSchema.parse({ port: '3000', debug: 'true' });
910
+ // { port: 3000, debug: true }
911
+
912
+ // Unions, literals, tuples
913
+ const statusSchema = Schema.union([
914
+ Schema.literal('active'),
915
+ Schema.literal('inactive'),
916
+ ]);
917
+
918
+ const pointSchema = Schema.tuple([
919
+ Schema.number(), Schema.number(),
920
+ ]);
921
+
922
+ // Custom refinements
923
+ const passwordSchema = Schema.string()
924
+ .min(8)
925
+ .refine(v => /[A-Z]/.test(v), 'Must have uppercase')
926
+ .refine(v => /\d/.test(v), 'Must have a number');
927
+
928
+ // Record (key-value maps)
929
+ const envSchema = Schema.record(Schema.string(), Schema.string());
930
+
931
+ // Recursive schemas
932
+ const categorySchema = Schema.object({
933
+ name: Schema.string().required(),
934
+ children: Schema.lazy(() => Schema.array(categorySchema)),
935
+ });
936
+ ```
937
+
938
+ ---
939
+
940
+ ## Collection Utilities (Lodash)
941
+
942
+ Full **Lodash-equivalent** utilities — arrays, objects, functions — zero dependencies.
943
+
944
+ ```js
945
+ const { _ } = require('voltjs-framework');
946
+
947
+ // Arrays
948
+ _.chunk([1,2,3,4,5], 2); // [[1,2],[3,4],[5]]
949
+ _.compact([0, 1, false, 2, '']); // [1, 2]
950
+ _.flatten([[1,[2]],[3]]); // [1,[2],3]
951
+ _.flattenDeep([[1,[2,[3]]]]); // [1,2,3]
952
+ _.uniq([1, 2, 2, 3]); // [1, 2, 3]
953
+ _.uniqBy(users, 'email'); // Unique by email
954
+ _.intersection([1,2], [2,3]); // [2]
955
+ _.difference([1,2,3], [2,3]); // [1]
956
+ _.union([1,2], [2,3]); // [1,2,3]
957
+ _.zip([1,2], ['a','b']); // [[1,'a'],[2,'b']]
958
+
959
+ // Grouping & sorting
960
+ _.groupBy(users, 'role'); // { admin: [...], user: [...] }
961
+ _.keyBy(users, 'id'); // { 1: {...}, 2: {...} }
962
+ _.sortBy(users, 'name'); // Sorted by name
963
+ _.orderBy(users, ['age','name'], ['desc','asc']);
964
+ _.countBy(users, 'role'); // { admin: 2, user: 5 }
965
+ _.partition(nums, n => n > 0); // [[positives], [negatives]]
966
+
967
+ // Aggregation
968
+ _.sum([1, 2, 3]); // 6
969
+ _.sumBy(items, 'price'); // Total price
970
+ _.mean([1, 2, 3, 4]); // 2.5
971
+ _.minBy(users, 'age'); // Youngest user
972
+ _.maxBy(users, 'age'); // Oldest user
973
+
974
+ // Random
975
+ _.sample([1, 2, 3]); // Random element
976
+ _.sampleSize([1,2,3,4], 2); // 2 random elements
977
+ _.shuffle([1, 2, 3, 4, 5]); // Shuffled
978
+ _.range(0, 10, 2); // [0, 2, 4, 6, 8]
979
+ _.times(5, i => i * 2); // [0, 2, 4, 6, 8]
980
+
981
+ // Objects
982
+ _.get(obj, 'a.b[0].c', 'default'); // Deep path access
983
+ _.set(obj, 'a.b.c', 42); // Deep path set
984
+ _.has(obj, 'a.b.c'); // true/false
985
+ _.pick(obj, ['name', 'email']); // { name, email }
986
+ _.omit(obj, ['password']); // Without password
987
+ _.merge(defaults, overrides); // Deep merge
988
+ _.cloneDeep(obj); // Deep clone
989
+ _.isEqual(objA, objB); // Deep equality
990
+ _.isEmpty({}); // true
991
+ _.mapValues(obj, v => v * 2); // Transform values
992
+ _.mapKeys(obj, k => k.toUpperCase());
993
+ _.invert({ a: 1, b: 2 }); // { 1: 'a', 2: 'b' }
994
+ _.freezeDeep(obj); // Deep freeze (immutable)
995
+
996
+ // Functions
997
+ const save = _.debounce(saveData, 300); // Debounce
998
+ const scroll = _.throttle(onScroll, 100); // Throttle
999
+ const loadOnce = _.once(loadConfig); // Execute only once
1000
+ const factorial = _.memoize(calcFactorial);// Memoize results
1001
+ _.curry(fn); // Curry
1002
+ _.pipe(fn1, fn2, fn3)(input); // Pipe (left to right)
1003
+ _.compose(fn3, fn2, fn1)(input); // Compose (right to left)
1004
+ await _.retry(fetchData, { attempts: 3 }); // Retry with backoff
1005
+ await _.delay(fn, 1000); // Delayed execution
1006
+ await _.sleep(500); // Sleep/wait
1007
+
1008
+ // Type checks
1009
+ _.isString('hello'); // true
1010
+ _.isNumber(42); // true
1011
+ _.isArray([]); // true
1012
+ _.isObject({}); // true
1013
+ _.isNil(null); // true
1014
+ _.isPlainObject({}); // true
1015
+ _.isEmpty([]); // true
1016
+
1017
+ // Misc
1018
+ _.toQueryString({ page: 1, q: 'hello' }); // 'page=1&q=hello'
1019
+ _.parseQueryString('page=1&q=hello'); // { page: '1', q: 'hello' }
1020
+ _.tryParse('{"a":1}'); // { a: 1 }
1021
+ _.uniqueId('user_'); // 'user_1'
1022
+ ```
1023
+
1024
+ ---
1025
+
1026
+ ## classNames / clsx
1027
+
1028
+ ```js
1029
+ const { _ } = require('voltjs-framework');
1030
+
1031
+ _.classNames('btn', { active: true, disabled: false }, 'primary');
1032
+ // => 'btn active primary'
1033
+
1034
+ _.classNames('flex', condition && 'hidden', ['p-4', { 'bg-red': error }]);
1035
+ // => 'flex hidden p-4 bg-red' (if condition and error are truthy)
1036
+
1037
+ _.clsx('text-lg', { bold: isBold }); // Alias for classNames
1038
+ ```
1039
+
1040
+ ---
1041
+
1042
+ ## Logging
1043
+
1044
+ ```js
1045
+ const { Logger } = require('voltjs-framework');
1046
+
1047
+ const log = new Logger({ level: 'debug', file: 'logs/app.log' });
1048
+
1049
+ log.info('Server started', { port: 3000 });
1050
+ log.debug('Query executed', { sql: '...', duration: '12ms' });
1051
+ log.warn('Deprecated API used');
1052
+ log.error('Connection failed', { error: err.message });
1053
+
1054
+ // Request logging middleware
1055
+ app.use(Logger.requestLogger());
1056
+
1057
+ // Child loggers
1058
+ const dbLog = log.child('database');
1059
+ dbLog.info('Connected'); // [database] Connected
1060
+
1061
+ // Timing
1062
+ const timer = log.time('query');
1063
+ await db.query('...');
1064
+ timer.end(); // "query completed in 12.34ms"
1065
+ ```
1066
+
1067
+ ---
1068
+
1069
+ ## HTTP Client
1070
+
1071
+ ```js
1072
+ const { HttpClient } = require('voltjs-framework');
1073
+
1074
+ // Quick usage
1075
+ const response = await HttpClient.get('https://api.example.com/users');
1076
+ console.log(response.data);
1077
+
1078
+ // Instance with defaults
1079
+ const api = new HttpClient({
1080
+ baseURL: 'https://api.example.com',
1081
+ timeout: 10000,
1082
+ retries: 2,
1083
+ });
1084
+
1085
+ api.setBearerToken('my-token');
1086
+
1087
+ const users = await api.get('/users');
1088
+ const created = await api.post('/users', { name: 'John' });
1089
+ const updated = await api.put('/users/1', { name: 'Jane' });
1090
+ await api.delete('/users/1');
1091
+
1092
+ // Download files
1093
+ await api.download('https://example.com/file.pdf', './downloads/file.pdf');
1094
+
1095
+ // SWR (stale-while-revalidate) — like SWR/React Query
1096
+ const fetcher = HttpClient.swr({ ttl: 30, revalidate: 120 });
1097
+ const data = await fetcher.get('/api/users'); // Cached + background refresh
1098
+ fetcher.mutate('/api/users', newData); // Optimistic update
1099
+ fetcher.invalidate('/api/users'); // Force refetch
1100
+
1101
+ // Polling
1102
+ const poller = HttpClient.poll('https://api.example.com/status', {
1103
+ interval: 5000,
1104
+ onData: (data) => console.log(data),
1105
+ until: (data) => data.status === 'complete',
1106
+ });
1107
+ poller.stop();
1108
+
1109
+ // Concurrent requests
1110
+ const [users, posts] = await HttpClient.all([
1111
+ HttpClient.get('/api/users'),
1112
+ HttpClient.get('/api/posts'),
1113
+ ]);
1114
+
1115
+ // Abortable requests
1116
+ const { promise, abort } = HttpClient.abortable('https://api.example.com/data');
1117
+ setTimeout(() => abort(), 5000);
1118
+ const result = await promise;
1119
+ ```
1120
+
1121
+ ---
1122
+
1123
+ ## CLI Commands
1124
+
1125
+ ```bash
1126
+ volt create <name> # Create a new project
1127
+ volt dev # Start dev server with hot reload
1128
+ volt build # Build for production
1129
+ volt start # Start production server
1130
+
1131
+ volt generate page <name> # Generate a page + view
1132
+ volt generate api <name> # Generate an API route
1133
+ volt generate component <name> # Generate a component
1134
+ volt generate model <name> # Generate a model
1135
+ volt generate middleware <name> # Generate middleware
1136
+ volt generate migration <name> # Generate a migration
1137
+ volt generate seeder <name> # Generate a seeder
1138
+
1139
+ volt db:migrate # Run migrations
1140
+ volt db:rollback # Rollback last migration
1141
+ volt db:seed # Run seeders
1142
+
1143
+ volt routes # List all routes
1144
+ volt lint # Lint project
1145
+ volt test # Run tests
1146
+ ```
1147
+
1148
+ ---
1149
+
1150
+ ## Configuration
1151
+
1152
+ **volt.config.js:**
1153
+ ```js
1154
+ module.exports = {
1155
+ port: 3000,
1156
+
1157
+ security: {
1158
+ csrf: true,
1159
+ cors: { origin: '*', credentials: true },
1160
+ rateLimit: { windowMs: 900000, max: 100 },
1161
+ helmet: true,
1162
+ },
1163
+
1164
+ database: {
1165
+ driver: 'sqlite', // 'memory' | 'sqlite' | 'mysql' | 'postgres'
1166
+ database: './app.db',
1167
+ },
1168
+
1169
+ views: {
1170
+ dir: './views',
1171
+ engine: 'volt',
1172
+ },
1173
+
1174
+ mail: {
1175
+ host: process.env.MAIL_HOST,
1176
+ port: 587,
1177
+ user: process.env.MAIL_USER,
1178
+ pass: process.env.MAIL_PASS,
1179
+ },
1180
+
1181
+ logging: {
1182
+ level: 'info',
1183
+ file: './logs/app.log',
1184
+ },
1185
+ };
1186
+ ```
1187
+
1188
+ All settings can be overridden via environment variables:
1189
+ - `PORT`, `NODE_ENV`
1190
+ - `DB_DRIVER`, `DB_HOST`, `DB_PORT`, `DB_DATABASE`, `DB_USER`, `DB_PASSWORD`
1191
+ - `MAIL_HOST`, `MAIL_PORT`, `MAIL_USER`, `MAIL_PASS`
1192
+ - `APP_SECRET`
1193
+
1194
+ ---
1195
+
1196
+ ## Project Structure
1197
+
1198
+ ```
1199
+ my-app/
1200
+ ├── app.js # Application entry point
1201
+ ├── volt.config.js # Configuration
1202
+ ├── package.json
1203
+ ├── .env # Environment variables
1204
+ ├── pages/ # File-based routes (auto-discovered)
1205
+ │ ├── index.js # → GET /
1206
+ │ └── about.js # → GET /about
1207
+ ├── api/ # API routes (auto-discovered)
1208
+ │ └── users.js # → /api/users
1209
+ ├── views/ # Templates
1210
+ │ ├── layouts/
1211
+ │ │ └── main.volt
1212
+ │ ├── partials/
1213
+ │ │ ├── header.volt
1214
+ │ │ └── footer.volt
1215
+ │ └── index.volt
1216
+ ├── components/ # Reusable components
1217
+ ├── models/ # Database models
1218
+ ├── middleware/ # Custom middleware
1219
+ ├── public/ # Static assets (served automatically)
1220
+ │ ├── css/
1221
+ │ ├── js/
1222
+ │ └── images/
1223
+ ├── database/
1224
+ │ ├── migrations/
1225
+ │ └── seeders/
1226
+ ├── storage/ # File uploads
1227
+ ├── tests/ # Test files
1228
+ └── logs/ # Log files
1229
+ ```
1230
+
1231
+ ---
1232
+
1233
+ ## Design Principles
1234
+
1235
+ 1. **Zero Config** — Works out of the box with sensible defaults
1236
+ 2. **Security First** — All protections enabled by default
1237
+ 3. **Batteries Included** — No hunting for packages
1238
+ 4. **Minimal Boilerplate** — 2 files to start a full app
1239
+ 5. **Progressive** — Use only what you need
1240
+ 6. **Zero External Dependencies** — Only `ws` for WebSocket support; everything else uses native Node.js
1241
+
1242
+ ---
1243
+
1244
+ ## Requirements
1245
+
1246
+ - **Node.js** >= 18.0.0
1247
+
1248
+ ## Optional Dependencies
1249
+
1250
+ | Package | For |
1251
+ |---------|-----|
1252
+ | `ws` | WebSocket support |
1253
+ | `better-sqlite3` | SQLite database |
1254
+ | `mysql2` | MySQL database |
1255
+ | `pg` | PostgreSQL database |
1256
+
1257
+ ---
1258
+
1259
+ ## License
1260
+
1261
+ MIT
1262
+
1263
+ ---
1264
+
1265
+ **Built with âš¡ by the VoltJS team.**