| 148 | getPort(): number { return API_PORT } |
| 149 | |
| 150 | private async killProcessOnPort(): Promise<void> { |
| 151 | const { execSync } = require('child_process') |
| 152 | |
| 153 | if (process.platform !== 'win32') { |
| 154 | try { execSync(`lsof -ti tcp:${API_PORT} | xargs kill -9 2>/dev/null || true`, { shell: true }) } catch {} |
| 155 | return |
| 156 | } |
| 157 | |
| 158 | for (let attempt = 0; attempt < 3; attempt++) { |
| 159 | let output = '' |
| 160 | try { |
| 161 | output = execSync(`netstat -ano | findstr ":${API_PORT} "`, { encoding: 'utf8', shell: true }) as string |
| 162 | } catch { break } |
| 163 | |
| 164 | const pids = new Set<string>() |
| 165 | for (const line of output.split('\n')) { |
| 166 | const match = line.trim().match(/\s+(\d+)$/) |
| 167 | if (match && match[1] !== '0') pids.add(match[1]) |
| 168 | } |
| 169 | if (pids.size === 0) break |
| 170 | |
| 171 | for (const pid of pids) { |
| 172 | try { execSync(`taskkill /PID ${pid} /T /F`, { shell: true }) } catch {} |
| 173 | } |
| 174 | await new Promise((r) => setTimeout(r, 300)) |
| 175 | } |
| 176 | } |
| 177 | |
| 178 | private async waitUntilReady(maxRetries = 180, delayMs = 500): Promise<void> { |
| 179 | for (let i = 0; i < maxRetries; i++) { |