@thalorlabs/middleware
v1.3.0
Published
Express.js middleware collection for TypeScript applications with authentication, logging, and error handling
Maintainers
Readme
@thalorlabs/middleware
A comprehensive Express.js middleware collection for TypeScript applications with authentication and error handling capabilities.
Installation
npm install @thalorlabs/middlewareFeatures
- Authentication middleware with API key validation
- Error handling middleware with try-catch wrapper and structured error responses
- Protected access middleware combining authentication and error handling
- TypeScript support with full type safety
- Configurable options for different use cases
- Request tracking with requestId and context support
- Structured error responses for consistent API responses
Quick Start
import express from 'express';
import {
protect,
TryCatchMiddleware,
protectedAccessMiddleware,
} from '@thalorlabs/middleware';
const app = express();
// Basic authentication middleware
app.use('/api', TryCatchMiddleware(protect));
// Protected route with custom handler
app.get(
'/api/data',
protectedAccessMiddleware(async (req, res) => {
res.json({ message: 'Protected data' });
}, 'your-api-key')
);
// Custom middleware with error handling
app.get(
'/api/custom',
TryCatchMiddleware(async (req, res) => {
// Your custom logic here
res.json({ success: true });
})
);Middleware Components
Authentication Middleware (protect)
Validates API keys from request headers.
import { protect } from '@thalorlabs/middleware';
// Basic usage (no validation - for testing)
app.use('/api', TryCatchMiddleware(protect));
// With API key validation
app.use(
'/api',
TryCatchMiddleware(async (req, res) => {
await protect(req, res, 'your-secret-api-key');
})
);
// With multiple valid API keys
app.use(
'/api',
TryCatchMiddleware(async (req, res) => {
await protect(req, res, ['key1', 'key2', 'key3']);
})
);Request Headers:
x-api-key: The API key to validate
Response:
- Sets
res.locals.apiKeywith the validated API key - Throws
AuthenticationErrorif validation fails
Error Handling Middleware (TryCatchMiddleware)
Wraps middleware functions with comprehensive error handling.
import { TryCatchMiddleware } from '@thalorlabs/middleware';
// Wrap any async middleware function
const safeMiddleware = TryCatchMiddleware(async (req, res, next) => {
// Your middleware logic here
// Errors will be automatically caught and handled
});
app.use('/api', safeMiddleware);Error Handling:
- CustomError instances: Returns structured error responses
- ZodError instances: Converts to ValidationError format
- MongoDB duplicate key errors: Converts to DatabaseError
- Generic errors: Returns appropriate HTTP status codes
Protected Access Middleware (protectedAccessMiddleware)
Combines authentication and error handling for protected routes.
import { protectedAccessMiddleware } from '@thalorlabs/middleware';
// Single API key
app.get(
'/api/protected',
protectedAccessMiddleware(async (req, res) => {
res.json({ message: 'This is protected data' });
}, 'your-api-key')
);
// Multiple API keys
app.post(
'/api/admin',
protectedAccessMiddleware(
async (req, res) => {
res.json({ message: 'Admin operation completed' });
},
['admin-key-1', 'admin-key-2']
)
);
// No API key validation (for testing)
app.get(
'/api/test',
protectedAccessMiddleware(async (req, res) => {
res.json({ message: 'Test endpoint' });
})
);Type Definitions
MiddlewareFunction
type MiddlewareFunction<T = Record<string, string>> = (
req: Request<T>,
res: Response,
next: NextFunction
) => Promise<void>;Error Handling
The middleware integrates with @thalorlabs/errors for consistent error responses:
CustomError Integration
import { BadRequestError, ValidationError } from '@thalorlabs/errors';
app.get(
'/api/example',
TryCatchMiddleware(async (req, res) => {
if (!req.query.id) {
throw new BadRequestError('ID parameter is required');
}
// Validation errors
if (someValidationFails) {
throw new ValidationError('Validation failed', [
{ field: 'email', message: 'Invalid email format' },
]);
}
res.json({ success: true });
})
);Error Response Format
{
"status": "failure",
"error": "Error message",
"timestamp": "2024-01-01T12:00:00.000Z",
"requestId": "req-123",
"context": {
"additional": "context"
}
}Advanced Usage
Custom Error Handling
import { TryCatchMiddleware } from '@thalorlabs/middleware';
const customErrorHandler = TryCatchMiddleware(async (req, res) => {
// Your logic that might throw errors
if (someCondition) {
throw new Error('Custom error message');
}
res.json({ success: true });
});
app.use('/api/custom', customErrorHandler);Multiple Middleware Layers
import { protect, TryCatchMiddleware } from '@thalorlabs/middleware';
// Authentication + custom logic
app.get(
'/api/data',
TryCatchMiddleware(async (req, res) => {
await protect(req, res, 'api-key');
}),
TryCatchMiddleware(async (req, res) => {
// Additional middleware logic
res.json({ data: 'some data' });
})
);Configuration
Environment Variables
# Optional: Set default API key
API_KEY=your-default-api-key
# Optional: Set environment
NODE_ENV=productionTypeScript Configuration
The package includes full TypeScript support. Make sure your tsconfig.json includes:
{
"compilerOptions": {
"target": "ES2020",
"module": "CommonJS",
"declaration": true,
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true
}
}Testing
# Run tests
npm test
# Run tests with coverage
npm run test:coverage
# Run tests in watch mode
npm run test:watchDependencies
@thalorlabs/errors: Error handling classes@thalorlabs/types: Type definitionsexpress: Express.js frameworkuuid: UUID generationzod: Schema validation (for error handling)
Peer Dependencies
express: ^4.18.0
Best Practices
1. Always Use TryCatchMiddleware
// Good
app.use('/api', TryCatchMiddleware(protect));
// Avoid
app.use('/api', protect); // Errors won't be handled properly2. Use Protected Access for Routes
// Good - combines auth and error handling
app.get('/api/data', protectedAccessMiddleware(handler, 'api-key'));
// More verbose but equivalent
app.get(
'/api/data',
TryCatchMiddleware(async (req, res) => {
await protect(req, res, 'api-key');
await handler(req, res);
})
);3. Provide API Keys
// Good - validates API keys
app.use(
'/api',
TryCatchMiddleware(async (req, res) => {
await protect(req, res, process.env.API_KEY);
})
);
// Avoid - no validation (only for testing)
app.use('/api', TryCatchMiddleware(protect));4. Use Request IDs for Tracing
import { v4 as uuidv4 } from 'uuid';
app.use((req, res, next) => {
req.headers['x-request-id'] = req.headers['x-request-id'] || uuidv4();
next();
});Migration Guide
From Basic Express Middleware
// Before
app.get('/api/data', async (req, res) => {
try {
// Validate API key
if (req.headers['x-api-key'] !== 'secret') {
return res.status(401).json({ error: 'Unauthorized' });
}
// Your logic
res.json({ data: 'some data' });
} catch (error) {
res.status(500).json({ error: 'Internal server error' });
}
});
// After
app.get(
'/api/data',
protectedAccessMiddleware(async (req, res) => {
res.json({ data: 'some data' });
}, 'secret')
);License
ISC
This middleware collection provides a solid foundation for building robust Express.js applications with proper authentication and error handling.
