++
This commit is contained in:
@@ -0,0 +1,157 @@
|
||||
# MiroSociety background launcher (Windows / PowerShell, dev mode)
|
||||
# Prereq: run deploy.ps1 first to install dependencies.
|
||||
# Frontend: http://localhost:31400 Backend: http://localhost:31401
|
||||
#
|
||||
# Usage (PowerShell): .\start.ps1
|
||||
# Already-running services will be restarted.
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||
$FrontendPort = 31400
|
||||
$BackendPort = 31401
|
||||
$VenvDir = Join-Path $ScriptDir 'backend\.venv'
|
||||
$VenvPy = Join-Path $VenvDir 'Scripts\python.exe'
|
||||
$BackendDir = Join-Path $ScriptDir 'backend'
|
||||
$FrontendDir = Join-Path $ScriptDir 'frontend'
|
||||
$RunDir = Join-Path $ScriptDir '.run'
|
||||
$BackendPidFile = Join-Path $RunDir 'backend.pid'
|
||||
$FrontendPidFile = Join-Path $RunDir 'frontend.pid'
|
||||
$BackendLog = Join-Path $ScriptDir 'backend.log'
|
||||
$FrontendLog = Join-Path $ScriptDir 'frontend.log'
|
||||
$BackendLogErr = Join-Path $ScriptDir 'backend.err.log'
|
||||
$FrontendLogErr = Join-Path $ScriptDir 'frontend.err.log'
|
||||
|
||||
Set-Location $ScriptDir
|
||||
|
||||
function Log($msg) { Write-Host "[start.ps1] $msg" -ForegroundColor Green }
|
||||
function Warn($msg) { Write-Host "[start.ps1] $msg" -ForegroundColor Yellow }
|
||||
function Err($msg) { Write-Host "[start.ps1] $msg" -ForegroundColor Red }
|
||||
|
||||
# --- Check dependencies ---
|
||||
foreach ($cmd in @('npm','node','curl')) {
|
||||
if (-not (Get-Command $cmd -ErrorAction SilentlyContinue)) {
|
||||
Err "Missing required command: $cmd"
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
if (-not (Test-Path $VenvPy)) {
|
||||
Err "Not found: $VenvPy -- please run deploy.ps1 first."
|
||||
exit 1
|
||||
}
|
||||
try {
|
||||
& $VenvPy -c "import uvicorn" 2>$null | Out-Null
|
||||
if ($LASTEXITCODE -ne 0) { throw }
|
||||
} catch {
|
||||
Err "uvicorn is missing in venv -- please run deploy.ps1 first."
|
||||
exit 1
|
||||
}
|
||||
if (-not (Test-Path (Join-Path $FrontendDir 'node_modules'))) {
|
||||
Err "Not found: frontend/node_modules -- please run deploy.ps1 first."
|
||||
exit 1
|
||||
}
|
||||
|
||||
if (-not (Test-Path $RunDir)) { New-Item -ItemType Directory -Path $RunDir | Out-Null }
|
||||
|
||||
# --- Helpers ---
|
||||
function Get-PidFromFile($file) {
|
||||
if (Test-Path $file) { return (Get-Content $file -Raw).Trim() }
|
||||
return $null
|
||||
}
|
||||
|
||||
function Stop-PidFile($pidFile, $label) {
|
||||
$procId = Get-PidFromFile $pidFile
|
||||
if ($procId -and (Get-Process -Id $procId -ErrorAction SilentlyContinue)) {
|
||||
try {
|
||||
Stop-Process -Id $procId -Force -ErrorAction SilentlyContinue
|
||||
Log "$label stopped (pid=$procId)"
|
||||
} catch { }
|
||||
}
|
||||
if (Test-Path $pidFile) { Remove-Item $pidFile -Force }
|
||||
}
|
||||
|
||||
function Free-Port($port) {
|
||||
$conns = Get-NetTCPConnection -LocalPort $port -State Listen -ErrorAction SilentlyContinue
|
||||
if ($conns) {
|
||||
$pids = ($conns | Select-Object -ExpandProperty OwningProcess -Unique)
|
||||
Warn "Port $port is occupied (pid: $($pids -join ',' )), killing..."
|
||||
foreach ($p in $pids) {
|
||||
try { Stop-Process -Id $p -Force -ErrorAction SilentlyContinue } catch { }
|
||||
}
|
||||
Start-Sleep -Seconds 1
|
||||
}
|
||||
}
|
||||
|
||||
# --- Start backend ---
|
||||
Free-Port $BackendPort
|
||||
Stop-PidFile $BackendPidFile 'Backend'
|
||||
Log "Starting backend FastAPI @ :$BackendPort (background)"
|
||||
if (Test-Path $BackendLog) { Clear-Content $BackendLog -Force }
|
||||
if (Test-Path $BackendLogErr) { Clear-Content $BackendLogErr -Force }
|
||||
|
||||
$backendArgs = @(
|
||||
'-m','uvicorn','app.main:app',
|
||||
'--host','0.0.0.0','--port',"$BackendPort"
|
||||
)
|
||||
|
||||
$backendProc = Start-Process -FilePath $VenvPy `
|
||||
-ArgumentList $backendArgs `
|
||||
-WorkingDirectory $BackendDir `
|
||||
-RedirectStandardOutput $BackendLog `
|
||||
-RedirectStandardError $BackendLogErr `
|
||||
-NoNewWindow `
|
||||
-PassThru
|
||||
$backendProc.Id | Out-File -FilePath $BackendPidFile -Encoding ascii -Force
|
||||
|
||||
# --- Start frontend ---
|
||||
Free-Port $FrontendPort
|
||||
Stop-PidFile $FrontendPidFile 'Frontend'
|
||||
Log "Starting frontend Vite @ :$FrontendPort (background)"
|
||||
if (Test-Path $FrontendLog) { Clear-Content $FrontendLog -Force }
|
||||
if (Test-Path $FrontendLogErr) { Clear-Content $FrontendLogErr -Force }
|
||||
|
||||
# On Windows, Start-Process cannot launch a `.cmd` shim by bare name.
|
||||
# Resolve `npx.cmd` -> its underlying `node.exe` and run `node ./node_modules/vite/bin/vite.js`.
|
||||
$npmCmd = (Get-Command npm.cmd -ErrorAction SilentlyContinue).Source
|
||||
if (-not $npmCmd) { Err 'Cannot locate npm.cmd in PATH'; exit 1 }
|
||||
$nodeExe = (Get-Command node -ErrorAction SilentlyContinue).Source
|
||||
$viteEntry = Join-Path $FrontendDir 'node_modules\vite\bin\vite.js'
|
||||
if (-not (Test-Path $viteEntry)) {
|
||||
Err "Not found: $viteEntry -- please run deploy.ps1 first."
|
||||
exit 1
|
||||
}
|
||||
|
||||
$frontendProc = Start-Process -FilePath $nodeExe `
|
||||
-ArgumentList @($viteEntry) `
|
||||
-WorkingDirectory $FrontendDir `
|
||||
-RedirectStandardOutput $FrontendLog `
|
||||
-RedirectStandardError $FrontendLogErr `
|
||||
-NoNewWindow `
|
||||
-PassThru
|
||||
$frontendProc.Id | Out-File -FilePath $FrontendPidFile -Encoding ascii -Force
|
||||
|
||||
# --- Health check ---
|
||||
Log "Waiting for services..."
|
||||
function Wait-For($url, $name) {
|
||||
for ($i = 0; $i -lt 30; $i++) {
|
||||
try {
|
||||
$r = curl.exe -sf $url
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
Log "$name is up (v) ($url)"
|
||||
return $true
|
||||
}
|
||||
} catch { }
|
||||
Start-Sleep -Seconds 1
|
||||
}
|
||||
Err "$name failed to start in time, check $name.log"
|
||||
return $false
|
||||
}
|
||||
|
||||
Wait-For "http://localhost:$BackendPort/health" 'Backend' | Out-Null
|
||||
Wait-For "http://localhost:$FrontendPort" 'Frontend' | Out-Null
|
||||
|
||||
Write-Host ''
|
||||
Log "All services ready (v)"
|
||||
Write-Host " Frontend: http://localhost:$FrontendPort"
|
||||
Write-Host " Backend : http://localhost:$BackendPort (health: /health)"
|
||||
Write-Host " Logs : backend.log / backend.err.log / frontend.log / frontend.err.log"
|
||||
Reference in New Issue
Block a user