| 51 | return parsed |
| 52 | } |
| 53 | |
| 54 | function validateProject(project) { |
| 55 | let stat |
| 56 | try { stat = fs.statSync(project) } catch { throw new Error(`Project directory does not exist: ${project}`) } |
| 57 | if (!stat.isDirectory()) throw new Error(`Project path is not a directory: ${project}`) |
| 58 | } |
| 59 | |
| 60 | function sleep(ms) { |
| 61 | return new Promise((resolve) => setTimeout(resolve, ms)) |
| 62 | } |
| 63 | |
| 64 | function terminateChild(child) { |
| 65 | if (!child || child.exitCode !== null) return |
| 66 | try { |
| 67 | if (process.platform === "win32" && child.pid) { |
| 68 | spawnSync("taskkill", ["/PID", String(child.pid), "/T", "/F"], { stdio: "ignore", windowsHide: true }) |
| 69 | return |
| 70 | } |
| 71 | if (child.pid) process.kill(-child.pid, "SIGTERM") |
| 72 | else child.kill("SIGTERM") |
| 73 | const force = setTimeout(() => { |
| 74 | try { |
| 75 | if (child.exitCode !== null) return |
| 76 | if (child.pid) process.kill(-child.pid, "SIGKILL") |