145 lines
4.8 KiB
PowerShell
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)) {
|
|
$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"
|