@thalorlabs/express-core
v1.1.0
Published
Shared Express/Lambda boilerplate for ThalorLabs microservices with configurable middleware and routing
Downloads
5
Readme
@thalorlabs/express-core
A shared Express/Lambda boilerplate package for ThalorLabs microservices, providing configurable middleware, routing, and server setup for consistent service architecture.
Installation
npm install @thalorlabs/express-coreFeatures
- Express Server Setup - Pre-configured Express application with essential middleware
- Lambda Integration - AWS Lambda handler wrapper for serverless deployment
- Configurable Middleware - CORS, Helmet, Compression, Morgan logging, Rate limiting
- Route Registration - Callback-based route registration system
- Environment Configuration - Environment-specific settings and overrides
- Error Handling - Centralized error handling and logging
- TypeScript Support - Full TypeScript definitions and type safety
Usage
Basic Express Server Setup
import { createApp, createServer } from '@thalorlabs/express-core';
const app = createApp({
cors: {
origin: process.env.ALLOWED_ORIGINS?.split(',') || [
'http://localhost:3000',
],
},
helmet: {
contentSecurityPolicy: false, // Disable CSP for development
},
rateLimit: {
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // limit each IP to 100 requests per windowMs
},
});
// Register your routes
app.use('/api/v1', (req, res, next) => {
// Your API routes here
res.json({ message: 'API v1' });
});
// Start server
const server = createServer(app, {
port: process.env.PORT || 3000,
host: process.env.HOST || 'localhost',
});
server.listen();Lambda Handler Setup
import { createLambdaHandler } from '@thalorlabs/express-core';
const app = createApp({
// Your app configuration
});
// Register routes
app.use('/api', (req, res) => {
res.json({ message: 'Hello from Lambda!' });
});
// Export Lambda handler
export const handler = createLambdaHandler(app);Custom Middleware Registration
import { createApp } from '@thalorlabs/express-core';
const app = createApp({
middleware: {
// Add custom middleware
customAuth: (req, res, next) => {
// Your authentication logic
next();
},
requestLogger: (req, res, next) => {
console.log(`${req.method} ${req.path}`);
next();
},
},
});
// Use custom middleware
app.use('/protected', app.middleware.customAuth);Environment-Specific Configuration
import { createApp, Environment } from '@thalorlabs/express-core';
const app = createApp({
environment: Environment.PRODUCTION,
cors: {
origin:
process.env.NODE_ENV === 'production'
? ['https://myapp.com']
: ['http://localhost:3000'],
},
logging: {
level: process.env.NODE_ENV === 'production' ? 'error' : 'debug',
},
});Available Components
Core Components
| Component | Description | Usage |
| --------------------- | --------------------------------------- | ---------------------------- |
| createApp | Creates configured Express application | createApp(options) |
| createServer | Creates HTTP server instance | createServer(app, options) |
| createLambdaHandler | Creates AWS Lambda handler | createLambdaHandler(app) |
| commonRouter | Common utility routes (health, metrics) | app.use(commonRouter) |
| apiRouter | API route registration helper | app.use('/api', apiRouter) |
Middleware Components
| Middleware | Description | Configuration |
| ------------- | ----------------------------- | --------------------------------------- |
| cors | Cross-Origin Resource Sharing | { origin: ['http://localhost:3000'] } |
| helmet | Security headers | { contentSecurityPolicy: false } |
| compression | Response compression | { level: 6 } |
| morgan | HTTP request logging | 'combined' or 'dev' |
| rateLimit | Request rate limiting | { windowMs: 900000, max: 100 } |
Configuration Options
App Configuration
interface AppConfig {
cors?: CorsOptions;
helmet?: HelmetOptions;
compression?: CompressionOptions;
morgan?: string | MorganOptions;
rateLimit?: RateLimitOptions;
middleware?: Record<string, RequestHandler>;
environment?: Environment;
logging?: LoggingConfig;
}Server Configuration
interface ServerConfig {
port?: number;
host?: string;
timeout?: number;
keepAlive?: boolean;
}Environment Enum
enum Environment {
DEVELOPMENT = 'development',
STAGING = 'staging',
UAT = 'uat',
PRODUCTION = 'production',
}Project Structure
src/
├── index.ts # Main exports
├── app.ts # Express app factory
├── server.ts # HTTP server factory
├── handler.ts # Lambda handler factory
├── middleware/ # Middleware components
│ ├── cors.ts # CORS configuration
│ ├── helmet.ts # Security headers
│ ├── compression.ts # Response compression
│ ├── morgan.ts # Request logging
│ └── rateLimit.ts # Rate limiting
├── routers/ # Router components
│ ├── commonRouter.ts # Common utility routes
│ └── apiRouter.ts # API route helper
└── types/ # Type definitions
├── AppConfig.ts # App configuration types
├── ServerConfig.ts # Server configuration types
└── Environment.ts # Environment enumMiddleware Configuration
CORS Configuration
const app = createApp({
cors: {
origin: ['http://localhost:3000', 'https://myapp.com'],
credentials: true,
methods: ['GET', 'POST', 'PUT', 'DELETE'],
allowedHeaders: ['Content-Type', 'Authorization'],
},
});Security Headers (Helmet)
const app = createApp({
helmet: {
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
styleSrc: ["'self'", "'unsafe-inline'"],
},
},
hsts: {
maxAge: 31536000,
includeSubDomains: true,
},
},
});Rate Limiting
const app = createApp({
rateLimit: {
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // limit each IP to 100 requests per windowMs
message: 'Too many requests from this IP',
standardHeaders: true,
legacyHeaders: false,
},
});Error Handling
The package includes centralized error handling:
import { ErrorHandler } from '@thalorlabs/express-core';
// Custom error handler
app.use(ErrorHandler.handle);
// Custom error types
throw new ErrorHandler.ValidationError('Invalid input data');
throw new ErrorHandler.NotFoundError('Resource not found');
throw new ErrorHandler.UnauthorizedError('Access denied');Lambda Deployment
Serverless Framework
# serverless.yml
service: my-microservice
provider:
name: aws
runtime: nodejs18.x
stage: ${opt:stage, 'dev'}
functions:
api:
handler: dist/handler.handler
events:
- http:
path: /{proxy+}
method: ANY
cors: trueAWS SAM
# template.yaml
Resources:
ApiFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: dist/
Handler: handler.handler
Runtime: nodejs18.x
Events:
Api:
Type: Api
Properties:
Path: /{proxy+}
Method: ANYEnvironment Variables
| Variable | Description | Default |
| ----------------- | ---------------------------------------- | ----------------------- |
| NODE_ENV | Environment (development, production) | development |
| PORT | Server port | 3000 |
| HOST | Server host | localhost |
| ALLOWED_ORIGINS | CORS allowed origins (comma-separated) | http://localhost:3000 |
| LOG_LEVEL | Logging level (debug, info, warn, error) | info |
TypeScript Support
This package includes full TypeScript support with:
- Complete type definitions for all components
- IntelliSense support for configuration options
- Compile-time type checking
- Express and Lambda type integration
Best Practices
Route Organization
// Register routes by feature
app.use('/api/users', userRoutes);
app.use('/api/orders', orderRoutes);
app.use('/api/products', productRoutes);
// Use common router for utilities
app.use(commonRouter);Middleware Order
// Recommended middleware order
app.use(helmet()); // Security headers
app.use(cors()); // CORS
app.use(compression()); // Compression
app.use(morgan('combined')); // Logging
app.use(rateLimit()); // Rate limiting
app.use(express.json()); // Body parsing
app.use(express.urlencoded({ extended: true }));Error Handling
// Always use try-catch in async routes
app.get('/api/data', async (req, res, next) => {
try {
const data = await fetchData();
res.json(data);
} catch (error) {
next(error);
}
});Development
Building
npm run buildTesting
npm testType Checking
npx tsc --noEmitLicense
ISC
