// ── Dependency Check ───────────────────────────────────────────────── // Verifies all packages listed in package.json are installed. // Auto-runs npm install if any are missing — zero manual setup steps. import { readFileSync, existsSync } from "node:fs" import { resolve, dirname } from "node:path" import { fileURLToPath } from "node:url" import { execSync } from "node:child_process" import { platform } from "node:os" const __dirname = dirname(fileURLToPath(import.meta.url)) const root = resolve(__dirname, "..") try { const pkg = JSON.parse(readFileSync(resolve(root, "package.json"), "utf8")) const allDeps = { ...pkg.dependencies, ...pkg.devDependencies } const missing = Object.keys(allDeps).filter(name => { const pkgDir = resolve(root, "node_modules", name) return !existsSync(resolve(pkgDir, "package.json")) }) if (missing.length > 0) { console.log(`\n${missing.length} package(s) missing: ${missing.join(", ")}`) console.log("Installing...\n") execSync("npm install --no-audit --no-fund", { cwd: root, stdio: "inherit", timeout: 120000 }) console.log("Dependencies installed\n") } } catch { // If package.json read or resolution fails, skip silently } // ── Port Precheck ────────────────────────────────────────────────── // Kills any existing processes on ports 3001, 3006, 3007, 3008. // These are the AI server, Next.js frontend, Signaling server, and // Python scraper respectively. // Runs before anything else starts to avoid EADDRINUSE errors. const PORTS = [3001, 3006, 3007, 3008] if (platform() === "win32") { // Windows: use netstat + findstr to find listening PIDs, then taskkill for (const port of PORTS) { try { const out = execSync(`netstat -ano | findstr "LISTENING" | findstr ":${port} "`, { encoding: "utf8", timeout: 5000 }) const lines = out.trim().split("\n").filter(Boolean) for (const line of lines) { const parts = line.trim().split(/\s+/) const pid = parts[parts.length - 1] if (pid) { try { execSync(`taskkill /F /PID ${pid}`, { stdio: "ignore", timeout: 3000 }); console.log(`Freed port ${port} (PID ${pid})`) } catch {} } } } catch {} } } else { // Linux/Mac: use lsof -ti to find PIDs, then kill -9 for (const port of PORTS) { try { const pid = execSync(`lsof -ti:${port} 2>/dev/null`, { encoding: "utf8", timeout: 5000 }).trim() if (pid) { execSync(`kill -9 ${pid}`, { stdio: "ignore", timeout: 3000 }) console.log(`Freed port ${port} (PID ${pid})`) } } catch {} } }