@nexved/backend-framework
v1.0.0
Published
Production-ready Node.js backend framework with multi-database support
Maintainers
Readme
Backend Framework
A production-ready Node.js backend framework with multi-database support, file-based routing, and a developer-first experience. Think Next.js, but for backends.
✨ Features
- 🔌 Multi-Database Support - Supabase, NeonDB, Firebase, MongoDB, MySQL, PostgreSQL
- 📁 File-Based Routing - Next.js-style API routes
- 🔐 Authentication - JWT tokens, password hashing, role-based access
- 💾 Caching - In-memory and Redis support
- 🛡️ Middleware - Rate limiting, validation, error handling, logging
- 🔄 ORM Integration - Prisma and Drizzle support
- 📝 TypeScript & JavaScript - Full support for both
- ⚡ Zero-Config Defaults - Works out of the box
🚀 Quick Start
Using CLI (Recommended)
npx @nexved/backend-frameworkThis will launch an interactive CLI to scaffold your project:
- Choose project name
- Select language (TypeScript/JavaScript)
- Pick databases (multi-select)
- Configure authentication
- Set up caching
- Choose ORM (Prisma/Drizzle/None)
Manual Setup
# Clone the template
git clone https://github.com/NexVed/Backend-framework.git my-app
cd my-app/templates/express/typescript
# Install dependencies
npm install
# Copy environment file
cp .env.example .env
# Start development
npm run dev📁 Project Structure
my-app/
├── app/
│ └── api/ # File-based routes
│ ├── health/
│ │ └── route.ts # GET /api/health
│ └── users/
│ ├── route.ts # GET/POST /api/users
│ └── [id]/
│ └── route.ts # GET/PUT/DELETE /api/users/:id
├── auth/ # Authentication module
├── cache/ # Caching (memory/redis)
├── core/ # Server & config
├── database/ # Database adapters
│ └── adapters/ # Provider implementations
├── middleware/ # Express middleware
├── orm/ # Prisma/Drizzle integration
├── utils/ # Response helpers, logger
├── backend.config.ts # Framework configuration
├── server.ts # Entry point
└── package.json📝 File-Based Routing
Create routes by adding files in app/api/:
// app/api/users/route.ts
export const GET = (req, res) => {
res.json({ users: [] });
};
export const POST = async (req, res) => {
const { name, email } = req.body;
// Create user...
res.status(201).json({ id: '1', name, email });
};Dynamic routes use brackets:
// app/api/users/[id]/route.ts
export const GET = (req, res) => {
const { id } = req.params;
res.json({ id, name: 'User' });
};
export const DELETE = (req, res) => {
const { id } = req.params;
// Delete user...
res.status(204).send();
};⚙️ Configuration
Edit backend.config.ts to configure your app:
import { defineConfig } from './core/config';
export default defineConfig({
server: {
port: 3000,
cors: { origin: '*', credentials: true },
},
database: {
default: 'supabase',
providers: {
supabase: {
url: process.env.SUPABASE_URL!,
anonKey: process.env.SUPABASE_ANON_KEY!,
},
mongodb: {
uri: process.env.MONGODB_URI!,
dbName: 'myapp',
},
},
},
auth: {
enabled: true,
jwt: {
secret: process.env.JWT_SECRET!,
expiresIn: '7d',
},
},
cache: {
enabled: true,
driver: 'memory', // or 'redis'
ttl: 3600,
},
});🔌 Database Usage
Using Database Manager
import { db } from './database';
// Use default database
const data = await db.default().from('users').select();
// Use specific provider
const supabase = db.supabase();
const { data: users } = await supabase.from('users').select('*');
// MongoDB
const mongodb = db.mongodb();
const users = await mongodb.collection('users').find({});
// PostgreSQL
const pg = db.postgresql();
const result = await pg.query('SELECT * FROM users WHERE id = $1', [userId]);Health Check
const health = await db.healthCheck();
// { supabase: true, mongodb: true, postgresql: false }🔐 Authentication
Protect Routes
import { requireAuth, requireRole } from './middleware/auth';
// Require authentication
app.get('/api/profile', requireAuth(), (req, res) => {
res.json({ user: req.user });
});
// Require specific role
app.delete('/api/admin', requireAuth(), requireRole('admin'), (req, res) => {
// Only admins can access
});Generate Tokens
import { generateToken, generateTokenPair, hashPassword, comparePassword } from './auth';
// Hash password
const hash = await hashPassword('mypassword');
// Verify password
const isValid = await comparePassword('mypassword', hash);
// Generate JWT
const token = await generateToken({ id: user.id, email: user.email });
// Generate access + refresh tokens
const { accessToken, refreshToken, expiresIn } = await generateTokenPair({ id: user.id });💾 Caching
import { cache, cacheKey, cachePatterns } from './cache';
// Simple cache
cache.set('user:1', userData, 3600); // TTL in seconds
const user = cache.get('user:1');
// Cache-aside pattern
const user = await cachePatterns.getOrSet(
cacheKey.entity('user', userId),
() => fetchUserFromDB(userId),
3600
);
// Invalidate on write
await cachePatterns.invalidateOnWrite(
cacheKey.entity('user', userId),
() => updateUser(userId, data)
);🛡️ Middleware
Rate Limiting
import { withRateLimit, strictRateLimit } from './middleware/rateLimit';
// Custom rate limit
app.use('/api', withRateLimit({ windowMs: 60000, max: 100 }));
// Strict limit for auth endpoints
app.post('/api/login', strictRateLimit(), loginHandler);Validation (Zod)
import { validateBody, validateQuery, schemas } from './middleware/validation';
import { z } from 'zod';
const createUserSchema = z.object({
name: z.string().min(1),
email: z.string().email(),
});
app.post('/api/users',
validateBody(createUserSchema),
(req, res) => {
// req.body is validated and typed
}
);
// With pagination
app.get('/api/users',
validateQuery(schemas.pagination),
(req, res) => {
const { page, limit } = req.query;
}
);📊 Response Helpers
import { success, created, paginated, notFound, badRequest } from './utils/response';
// Success response
success(res, { user });
// { success: true, data: { user } }
// Created (201)
created(res, { id: '1', name: 'New User' });
// Paginated
paginated(res, users, { page: 1, limit: 10, total: 100, totalPages: 10 });
// { success: true, data: [...], meta: { page, limit, total, totalPages } }
// Errors
badRequest(res, 'Invalid input', { field: 'email' });
notFound(res, 'User');
// { success: false, error: 'Not Found', message: 'User not found' }📝 Logging
import { logger, createLogger } from './utils/logger';
logger.info('Server started', { port: 3000 });
logger.error('Database error', error, { userId: '123' });
// Child logger with context
const userLogger = logger.child({ userId: '123' });
userLogger.info('User action'); // Automatically includes userId🗄️ ORM Integration
Prisma
import { prisma, connectPrisma, withTransaction } from './orm/prisma';
// Use Prisma client
const users = await prisma.user.findMany();
// With transaction
const result = await withTransaction(async (tx) => {
const user = await tx.user.create({ data: { name: 'John' } });
await tx.profile.create({ data: { userId: user.id } });
return user;
});Drizzle
import { initDrizzle, getDrizzle, eq, desc } from './orm/drizzle';
import { users } from './db/schema';
// Initialize with Neon
await initDrizzle('neon', process.env.DATABASE_URL!);
const db = getDrizzle();
const allUsers = await db.select().from(users).where(eq(users.active, true));🌍 Environment Variables
# Server
PORT=3000
NODE_ENV=development
# Authentication
JWT_SECRET=your-secret-key
# Databases (configure as needed)
SUPABASE_URL=https://xxx.supabase.co
SUPABASE_ANON_KEY=xxx
MONGODB_URI=mongodb://localhost:27017
DATABASE_URL=postgresql://user:pass@localhost:5432/db
# Cache
REDIS_URL=redis://localhost:6379
# Logging
LOG_LEVEL=info📦 Supported Databases
| Database | Type | Package | |----------|------|---------| | Supabase | Cloud PostgreSQL | @supabase/supabase-js | | NeonDB | Serverless PostgreSQL | @neondatabase/serverless | | Firebase | Cloud Firestore | firebase-admin | | MongoDB | NoSQL | mongodb | | MySQL | SQL | mysql2 | | PostgreSQL | SQL | pg |
🤝 Contributing
Contributions are welcome! Please read our contributing guidelines.
📄 License
MIT © NexVed
