veloxapi
Version:
An ultra-fast, zero-dependency Node.js web framework built entirely with Node.js built-in modules
916 lines (689 loc) • 22.7 kB
Markdown
# VeloxAPI
> **Ultra-fast, zero-dependency Node.js web framework**
[](https://www.npmjs.com/package/veloxapi)
[](LICENSE)
[](https://nodejs.org/)
[](./tests)
[](package.json)
VeloxAPI is a high-performance web framework built entirely with Node.js built-in modules. **Zero dependencies**, maximum speed, production-ready.
---
## ⚡ Why VeloxAPI?
### The Problem with Traditional Frameworks
Most Node.js frameworks come with baggage:
```bash
# Express.js dependencies
express@4.18.0
├── body-parser (+ 15 deps)
├── cookie (+ 2 deps)
├── debug (+ 3 deps)
└── ... 30+ total dependencies
# Fastify dependencies
fastify@4.x
├── ajv (+ 10 deps)
├── fast-json-stringify (+ 5 deps)
└── ... 20+ total dependencies
```
**Every dependency:**
- 🐌 Adds startup overhead
- 🔓 Introduces security vulnerabilities
- 💔 Can break with updates
- 📦 Increases bundle size
### The VeloxAPI Solution
```bash
veloxapi@0.2.0-alpha.1
└── (zero dependencies)
```
**Built entirely with Node.js native modules:**
- ⚡ **Maximum Performance** - No external overhead, optimized algorithms
- 🛡️ **Secure** - No third-party vulnerabilities
- 🪶 **Lightweight** - ~50KB bundle size
- 🎯 **Predictable** - No breaking changes from dependencies
- 🚀 **Fast Startup** - No dependency tree to load
---
## 🏆 VeloxAPI vs Other Frameworks
| Feature | VeloxAPI | Fastify | Express | Koa |
|---------|----------|---------|---------|-----|
| **Dependencies** | 0 | 20+ | 30+ | 5+ |
| **Routing Speed** | O(log n) radix | O(log n) radix | O(n) linear | O(n) linear |
| **Body Parsing** | Lazy (on-demand) | Eager | Eager | Plugin |
| **Streaming** | Built-in | Plugin | Limited | Plugin |
| **Typed Params** | Built-in (12 types) | None | None | None |
| **Object Pooling** | Built-in | None | None | None |
| **Security** | Built-in | Plugin | Plugin | Plugin |
| **Bundle Size** | ~50KB | ~200KB | ~150KB | ~80KB |
### Key Differentiators
1. **Zero Dependencies** - Complete control, no external risks
2. **Radix Tree Routing** - O(log n) lookups vs O(n) linear (Express/Koa)
3. **Lazy Body Parsing** - Parse only when needed (performance win)
4. **Object Pooling** - Reuse Request/Response objects (reduces GC)
5. **Typed Parameters** - Built-in validation (12 types)
6. **True Streaming** - Constant memory usage for large files
---
## 🚀 Quick Start
### Requirements
- **Node.js 18+** (with ES modules support)
- **ES Modules** - Your package.json needs `"type": "module"`
### Installation
```bash
npm install veloxapi
```
### Your First Server (30 seconds)
```javascript
import { VeloxServer, VeloxRouter } from 'veloxapi';
const router = new VeloxRouter();
router.get('/', (res) => {
res.sendJSON({ message: 'Hello VeloxAPI!' });
});
const server = new VeloxServer()
.setPort(3000)
.setRouter(router)
.start();
console.log('🚀 Server running at http://localhost:3000');
```
**Run it:**
```bash
node server.js
```
Visit http://localhost:3000 - You're done! 🎉
---
## 💡 Core Concepts
### 1. The Router (Define Your Routes)
```javascript
import { VeloxRouter } from 'veloxapi';
const router = new VeloxRouter();
// Basic routes
router.get('/users', (res) => {
res.sendJSON({ users: [] });
});
router.post('/users', async (res, req) => {
const body = await req.getBody();
res.status(201).sendJSON({ user: body });
});
```
### 2. The Server (Start Listening)
```javascript
import { VeloxServer } from 'veloxapi';
const server = new VeloxServer()
.setPort(3000) // Port number
.setHost('0.0.0.0') // Bind to all interfaces
.setRouter(router) // Attach your router
.start(); // Start listening
```
### 3. Handler Signature
```javascript
router.get('/path', (res, req, query, params, data) => {
// res - Response object (send data)
// req - Request object (get data)
// query - Query parameters (?page=1)
// params - Route parameters (/:id)
// data - Shared data from middleware
});
```
---
## 📚 Progressive Examples
### Example 1: Simple API (Beginner)
```javascript
import { VeloxServer, VeloxRouter } from 'veloxapi';
const router = new VeloxRouter();
router.get('/api/status', (res) => {
res.sendJSON({
status: 'ok',
timestamp: Date.now()
});
});
router.get('/api/hello/:name', (res, req, query, params) => {
res.sendJSON({
message: `Hello, ${params.name}!`
});
});
new VeloxServer().setPort(3000).setRouter(router).start();
```
**Test it:**
```bash
curl http://localhost:3000/api/status
curl http://localhost:3000/api/hello/Alice
```
---
### Example 2: REST API with Validation (Intermediate)
```javascript
import { VeloxServer, VeloxRouter } from 'veloxapi';
const router = new VeloxRouter();
const users = [
{ id: 1, name: 'Alice', email: 'alice@example.com' },
{ id: 2, name: 'Bob', email: 'bob@example.com' }
];
// List all users
router.get('/api/users', (res) => {
res.sendJSON({ users, total: users.length });
});
// Get user by ID (with type validation!)
router.get('/api/users/:id=number', (res, req, query, params) => {
const user = users.find(u => u.id === params.id);
if (!user) {
return res.sendError('User not found', 404);
}
res.sendJSON({ user });
});
// Create user with validation
router.post('/api/users', async (res, req) => {
const body = await req.getBody();
// Validate required fields
if (!body.name || !body.email) {
return res.sendError('Missing name or email', 400);
}
const user = {
id: users.length + 1,
name: body.name,
email: body.email
};
users.push(user);
res.status(201).sendJSON({ user });
});
// Update user
router.put('/api/users/:id=number', async (res, req, query, params) => {
const user = users.find(u => u.id === params.id);
if (!user) {
return res.sendError('User not found', 404);
}
const body = await req.getBody();
Object.assign(user, body);
res.sendJSON({ user });
});
// Delete user
router.delete('/api/users/:id=number', (res, req, query, params) => {
const index = users.findIndex(u => u.id === params.id);
if (index === -1) {
return res.sendError('User not found', 404);
}
users.splice(index, 1);
res.status(204).send();
});
new VeloxServer().setPort(3000).setRouter(router).start();
```
**Test the CRUD API:**
```bash
# List users
curl http://localhost:3000/api/users
# Get user
curl http://localhost:3000/api/users/1
# Create user
curl -X POST http://localhost:3000/api/users \
-H "Content-Type: application/json" \
-d '{"name":"Charlie","email":"charlie@example.com"}'
# Update user
curl -X PUT http://localhost:3000/api/users/1 \
-H "Content-Type: application/json" \
-d '{"name":"Alice Smith"}'
# Delete user
curl -X DELETE http://localhost:3000/api/users/2
```
---
### Example 3: Middleware & Authentication (Advanced)
```javascript
import { VeloxServer, VeloxRouter } from 'veloxapi';
import crypto from 'crypto';
const router = new VeloxRouter();
// Mock users database
const users = new Map([
['token-alice', { id: 1, name: 'Alice', role: 'admin' }],
['token-bob', { id: 2, name: 'Bob', role: 'user' }]
]);
// Logging middleware (runs on ALL requests)
router.use((res, req, query, params, data, next) => {
const start = Date.now();
console.log(`→ ${req.getMethod()} ${req.getPathname()}`);
// Run after response
res.on('finish', () => {
const duration = Date.now() - start;
console.log(`← ${res.statusCode} (${duration}ms)`);
});
next();
});
// CORS middleware (runs on ALL requests)
router.use((res, req, query, params, data, next) => {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
next();
});
// Auth middleware (runs ONLY on POST/PUT/DELETE)
router.use((res, req, query, params, data, next) => {
const token = req.getHeader('authorization')?.replace('Bearer ', '');
if (!token) {
return res.sendError('Missing authorization token', 401);
}
const user = users.get(token);
if (!user) {
return res.sendError('Invalid token', 401);
}
data.user = user; // Store user in shared data
next();
}, '@method POST,PUT,DELETE');
// Admin-only middleware
const requireAdmin = (res, req, query, params, data, next) => {
if (data.user.role !== 'admin') {
return res.sendError('Admin access required', 403);
}
next();
};
// Public route (no auth required)
router.get('/api/public', (res) => {
res.sendJSON({ message: 'Public data' });
});
// Protected route (auth required)
router.post('/api/posts', async (res, req, query, params, data) => {
const body = await req.getBody();
res.status(201).sendJSON({
post: body,
author: data.user.name // From auth middleware
});
});
// Admin-only route
router.delete('/api/users/:id', requireAdmin, (res, req, query, params, data) => {
res.sendJSON({
deleted: params.id,
by: data.user.name
});
});
new VeloxServer().setPort(3000).setRouter(router).start();
```
**Test middleware:**
```bash
# Public route (no auth)
curl http://localhost:3000/api/public
# Protected route (needs auth)
curl -X POST http://localhost:3000/api/posts \
-H "Authorization: Bearer token-alice" \
-H "Content-Type: application/json" \
-d '{"title":"My Post"}'
# Admin route (needs admin)
curl -X DELETE http://localhost:3000/api/users/123 \
-H "Authorization: Bearer token-alice"
```
---
### Example 4: File Uploads & Streaming (Production)
```javascript
import { VeloxServer, VeloxRouter } from 'veloxapi';
import { writeFile, mkdir } from 'fs/promises';
import { existsSync } from 'fs';
import path from 'path';
const router = new VeloxRouter();
// Ensure upload directory exists
if (!existsSync('./uploads')) {
await mkdir('./uploads', { recursive: true });
}
// Upload single or multiple files
router.post('/api/upload', async (res, req) => {
const body = await req.getBody();
if (!body.files || body.files.length === 0) {
return res.sendError('No files uploaded', 400);
}
const uploaded = [];
for (const file of body.files) {
const filename = `${Date.now()}-${file.filename}`;
const filepath = path.join('./uploads', filename);
await writeFile(filepath, file.data);
uploaded.push({ filename, size: file.data.length });
}
res.status(201).sendJSON({
uploaded: uploaded.length,
files: uploaded
});
});
// Stream file download (constant memory!)
router.get('/api/download/:filename', async (res, req, query, params) => {
const filename = params.filename;
// Security: prevent path traversal
if (filename.includes('..') || filename.includes('/')) {
return res.sendError('Invalid filename', 400);
}
try {
await res.sendFile(filename, './uploads');
} catch (err) {
res.sendError('File not found', 404);
}
});
// List uploaded files
router.get('/api/files', async (res) => {
const { readdir, stat } = await import('fs/promises');
const files = await readdir('./uploads');
const fileList = await Promise.all(
files.map(async (name) => {
const stats = await stat(path.join('./uploads', name));
return {
name,
size: stats.size,
modified: stats.mtime
};
})
);
res.sendJSON({ files: fileList, total: fileList.length });
});
new VeloxServer().setPort(3000).setRouter(router).start();
```
**Test file operations:**
```bash
# Upload file
curl -X POST http://localhost:3000/api/upload \
-F "file=@./photo.jpg"
# List files
curl http://localhost:3000/api/files
# Download file
curl http://localhost:3000/api/download/1234567890-photo.jpg -O
```
---
## ✨ Key Features
### 🎯 Typed Parameters (12 Validators)
Automatic validation and type conversion:
```javascript
// Number validation
router.get('/users/:id=number', (res, req, query, params) => {
console.log(typeof params.id); // 'number'
res.sendJSON({ userId: params.id });
});
// Email validation
router.get('/verify/:email=email', (res, req, query, params) => {
res.sendJSON({ email: params.email });
});
// UUID validation
router.get('/orders/:orderId=uuid', (res, req, query, params) => {
res.sendJSON({ orderId: params.orderId });
});
```
**Available validators:** `string`, `number`, `int`, `float`, `boolean`, `email`, `url`, `uuid`, `slug`, `alpha`, `alphanumeric`, `hex`
### 💤 Lazy Body Parsing
Parse only when needed for better performance:
```javascript
// Body parsed ONLY if handler calls getBody()
router.post('/users', async (res, req) => {
const body = await req.getBody(); // Parse here
res.status(201).sendJSON({ user: body });
});
// No parsing overhead if not needed
router.post('/webhook', (res, req) => {
res.sendJSON({ received: true }); // Body never parsed
});
```
**Supports:** JSON, XML, YAML, form-data, multipart file uploads
### 🌊 True Streaming
Constant memory usage for large files:
```javascript
// Stream 1GB file with only ~1MB memory usage
router.get('/video/:id', async (res, req, query, params) => {
await res.sendFile(`${params.id}.mp4`, './videos');
// Handles range requests, MIME detection, streaming automatically
});
```
### ⚡ Object Pooling (v0.2.0+)
Reuse objects for reduced GC overhead:
```javascript
const server = new VeloxServer()
.setPort(3000)
.setRouter(router)
.start();
// Check pool statistics
console.log(server.getStats());
// {
// requestPool: { size: 50, available: 45, created: 100 },
// responsePool: { size: 50, available: 45, created: 100 }
// }
```
---
## 🎓 Learning Path
Start your VeloxAPI journey with our comprehensive tutorials:
1. **[Getting Started](./learn/01-getting-started.md)** - Build your first API in 15 minutes
2. **[Typed Parameters](./learn/02-typed-parameters.md)** - Master automatic validation
3. **[Body Parsing](./learn/03-body-parsing.md)** - Handle POST/PUT data like a pro
4. **[Middleware](./learn/04-middleware.md)** - Build reusable logic chains
5. **[Performance](./learn/05-performance.md)** - Production optimization tips
**More tutorials coming soon:**
- Authentication & Security
- File Streaming & Uploads
- Testing Strategies
- Deployment & Observability
- Performance Benchmarking
---
## 📖 Complete API Reference
### Server API
```javascript
const server = new VeloxServer()
.setPort(3000) // Set port (default: 3000)
.setHost('0.0.0.0') // Set host (default: localhost)
.setRouter(router) // Attach router
.enableHTTPS({ key, cert }) // Enable HTTPS
.start(); // Start server
// Methods
server.getStats(); // Get pool statistics
server.stop(); // Stop server
server.close(); // Alias for stop()
```
### Router API
```javascript
const router = new VeloxRouter();
// HTTP methods
router.get(path, handler);
router.post(path, handler);
router.put(path, handler);
router.delete(path, handler);
router.patch(path, handler);
// Middleware
router.use(middleware); // All routes
router.use(middleware, '@method POST'); // POST only
router.use(middleware, '@path /api/*'); // Path pattern
```
### Response Methods
```javascript
res.sendJSON({ data }) // JSON response
res.sendHTML('<h1>Hello</h1>') // HTML response
res.sendText('Hello') // Plain text
res.sendFile('file.pdf', './dir') // Stream file (range requests)
res.sendBuffer(buffer, 'image/png') // Binary data
res.sendError('Not found', 404) // Error response
res.redirect('/new-path', 302) // Redirect
res.status(201) // Set status code
res.setHeader('X-Custom', 'value') // Set header
res.setCookie('token', 'abc', options) // Set cookie
```
### Request Methods
```javascript
await req.getBody() // Parse body (JSON/XML/form/multipart)
req.getQuery() // Query parameters object
req.getHeader('name') // Get header value
req.getMethod() // HTTP method (GET, POST, etc.)
req.getPathname() // URL pathname
req.getCookies() // Parse cookies
req.isSecure() // Check if HTTPS
```
### Handler Signature
```javascript
function handler(res, req, query, params, data, next) {
// res - Response object
// req - Request object
// query - Query parameters (?page=1)
// params - Route parameters (/:id)
// data - Shared object (middleware communication)
// next - Call next middleware (middleware only)
}
```
---
## 🔧 Best Practices
### 1. Organize Routes by Resource
```javascript
// users.js
export function usersRouter(router) {
router.get('/api/users', listUsers);
router.post('/api/users', createUser);
router.get('/api/users/:id=number', getUser);
}
// posts.js
export function postsRouter(router) {
router.get('/api/posts', listPosts);
router.post('/api/posts', createPost);
}
// main.js
import { VeloxRouter } from 'veloxapi';
import { usersRouter } from './users.js';
import { postsRouter } from './posts.js';
const router = new VeloxRouter();
usersRouter(router);
postsRouter(router);
```
### 2. Use Environment Variables
```javascript
import 'dotenv/config'; // or your env loader
const server = new VeloxServer()
.setPort(process.env.PORT || 3000)
.setHost(process.env.HOST || '0.0.0.0')
.setRouter(router)
.start();
```
### 3. Centralized Error Handling
```javascript
// error-handler.js
export function errorHandler(res, req, query, params, data, next) {
try {
next();
} catch (err) {
console.error('Error:', err);
res.sendError('Internal server error', 500);
}
}
// main.js
router.use(errorHandler); // Add first
```
### 4. Request Validation
```javascript
function validateUser(body) {
const errors = [];
if (!body.name || body.name.length < 2) {
errors.push('Name must be at least 2 characters');
}
if (!body.email || !body.email.includes('@')) {
errors.push('Invalid email address');
}
return errors;
}
router.post('/api/users', async (res, req) => {
const body = await req.getBody();
const errors = validateUser(body);
if (errors.length > 0) {
return res.status(400).sendJSON({ errors });
}
// Create user...
});
```
### 5. Security Headers
```javascript
router.use((res, req, query, params, data, next) => {
res.setHeader('X-Content-Type-Options', 'nosniff');
res.setHeader('X-Frame-Options', 'DENY');
res.setHeader('X-XSS-Protection', '1; mode=block');
res.setHeader('Strict-Transport-Security', 'max-age=31536000');
next();
});
```
---
## 🧪 Testing
```bash
npm test # Run all 148 tests
npm run test:coverage # With coverage report
npm run test:watch # Watch mode
```
**Write your own tests:**
```javascript
import { VeloxServer, VeloxRouter } from 'veloxapi';
import { test } from 'node:test';
import assert from 'node:assert';
test('GET /api/status returns 200', async () => {
const router = new VeloxRouter();
router.get('/api/status', (res) => {
res.sendJSON({ status: 'ok' });
});
const server = new VeloxServer()
.setPort(3001)
.setRouter(router)
.start();
const response = await fetch('http://localhost:3001/api/status');
const data = await response.json();
assert.strictEqual(data.status, 'ok');
server.stop();
});
```
---
## 📈 Performance & Benchmarking
### Architecture Optimizations
- **Radix Tree Routing** - O(log n) lookups vs O(n) linear
- **Object Pooling** - Reuse Request/Response objects (reduces GC)
- **Lazy Body Parsing** - Parse only when needed
- **Streaming I/O** - Constant memory for large files
- **Zero Dependencies** - No external overhead
### Benchmark Your API
```bash
# Install autocannon
npm install -g autocannon
# Simple GET benchmark
autocannon -c 100 -d 30 http://localhost:3000/api/status
# POST with body
autocannon -c 100 -d 30 -m POST \
-H "Content-Type: application/json" \
-b '{"name":"test"}' \
http://localhost:3000/api/users
```
**Comprehensive benchmarks vs Fastify/Express/Koa coming soon.**
---
## 🛣️ Roadmap
### v0.2.0-alpha.1 (Current)
- ✅ Object pooling with Request/Response pools
- ✅ True streaming for constant memory usage
- ✅ Comprehensive testing (148/148 tests)
- ✅ Tutorial system
- ✅ Enhanced documentation
### v0.3.0 (Next)
- [ ] Static file middleware with ETag
- [ ] Rate limiting (token bucket algorithm)
- [ ] JSON schema validation
- [ ] Response compression (gzip/brotli)
### v1.0.0 (Production)
- [ ] CLI tool (`velox init`, generators)
- [ ] Plugin system
- [ ] TypeScript definitions
- [ ] Production battle-tested
### Future
- [ ] Worker clustering
- [ ] HTTP/2 support
- [ ] WebSocket support
- [ ] Native performance addons (optional)
---
## 🏆 Why Choose VeloxAPI?
### ✅ Choose VeloxAPI if you want:
- **Maximum performance** with zero external overhead
- **Complete control** over your framework
- **Security** without third-party vulnerabilities
- **Predictability** with no dependency breaking changes
- **Lightweight** deployment (<50KB)
- **Modern features** (typed params, streaming, pooling)
### ⚠️ Consider alternatives if you need:
- **TypeScript source** (we provide JS + future TS definitions)
- **Massive ecosystem** (Express/Fastify have more plugins)
- **Enterprise support** (community-driven for now)
---
## 🤝 Contributing
We welcome contributions! Here's how:
1. **Fork** the repository
2. **Create** your feature branch (`git checkout -b feature/amazing`)
3. **Run** tests (`npm test`)
4. **Commit** your changes (`git commit -am 'Add amazing feature'`)
5. **Push** to the branch (`git push origin feature/amazing`)
6. **Open** a Pull Request
See [CONTRIBUTING.md](CONTRIBUTING.md) for detailed guidelines.
---
## 📄 License
MIT © VeloxAPI Contributors
---
## 🔗 Resources
- **[Documentation](./learn/README.md)** - Complete learning path
- **[API Reference](./docs/API.md)** - Detailed API docs
- **[Examples](./examples/)** - Code examples
- **[Changelog](./CHANGELOG.md)** - Version history
---
**Made with ❤️ for performance**