#!/usr/bin/env node const { exec } = require('child_process'); const { promisify } = require('util'); const chalk = require('chalk'); const execAsync = promisify(exec); const ports = [3000, 3001, 8000]; async function killProcessOnPort(port) { try { console.log(chalk.blue(`๐Ÿ” Checking if port ${port} is in use...`)); if (process.platform === 'darwin' || process.platform === 'linux') { // Try with lsof first try { const { stdout } = await execAsync(`lsof -i :${port} -t`); if (stdout.trim()) { console.log(chalk.yellow(`โš ๏ธ Port ${port} is in use. Attempting to terminate processes...`)); const pids = stdout.trim().split('\n').filter(Boolean); for (const pid of pids) { try { await execAsync(`kill -9 ${pid}`); console.log(chalk.green(`โœ… Terminated process ${pid} using port ${port}`)); } catch (error) { console.error(chalk.red(`Failed to kill process ${pid}: ${error.message}`)); } } } else { console.log(chalk.green(`โœ… Port ${port} is available`)); } } catch (lsofError) { // Fallback to netstat if lsof fails try { const { stdout } = await execAsync(`netstat -anp 2>/dev/null | grep ${port} | grep LISTEN`); if (stdout.trim()) { console.log(chalk.yellow(`โš ๏ธ Port ${port} is in use. Using netstat fallback...`)); // Extract PIDs with regex - this is more complex with netstat const pidRegex = /\s(\d+)\/\w+\s*$/; const matches = stdout.match(pidRegex); if (matches && matches[1]) { const pid = matches[1]; try { await execAsync(`kill -9 ${pid}`); console.log(chalk.green(`โœ… Terminated process ${pid} using port ${port}`)); } catch (error) { console.error(chalk.red(`Failed to kill process ${pid}: ${error.message}`)); } } else { console.log(chalk.yellow(`โš ๏ธ Could not extract PID from netstat output`)); } } else { console.log(chalk.green(`โœ… Port ${port} is available`)); } } catch (netstatError) { console.log(chalk.yellow(`โš ๏ธ Could not check port ${port}: Both lsof and netstat failed`)); } } } else if (process.platform === 'win32') { // Windows approach const { stdout } = await execAsync(`netstat -ano | findstr :${port}`); if (stdout.trim()) { console.log(chalk.yellow(`โš ๏ธ Port ${port} is in use. Attempting to terminate processes...`)); const pids = stdout.split('\n') .filter(line => line.includes(`:${port}`)) .map(line => line.trim().split(/\s+/).pop() || '') .filter(Boolean); for (const pid of pids) { try { await execAsync(`taskkill /F /PID ${pid}`); console.log(chalk.green(`โœ… Terminated process ${pid} using port ${port}`)); } catch (error) { console.error(chalk.red(`Failed to kill process ${pid}: ${error.message}`)); } } } else { console.log(chalk.green(`โœ… Port ${port} is available`)); } } } catch (error) { // General error handling console.log(chalk.yellow(`โš ๏ธ Could not check port ${port}: ${error.message}`)); console.log(chalk.blue('Continuing anyway...')); } } async function main() { console.log(chalk.cyan.bold('๐Ÿงน Port Cleanup Utility')); console.log(chalk.cyan('---------------------')); for (const port of ports) { await killProcessOnPort(port); } console.log(chalk.green('โœ… Port cleanup complete')); } main().catch(error => { console.error(chalk.red(`โŒ Unhandled error: ${error.message}`)); console.log(chalk.yellow('Continuing with startup anyway...')); process.exit(0); // Exit successfully even if port killing fails });