feat: check for port in use and add instructions on fixing

This commit is contained in:
lucas-neynar 2025-03-17 13:27:04 -07:00
parent be7f23a88b
commit fba2fbc134
No known key found for this signature in database
2 changed files with 48 additions and 11 deletions

View File

@ -1,6 +1,6 @@
{ {
"name": "create-neynar-farcaster-frame", "name": "create-neynar-farcaster-frame",
"version": "1.0.7", "version": "1.0.8",
"type": "module", "type": "module",
"files": [ "files": [
"bin/index.js" "bin/index.js"

View File

@ -6,6 +6,19 @@ let nextDev;
let isCleaningUp = false; let isCleaningUp = false;
async function startDev() { async function startDev() {
// Check if port 3000 is already in use
const isPortInUse = await checkPort(3000);
if (isPortInUse) {
console.error('Port 3000 is already in use. To find and kill the process using this port:\n\n' +
'1. On macOS/Linux, run: lsof -i :3000\n' +
' On Windows, run: netstat -ano | findstr :3000\n\n' +
'2. Note the PID (Process ID) from the output\n\n' +
'3. On macOS/Linux, run: kill -9 <PID>\n' +
' On Windows, run: taskkill /PID <PID> /F\n\n' +
'Then try running this command again.');
process.exit(1);
}
// Start localtunnel and get URL // Start localtunnel and get URL
tunnel = await localtunnel({ port: 3000 }); tunnel = await localtunnel({ port: 3000 });
let ip; let ip;
@ -53,28 +66,52 @@ async function startDev() {
try { try {
if (nextDev) { if (nextDev) {
try {
// Kill the main process first // Kill the main process first
nextDev.kill('SIGKILL'); nextDev.kill('SIGKILL');
// Then kill any remaining child processes in the group // Then kill any remaining child processes in the group
if (nextDev?.pid) { if (nextDev?.pid) {
try {
process.kill(-nextDev.pid); process.kill(-nextDev.pid);
} catch (e) {
// Ignore ESRCH errors when killing process group
if (e.code !== 'ESRCH') throw e;
}
} }
console.log('🛑 Next.js dev server stopped'); console.log('🛑 Next.js dev server stopped');
} catch (e) {
// Ignore errors when killing nextDev
console.log('Note: Next.js process already terminated');
}
} }
if (tunnel) { if (tunnel) {
try {
await tunnel.close(); await tunnel.close();
console.log('🌐 Tunnel closed'); console.log('🌐 Tunnel closed');
} catch (e) {
console.log('Note: Tunnel already closed');
}
} }
// Force kill any remaining processes on port 3000 // Force kill any remaining processes on port 3000
try { try {
if (process.platform === 'darwin') { // macOS if (process.platform === 'darwin') { // macOS
await spawn('lsof', ['-ti', ':3000']).stdout.on('data', (data) => { const lsof = spawn('lsof', ['-ti', ':3000']);
lsof.stdout.on('data', (data) => {
data.toString().split('\n').forEach(pid => { data.toString().split('\n').forEach(pid => {
if (pid) process.kill(parseInt(pid), 'SIGKILL'); if (pid) {
try {
process.kill(parseInt(pid), 'SIGKILL');
} catch (e) {
// Ignore ESRCH errors when killing individual processes
if (e.code !== 'ESRCH') throw e;
}
}
}); });
}); });
// Wait for lsof to complete
await new Promise((resolve) => lsof.on('close', resolve));
} }
} catch (e) { } catch (e) {
// Ignore errors if no process found // Ignore errors if no process found