UNPKG

portfree

Version:

A cross-platform CLI tool for managing processes running on specific ports

203 lines 8.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.PortManager = void 0; const platform_detector_1 = require("../utils/platform-detector"); const validator_1 = require("../utils/validator"); const errors_1 = require("../errors"); const logger_1 = require("../utils/logger"); /** * Port Manager core business logic * Coordinates platform adapters to provide cross-platform port management functionality */ class PortManager { constructor(adapter, getPlatformAdapterFn) { this.adapter = null; this._initialized = false; this.logger = (0, logger_1.createLogger)('PortManager'); if (adapter) { this.adapter = adapter; this._initialized = true; } this.getPlatformAdapterFn = getPlatformAdapterFn || platform_detector_1.getPlatformAdapter; } /** * Initialize the port manager with the appropriate platform adapter * @throws If platform adapter cannot be initialized */ async initialize() { if (this._initialized) { this.logger.debug('Port manager already initialized'); return; } try { this.logger.debug('Initializing port manager'); const AdapterClassOrInstance = await this.getPlatformAdapterFn(); // Handle both class constructors and direct instances (for testing) if (typeof AdapterClassOrInstance === 'function') { this.adapter = new AdapterClassOrInstance(); } else if (AdapterClassOrInstance && typeof AdapterClassOrInstance === 'object') { // For testing - when getPlatformAdapter returns a mock instance this.adapter = AdapterClassOrInstance; } else { throw new Error('Invalid adapter returned from getPlatformAdapter'); } this.logger.debug('Platform adapter obtained:', { platform: process.platform }); // Verify adapter compatibility if (!this.adapter) { throw new errors_1.SystemError('Failed to create adapter instance'); } const isCompatible = await this.adapter.isCompatible(); if (!isCompatible) { this.logger.error('Platform adapter is not compatible with current system'); throw new errors_1.SystemError('Platform adapter is not compatible with current system'); } this._initialized = true; this.logger.info('Port manager initialized successfully'); } catch (error) { const err = error; this.logger.error('Failed to initialize port manager:', err.message); if (error instanceof errors_1.SystemError) { throw error; } throw new errors_1.SystemError(`Failed to initialize port manager: ${err.message}`); } } /** * Check processes running on the specified port with detailed information * @param port - Port number to check * @returns Array of Process objects running on the port * @throws If port number is invalid or port lookup fails */ async checkPort(port) { // Validate port number const validPort = (0, validator_1.validatePort)(port); this.logger.debug('Checking port:', { port: validPort }); // Ensure adapter is initialized await this.initialize(); if (!this.adapter) { throw new errors_1.SystemError('Port manager adapter not initialized'); } try { const processes = await this.adapter.findProcessByPort(validPort); this.logger.debug('Port check completed:', { port: validPort, processCount: processes.length }); return processes || []; } catch (error) { const err = error; this.logger.error('Port check failed:', { port: validPort, error: err.message }); if (error instanceof errors_1.SystemError || error instanceof errors_1.ValidationError || error instanceof errors_1.PermissionError || error instanceof errors_1.NetworkError) { throw error; } // Check if this looks like a network-related error if (err.message.includes('network') || err.message.includes('connection') || err.message.includes('timeout') || err.message.includes('unreachable')) { throw new errors_1.NetworkError(`Network error while checking port ${validPort}: ${err.message}`, validPort, 'port check'); } throw new errors_1.SystemError(`Failed to check port ${validPort}: ${err.message}`); } } /** * Kill a process by PID with error handling * @param pid - Process ID to terminate * @returns True if process was successfully terminated * @throws If PID is invalid, insufficient permissions, or process termination fails */ async killProcess(pid) { // Validate PID const validPid = (0, validator_1.validatePid)(pid); this.logger.debug('Attempting to kill process:', { pid: validPid }); // Ensure adapter is initialized await this.initialize(); if (!this.adapter) { throw new errors_1.SystemError('Port manager adapter not initialized'); } try { const success = await this.adapter.killProcess(validPid); this.logger.info('Process kill attempt completed:', { pid: validPid, success }); return success; } catch (error) { const err = error; this.logger.error('Process kill failed:', { pid: validPid, error: err.message }); if (error instanceof errors_1.SystemError || error instanceof errors_1.ValidationError || error instanceof errors_1.PermissionError || error instanceof errors_1.NetworkError) { throw error; } throw new errors_1.SystemError(`Failed to kill process ${validPid}: ${err.message}`); } } /** * Get detailed information about a process by PID * @param pid - Process ID * @returns Process details object * @throws If PID is invalid or process details cannot be retrieved */ async getProcessDetails(pid) { // Validate PID const validPid = (0, validator_1.validatePid)(pid); // Ensure adapter is initialized await this.initialize(); if (!this.adapter) { throw new errors_1.SystemError('Port manager adapter not initialized'); } try { const details = await this.adapter.getProcessDetails(validPid); return details; } catch (error) { const err = error; if (error instanceof errors_1.SystemError || error instanceof errors_1.ValidationError || error instanceof errors_1.PermissionError || error instanceof errors_1.NetworkError) { throw error; } throw new errors_1.SystemError(`Failed to get process details for PID ${validPid}: ${err.message}`); } } /** * Check if a specific port is available (no processes running on it) * @param port - Port number to check * @returns True if port is available, false if occupied * @throws If port number is invalid or port lookup fails */ async isPortAvailable(port) { // Validate port number const validPort = (0, validator_1.validatePort)(port); // Ensure adapter is initialized await this.initialize(); if (!this.adapter) { throw new errors_1.SystemError('Port manager adapter not initialized'); } try { const processes = await this.adapter.findProcessByPort(validPort); return !processes || processes.length === 0; } catch (error) { const err = error; if (error instanceof errors_1.SystemError || error instanceof errors_1.ValidationError || error instanceof errors_1.PermissionError || error instanceof errors_1.NetworkError) { throw error; } throw new errors_1.SystemError(`Failed to check port availability ${validPort}: ${err.message}`); } } /** * Get the current platform adapter instance * @returns Platform adapter instance or null if not initialized */ getAdapter() { return this.adapter; } /** * Check if the port manager is initialized * @returns True if initialized */ isInitialized() { return this._initialized; } } exports.PortManager = PortManager; //# sourceMappingURL=port-manager.js.map