diff --git a/README.md b/README.md index 81a9359..93d0552 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# 🚀 BunGate +# 🚀 Bungate > **The Lightning-Fast HTTP Gateway & Load Balancer for the Modern Web** @@ -7,27 +7,27 @@ [![Performance](https://img.shields.io/badge/Performance-Blazing%20Fast-orange)](https://github.com/BackendStack21/bungate) [![License](https://img.shields.io/badge/License-MIT-green)](./LICENSE) -**BunGate** is a next-generation HTTP gateway and load balancer that harnesses the incredible speed of Bun.js to deliver unparalleled performance for modern web applications. Built from the ground up with TypeScript, it provides enterprise-grade features with zero-config simplicity. +**Bungate** is a next-generation HTTP gateway and load balancer that harnesses the incredible speed of Bun to deliver unparalleled performance for modern web applications. Built from the ground up with TypeScript, it provides enterprise-grade features with zero-config simplicity. -## ⚡ Why BunGate? +## ⚡ Why Bungate? -- **🔥 Blazing Fast**: Built on Bun.js - up to 4x faster than Node.js alternatives +- **🔥 Blazing Fast**: Built on Bun - up to 4x faster than Node.js alternatives - **🎯 Zero Config**: Works out of the box with sensible defaults -- **🧠 Smart Load Balancing**: 5 supported load balancing algorithms: `round-robin`, `least-connections`, `random`, `weighted`, `ip-hash` +- **🧠 Smart Load Balancing**: 5 load balancing algorithms: `round-robin`, `least-connections`, `random`, `weighted`, `ip-hash` - **🛡️ Production Ready**: Circuit breakers, health checks, and auto-failover - **🔐 Built-in Authentication**: JWT, API keys, JWKS, and OAuth2 support out of the box - **🎨 Developer Friendly**: Full TypeScript support with intuitive APIs - **📊 Observable**: Built-in metrics, logging, and monitoring - **🔧 Extensible**: Powerful middleware system for custom logic -> See Benchmarks comparing BunGate with Nginx and Envoy in the [benchmark directory](./benchmark). +> See benchmarks comparing Bungate with Nginx and Envoy in the [benchmark directory](./benchmark). ## 🚀 Quick Start Get up and running in less than 60 seconds: ```bash -# Install BunGate +# Install Bungate bun add bungate # Create your gateway @@ -47,16 +47,17 @@ const gateway = new BunGateway({ gateway.addRoute({ pattern: '/api/*', loadBalancer: { + strategy: 'least-connections', targets: [ - 'http://api1.example.com', - 'http://api2.example.com', - 'http://api3.example.com', + { url: 'http://api1.example.com' }, + { url: 'http://api2.example.com' }, + { url: 'http://api3.example.com' }, ], - strategy: 'least-connections', healthCheck: { enabled: true, interval: 30000, timeout: 5000, + path: '/health', }, }, }) @@ -74,7 +75,7 @@ gateway.addRoute({ // Start the gateway await gateway.listen() -console.log('🚀 BunGate running on http://localhost:3000') +console.log('🚀 Bungate running on http://localhost:3000') ``` **That's it!** Your high-performance gateway is now handling traffic with: @@ -92,7 +93,7 @@ console.log('🚀 BunGate running on http://localhost:3000') ### 🚀 **Performance & Scalability** - **High Throughput**: Handle thousands of requests per second -- **Low Latency**: Low latency routing with minimal overhead +- **Low Latency**: Minimal overhead routing with optimized request processing - **Memory Efficient**: Optimized for high-concurrent workloads - **Auto-scaling**: Dynamic target management and health monitoring - **Cluster Mode**: Multi-process clustering for maximum CPU utilization @@ -100,26 +101,28 @@ console.log('🚀 BunGate running on http://localhost:3000') ### 🎯 **Load Balancing Strategies** - **Round Robin**: Equal distribution across all targets -- **Weighted Round Robin**: Distribute based on server capacity -- **Least Connections**: Route to least busy server -- **IP Hash**: Consistent routing based on client IP +- **Weighted**: Distribute based on server capacity and weights +- **Least Connections**: Route to the least busy server +- **IP Hash**: Consistent routing based on client IP for session affinity - **Random**: Randomized distribution for even load -- **Sticky Sessions**: Session affinity with cookie support +- **Sticky Sessions**: Session affinity with cookie-based persistence ### 🛡️ **Reliability & Resilience** - **Circuit Breaker Pattern**: Automatic failure detection and recovery - **Health Checks**: Active monitoring with custom validation -- **Timeout Management**: Route-level timeout controls +- **Timeout Management**: Route-level and global timeout controls +- **Auto-failover**: Automatic traffic rerouting on service failures +- **Graceful Degradation**: Fallback responses and cached data support ### 🔧 **Advanced Features** - **Authentication & Authorization**: JWT, API keys, JWKS, OAuth2/OIDC support -- **Middleware System**: Custom request/response processing +- **Middleware System**: Custom request/response processing pipeline - **Path Rewriting**: URL transformation and routing rules - **Rate Limiting**: Flexible rate limiting with custom key generation - **CORS Support**: Full cross-origin resource sharing configuration -- **Request/Response Hooks**: Lifecycle event handling +- **Request/Response Hooks**: Comprehensive lifecycle event handling ### 📊 **Monitoring & Observability** @@ -131,11 +134,11 @@ console.log('🚀 BunGate running on http://localhost:3000') ### 🎨 **Developer Experience** -- **TypeScript First**: Full type safety and IntelliSense -- **Zero Dependencies**: Minimal footprint with essential features +- **TypeScript First**: Full type safety and IntelliSense support +- **Zero Dependencies**: Minimal footprint with essential features only - **Hot Reload**: Development mode with automatic restarts -- **Rich Examples**: Comprehensive documentation and examples -- **Testing Support**: Built-in testing utilities and mocks +- **Rich Documentation**: Comprehensive examples and API documentation +- **Testing Support**: Built-in utilities for testing and development ## 🏗️ Real-World Examples @@ -189,7 +192,7 @@ gateway.addRoute({ hooks: { onError(req, error): Promise { // Fallback to cached payment status - return getCachedPaymentStatus(req.params.id) + return getCachedPaymentStatus(req.url) }, }, }) @@ -246,11 +249,6 @@ Distribute traffic intelligently across multiple backends: gateway.addRoute({ pattern: '/products/*', loadBalancer: { - targets: [ - 'http://api1.example.com', - 'http://api2.example.com', - 'http://api3.example.com', - ], strategy: 'weighted', targets: [ { url: 'http://products-primary:3000', weight: 70 }, @@ -271,16 +269,11 @@ gateway.addRoute({ gateway.addRoute({ pattern: '/app/*', loadBalancer: { - targets: [ - 'http://api1.example.com', - 'http://api2.example.com', - 'http://api3.example.com', - ], strategy: 'ip-hash', targets: [ - 'http://app-server-1:3000', - 'http://app-server-2:3000', - 'http://app-server-3:3000', + { url: 'http://app-server-1:3000' }, + { url: 'http://app-server-2:3000' }, + { url: 'http://app-server-3:3000' }, ], stickySession: { enabled: true, @@ -354,7 +347,7 @@ gateway.addRoute({ ## 🔐 **Built-in Authentication** -BunGate provides comprehensive authentication support out of the box: +Bungate provides comprehensive authentication support out of the box: #### JWT Authentication @@ -536,24 +529,9 @@ touch gateway.ts import { BunGateway, BunGateLogger } from 'bungate' const logger = new BunGateLogger({ - level: 'error', - transport: { - target: 'pino-pretty', - options: { - colorize: true, - translateTime: 'SYS:standard', - ignore: 'pid,hostname', - }, - }, - serializers: { - req: (req) => ({ - method: req.method, - url: req.url, - }), - res: (res) => ({ - statusCode: res.status, - }), - }, + level: 'info', + format: 'pretty', + enableRequestLogging: true, }) const gateway = new BunGateway({ @@ -585,18 +563,18 @@ gateway.addRoute({ }, }) -// Add public routes with another layer of authentication +// Add public routes with API key authentication gateway.addRoute({ pattern: '/api/public/*', target: 'http://public-service:3002', auth: { apiKeys: ['public-key-1', 'public-key-2'], - apiKeyHeader: 'x-public-key', + apiKeyHeader: 'x-api-key', }, }) await gateway.listen() -console.log('🚀 BunGate running on http://localhost:3000') +console.log('🚀 Bungate running on http://localhost:3000') ``` ## 📄 License @@ -607,6 +585,8 @@ MIT Licensed - see [LICENSE](LICENSE) for details.
-**Built with ❤️ for the JavaScript Community** +**Built with ❤️ by BackendStack21 for the JavaScript Community** + +[🏠 Homepage](https://github.com/BackendStack21/bungate) | [📚 Documentation](https://github.com/BackendStack21/bungate#readme) | [🐛 Issues](https://github.com/BackendStack21/bungate/issues) | [💬 Discussions](https://github.com/BackendStack21/bungate/discussions)
diff --git a/package.json b/package.json index bfa0bf5..fd95f79 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,16 @@ "version": "0.2.0", "license": "MIT", "description": "A high-performance HTTP gateway for Bun, designed for microservices and API gateways.", + "keywords": [ + "javascript", + "typescript", + "bun", + "gateway", + "microservices", + "api-gateway", + "http", + "performance" + ], "scripts": { "test": "bun test", "test:integration": "bun test test/integration.test.ts", diff --git a/src/cluster/cluster-manager.ts b/src/cluster/cluster-manager.ts index 5393eed..75e04d8 100644 --- a/src/cluster/cluster-manager.ts +++ b/src/cluster/cluster-manager.ts @@ -1,24 +1,81 @@ +/** + * High-Availability Cluster Manager for Bungate + * + * Manages multiple worker processes for horizontal scaling and fault tolerance. + * Provides automatic worker spawning, health monitoring, graceful restarts, + * and load distribution across CPU cores for maximum performance. + * + * Features: + * - Automatic worker process management and scaling + * - Intelligent restart policies with backoff strategies + * - Graceful shutdown with connection draining + * - Real-time health monitoring and failure detection + * - Zero-downtime deployments with rolling restarts + * - Resource monitoring and performance optimization + * - Signal-based management (SIGINT, SIGTERM, SIGUSR2) + * - Comprehensive logging and operational visibility + * + * @example + * ```ts + * const clusterManager = new ClusterManager({ + * workers: 4, + * restartWorkers: true, + * maxRestarts: 10, + * shutdownTimeout: 30000 + * }, logger, './worker.js') + * + * await clusterManager.start() + * ``` + */ + import { spawn, type Subprocess } from 'bun' import { cpus } from 'os' import type { Logger } from '../interfaces/logger' import type { ClusterConfig } from '../interfaces/gateway' +/** + * Worker process information for tracking and management + */ export interface WorkerInfo { + /** Unique worker identifier */ id: number + /** Bun subprocess instance */ process: Subprocess + /** Number of times this worker has been restarted */ restarts: number + /** Timestamp of last restart attempt */ lastRestartTime: number + /** Flag indicating worker is in shutdown process */ isExiting: boolean } +/** + * Production-grade cluster manager for multi-process deployments + * + * Orchestrates worker processes with intelligent health monitoring, + * automatic recovery, and zero-downtime deployment capabilities. + */ export class ClusterManager { + /** Cluster configuration with scaling and restart policies */ private config: ClusterConfig + /** Logger instance for operational monitoring */ private logger?: Logger + /** Map of active worker processes */ private workers: Map = new Map() + /** Counter for generating unique worker IDs */ private nextWorkerId = 1 + /** Flag indicating cluster shutdown in progress */ private isShuttingDown = false + /** Path to worker script for spawning processes */ private workerScript: string + /** + * Initialize cluster manager with configuration and dependencies + * + * @param config - Cluster configuration including worker count and restart policies + * @param logger - Logger instance for monitoring and debugging + * @param workerScript - Path to worker script to execute + */ constructor(config: ClusterConfig, logger?: Logger, workerScript?: string) { this.config = { enabled: true, @@ -35,6 +92,14 @@ export class ClusterManager { this.workerScript = workerScript || process.argv[1] || 'worker.js' } + /** + * Start the cluster with configured worker processes + * + * Spawns worker processes, sets up signal handlers, and begins health monitoring. + * Provides graceful startup with proper error handling and logging. + * + * @returns Promise that resolves when cluster is fully operational + */ async start(): Promise { if (!this.config.enabled) { this.logger?.info('Cluster mode disabled') @@ -43,7 +108,7 @@ export class ClusterManager { this.logger?.info(`Starting cluster with ${this.config.workers} workers`) - // Set up signal handlers + // Configure signal handlers for graceful lifecycle management process.on('SIGINT', this.gracefulShutdown.bind(this)) process.on('SIGTERM', this.gracefulShutdown.bind(this)) process.on('SIGUSR2', this.restartAllWorkers.bind(this)) diff --git a/src/gateway/gateway.ts b/src/gateway/gateway.ts index 6bbe9e7..a92ccad 100644 --- a/src/gateway/gateway.ts +++ b/src/gateway/gateway.ts @@ -1,3 +1,39 @@ +/** + * Bungate API Gateway Implementation + * + * A high-performance, production-ready API gateway built on Bun runtime with 0http-bun router. + * Provides comprehensive routing, middleware support, load balancing, and proxy capabilities + * for microservices architectures and API management. + * + * Key Features: + * - Ultra-fast HTTP routing with parameter and wildcard support + * - Built-in load balancing with multiple strategies + * - Circuit breaker pattern for fault tolerance + * - JWT authentication and CORS support + * - Request/response transformation and validation + * - Comprehensive logging and metrics collection + * - Multi-process clustering for high availability + * - Hot reload and graceful shutdown capabilities + * + * @example + * ```ts + * const gateway = new BunGateway({ + * server: { port: 3000 }, + * routes: [ + * { + * pattern: '/api/users/*', + * target: 'http://user-service:3000', + * loadBalancer: { strategy: 'round-robin' } + * } + * ], + * cors: { origin: '*' }, + * auth: { secret: 'your-jwt-secret' } + * }) + * + * await gateway.listen(3000) + * ``` + */ + import http from '0http-bun' import type { Server } from 'bun' import type { Gateway, GatewayConfig } from '../interfaces/gateway' @@ -28,20 +64,41 @@ import { HttpLoadBalancer } from '../load-balancer/http-load-balancer' import type { ProxyInstance } from '../interfaces/proxy' import { ClusterManager } from '../cluster/cluster-manager' +/** + * Production-grade API Gateway implementation + * + * Orchestrates request routing, middleware processing, and backend communication + * with enterprise features for scalability and reliability. + */ export class BunGateway implements Gateway { + /** Gateway configuration including routes, middleware, and server settings */ private config: GatewayConfig + /** 0http-bun router instance for high-performance request routing */ private router: IRouter + /** Bun server instance when using built-in server */ private server: Server | null = null + /** Map of route patterns to their proxy instances */ private proxies: Map = new Map() + /** Map of route patterns to their load balancer instances */ private loadBalancers: Map = new Map() + /** Cluster manager for multi-process deployments */ private clusterManager: ClusterManager | null = null + /** Flag indicating if this process is the cluster master */ private isClusterMaster: boolean = false + /** + * Initialize the API Gateway with comprehensive configuration + * + * Sets up routing, middleware chain, clustering, and backend services. + * Automatically configures load balancers and proxy instances for defined routes. + * + * @param config - Gateway configuration object with routes, middleware, and server options + */ constructor(config: GatewayConfig = {}) { this.config = config this.isClusterMaster = !process.env.CLUSTER_WORKER - // Initialize cluster manager if cluster mode is enabled and we're the master + // Initialize cluster manager for multi-process deployment if (this.config.cluster?.enabled && this.isClusterMaster) { this.clusterManager = new ClusterManager( this.config.cluster, diff --git a/src/index.ts b/src/index.ts index 4730c8a..72e1452 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,48 +1,201 @@ /** - * BunGate - High-performance API Gateway built on Bun.js + * Bungate - Ultra-Fast API Gateway for Modern Applications * - * Main entry point for the BunGate library. - * Exports all core classes, interfaces, and utilities. + * A production-ready, high-performance API gateway built on Bun runtime with comprehensive + * enterprise features for microservices architectures, API management, and cloud-native deployments. + * + * ## Key Features + * + * ### 🚀 **Ultra-High Performance** + * - Built on Bun's lightning-fast JavaScript runtime + * - Zero-copy request forwarding with minimal overhead + * - Optimized routing with 0http-bun for maximum throughput + * - Connection pooling and keep-alive for backend efficiency + * + * ### 🛠 **Enterprise-Grade Features** + * - Multiple load balancing strategies (round-robin, least-connections, weighted, etc.) + * - Circuit breaker pattern for fault tolerance and resilience + * - JWT authentication and comprehensive CORS support + * - Request/response transformation and validation + * - Rate limiting and abuse protection mechanisms + * + * ### 📊 **Production Monitoring** + * - Structured logging with request correlation IDs + * - Prometheus metrics and health check endpoints + * - Real-time performance monitoring and alerting + * - Comprehensive error tracking and debugging tools + * + * ### 🔧 **Developer Experience** + * - TypeScript-first with excellent IDE support + * - Hot reload and development-friendly features + * - Extensive configuration options with sensible defaults + * - Rich middleware ecosystem and plugin architecture + * + * ### ⚡ **Deployment Flexibility** + * - Multi-process clustering for horizontal scaling + * - Docker and Kubernetes ready with health checks + * - Zero-downtime deployments with graceful shutdown + * - Cloud-native design with 12-factor app principles + * + * ## Quick Start + * + * ```typescript + * import { createGateway } from 'bungate' + * + * const gateway = createGateway({ + * server: { port: 3000 }, + * routes: [ + * { + * pattern: '/api/users/*', + * target: 'http://user-service:3000', + * loadBalancer: { + * strategy: 'least-connections', + * targets: [ + * { url: 'http://user-service-1:3000' }, + * { url: 'http://user-service-2:3000' } + * ] + * } + * } + * ], + * cors: { origin: '*' }, + * auth: { secret: process.env.JWT_SECRET } + * }) + * + * await gateway.listen() + * console.log('🚀 Bungate API Gateway running on port 3000') + * ``` + * + * ## Architecture + * + * ``` + * ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ + * │ Client │────│ Bungate │────│ Services │ + * │ Application │ │ Gateway │ │ Backend │ + * └─────────────┘ └─────────────┘ └─────────────┘ + * │ + * ┌─────────────┐ + * │ Middleware │ + * │ Stack │ + * └─────────────┘ + * ``` + * + * @author BackendStack21 + * @license MIT + * @homepage https://github.com/BackendStack21/bungate */ // ==================== CORE CLASSES ==================== -// Gateway + +/** + * Primary gateway implementation - the heart of Bungate + * Provides comprehensive API gateway functionality with routing, middleware, and clustering + */ export { BunGateway } from './gateway/gateway' -// Load Balancer + +/** + * High-performance load balancer with multiple strategies + * Supports round-robin, least-connections, weighted, random, and IP-hash algorithms + */ export { HttpLoadBalancer, createLoadBalancer, } from './load-balancer/http-load-balancer' -// Proxy + +/** + * Intelligent proxy with circuit breaker and connection pooling + * Built on fetch-gate for reliable backend communication + */ export { GatewayProxy, createGatewayProxy } from './proxy/gateway-proxy' -// Logger + +/** + * Production-grade structured logger with request tracing + * Based on Pino for high-performance logging with minimal overhead + */ export { BunGateLogger, createLogger } from './logger/pino-logger' -// Cluster Manager + +/** + * Multi-process cluster manager for horizontal scaling + * Provides automatic worker management and graceful restarts + */ export { ClusterManager } from './cluster/cluster-manager' // ==================== CONVENIENCE EXPORTS ==================== -// Re-export all interfaces from the main interfaces index + +/** + * Complete TypeScript interface definitions for excellent IDE support + * Includes all configuration options, request/response types, and middleware interfaces + */ export * from './interfaces/index' + // ==================== DEFAULT EXPORT ==================== -// Default export for the main gateway class + +/** + * Default export provides the main BunGateway class for simple imports + * Use: import Gateway from 'bungate' + */ export { BunGateway as default } from './gateway/gateway' -import type { GatewayConfig } from './interfaces/gateway' // ==================== UTILITIES ==================== -// Import for internal use in utility functions + +import type { GatewayConfig } from './interfaces/gateway' import { BunGateway } from './gateway/gateway' + /** - * Create a new BunGate instance with default configuration - * @param config Gateway configuration options - * @returns BunGateway instance + * Factory function to create a new Bungate instance with configuration + * + * Provides a convenient way to create and configure a gateway instance + * with TypeScript support and validation. + * + * @param config - Gateway configuration options + * @returns Configured BunGateway instance ready for use + * + * @example + * ```typescript + * const gateway = createGateway({ + * server: { port: 3000, hostname: '0.0.0.0' }, + * routes: [ + * { + * pattern: '/api/*', + * target: 'http://backend:3000', + * auth: { secret: 'your-jwt-secret' } + * } + * ], + * cors: { origin: ['https://app.example.com'] }, + * rateLimit: { max: 100, windowMs: 900000 } + * }) + * + * await gateway.listen() + * ``` */ export function createGateway(config: GatewayConfig): BunGateway { return new BunGateway(config) } + /** - * Library metadata + * Library metadata and version information + * Useful for debugging, monitoring, and compatibility checks */ export const BUNGATE_INFO = { - name: 'BunGate', - description: 'High-performance API Gateway built on Bun.js', - author: '21no.de', + /** Library name */ + name: 'Bungate', + /** Short description */ + description: 'Ultra-fast API Gateway built on Bun runtime', + /** Library author */ + author: 'BackendStack21', + /** Open source license */ license: 'MIT', + /** Project homepage and documentation */ homepage: 'https://github.com/BackendStack21/bungate', -} + /** Supported Node.js/Bun versions */ + engines: { + bun: '>=1.0.0', + node: '>=18.0.0', + }, + /** Key features for marketing and documentation */ + features: [ + 'Ultra-high performance HTTP routing', + 'Multiple load balancing strategies', + 'Circuit breaker fault tolerance', + 'JWT authentication & CORS support', + 'Prometheus metrics & monitoring', + 'Multi-process clustering', + 'TypeScript-first development', + ], +} as const diff --git a/src/interfaces/gateway.ts b/src/interfaces/gateway.ts index a5e093c..07557e4 100644 --- a/src/interfaces/gateway.ts +++ b/src/interfaces/gateway.ts @@ -10,232 +10,457 @@ import type { ProxyOptions } from './proxy' import type { Logger } from './logger' /** - * Cluster configuration interface + * Cluster configuration for multi-process gateway deployment + * Enables horizontal scaling by spawning multiple worker processes */ export interface ClusterConfig { /** - * Enable cluster mode + * Enable cluster mode for multi-process deployment + * @default false */ enabled?: boolean /** - * Number of workers (defaults to CPU count) + * Number of worker processes to spawn + * @default os.cpus().length (number of CPU cores) */ workers?: number /** - * Restart workers on exit + * Automatically restart workers when they exit unexpectedly + * @default true */ restartWorkers?: boolean /** - * Maximum number of restart attempts per worker + * Maximum number of restart attempts per worker before giving up + * @default 10 */ maxRestarts?: number /** - * Delay between restart attempts (in milliseconds) + * Delay between worker restart attempts in milliseconds + * @default 1000 */ restartDelay?: number /** - * Graceful shutdown timeout (in milliseconds) + * Maximum time to wait for graceful worker shutdown in milliseconds + * @default 5000 */ shutdownTimeout?: number /** - * Worker respawn threshold (if worker dies more than this many times in respawnThreshold time, don't respawn) + * Maximum worker deaths before stopping respawn attempts + * If a worker dies more than this many times within the threshold time window, + * it won't be respawned to prevent infinite restart loops + * @default 5 */ respawnThreshold?: number /** - * Worker respawn threshold time window (in milliseconds) + * Time window for respawn threshold tracking in milliseconds + * @default 60000 (1 minute) */ respawnThresholdTime?: number } /** - * Gateway configuration interface + * Main gateway configuration interface + * Defines all available options for configuring the Bungate API Gateway */ export interface GatewayConfig { /** - * Server configuration + * Server configuration options */ server?: { + /** + * Port number for the gateway server + * @default 3000 + */ port?: number + /** + * Hostname or IP address to bind to + * @default "0.0.0.0" + */ hostname?: string + /** + * Enable development mode with enhanced debugging + * @default false + */ development?: boolean } /** - * Cluster configuration + * Multi-process cluster configuration */ cluster?: ClusterConfig /** - * Default route handler (404 handler) + * Default route handler for unmatched requests (404 handler) + * Called when no registered routes match the incoming request + * @example + * ```ts + * defaultRoute: (req) => new Response('Not Found', { status: 404 }) + * ``` */ defaultRoute?: (req: ZeroRequest) => Response | Promise /** - * Global error handler + * Global error handler for uncaught exceptions + * Called when any route handler or middleware throws an error + * @example + * ```ts + * errorHandler: (err) => new Response(err.message, { status: 500 }) + * ``` */ errorHandler?: (err: Error) => Response | Promise /** - * Routes configuration + * Array of route configurations + * Defines the routing rules and handlers for the gateway */ routes?: RouteConfig[] /** - * Global proxy configuration + * Global proxy configuration applied to all routes + * Settings here can be overridden by individual route configurations */ proxy?: ProxyOptions /** - * CORS configuration + * Cross-Origin Resource Sharing (CORS) configuration + * Controls browser access from different origins */ cors?: { + /** + * Allowed origins for cross-origin requests + * @example + * - `"*"` - Allow all origins + * - `"https://example.com"` - Allow specific origin + * - `["https://app1.com", "https://app2.com"]` - Allow multiple origins + * - `(origin, req) => origin.endsWith(".mycompany.com")` - Dynamic validation + */ origin?: | string | string[] | boolean | ((origin: string, req: ZeroRequest) => boolean | string) + /** + * Allowed HTTP methods for CORS requests + * @default ["GET", "HEAD", "PUT", "PATCH", "POST", "DELETE"] + */ methods?: string[] + /** + * Headers that clients are allowed to send + * @default ["Content-Type", "Authorization"] + */ allowedHeaders?: string[] + /** + * Headers exposed to the client + * @default [] + */ exposedHeaders?: string[] + /** + * Allow credentials (cookies, authorization headers) + * @default false + */ credentials?: boolean + /** + * How long browsers can cache CORS information in seconds + * @default 86400 (24 hours) + */ maxAge?: number } /** - * Rate limiting configuration + * Rate limiting configuration to prevent abuse + * Protects against excessive requests from clients */ rateLimit?: { + /** + * Time window for rate limiting in milliseconds + * @default 900000 (15 minutes) + */ windowMs?: number + /** + * Maximum number of requests per window + * @default 100 + */ max?: number + /** + * Function to generate unique keys for rate limiting + * Used to identify clients (by IP, user ID, etc.) + * @default (req) => req.ip + */ keyGenerator?: (req: ZeroRequest) => string + /** + * Include rate limit info in standard headers + * Adds X-RateLimit-* headers to responses + * @default true + */ standardHeaders?: boolean } /** - * JWT Authentication configuration + * JWT (JSON Web Token) authentication configuration + * Enables token-based authentication for protected routes */ auth?: JWTAuthOptions /** - * Body parser configuration + * Request body parsing configuration + * Controls how request bodies are parsed and made available */ bodyParser?: BodyParserOptions /** - * Logging configuration + * Logging configuration and logger instance + * Controls how gateway events and requests are logged */ logger?: Logger /** - * Health check configuration + * Health check endpoint configuration + * Provides a simple health check endpoint for monitoring */ healthCheck?: { + /** + * Path for the health check endpoint + * @default "/health" + */ path?: string + /** + * Enable the health check endpoint + * @default true + */ enabled?: boolean } /** - * Metrics configuration + * Metrics collection and Prometheus integration + * Enables performance monitoring and observability */ metrics?: { + /** + * Enable metrics collection + * @default false + */ enabled?: boolean + /** + * Endpoint path for metrics exposure + * @default "/metrics" + */ endpoint?: string + /** + * Collect default Node.js/Bun runtime metrics + * @default true + */ collectDefaultMetrics?: boolean } } /** - * Gateway interface - follows 0http-bun router pattern + * Main Gateway interface following the 0http-bun router pattern + * Provides a complete API gateway with routing, middleware, and proxy capabilities */ export interface Gateway { /** - * Main fetch handler for Bun.serve + * Main fetch handler compatible with Bun.serve() + * This is the core handler that processes all incoming HTTP requests + * @param req - The incoming HTTP request + * @returns Response or Promise that resolves to a Response */ fetch: (req: Request) => Response | Promise /** - * Register middleware (global) + * Register global middleware that applies to all routes + * @param middleware - Middleware function to apply globally + * @returns Gateway instance for method chaining + * @example + * ```ts + * gateway.use(corsMiddleware) + * ``` */ use(middleware: RequestHandler): this /** - * Register middleware for specific path + * Register middleware for a specific path pattern + * @param pattern - URL pattern to match (supports wildcards and parameters) + * @param middleware - Middleware function to apply to matching routes + * @returns Gateway instance for method chaining + * @example + * ```ts + * gateway.use('/api/*', authMiddleware) + * ``` */ use(pattern: string, middleware: RequestHandler): this /** - * Register multiple middlewares + * Register multiple middlewares at once + * @param middlewares - Array of middleware functions + * @returns Gateway instance for method chaining + * @example + * ```ts + * gateway.use(corsMiddleware, authMiddleware, loggingMiddleware) + * ``` */ use(...middlewares: RequestHandler[]): this /** * Register route handler for specific HTTP method and pattern + * @param method - HTTP method (GET, POST, PUT, etc.) + * @param pattern - URL pattern with optional parameters (e.g., '/users/:id') + * @param handlers - Route handler functions (middleware and final handler) + * @returns Gateway instance for method chaining + * @example + * ```ts + * gateway.on('GET', '/users/:id', validateAuth, getUserHandler) + * ``` */ on(method: string, pattern: string, ...handlers: RequestHandler[]): this /** - * HTTP method shortcuts + * HTTP method convenience methods for route registration + * Each method registers a route for the specific HTTP verb + */ + + /** + * Register GET route handler + * @param pattern - URL pattern to match + * @param handlers - Route handler functions + * @example + * ```ts + * gateway.get('/users', getAllUsers) + * gateway.get('/users/:id', getUser) + * ``` */ get(pattern: string, ...handlers: RequestHandler[]): this + + /** + * Register POST route handler + * @param pattern - URL pattern to match + * @param handlers - Route handler functions + */ post(pattern: string, ...handlers: RequestHandler[]): this + + /** + * Register PUT route handler + * @param pattern - URL pattern to match + * @param handlers - Route handler functions + */ put(pattern: string, ...handlers: RequestHandler[]): this + + /** + * Register PATCH route handler + * @param pattern - URL pattern to match + * @param handlers - Route handler functions + */ patch(pattern: string, ...handlers: RequestHandler[]): this + + /** + * Register DELETE route handler + * @param pattern - URL pattern to match + * @param handlers - Route handler functions + */ delete(pattern: string, ...handlers: RequestHandler[]): this + + /** + * Register HEAD route handler + * @param pattern - URL pattern to match + * @param handlers - Route handler functions + */ head(pattern: string, ...handlers: RequestHandler[]): this + + /** + * Register OPTIONS route handler + * @param pattern - URL pattern to match + * @param handlers - Route handler functions + */ options(pattern: string, ...handlers: RequestHandler[]): this + + /** + * Register route handler for all HTTP methods + * @param pattern - URL pattern to match + * @param handlers - Route handler functions + */ all(pattern: string, ...handlers: RequestHandler[]): this /** - * Add a route configuration dynamically + * Add a complete route configuration dynamically at runtime + * Useful for dynamic route registration after gateway initialization + * @param route - Complete route configuration object + * @example + * ```ts + * gateway.addRoute({ + * pattern: '/api/users', + * target: 'http://user-service:3000', + * methods: ['GET', 'POST'] + * }) + * ``` */ addRoute(route: RouteConfig): void /** - * Remove a route dynamically. - * - * @todo: NOT IMPLEMENTED IN 0http-bun YET + * Remove a route dynamically by pattern + * Note: This feature depends on 0http-bun router capabilities + * @param pattern - URL pattern to remove + * @deprecated This method may not be fully implemented yet */ removeRoute(pattern: string): void /** - * Get current gateway configuration + * Get the current gateway configuration + * Returns a copy of the configuration used to initialize the gateway + * @returns Current gateway configuration object */ getConfig(): GatewayConfig /** - * Start the gateway server (if not using Bun.serve directly) + * Start the gateway server on the specified port + * Alternative to using Bun.serve() directly with the fetch handler + * @param port - Port number to listen on (overrides config.server.port) + * @returns Promise that resolves to the Bun server instance + * @example + * ```ts + * const server = await gateway.listen(3000) + * console.log(`Gateway running on port ${server.port}`) + * ``` */ listen(port?: number): Promise /** - * Stop the gateway server + * Gracefully stop the gateway server + * Closes all connections and performs cleanup + * @returns Promise that resolves when server is fully stopped */ close(): Promise } /** - * Gateway factory configuration + * Gateway factory configuration interface + * Simplified configuration for basic gateway setup + * @deprecated Use GatewayConfig instead for full feature support */ export interface IGatewayConfig { /** - * Port number (for reference) + * Port number for the gateway server + * @default 3000 */ port?: number /** - * Default route handler (404 handler) + * Default route handler for unmatched requests (404 handler) + * @param req - The incoming request object + * @returns Response for unmatched routes */ defaultRoute?: (req: ZeroRequest) => Response | Promise /** - * Global error handler + * Global error handler for uncaught exceptions + * @param err - The error that occurred + * @param req - The request that caused the error + * @returns Error response */ errorHandler?: (err: Error, req: ZeroRequest) => Response | Promise } diff --git a/src/interfaces/index.ts b/src/interfaces/index.ts index 7b62be2..3c902ed 100644 --- a/src/interfaces/index.ts +++ b/src/interfaces/index.ts @@ -1,10 +1,28 @@ +/** + * Bungate API Gateway - TypeScript Interface Definitions + * + * This module exports all the TypeScript interfaces and types used throughout + * the Bungate API Gateway. These interfaces provide type safety and excellent + * IDE autocompletion for gateway configuration and development. + * + * @example + * ```ts + * import { GatewayConfig, RouteConfig } from 'bungate' + * + * const config: GatewayConfig = { + * server: { port: 3000 }, + * routes: [...] + * } + * ``` + */ + // Core Gateway Interface export type { Gateway, GatewayConfig, ClusterConfig } from './gateway' // Route Management export type { RouteConfig } from './route' -// Middleware System +// Middleware System - Re-exports from 0http-bun for compatibility export type { ZeroRequest, StepFunction, @@ -13,31 +31,35 @@ export type { IRouter, IRouterConfig, MiddlewareManager, - // All 0http-bun middleware types + // Authentication & Security LoggerOptions, JWTAuthOptions, APIKeyAuthOptions, JWKSLike, TokenExtractionOptions, + // Rate Limiting RateLimitOptions, MemoryStore, + // CORS CORSOptions, + // Body Parsing BodyParserOptions, JSONParserOptions, TextParserOptions, URLEncodedParserOptions, MultipartParserOptions, + // Metrics & Monitoring PrometheusMetrics, PrometheusMiddlewareOptions, MetricsHandlerOptions, PrometheusIntegration, - // Trouter types + // Router Types Trouter, Pattern, Methods, } from './middleware' -// Proxy Functionality +// Proxy Functionality - Re-exports from fetch-gate for compatibility export type { ProxyOptions, ProxyHandler, @@ -57,10 +79,7 @@ export type { } from './proxy' export type { CircuitState } from './proxy' -// Rate Limiting -// Rate limiting - now using 0http-bun's built-in rate limiter - -// Load Balancing +// Load Balancing - High-availability request distribution export type { LoadBalancer, LoadBalancerConfig, @@ -68,5 +87,5 @@ export type { LoadBalancerStats, } from './load-balancer' -// Logging +// Logging - Structured logging with request tracing export type { Logger, LoggerConfig, LogEntry } from './logger' diff --git a/src/interfaces/load-balancer.ts b/src/interfaces/load-balancer.ts index 24f9f03..6beece2 100644 --- a/src/interfaces/load-balancer.ts +++ b/src/interfaces/load-balancer.ts @@ -1,55 +1,78 @@ import type { Logger } from './logger' +/** + * Represents a target server in the load balancer pool + * Contains both configuration and runtime state information + */ export interface LoadBalancerTarget { /** - * Target URL + * Target service URL (including protocol, host, and port) + * @example 'http://service1.internal:3000' or 'https://api.service.com' */ url: string /** - * Target weight for weighted strategies + * Relative weight for weighted load balancing strategies + * Higher values receive more traffic + * @default 1 + * @example 5 (receives 5x more traffic than weight=1 targets) */ weight?: number /** - * Whether target is healthy + * Current health status of the target + * Automatically updated by health checks + * @default true */ healthy?: boolean /** - * Number of active connections + * Number of active connections to this target + * Used by least-connections strategy + * @default 0 */ connections?: number /** * Average response time in milliseconds + * Used for performance-based routing decisions + * @default 0 */ averageResponseTime?: number /** - * Last health check timestamp + * Timestamp of the last successful health check + * @default Date.now() */ lastHealthCheck?: number /** - * Target metadata + * Additional metadata for this target + * Can store custom properties for routing decisions + * @example { region: 'us-east-1', datacenter: 'primary' } */ metadata?: Record } +/** + * Load balancer configuration for distributing requests across multiple targets + * Supports various strategies and health checking capabilities + */ export interface LoadBalancerConfig { /** - * Load balancing strategy + * Load balancing strategy for request distribution + * @default 'round-robin' */ strategy: - | 'round-robin' - | 'least-connections' - | 'random' - | 'weighted' - | 'ip-hash' + | 'round-robin' // Distributes requests evenly in rotation + | 'least-connections' // Routes to target with fewest active connections + | 'random' // Randomly selects a target + | 'weighted' // Uses target weights for distribution + | 'ip-hash' // Routes based on client IP hash for session affinity /** - * List of targets + * List of backend targets to load balance across + * Runtime properties (healthy, connections, etc.) are managed automatically */ targets: Omit< LoadBalancerTarget, @@ -57,28 +80,65 @@ export interface LoadBalancerConfig { >[] /** - * Health check configuration + * Health check configuration for monitoring target availability */ healthCheck?: { + /** + * Enable health checking + * @default true + */ enabled: boolean + /** + * Health check interval in milliseconds + * @default 30000 (30 seconds) + */ interval: number + /** + * Health check request timeout in milliseconds + * @default 5000 (5 seconds) + */ timeout: number + /** + * Health check endpoint path + * @default '/health' + */ path: string + /** + * Expected HTTP status code for healthy response + * @default 200 + */ expectedStatus?: number + /** + * Expected response body content for validation + * @example 'OK' or 'healthy' + */ expectedBody?: string } /** - * Sticky session configuration + * Sticky session configuration for session affinity + * Ensures requests from the same client go to the same target */ stickySession?: { + /** + * Enable sticky sessions + * @default false + */ enabled: boolean + /** + * Cookie name for session tracking + * @default 'lb-session' + */ cookieName?: string + /** + * Session TTL in milliseconds + * @default 3600000 (1 hour) + */ ttl?: number } /** - * Logger instance for load balancer operations + * Logger instance for load balancer operations and debugging */ logger?: Logger } diff --git a/src/interfaces/logger.ts b/src/interfaces/logger.ts index 5d61440..dcd2574 100644 --- a/src/interfaces/logger.ts +++ b/src/interfaces/logger.ts @@ -3,167 +3,267 @@ import type { LoggerOptions as PinoLoggerOptions, } from 'pino' +/** + * Structured log entry interface for consistent logging across the gateway + */ export interface LogEntry { /** - * Log level + * Log severity level + * - info: General information and normal operation + * - debug: Detailed information for debugging + * - warn: Warning messages for potential issues + * - error: Error messages for failures and exceptions */ level: 'info' | 'debug' | 'warn' | 'error' /** - * Log message + * Human-readable log message + * @example 'Request processed successfully' or 'Failed to connect to target service' */ message: string /** - * Timestamp + * Unix timestamp in milliseconds when the log entry was created */ timestamp: number /** - * Request ID for tracing + * Unique request identifier for distributed tracing + * Helps correlate logs across multiple services + * @example 'req-123e4567-e89b-12d3-a456-426614174000' */ requestId?: string /** - * Additional log data + * Additional structured data related to the log entry + * @example { userId: '123', action: 'login', duration: 150 } */ data?: Record /** - * Request information + * HTTP request information for request-related logs */ request?: { + /** HTTP method (GET, POST, etc.) */ method: string + /** Full request URL */ url: string + /** Request headers (may be filtered for security) */ headers?: Record + /** User agent string */ userAgent?: string + /** Client IP address */ ip?: string } /** - * Response information + * HTTP response information for response-related logs */ response?: { + /** HTTP status code */ status: number + /** Response headers */ headers?: Record + /** Request processing duration in milliseconds */ duration: number + /** Response body size in bytes */ size?: number } /** - * Error information + * Error information for exception logs */ error?: { + /** Error class name */ name: string + /** Error message */ message: string + /** Stack trace (may be omitted in production) */ stack?: string } } +/** + * Logger configuration extending Pino logger options + * Provides gateway-specific logging features and customization + */ export interface LoggerConfig extends Partial { /** - * Minimum log level + * Minimum log level to output + * Messages below this level will be ignored + * @default 'info' */ level?: 'info' | 'debug' | 'warn' | 'error' /** - * Log format + * Log output format + * - json: Structured JSON format for production + * - pretty: Human-readable format for development + * @default 'json' */ format?: 'json' | 'pretty' /** - * Whether to include request headers + * Include HTTP headers in request/response logs + * May be disabled for security or performance reasons + * @default false */ includeHeaders?: boolean /** - * Whether to include request/response body + * Include request/response body content in logs + * Should be disabled in production for security and performance + * @default false */ includeBody?: boolean /** - * Custom log formatter + * Custom formatter function for log entries + * Allows complete control over log output format */ formatter?: (entry: LogEntry) => string /** * Log output destination + * @default 'console' */ output?: 'console' | 'file' | 'custom' /** - * File path for file output + * File path for file-based logging + * Required when output is 'file' */ filePath?: string /** - * Custom log handler + * Custom log handler for advanced log processing + * Called for each log entry when output is 'custom' */ handler?: (entry: LogEntry) => void | Promise /** - * Enable request/response logging + * Enable automatic request/response logging + * Logs all HTTP requests and responses passing through the gateway + * @default true */ enableRequestLogging?: boolean /** * Enable performance metrics logging + * Logs timing and performance information + * @default false */ enableMetrics?: boolean } +/** + * Gateway logger interface with enhanced functionality + * Provides structured logging with request tracing and performance monitoring + */ export interface Logger { /** - * Underlying Pino logger instance + * Access to the underlying Pino logger instance + * For advanced usage and direct Pino feature access */ readonly pino: PinoLogger /** - * Log info message + * Log informational messages + * @param message - Log message + * @param data - Additional structured data */ info(message: string, data?: Record): void + /** + * Log informational messages with object data + * @param obj - Structured log data + * @param message - Optional message + */ info(obj: object, message?: string): void /** - * Log debug message + * Log debug messages for troubleshooting + * @param message - Debug message + * @param data - Additional debug data */ debug(message: string, data?: Record): void + /** + * Log debug messages with object data + * @param obj - Structured debug data + * @param message - Optional message + */ debug(obj: object, message?: string): void /** - * Log warning message + * Log warning messages for potential issues + * @param message - Warning message + * @param data - Additional context data */ warn(message: string, data?: Record): void + /** + * Log warning messages with object data + * @param obj - Structured warning data + * @param message - Optional message + */ warn(obj: object, message?: string): void /** - * Log error message + * Log error messages for failures and exceptions + * @param message - Error message + * @param error - Error object with stack trace + * @param data - Additional error context */ error(message: string, error?: Error, data?: Record): void + /** + * Log error messages with object data + * @param obj - Structured error data + * @param message - Optional message + */ error(obj: object, message?: string): void /** - * Log request/response + * Log HTTP request and response information + * Automatically called for all gateway requests when request logging is enabled + * @param request - HTTP request object + * @param response - HTTP response object (optional for request-only logging) + * @param duration - Request processing time in milliseconds */ logRequest(request: Request, response?: Response, duration?: number): void /** - * Create child logger with additional context + * Create a child logger with additional context + * Child loggers inherit parent configuration but add extra context to all logs + * @param context - Additional context to include in all child logger messages + * @returns New logger instance with added context + * @example + * ```ts + * const routeLogger = logger.child({ route: '/api/users', version: 'v1' }) + * routeLogger.info('Processing request') // Includes route and version context + * ``` */ child(context: Record): Logger /** - * Set log level + * Change the minimum log level at runtime + * @param level - New minimum log level */ setLevel(level: LoggerConfig['level']): void /** - * Get current log level + * Get the current minimum log level + * @returns Current log level */ getLevel(): LoggerConfig['level'] /** - * Log performance metrics + * Log performance metrics for monitoring and optimization + * @param component - Component or service name + * @param operation - Operation being measured + * @param duration - Operation duration in milliseconds + * @param metadata - Additional performance context + * @example + * ```ts + * logger.logMetrics('proxy', 'forward_request', 150, { target: 'user-service' }) + * ``` */ logMetrics( component: string, diff --git a/src/interfaces/middleware.ts b/src/interfaces/middleware.ts index d4af752..d5fc247 100644 --- a/src/interfaces/middleware.ts +++ b/src/interfaces/middleware.ts @@ -1,6 +1,7 @@ /** * Import and re-export core 0http-bun types directly from the package - * This ensures 100% compatibility and eliminates duplication + * This ensures 100% compatibility and eliminates duplication while providing + * enhanced TypeScript support for gateway middleware development */ import type { ZeroRequest, @@ -11,80 +12,91 @@ import type { ParsedFile, } from '0http-bun' -// Import all middleware types from 0http-bun +// Import all middleware types from 0http-bun for comprehensive middleware support import type { - // Logger middleware + // Logger middleware for request/response logging LoggerOptions, - // JWT/Auth middleware + // JWT/Auth middleware for security JWTAuthOptions, APIKeyAuthOptions, JWKSLike, TokenExtractionOptions, - // Rate limiting middleware + // Rate limiting middleware for abuse prevention RateLimitOptions, RateLimitStore, MemoryStore, - // CORS middleware + // CORS middleware for cross-origin requests CORSOptions, - // Body parser middleware + // Body parser middleware for request parsing BodyParserOptions, JSONParserOptions, TextParserOptions, URLEncodedParserOptions, MultipartParserOptions, - // Prometheus middleware + // Prometheus middleware for metrics collection PrometheusMetrics, PrometheusMiddlewareOptions, MetricsHandlerOptions, PrometheusIntegration, } from '0http-bun/lib/middleware' -// Import trouter types used by 0http-bun +// Import trouter types used by 0http-bun for routing export type { Trouter } from 'trouter' -// Pattern and Methods are type aliases, we need to define them based on trouter source +// Pattern and Methods type definitions based on trouter specifications +// These types define the supported URL patterns and HTTP methods for routing + +/** + * URL pattern type for route matching + * Supports both string patterns and regular expressions + */ export type Pattern = RegExp | string + +/** + * Comprehensive HTTP methods enum for complete HTTP specification support + * Includes standard and extended HTTP methods for various use cases + */ export type Methods = - | 'ACL' - | 'BIND' - | 'CHECKOUT' - | 'CONNECT' - | 'COPY' - | 'DELETE' - | 'GET' - | 'HEAD' - | 'LINK' - | 'LOCK' - | 'M-SEARCH' - | 'MERGE' - | 'MKACTIVITY' - | 'MKCALENDAR' - | 'MKCOL' - | 'MOVE' - | 'NOTIFY' - | 'OPTIONS' - | 'PATCH' - | 'POST' - | 'PRI' - | 'PROPFIND' - | 'PROPPATCH' - | 'PURGE' - | 'PUT' - | 'REBIND' - | 'REPORT' - | 'SEARCH' - | 'SOURCE' - | 'SUBSCRIBE' - | 'TRACE' - | 'UNBIND' - | 'UNLINK' - | 'UNLOCK' - | 'UNSUBSCRIBE' + | 'ACL' // Access Control List + | 'BIND' // WebDAV binding + | 'CHECKOUT' // Version control + | 'CONNECT' // HTTP tunnel + | 'COPY' // WebDAV copy + | 'DELETE' // Delete resource + | 'GET' // Retrieve resource + | 'HEAD' // Retrieve headers only + | 'LINK' // Link resource + | 'LOCK' // WebDAV lock + | 'M-SEARCH' // Multicast search + | 'MERGE' // Version control merge + | 'MKACTIVITY' // WebDAV activity + | 'MKCALENDAR' // CalDAV calendar + | 'MKCOL' // WebDAV collection + | 'MOVE' // WebDAV move + | 'NOTIFY' // Event notification + | 'OPTIONS' // Capability inquiry + | 'PATCH' // Partial update + | 'POST' // Create/submit data + | 'PRI' // HTTP/2 connection preface + | 'PROPFIND' // WebDAV property find + | 'PROPPATCH' // WebDAV property patch + | 'PURGE' // Cache purge + | 'PUT' // Create/update resource + | 'REBIND' // WebDAV rebind + | 'REPORT' // WebDAV report + | 'SEARCH' // Search request + | 'SOURCE' // Source retrieval + | 'SUBSCRIBE' // Event subscription + | 'TRACE' // Message loop-back test + | 'UNBIND' // WebDAV unbind + | 'UNLINK' // Unlink resource + | 'UNLOCK' // WebDAV unlock + | 'UNSUBSCRIBE' // Event unsubscription // Re-export core types export type { diff --git a/src/interfaces/proxy.ts b/src/interfaces/proxy.ts index 56890b3..ef5c03d 100644 --- a/src/interfaces/proxy.ts +++ b/src/interfaces/proxy.ts @@ -1,6 +1,7 @@ /** * Import and re-export fetch-gate types directly from the package - * This ensures 100% compatibility and eliminates duplication + * This ensures 100% compatibility with fetch-gate while providing + * enhanced TypeScript support for proxy functionality in the gateway */ import type { ProxyOptions, @@ -46,11 +47,23 @@ import type { ZeroRequest } from './middleware' /** * Gateway-specific proxy handler interface - * Extends fetch-gate functionality with ZeroRequest support + * Extends fetch-gate functionality with enhanced ZeroRequest support + * and gateway-specific features for request forwarding */ export interface ProxyHandler { /** - * Proxy a request to target (gateway-specific with ZeroRequest) + * Proxy a request to a target service + * @param req - The gateway request object with enhanced context + * @param source - Target URL or service identifier + * @param opts - Additional proxy options for this request + * @returns Promise resolving to the proxied response + * @example + * ```ts + * const response = await proxy.proxy(req, 'http://user-service:3000', { + * timeout: 5000, + * headers: { 'X-Gateway': 'bungate' } + * }) + * ``` */ proxy( req: ZeroRequest, @@ -59,33 +72,43 @@ export interface ProxyHandler { ): Promise /** - * Close proxy instance + * Gracefully close the proxy instance + * Cleans up resources and closes any open connections */ close(): void /** - * Get circuit breaker state + * Get the current circuit breaker state for monitoring + * @returns Current circuit state (CLOSED, OPEN, HALF_OPEN) */ getCircuitBreakerState(): CircuitState /** - * Get circuit breaker failures + * Get the number of consecutive failures in the circuit breaker + * @returns Number of failures that contributed to circuit breaker state */ getCircuitBreakerFailures(): number /** - * Clear URL cache + * Clear the internal URL cache for DNS and connection pooling + * Useful for forcing reconnection to updated services */ clearURLCache(): void } /** * Gateway-specific proxy factory function return type + * Provides a simplified interface for proxy operations */ export interface ProxyInstance { + /** Proxy method for request forwarding */ proxy: ProxyHandler['proxy'] + /** Close method for cleanup */ close: ProxyHandler['close'] + /** Circuit breaker state inspection */ getCircuitBreakerState: ProxyHandler['getCircuitBreakerState'] + /** Circuit breaker failure count */ getCircuitBreakerFailures: ProxyHandler['getCircuitBreakerFailures'] + /** URL cache management */ clearURLCache: ProxyHandler['clearURLCache'] } diff --git a/src/interfaces/route.ts b/src/interfaces/route.ts index 05d48b5..ad4966c 100644 --- a/src/interfaces/route.ts +++ b/src/interfaces/route.ts @@ -11,83 +11,121 @@ import type { ZeroRequest, } from './middleware' +/** + * Route configuration interface for defining individual routes in the gateway + * Each route can handle requests through either direct handlers or by proxying to backend services + */ export interface RouteConfig { /** - * Route path pattern + * URL pattern to match incoming requests + * Supports wildcards (*) and parameters (:param) + * @example + * - '/users' - Exact match + * - '/users/*' - Wildcard match + * - '/users/:id' - Parameter match + * - '/api/v1/users/:id/posts/:postId' - Multiple parameters */ pattern: string /** - * Target service URL for proxying + * Target service URL for proxying requests + * When specified, requests matching this route will be forwarded to this URL + * @example 'http://user-service:3000' or 'https://api.example.com' */ target?: string /** - * Direct route handler (alternative to proxy) + * Direct route handler function (alternative to proxying) + * Use this for handling requests locally instead of forwarding to another service + * @example + * ```ts + * handler: (req) => new Response('Hello World') + * ``` */ handler?: RequestHandler /** * HTTP methods allowed for this route + * @default ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS'] + * @example ['GET', 'POST'] - Only allow GET and POST requests */ methods?: string[] /** - * Route-specific middlewares + * Route-specific middleware functions + * These middlewares run only for this route, in addition to global middlewares + * @example [authMiddleware, validationMiddleware] */ middlewares?: RequestHandler[] /** - * Route-specific timeout in milliseconds + * Request timeout for this route in milliseconds + * Overrides global timeout settings + * @default 30000 (30 seconds) */ timeout?: number /** - * Proxy configuration (following fetch-gate pattern) + * Proxy configuration options (follows fetch-gate pattern) + * Controls how requests are forwarded to backend services */ proxy?: { /** - * Custom headers to add to proxied requests + * Additional headers to include in proxied requests + * These headers are merged with the original request headers + * @example { 'X-Forwarded-For': 'gateway', 'Authorization': 'Bearer token' } */ headers?: Record /** - * Request timeout in milliseconds + * Request timeout in milliseconds for proxy requests + * @default 30000 (30 seconds) */ timeout?: number /** - * Whether to follow redirects + * Whether to automatically follow HTTP redirects + * @default true */ followRedirects?: boolean /** * Maximum number of redirects to follow + * @default 5 */ maxRedirects?: number /** - * Path rewriting rules + * Path rewriting rules for modifying the request path before forwarding + * @example + * - Object: { '^/api/v1': '/v1', '^/old': '/new' } + * - Function: (path) => path.replace('/api', '') */ pathRewrite?: Record | ((path: string) => string) /** - * Query parameters to add + * Additional query parameters to append to proxied requests + * @example { 'version': '1.0', 'source': 'gateway' } or 'version=1.0&source=gateway' */ queryString?: Record | string /** - * Custom fetch options + * Custom fetch options for the proxy request + * Allows fine-grained control over the request behavior */ request?: RequestInit } /** - * Hooks (following fetch-gate pattern) + * Lifecycle hooks for request/response processing (follows fetch-gate pattern) + * Provides fine-grained control over the proxy request lifecycle */ hooks?: { /** - * Called before request is sent to target + * Called before the request is sent to the target service + * Allows modification of request or proxy options + * @param req - The incoming request object + * @param opts - The proxy configuration options */ beforeRequest?: ( req: ZeroRequest, @@ -95,7 +133,11 @@ export interface RouteConfig { ) => void | Promise /** - * Called after response is received + * Called after the response is received from the target service + * Allows inspection or modification of the response + * @param req - The original request object + * @param res - The response from the target service + * @param body - The response body stream (if available) */ afterResponse?: ( req: ZeroRequest, @@ -104,47 +146,78 @@ export interface RouteConfig { ) => void | Promise /** - * Called when an error occurs + * Called when an error occurs during request processing + * Can return a custom error response + * @param req - The original request object + * @param error - The error that occurred + * @returns Optional custom error response */ onError?: ( req: Request, error: Error, ) => void | Promise | Promise - /** Hook called before the circuit breaker executes the request */ + /** + * Called before the circuit breaker executes the request + * Allows inspection of circuit breaker state + */ beforeCircuitBreakerExecution?: BeforeCircuitBreakerHook - /** Hook called after the circuit breaker completes (success or failure) */ + /** + * Called after the circuit breaker completes (success or failure) + * Provides access to execution results and metrics + */ afterCircuitBreakerExecution?: AfterCircuitBreakerHook } /** - * Circuit breaker configuration + * Circuit breaker configuration for fault tolerance + * Automatically handles service failures by opening the circuit when error thresholds are exceeded */ circuitBreaker?: CircuitBreakerOptions /** - * Load balancing configuration + * Load balancing configuration for distributing requests across multiple targets + * When multiple targets are specified, requests will be distributed according to the strategy */ loadBalancer?: Omit /** - * JWT Authentication configuration + * JWT authentication configuration for this route + * Enables token-based authentication for protected endpoints */ auth?: JWTAuthOptions /** - * Rate limiting configuration (using 0http-bun's rate limiter) + * Rate limiting configuration specific to this route + * Controls the number of requests allowed per time window */ rateLimit?: RateLimitOptions /** - * Route metadata + * Route metadata for documentation and introspection + * Useful for API documentation generation and monitoring */ meta?: { + /** + * Human-readable name for this route + * @example 'Get User Profile' + */ name?: string + /** + * Description of what this route does + * @example 'Retrieves user profile information by user ID' + */ description?: string + /** + * API version for this route + * @example 'v1.2.0' + */ version?: string + /** + * Tags for categorizing routes + * @example ['users', 'profile', 'public-api'] + */ tags?: string[] } } diff --git a/src/load-balancer/http-load-balancer.ts b/src/load-balancer/http-load-balancer.ts index a231af6..e4902fd 100644 --- a/src/load-balancer/http-load-balancer.ts +++ b/src/load-balancer/http-load-balancer.ts @@ -1,6 +1,31 @@ /** - * Load balancer implementation using basic JavaScript structures - * Supports multiple strategies: round-robin, least-connections, weighted, random, ip-hash + * HTTP Load Balancer Implementation + * + * A high-performance load balancer that distributes incoming requests across multiple + * backend targets using various strategies. Supports health checking, sticky sessions, + * and comprehensive monitoring for production-grade API gateway deployments. + * + * Features: + * - Multiple load balancing strategies (round-robin, least-connections, weighted, random, ip-hash) + * - Automatic health checking with configurable intervals and validation + * - Sticky session support for session affinity + * - Real-time statistics and monitoring + * - Circuit breaker pattern for fault tolerance + * - Comprehensive logging and observability + * + * @example + * ```ts + * const loadBalancer = new HttpLoadBalancer({ + * strategy: 'least-connections', + * targets: [ + * { url: 'http://service1:3000', weight: 2 }, + * { url: 'http://service2:3000', weight: 1 } + * ], + * healthCheck: { enabled: true, interval: 30000, path: '/health' } + * }) + * + * const target = loadBalancer.selectTarget(request) + * ``` */ import type { LoadBalancer, @@ -13,37 +38,62 @@ import { defaultLogger } from '../logger/pino-logger' import * as crypto from 'crypto' /** - * Internal target with additional tracking data + * Internal target representation with runtime tracking data + * Extends the base LoadBalancerTarget with operational metrics */ interface InternalTarget extends LoadBalancerTarget { + /** Number of requests routed to this target */ requests: number + /** Number of failed requests to this target */ errors: number + /** Cumulative response time for average calculation */ totalResponseTime: number + /** Timestamp of last request to this target */ lastUsed: number } /** - * Session tracking for sticky sessions + * Session tracking for sticky session functionality + * Maintains client-to-target affinity for stateful applications */ interface Session { + /** Target URL this session is bound to */ targetUrl: string + /** Session creation timestamp */ createdAt: number + /** Session expiration timestamp */ expiresAt: number } /** - * Load balancer implementation + * Production-ready HTTP Load Balancer Implementation + * + * Provides intelligent request distribution across multiple backend services + * with enterprise-grade features for high-availability deployments. */ export class HttpLoadBalancer implements LoadBalancer { + /** Map of target URLs to their internal tracking data */ private targets = new Map() + /** Load balancer configuration */ private config: LoadBalancerConfig - private currentIndex = 0 // For round-robin + /** Current index for round-robin strategy */ + private currentIndex = 0 + /** Total number of requests processed */ private totalRequests = 0 + /** Health check interval timer */ private healthCheckInterval?: Timer - private sessions = new Map() // For sticky sessions + /** Session tracking for sticky sessions */ + private sessions = new Map() + /** Session cleanup interval timer */ private sessionCleanupInterval?: Timer + /** Logger instance for monitoring and debugging */ private logger: Logger + /** + * Initialize the load balancer with configuration and start background services + * + * @param config - Load balancer configuration including strategy, targets, and options + */ constructor(config: LoadBalancerConfig) { this.config = { ...config } this.logger = config.logger ?? defaultLogger @@ -55,24 +105,39 @@ export class HttpLoadBalancer implements LoadBalancer { stickySessionEnabled: config.stickySession?.enabled, }) - // Initialize targets + // Initialize all configured targets for (const target of config.targets) { this.addTarget(target) } - // Start health checks if enabled + // Start health monitoring if enabled if (config.healthCheck?.enabled) { this.startHealthChecks() } - // Start session cleanup if sticky sessions enabled + // Start session management if sticky sessions are enabled if (config.stickySession?.enabled) { this.startSessionCleanup() } } /** - * Select next target based on strategy + * Select the optimal target for the incoming request + * + * Uses the configured load balancing strategy to distribute requests intelligently + * across healthy targets. Supports sticky sessions for session affinity. + * + * @param request - The incoming HTTP request to route + * @returns Selected target or null if no healthy targets available + * + * @example + * ```ts + * const target = loadBalancer.selectTarget(request) + * if (target) { + * // Forward request to target.url + * const response = await fetch(`${target.url}${request.url}`) + * } + * ``` */ selectTarget(request: Request): LoadBalancerTarget | null { const startTime = Date.now() @@ -149,7 +214,21 @@ export class HttpLoadBalancer implements LoadBalancer { } /** - * Add a target to the load balancer + * Add a new target to the load balancer pool + * + * Initializes tracking data and makes the target available for request routing. + * Can be used for dynamic scaling by adding targets at runtime. + * + * @param target - Target configuration to add + * + * @example + * ```ts + * loadBalancer.addTarget({ + * url: 'http://new-service:3000', + * weight: 2, + * metadata: { region: 'us-west-2' } + * }) + * ``` */ addTarget(target: LoadBalancerTarget): void { const internalTarget: InternalTarget = { @@ -167,14 +246,37 @@ export class HttpLoadBalancer implements LoadBalancer { } /** - * Remove a target from the load balancer + * Remove a target from the load balancer pool + * + * Immediately stops routing requests to the specified target. + * Useful for maintenance, scaling down, or handling failed services. + * + * @param url - Target URL to remove from the pool + * + * @example + * ```ts + * // Remove a failed service + * loadBalancer.removeTarget('http://failed-service:3000') + * ``` */ removeTarget(url: string): void { this.targets.delete(url) } /** - * Update target health status + * Update the health status of a specific target + * + * Called by health checks or external monitoring systems to mark + * targets as healthy or unhealthy, affecting routing decisions. + * + * @param url - Target URL to update + * @param healthy - New health status + * + * @example + * ```ts + * // Mark a target as unhealthy after circuit breaker opens + * loadBalancer.updateTargetHealth('http://service:3000', false) + * ``` */ updateTargetHealth(url: string, healthy: boolean): void { const target = this.targets.get(url) @@ -185,21 +287,43 @@ export class HttpLoadBalancer implements LoadBalancer { } /** - * Get all targets + * Get all configured targets with their current status + * + * Returns complete target information including health status, + * connection counts, and performance metrics. + * + * @returns Array of all targets with runtime data */ getTargets(): LoadBalancerTarget[] { return Array.from(this.targets.values()) } /** - * Get healthy targets only + * Get only healthy targets available for routing + * + * Filters out unhealthy targets that should not receive traffic. + * Used internally by routing strategies and externally for monitoring. + * + * @returns Array of healthy targets ready to handle requests */ getHealthyTargets(): LoadBalancerTarget[] { return Array.from(this.targets.values()).filter((target) => target.healthy) } /** - * Get load balancer statistics + * Get comprehensive load balancer statistics + * + * Provides operational metrics for monitoring, alerting, and capacity planning. + * Includes per-target statistics and overall performance data. + * + * @returns Statistics object with performance and health metrics + * + * @example + * ```ts + * const stats = loadBalancer.getStats() + * console.log(`Total requests: ${stats.totalRequests}`) + * console.log(`Healthy targets: ${stats.healthyTargets}/${stats.totalTargets}`) + * ``` */ getStats(): LoadBalancerStats { const targetStats: Record = {} diff --git a/src/logger/pino-logger.ts b/src/logger/pino-logger.ts index a7b3884..b534e40 100644 --- a/src/logger/pino-logger.ts +++ b/src/logger/pino-logger.ts @@ -1,17 +1,53 @@ /** - * Pino-based logger implementation for BunGate + * Production-Grade Pino Logger Implementation for Bungate + * + * A high-performance, structured logging solution built on Pino with gateway-specific + * enhancements for request tracing, performance monitoring, and operational visibility. + * + * Features: + * - Ultra-fast JSON logging with minimal overhead + * - Structured request/response logging with correlation IDs + * - Performance metrics and timing information + * - Configurable log levels and output formats + * - Support for file, console, and custom output destinations + * - Child logger creation for contextual logging + * - Health check and load balancing event logging + * - Integration with monitoring and alerting systems + * + * @example + * ```ts + * const logger = new BunGateLogger({ + * level: 'info', + * format: 'json', + * enableRequestLogging: true, + * enableMetrics: true + * }) + * + * logger.info('Gateway started', { port: 3000, version: '1.0.0' }) + * logger.logRequest(request, response, 150) + * ``` */ import pino from 'pino' import type { LoggerOptions, Logger as PinoLogger } from 'pino' import type { Logger, LoggerConfig } from '../interfaces/logger' /** - * Enhanced logger that wraps Pino with BunGate-specific functionality + * Enhanced Pino logger with gateway-specific functionality + * + * Provides structured logging, request tracing, and performance monitoring + * optimized for high-throughput API gateway operations. */ export class BunGateLogger implements Logger { + /** Direct access to underlying Pino logger for advanced usage */ readonly pino: PinoLogger + /** Logger configuration with gateway-specific options */ private config: LoggerConfig + /** + * Initialize the logger with comprehensive configuration + * + * @param config - Logger configuration including level, format, and output options + */ constructor(config: LoggerConfig = {}) { this.config = { level: 'info', @@ -21,13 +57,13 @@ export class BunGateLogger implements Logger { ...config, } - // Create Pino logger with configuration + // Configure Pino logger with gateway-optimized settings const pinoConfig: any = { level: this.config.level, ...config, } - // Set up pretty printing if requested + // Configure pretty printing for development if (this.config.format === 'pretty') { pinoConfig.transport = { target: 'pino-pretty', @@ -39,7 +75,7 @@ export class BunGateLogger implements Logger { } } - // Set up file output if requested + // Configure file output for production logging if (this.config.output === 'file' && this.config.filePath) { pinoConfig.transport = { target: 'pino/file', diff --git a/src/proxy/gateway-proxy.ts b/src/proxy/gateway-proxy.ts index f37adf4..c058f35 100644 --- a/src/proxy/gateway-proxy.ts +++ b/src/proxy/gateway-proxy.ts @@ -1,3 +1,37 @@ +/** + * Gateway Proxy Implementation + * + * A high-performance HTTP proxy built on fetch-gate with enhanced gateway features. + * Provides intelligent request forwarding, circuit breaker pattern, connection pooling, + * and comprehensive monitoring for reliable microservices communication. + * + * Features: + * - Circuit breaker protection against cascading failures + * - Connection pooling and keep-alive for performance + * - Request/response transformation capabilities + * - Comprehensive error handling and retry logic + * - Real-time health monitoring and metrics + * - Support for ZeroRequest enhanced context + * + * @example + * ```ts + * const proxy = createGatewayProxy({ + * timeout: 5000, + * circuitBreaker: { + * errorThreshold: 50, + * resetTimeout: 30000 + * }, + * hooks: { + * beforeRequest: (req) => { + * req.headers.set('X-Gateway', 'bungate') + * } + * } + * }) + * + * const response = await proxy.proxy(request, 'http://backend-service:3000') + * ``` + */ + import type { ProxyHandler, ProxyInstance } from '../interfaces/proxy' import type { ProxyOptions, @@ -8,42 +42,96 @@ import { FetchProxy } from 'fetch-gate/lib/proxy' import type { ZeroRequest } from '../interfaces/middleware' /** - * GatewayProxy wraps fetch-gate's FetchProxy to support ZeroRequest and gateway-specific features + * Gateway-enhanced proxy handler with ZeroRequest support + * + * Wraps fetch-gate's FetchProxy to provide seamless integration with the gateway's + * enhanced request context and middleware pipeline while maintaining full compatibility + * with fetch-gate's advanced features. */ export class GatewayProxy implements ProxyHandler { + /** Underlying fetch-gate proxy instance for core functionality */ private fetchProxy: FetchProxy + /** + * Initialize the gateway proxy with fetch-gate options + * + * @param options - Proxy configuration including timeouts, circuit breaker, and hooks + */ constructor(options: ProxyOptions) { this.fetchProxy = new FetchProxy(options) } + /** + * Proxy a request to the target service with gateway enhancements + * + * @param req - Enhanced ZeroRequest with gateway context + * @param source - Target service URL or identifier + * @param opts - Request-specific proxy options + * @returns Promise resolving to the proxied response + */ async proxy( req: ZeroRequest, source?: string, opts?: ProxyRequestOptions, ): Promise { + // Cast ZeroRequest to standard Request for fetch-gate compatibility return this.fetchProxy.proxy(req as Request, source, opts) } + /** + * Gracefully close the proxy and clean up resources + * Closes connection pools and cancels pending requests + */ close(): void { this.fetchProxy.close() } + /** + * Get current circuit breaker state for monitoring + * + * @returns Current circuit state (CLOSED, OPEN, HALF_OPEN) + */ getCircuitBreakerState(): CircuitState { return this.fetchProxy.getCircuitBreakerState() } + /** + * Get number of consecutive failures in circuit breaker + * + * @returns Failure count contributing to circuit state + */ getCircuitBreakerFailures(): number { return this.fetchProxy.getCircuitBreakerFailures() } + /** + * Clear internal URL cache for DNS and connection pooling + * Useful for forcing reconnection after service updates + */ clearURLCache(): void { this.fetchProxy.clearURLCache() } } /** - * Factory function to create a ProxyInstance for gateway use + * Factory function to create a ProxyInstance for gateway integration + * + * Creates a simplified proxy interface optimized for gateway usage patterns. + * Provides all essential proxy methods in a convenient, injectable format. + * + * @param options - Proxy configuration options + * @returns ProxyInstance with proxy methods for gateway integration + * + * @example + * ```ts + * const proxy = createGatewayProxy({ + * timeout: 10000, + * circuitBreaker: { errorThreshold: 5, resetTimeout: 60000 } + * }) + * + * // Use in route handler + * const response = await proxy.proxy(req, 'http://api.service.com') + * ``` */ export function createGatewayProxy(options: ProxyOptions): ProxyInstance { const handler = new GatewayProxy(options)