All-in-one middleware toolkit for Express.js — auth, validation, rate limiting, error handling.
npm install @sharey1332/express-guard- 🔐 JWT Auth — Bearer token middleware with role-based access
- ✅ Validation — Schema-based request validation
- 🚦 Rate Limiting — Configurable per-route limits
- 🛡️ Error Handling — Consistent API error responses
- 📝 Request Logger — Dev-friendly request logging
- ⚡ TypeScript — Full type support
import express from 'express'
import { auth, validate, rateLimit, errorHandler, logger } from '@sharey1332/express-guard'
const app = express()
app.use(express.json())
app.use(logger())
// Public route with rate limiting
app.post('/login', rateLimit({ max: 5, window: '15m' }), (req, res) => {
res.json({ token: 'xxx' })
})
// Protected route with validation
app.post('/users',
auth({ secret: process.env.JWT_SECRET }),
validate({
body: {
email: { type: 'email', required: true },
password: { type: 'string', min: 8 }
}
}),
(req, res) => {
res.json({ user: req.body })
}
)
// Error handler (must be last)
app.use(errorHandler())
app.listen(3000)import { auth } from '@sharey1332/express-guard'
// Basic usage
app.use('/api', auth({ secret: 'your-secret' }))
// With role check
app.get('/admin', auth({ secret: 'xxx', roles: ['admin'] }), handler)
// Access user in route
app.get('/me', auth({ secret: 'xxx' }), (req, res) => {
res.json(req.user) // { id, email, role, ... }
})Options:
| Option | Type | Default | Description |
|---|---|---|---|
secret |
string |
— | JWT secret (required) |
roles |
string[] |
[] |
Allowed roles |
algorithms |
string[] |
['HS256'] |
JWT algorithms |
import { validate } from '@sharey1332/express-guard'
app.post('/register',
validate({
body: {
email: { type: 'email', required: true },
password: { type: 'string', min: 8, max: 100 },
age: { type: 'number', min: 18 }
},
query: {
ref: { type: 'string' }
}
}),
handler
)Types: string, number, boolean, email, url, uuid, array, object
Rules: required, min, max, pattern, enum, custom
// Custom validation
validate({
body: {
username: {
type: 'string',
custom: (value) => {
if (value.includes(' ')) throw new Error('No spaces allowed')
return true
}
}
}
})import { rateLimit } from '@sharey1332/express-guard'
// 100 requests per 15 minutes
app.use('/api', rateLimit({ max: 100, window: '15m' }))
// Strict limit for auth routes
app.use('/auth', rateLimit({ max: 5, window: '15m' }))
// Custom key generator
app.use(rateLimit({
max: 100,
window: '1h',
keyGenerator: (req) => req.user?.id || req.ip
}))Options:
| Option | Type | Default | Description |
|---|---|---|---|
max |
number |
100 |
Max requests |
window |
string |
'15m' |
Time window (s/m/h) |
keyGenerator |
function |
IP-based | Custom key function |
skip |
function |
— | Skip condition |
message |
string |
'Too many requests' |
Error message |
import { errorHandler, ApiError } from '@sharey1332/express-guard'
// Throw errors anywhere
app.get('/user/:id', async (req, res) => {
const user = await db.findUser(req.params.id)
if (!user) throw new ApiError('User not found', 404)
res.json(user)
})
// Global error handler
app.use(errorHandler())Response format:
{
"success": false,
"error": {
"message": "User not found",
"code": 404
}
}import { logger } from '@sharey1332/express-guard'
app.use(logger())
// Output: POST /api/users 201 23ms
app.use(logger({ format: 'detailed' }))
// Output: [2025-01-05 14:30:00] POST /api/users 201 23ms - 156bimport { asyncHandler } from '@sharey1332/express-guard'
// Automatically catches async errors
app.get('/users', asyncHandler(async (req, res) => {
const users = await db.getUsers()
res.json(users)
}))import { Request } from 'express'
import { AuthRequest } from '@sharey1332/express-guard'
// req.user is typed
app.get('/me', auth({ secret: 'xxx' }), (req: AuthRequest, res) => {
res.json({ id: req.user.id })
})MIT
built by @sharey1332