param( [int]$ApiPort = 3456, [int]$VitePort = 5173 ) $ErrorActionPreference = 'Stop' $repoRoot = Split-Path -Parent $PSScriptRoot Set-Location $repoRoot function Test-ApiReady { param([int]$Port) try { $response = Invoke-WebRequest -UseBasicParsing -Uri "http://127.0.0.1:$Port/api/products" -TimeoutSec 2 return $response.StatusCode -eq 200 } catch { return $false } } $apiProcess = $null $startedApi = $false if (Test-ApiReady -Port $ApiPort) { Write-Host "JV API already running on http://127.0.0.1:$ApiPort" } else { Write-Host "Starting JV API on http://127.0.0.1:$ApiPort ..." $apiProcess = Start-Process -FilePath bun -ArgumentList 'api/server.ts' -WorkingDirectory $repoRoot -PassThru -WindowStyle Hidden $startedApi = $true $ready = $false for ($i = 0; $i -lt 30; $i++) { if ($apiProcess.HasExited) { throw "JV API exited early with code $($apiProcess.ExitCode). Run 'bun api/server.ts' for details." } if (Test-ApiReady -Port $ApiPort) { $ready = $true break } Start-Sleep -Milliseconds 500 } if (-not $ready) { if ($apiProcess -and -not $apiProcess.HasExited) { Stop-Process -Id $apiProcess.Id -Force } throw "JV API did not become ready on http://127.0.0.1:$ApiPort." } Write-Host "JV API ready." } try { Write-Host "Starting Vite dashboard on http://127.0.0.1:$VitePort ..." bunx vite --host 127.0.0.1 --port $VitePort } finally { if ($startedApi -and $apiProcess -and -not $apiProcess.HasExited) { Write-Host "Stopping JV API process $($apiProcess.Id)." Stop-Process -Id $apiProcess.Id -Force } }