@unidev-hub/api-framework
v1.0.45
Published
A comprehensive framework for building API services with Express
Readme
@unidev-hub/api-framework
A comprehensive TypeScript API framework for building robust microservices with Express that provides:
- 🚀 Complete server initialization with intelligent defaults
- 🔐 Authentication with Azure AD, JWT, or custom providers
- 📊 Database connectivity with PostgreSQL, MongoDB, or custom connectors
- 🏥 Health checks with Kubernetes-ready probes via @unidev-hub/health
- 📚 OpenAPI documentation with Swagger UI and ReDoc
- 🛡️ Security with Helmet, CORS, and rate limiting
- 🔄 Standardized responses with consistent formatting
- 🚫 Error handling with proper status codes and logging
- ✅ Request validation using Joi schemas
- 📈 Metrics collection for monitoring
- 🔍 Correlation ID tracking across microservices
- 🔄 Lifecycle hooks for customizing server startup and shutdown
- ⚙️ Environment-specific configuration with automatic detection
- 🔔 Event system for cross-component communication
- 🧩 Plugin system for extending functionality
- 📱 Feature toggles for controlled feature rollouts
- 🔄 Circuit breakers for resilient external service calls
Installation
npm install @unidev-hub/api-framework --saveQuick Start
Start a complete API service with just a few lines of code:
// src/index.ts
import { startServer } from '@unidev-hub/api-framework';
import { setupRoutes } from './routes';
// Start the server with minimal configuration
startServer({
serviceName: 'product-service',
setupRoutes
}).catch((error) => {
console.error('Failed to start service:', error);
process.exit(1);
});
// src/routes/index.ts
import { Application, RequestHandler, Router } from 'express';
import { Logger } from '@unidev-hub/logger';
import { DatabaseConnection } from '@unidev-hub/database';
export async function setupRoutes(
app: Application,
dbConnection: DatabaseConnection | null,
authMiddleware: RequestHandler,
logger: Logger
): Promise<void> {
const router = Router();
// Public routes
router.get('/hello', (req, res) => {
res.json({ message: 'Hello, World!' });
});
// Protected routes (requires authentication)
router.get('/protected', authMiddleware, (req, res) => {
res.json({ message: 'This is a protected endpoint', user: req.user });
});
// Mount routes to API base path
app.use('/products', router);
logger.info('Routes configured');
}Core Features
Server Initialization
The framework provides a complete server initialization flow with smart defaults:
import { startServer } from '@unidev-hub/api-framework';
// Start a server with more advanced options
startServer({
serviceName: 'user-service',
// Database configuration
database: {
type: 'postgres',
connection: {
host: process.env.DB_HOST,
port: parseInt(process.env.DB_PORT || '5432'),
username: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME
}
},
// Authentication configuration
auth: {
type: 'jwt',
jwt: {
secret: process.env.JWT_SECRET,
issuer: 'mycompany.com'
}
},
// API settings
api: {
basePath: '/api/v1',
cors: true,
helmet: true,
bodyLimit: '2mb'
},
// Routes setup
setupRoutes
});Authentication
Multiple authentication strategies are supported out of the box:
// JWT Authentication
auth: {
type: 'jwt',
jwt: {
secret: process.env.JWT_SECRET,
issuer: 'mycompany.com',
audience: 'my-api'
}
}
// Azure AD Authentication
auth: {
type: 'azure',
azure: {
tenantId: process.env.AZURE_TENANT_ID,
clientId: process.env.AZURE_CLIENT_ID,
clientSecret: process.env.AZURE_CLIENT_SECRET,
apiScope: 'api/.default'
}
}
// No Authentication (for development)
auth: {
type: 'none',
required: false
}
// Custom Authentication
auth: {
type: 'custom',
customAuthFn: async (app, config, logger) => {
// Return a middleware function
return (req, res, next) => {
// Custom authentication logic
next();
};
}
}
// OAuth2 Authentication
auth: {
type: 'oauth2',
oauth2: {
issuerUrl: 'https://identity.example.com',
clientId: process.env.OAUTH_CLIENT_ID,
audience: 'https://api.example.com'
}
}Database Connectivity
The framework provides flexible database connectivity options:
// PostgreSQL configuration
database: {
type: 'postgres',
connection: {
host: process.env.DB_HOST || 'localhost',
port: parseInt(process.env.DB_PORT || '5432'),
username: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME,
ssl: process.env.DB_SSL === 'true',
poolSize: parseInt(process.env.DB_POOL_SIZE || '10')
}
}
// MongoDB configuration
database: {
type: 'mongodb',
connection: {
uri: process.env.MONGO_URI || 'mongodb://localhost:27017/myapp',
options: {
useNewUrlParser: true,
useUnifiedTopology: true,
maxPoolSize: 10
}
}
}
// Custom database connection
database: {
type: 'custom',
initialize: async (config, logger) => {
// Custom database initialization logic
const connection = await customDbConnect();
logger.info('Custom database connected');
// Return connection object and cleanup function
return {
connection,
cleanup: async () => {
await connection.close();
logger.info('Custom database disconnected');
}
};
}
}Advanced Health Checks
Health checks are now powered by @unidev-hub/health, providing Kubernetes-compatible health endpoints:
import { startServer, Status } from '@unidev-hub/api-framework';
// Configure health checks
startServer({
// ...other options
health: {
// Custom health indicators
customIndicators: [
{
name: 'redis-cache',
check: async () => {
// Check if Redis is healthy
return {
status: Status.UP,
details: { responseTime: '5ms' }
};
}
}
],
// HTTP dependency checks
httpDependencies: [
{
name: 'auth-service',
url: 'http://auth-service/health',
timeout: 2000
}
],
// Database health checks (automatically configured if database is set up)
database: {
enabled: true,
timeout: 3000
},
// Memory usage thresholds
memory: {
enabled: true,
threshold: 90 // Percentage
},
// CPU usage thresholds
cpu: {
enabled: true,
threshold: 80 // Percentage
}
}
});This provides four standard health check endpoints:
/health: Basic health status/health/liveness: Kubernetes liveness probe/health/readiness: Kubernetes readiness probe/health/details: Detailed health report
Middleware Configuration
Configure custom middleware for your API:
startServer({
// ...other options
middleware: {
// Global middleware to execute before routes
before: [
(req, res, next) => {
// Add request timestamp
req.timestamp = new Date();
next();
},
// Add third-party middleware
compression(),
cookieParser()
],
// Route-specific middleware (applied only to routes under a specific path)
routes: [
{
path: '/uploads',
handlers: [
multer({ dest: 'uploads/' }).single('file'),
(req, res, next) => {
// Process uploaded files
next();
}
]
}
],
// Global middleware to execute