UNPKG

fortify2-js

Version:

MOST POWERFUL JavaScript Security Library! Military-grade cryptography + 19 enhanced object methods + quantum-resistant algorithms + perfect TypeScript support. More powerful than Lodash with built-in security.

158 lines (154 loc) 5.24 kB
'use strict'; var http = require('http'); /** * Port Manager - Handles automatic port switching when ports are in use */ class PortManager { constructor(originalPort, config) { this.originalPort = originalPort; this.config = { enabled: false, maxAttempts: 10, startPort: originalPort, strategy: "increment", ...config, }; } /** * Check if a port is available */ async isPortAvailable(port, host = "localhost") { return new Promise((resolve) => { const server = http.createServer(); let resolved = false; const cleanup = () => { if (!resolved) { resolved = true; try { server.close(); } catch (e) { // Ignore cleanup errors } } }; // Set a timeout to avoid hanging const timeout = setTimeout(() => { cleanup(); resolve(false); }, 1000); // Use 127.0.0.1 for port availability check to ensure proper conflict detection // This works around a Bun issue where multiple servers can bind to "localhost" const checkHost = host === "localhost" ? "127.0.0.1" : host; server.listen(port, checkHost, () => { clearTimeout(timeout); cleanup(); resolve(true); }); server.on("error", (err) => { clearTimeout(timeout); cleanup(); // EADDRINUSE means port is in use resolve(err.code !== "EADDRINUSE"); }); }); } /** * Generate next port based on strategy */ getNextPort(currentPort, attempt) { const { strategy, portRange, predefinedPorts } = this.config; switch (strategy) { case "increment": return currentPort + attempt; case "random": if (portRange) { const [min, max] = portRange; return Math.floor(Math.random() * (max - min + 1)) + min; } return currentPort + Math.floor(Math.random() * 1000) + 1; case "predefined": if (predefinedPorts && predefinedPorts.length > 0) { return predefinedPorts[attempt % predefinedPorts.length]; } // Fallback to increment if no predefined ports return currentPort + attempt; default: return currentPort + attempt; } } /** * Validate port number */ isValidPort(port) { return port >= 1 && port <= 65535; } /** * Find an available port automatically */ async findAvailablePort(host = "localhost") { const result = { success: false, port: this.originalPort, originalPort: this.originalPort, attempts: 0, switched: false, }; // If auto port switch is disabled, just check the original port if (!this.config?.enabled) { const available = await this.isPortAvailable(this.originalPort, host); result.success = available; result.attempts = 1; return result; } const { maxAttempts, startPort, portRange } = this.config; let currentPort = startPort || this.originalPort; // First, try the original port if (await this.isPortAvailable(this.originalPort, host)) { result.success = true; result.attempts = 1; return result; } // If original port is not available, start searching for (let attempt = 1; attempt <= maxAttempts; attempt++) { currentPort = this.getNextPort(startPort || this.originalPort, attempt); // Validate port range if specified if (portRange) { const [min, max] = portRange; if (currentPort < min || currentPort > max) { continue; } } // Validate port number if (!this.isValidPort(currentPort)) { continue; } result.attempts = attempt + 1; if (await this.isPortAvailable(currentPort, host)) { result.success = true; result.port = currentPort; result.switched = true; // Call the callback if provided if (this.config?.onPortSwitch) { this.config.onPortSwitch(this.originalPort, currentPort); } break; } } return result; } /** * Get configuration summary */ getConfig() { return { ...this.config }; } /** * Update configuration */ updateConfig(newConfig) { this.config = { ...this.config, ...newConfig }; } } exports.PortManager = PortManager; //# sourceMappingURL=PortManager.js.map