backend.in
Version:
A npm module that could help node.js servers in one line of code
177 lines (150 loc) • 5.36 kB
Markdown
# backend.in
A batteries-included Express server bootstrap for Node.js. Start a production-ready backend in one line with optional auth, MongoDB, Redis sessions, file storage, email, rate limiting, and analytics.
- ESM + CJS ready, TypeScript types included
- Tier-based feature gating for SaaS plans or internal environments
- Pluggable middlewares and custom routes
## Installation
```bash
npm i backend.in
# peer deps you likely want
npm i express mongoose jsonwebtoken express-session multer helmet cors morgan express-rate-limit nodemailer redis uuid axios bcryptjs
```
## Quick start
```ts
import { startServer } from 'backend.in'
import mongoose, { Schema, model } from 'mongoose'
// Simple User Model
const UserSchema = new Schema({
email: { type: String, unique: true },
password: String,
role: { type: String, default: 'user' },
emailVerified: { type: Boolean, default: false },
})
const User = model('User', UserSchema)
await startServer({
apiKey: 'premium', // can be one of: starter | basic | premium | advanced (or use validationService)
secret: 'my-secret', // used for sessions
port: 3000,
projectId: 'demo-project',
tier: 'premium',
baseRoute: '/api',
// Database + Auth
mongoUri: process.env.MONGO_URI!,
auth: {
enabled: true,
advanced: true,
model: User,
jwt: {
accessTokenSecret: process.env.JWT_SECRET!,
refreshTokenSecret: process.env.JWT_REFRESH_SECRET!,
accessTokenExpiresIn: '1h',
refreshTokenExpiresIn: '7d',
},
requireEmailVerification: true,
roleField: 'role',
},
// Sessions (optionally with Redis)
session: {
enabled: true,
redis: true,
options: {
secret: 'my-secret',
resave: false,
saveUninitialized: false,
},
},
redis: { enabled: true, url: process.env.REDIS_URL },
// Storage
storage: {
enabled: true,
config: {
uploadDir: 'uploads',
staticRoute: '/uploads',
maxFileSize: 5 * 1024 * 1024,
allowedMimeTypes: ['image/png', 'image/jpeg'],
},
},
// Email (for verification / reset)
email: {
transporterOptions: {
host: process.env.SMTP_HOST,
port: Number(process.env.SMTP_PORT || 587),
secure: false,
auth: { user: process.env.SMTP_USER, pass: process.env.SMTP_PASS },
},
from: 'no-reply@example.com',
},
// Security & Ops
enableHelmet: true,
enableCors: true,
enableLogging: true,
rateLimit: {
windowMs: 15 * 60 * 1000,
max: 200,
tierOverrides: { starter: { max: 50 } },
},
// Custom middlewares/routes
libraries: [],
routes: [
{
method: 'get',
path: '/hello',
handlers: [(req, res) => res.json({ hello: 'world' })],
},
],
})
```
Health check: GET `/api/health`
## Auth Routes
When `auth.enabled=true` and the selected tier includes database:
- POST `/api/auth/signup` (advanced only): { email, password, ... }
- POST `/api/auth/login`: { email, password }
- POST `/api/auth/refresh`: { refreshToken } (when refresh secret configured)
- GET `/api/auth/me`: requires `Authorization: Bearer <accessToken>`
- PUT `/api/auth/update`: update profile (excludes password)
- PUT `/api/auth/change-password`: { oldPassword, newPassword }
- POST `/api/auth/forgot-password` (advanced): { email }
- POST `/api/auth/reset-password` (advanced): { token, newPassword }
- GET `/api/auth/verify-email` (advanced): ?token=...
You can override route paths using `auth.routes`.
## Options Reference
```ts
startServer<T extends Document>({
apiKey, secret, port, projectId, tier,
usage?,
validationService?: { url: string; validateEndpoint: string; reportUsageEndpoint: string },
libraries?: Array<(req, res, next) => void>,
routes?: Array<{ method: "get"|"post"|"put"|"delete"|"patch"; path: string; handlers: any[] }>,
credentials?: { apiKey?: string; secret?: string },
mongoUri?: string,
baseRoute?: string,
auth?: {
enabled?: boolean;
model?: Model<T>;
jwt?: { accessTokenSecret: string; refreshTokenSecret?: string; accessTokenExpiresIn?: string|number; refreshTokenExpiresIn?: string|number };
advanced?: boolean;
routes?: { signup?; login?; logout?; me?; refresh?; update?; changePassword?; forgotPassword?; resetPassword?; verifyEmail? };
requireEmailVerification?: boolean;
roleField?: string;
};
session?: { enabled?: boolean; options?: session.SessionOptions; redis?: boolean };
storage?: { enabled?: boolean; config?: { uploadDir?; multerStorage?; staticRoute?; maxFileSize?; allowedMimeTypes? } };
enableHelmet?: boolean;
enableCors?: boolean | cors.CorsOptions;
enableLogging?: boolean;
rateLimit?: { windowMs?; max?; message?; tierOverrides?: Partial<Record<"starter"|"basic"|"premium"|"advanced", { max: number }>> } | false;
email?: { transporterOptions: nodemailer.TransportOptions; from?: string; sendVerificationEmail?; sendResetEmail? } | false;
redis?: { enabled?: boolean; url?: string };
validators?: { signup?; login?; resetPassword? };
webhooks?: { onUserSignup?; onUserLogin?; onError? };
analytics?: { enabled?: boolean; ignorePaths?: string[] };
})
```
## Programmatic Shutdown
```ts
import { stopServer } from 'backend.in'
await stopServer()
```
This disconnects MongoDB and quits Redis to enable graceful test teardown or rolling restarts.
## License
MIT