claude-code-watch 0.0.2 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/server/server.js +47 -2
package/package.json
CHANGED
package/src/server/server.js
CHANGED
|
@@ -301,7 +301,35 @@ class DashboardServer {
|
|
|
301
301
|
return w;
|
|
302
302
|
}
|
|
303
303
|
|
|
304
|
-
|
|
304
|
+
async killExistingPort(port) {
|
|
305
|
+
let cmd;
|
|
306
|
+
if (process.platform === 'win32') {
|
|
307
|
+
cmd = `netstat -ano | findstr :${port} | findstr LISTENING`;
|
|
308
|
+
} else {
|
|
309
|
+
cmd = `lsof -ti:${port}`;
|
|
310
|
+
}
|
|
311
|
+
try {
|
|
312
|
+
const result = cp.execSync(cmd, { encoding: 'utf-8' }).trim();
|
|
313
|
+
if (!result) return false;
|
|
314
|
+
const pids = result.split('\n').map(s => s.trim()).filter(Boolean);
|
|
315
|
+
for (const pid of pids) {
|
|
316
|
+
try {
|
|
317
|
+
if (process.platform === 'win32') {
|
|
318
|
+
cp.execSync(`taskkill /PID ${pid} /F`, { encoding: 'utf-8' });
|
|
319
|
+
} else {
|
|
320
|
+
process.kill(parseInt(pid, 10), 'SIGKILL');
|
|
321
|
+
}
|
|
322
|
+
} catch {}
|
|
323
|
+
}
|
|
324
|
+
// Wait briefly for the port to be released
|
|
325
|
+
await new Promise(r => setTimeout(r, 500));
|
|
326
|
+
return true;
|
|
327
|
+
} catch {
|
|
328
|
+
return false;
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
async start(options = {}) {
|
|
305
333
|
const skipHistory = options.skipHistory || false;
|
|
306
334
|
const pollMs = options.pollMs || 500;
|
|
307
335
|
const activeWindow = options.activeWindow || 5 * 60 * 1000;
|
|
@@ -314,6 +342,12 @@ class DashboardServer {
|
|
|
314
342
|
maxSessions,
|
|
315
343
|
};
|
|
316
344
|
|
|
345
|
+
// Proactively kill any process occupying the port before starting
|
|
346
|
+
const killed = await this.killExistingPort(this.port);
|
|
347
|
+
if (killed) {
|
|
348
|
+
console.log(`Previous instance on port ${this.port} killed, restarting...`);
|
|
349
|
+
}
|
|
350
|
+
|
|
317
351
|
this.server = http.createServer((req, res) => {
|
|
318
352
|
this.handleHTTP(req, res).catch(() => {
|
|
319
353
|
if (!res.headersSent) {
|
|
@@ -326,6 +360,17 @@ class DashboardServer {
|
|
|
326
360
|
this.wss = new WebSocketServer({ server: this.server });
|
|
327
361
|
this.wss.on('connection', (ws) => this.onWsConnection(ws));
|
|
328
362
|
|
|
363
|
+
// Register error handler once (not inside doListen to avoid accumulation)
|
|
364
|
+
this.server.on('error', (err) => {
|
|
365
|
+
if (err.code === 'EADDRINUSE') {
|
|
366
|
+
console.error(`Port ${this.port} is still in use after attempting to free it. Exiting.`);
|
|
367
|
+
process.exit(1);
|
|
368
|
+
} else {
|
|
369
|
+
console.error(`Server error: ${err.message}`);
|
|
370
|
+
process.exit(1);
|
|
371
|
+
}
|
|
372
|
+
});
|
|
373
|
+
|
|
329
374
|
const w = this.setupWatcher(watcherOpts);
|
|
330
375
|
|
|
331
376
|
w.init().then(() => {
|
|
@@ -367,7 +412,7 @@ class DashboardServer {
|
|
|
367
412
|
}
|
|
368
413
|
}
|
|
369
414
|
|
|
370
|
-
function startServer(options = {}) {
|
|
415
|
+
async function startServer(options = {}) {
|
|
371
416
|
const ds = new DashboardServer(options);
|
|
372
417
|
return ds.start(options);
|
|
373
418
|
}
|