UNPKG

@ordojs/cli

Version:

Command-line interface for OrdoJS framework

130 lines 4.3 kB
/** * @fileoverview OrdoJS CLI - Port Manager * * Handles port allocation, detection of conflicts, and finding available ports. */ import net from 'net'; import { logger } from '../utils/index.js'; /** * Port range for automatic allocation */ const PORT_RANGE = { MIN: 3000, MAX: 3999 }; /** * PortManager class for handling port allocation and conflict resolution */ export class PortManager { usedPorts; basePort; /** * Create a new PortManager instance * * @param basePort - The preferred base port to use (default: 3000) */ constructor(basePort = PORT_RANGE.MIN) { this.usedPorts = new Set(); this.basePort = basePort; } /** * Check if a port is available * * @param port - The port to check * @returns Promise resolving to true if the port is available, false otherwise */ async isPortAvailable(port) { return new Promise((resolve) => { const server = net.createServer(); server.once('error', (err) => { const error = err; if (error.code === 'EADDRINUSE') { resolve(false); } else { // Other errors also indicate the port is not usable resolve(false); } }); server.once('listening', () => { // Close the server and resolve with true (port is available) server.close(() => { resolve(true); }); }); // Try to listen on the port server.listen(port, '127.0.0.1'); }); } /** * Find an available port starting from the specified port * * @param startPort - The port to start checking from * @returns Promise resolving to an available port number */ async findAvailablePort(startPort = this.basePort) { // Start from the requested port let port = startPort; // Try ports in sequence until we find an available one while (port <= PORT_RANGE.MAX) { if (await this.isPortAvailable(port)) { return port; } port++; } // If we've exhausted the range, throw an error throw new Error(`No available ports found in range ${startPort}-${PORT_RANGE.MAX}`); } /** * Allocate a port for a specific service * * @param serviceName - Name of the service requesting a port * @param preferredPort - Preferred port to use if available * @returns Promise resolving to the allocated port number */ async allocatePort(serviceName, preferredPort) { const startPort = preferredPort || this.basePort; try { // Check if the preferred port is available if (preferredPort && await this.isPortAvailable(preferredPort)) { this.usedPorts.add(preferredPort); logger.debug(`Allocated port ${preferredPort} for ${serviceName}`); return preferredPort; } // Find an available port const port = await this.findAvailablePort(startPort); this.usedPorts.add(port); if (preferredPort && port !== preferredPort) { logger.warn(`Preferred port ${preferredPort} for ${serviceName} was not available, using ${port} instead`); } else { logger.debug(`Allocated port ${port} for ${serviceName}`); } return port; } catch (error) { logger.error(`Failed to allocate port for ${serviceName}: ${error instanceof Error ? error.message : String(error)}`); throw error; } } /** * Release a previously allocated port * * @param port - The port to release */ releasePort(port) { if (this.usedPorts.has(port)) { this.usedPorts.delete(port); logger.debug(`Released port ${port}`); } } /** * Get all currently allocated ports * * @returns Set of allocated port numbers */ getAllocatedPorts() { return new Set(this.usedPorts); } } //# sourceMappingURL=port-manager.js.map