feat(ProcessManager): add Bun availability check and improve PID file validation

- Implemented a method to check if Bun is available in the system PATH.
- Updated the startWithBun method to return an error if Bun is not found.
- Enhanced PID file parsing to validate required fields and their types.
- Cleaned up stale PID files if the process is no longer alive.

fix(SettingsRoutes): clear port cache after updating settings

- Added a call to clearPortCache after writing updated settings to ensure the application uses the latest configuration.
This commit is contained in:
Alex Newman
2025-12-12 17:48:41 -05:00
parent 9f1745bdec
commit 1491123706
27 changed files with 247 additions and 316 deletions
+28 -3
View File
@@ -1,7 +1,7 @@
import { existsSync, readFileSync, writeFileSync, unlinkSync, mkdirSync } from 'fs';
import { createWriteStream } from 'fs';
import { join } from 'path';
import { spawn } from 'child_process';
import { spawn, spawnSync } from 'child_process';
import { homedir } from 'os';
import { DATA_DIR } from '../../shared/paths.js';
@@ -47,7 +47,23 @@ export class ProcessManager {
return this.startWithBun(workerScript, logFile, port);
}
private static isBunAvailable(): boolean {
try {
const result = spawnSync('bun', ['--version'], { stdio: 'pipe', timeout: 5000 });
return result.status === 0;
} catch {
return false;
}
}
private static async startWithBun(script: string, logFile: string, port: number): Promise<{ success: boolean; pid?: number; error?: string }> {
if (!this.isBunAvailable()) {
return {
success: false,
error: 'Bun is required but not found in PATH. Install from https://bun.sh'
};
}
try {
const isWindows = process.platform === 'win32';
@@ -129,7 +145,11 @@ export class ProcessManager {
static async isRunning(): Promise<boolean> {
const info = this.getPidInfo();
if (!info) return false;
return this.isProcessAlive(info.pid);
const alive = this.isProcessAlive(info.pid);
if (!alive) {
this.removePidFile(); // Clean up stale PID file
}
return alive;
}
// Helper methods
@@ -137,7 +157,12 @@ export class ProcessManager {
try {
if (!existsSync(PID_FILE)) return null;
const content = readFileSync(PID_FILE, 'utf-8');
return JSON.parse(content) as PidInfo;
const parsed = JSON.parse(content);
// Validate required fields have correct types
if (typeof parsed.pid !== 'number' || typeof parsed.port !== 'number') {
return null;
}
return parsed as PidInfo;
} catch {
return null;
}