#!/usr/bin/env node /** * Free PORT (default 3010) so npm run dev can bind after orphaned node --watch processes. */ const { execSync } = require('child_process'); const port = String(process.env.PORT || 3010).trim(); function pidsListening() { try { const out = execSync(`lsof -tiTCP:${port} -sTCP:LISTEN`, { encoding: 'utf8' }).trim(); if (!out) return []; return [...new Set(out.split(/\s+/).filter(Boolean))]; } catch { return []; } } const pids = pidsListening(); if (!pids.length) { console.log(`[free-port] :${port} already free`); process.exit(0); } for (const pid of pids) { try { process.kill(Number(pid), 'SIGKILL'); console.log(`[free-port] killed pid ${pid} on :${port}`); } catch (err) { console.warn(`[free-port] could not kill ${pid}:`, err.message); } } // brief wait for OS to release the socket Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 300); const left = pidsListening(); if (left.length) { console.error(`[free-port] still in use by: ${left.join(', ')}`); process.exit(1); } console.log(`[free-port] :${port} is free`);