Files
Live_RC/windows/setup.ps1
2026-08-25 19:45:40 +02:00

145 lines
4.8 KiB
PowerShell

[CmdletBinding()]
param(
[switch]$OpenFirewall,
[switch]$StartServer
)
$ErrorActionPreference = "Stop"
$ProjectRoot = (Resolve-Path (Join-Path $PSScriptRoot "..")).Path
function Write-Step([string]$Message) {
Write-Host ""
Write-Host "==> $Message" -ForegroundColor Cyan
}
function Refresh-ProcessPath {
$machinePath = [Environment]::GetEnvironmentVariable("Path", "Machine")
$userPath = [Environment]::GetEnvironmentVariable("Path", "User")
$env:Path = "$machinePath;$userPath"
}
function Get-NodeMajor {
$node = Get-Command node.exe -ErrorAction SilentlyContinue
if (-not $node) {
return $null
}
$rawVersion = (& $node.Source --version).Trim().TrimStart("v")
$majorText = $rawVersion.Split(".")[0]
$major = 0
if ([int]::TryParse($majorText, [ref]$major)) {
return $major
}
return $null
}
function Install-NodeLts {
$winget = Get-Command winget.exe -ErrorAction SilentlyContinue
if (-not $winget) {
throw "Node.js 22/24 LTS is required. Install it from https://nodejs.org/en/download and run this script again."
}
Write-Step "Installing Node.js LTS with winget"
& $winget.Source install --id OpenJS.NodeJS.LTS --exact --accept-source-agreements --accept-package-agreements
if ($LASTEXITCODE -ne 0) {
throw "winget could not install Node.js LTS (exit code $LASTEXITCODE)."
}
Refresh-ProcessPath
}
function Install-VcRuntime {
$winget = Get-Command winget.exe -ErrorAction SilentlyContinue
if (-not $winget) {
Write-Warning "winget was not found; Microsoft Visual C++ 2015-2022 x64 Runtime could not be checked."
return
}
Write-Step "Installing Microsoft Visual C++ 2015-2022 x64 Runtime"
& $winget.Source install --id "Microsoft.VCRedist.2015+.x64" --exact --silent --accept-source-agreements --accept-package-agreements
if ($LASTEXITCODE -ne 0) {
Write-Warning "Visual C++ Runtime install/check returned exit code $LASTEXITCODE. AMMC may still work if it is already installed."
}
}
Write-Host "JMK RB RaceController - Windows 11 setup" -ForegroundColor White
Write-Host "Project: $ProjectRoot"
$nodeMajor = Get-NodeMajor
if ($null -eq $nodeMajor -or $nodeMajor -lt 22 -or $nodeMajor -ge 27) {
Install-NodeLts
$nodeMajor = Get-NodeMajor
}
if ($null -eq $nodeMajor -or $nodeMajor -lt 22 -or $nodeMajor -ge 27) {
throw "A supported Node.js version was not found after installation. Reopen PowerShell and run windows\setup.ps1 again."
}
Install-VcRuntime
$nodeCommand = (Get-Command node.exe).Source
$npmCommand = (Get-Command npm.cmd -ErrorAction SilentlyContinue).Source
if (-not $npmCommand) {
throw "npm.cmd was not found. Repair the Node.js installation and run this script again."
}
Write-Step "Checking runtime"
Write-Host "Node: $(& $nodeCommand --version)"
Write-Host "npm: $(& $npmCommand --version)"
Write-Host "OS: $([Environment]::OSVersion.VersionString) / $env:PROCESSOR_ARCHITECTURE"
Set-Location $ProjectRoot
Write-Step "Installing locked npm dependencies"
if (Test-Path (Join-Path $ProjectRoot "package-lock.json")) {
& $npmCommand ci --no-audit --no-fund
} else {
& $npmCommand install --no-audit --no-fund
}
if ($LASTEXITCODE -ne 0) {
Write-Host ""
Write-Host "If better-sqlite3 attempted a source build, run this once as Administrator:" -ForegroundColor Yellow
Write-Host ' & "C:\Program Files\nodejs\install_tools.bat"' -ForegroundColor Yellow
throw "npm dependency installation failed (exit code $LASTEXITCODE)."
}
Write-Step "Verifying Express, SQLite and bundled AMMC"
& $nodeCommand scripts\verify-install.js
if ($LASTEXITCODE -ne 0) {
throw "Runtime verification failed (exit code $LASTEXITCODE)."
}
if ($OpenFirewall) {
Write-Step "Adding Windows Firewall rules"
$isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole(
[Security.Principal.WindowsBuiltInRole]::Administrator
)
if (-not $isAdmin) {
Write-Warning "Firewall rules require an Administrator PowerShell. Setup continues without them."
} else {
foreach ($port in @(8081, 9000, 9001, 9002, 9003)) {
$ruleName = "JMK RB RaceController TCP $port"
if (-not (Get-NetFirewallRule -DisplayName $ruleName -ErrorAction SilentlyContinue)) {
New-NetFirewallRule -DisplayName $ruleName -Direction Inbound -Protocol TCP -LocalPort $port -Action Allow | Out-Null
}
Write-Host "Firewall: TCP $port allowed"
}
}
}
if ($StartServer) {
Write-Step "Restarting RaceController after installation"
& $npmCommand restart
if ($LASTEXITCODE -ne 0) {
throw "RaceController did not restart (exit code $LASTEXITCODE)."
}
}
Write-Host ""
Write-Host "Windows setup completed." -ForegroundColor Green
Write-Host "Start: npm.cmd start"
Write-Host "Restart: npm.cmd restart"
Write-Host "Status: npm.cmd run status"
Write-Host "Stop: npm.cmd stop"
Write-Host "Open: http://localhost:8081"