"Add Windows installer and driver training rewards"
This commit is contained in:
143
windows/setup.ps1
Normal file
143
windows/setup.ps1
Normal file
@@ -0,0 +1,143 @@
|
||||
[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 "Starting RaceController"
|
||||
& $npmCommand start
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "RaceController did not start (exit code $LASTEXITCODE)."
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "Windows setup completed." -ForegroundColor Green
|
||||
Write-Host "Start: npm start"
|
||||
Write-Host "Status: npm run status"
|
||||
Write-Host "Stop: npm stop"
|
||||
Write-Host "Open: http://localhost:8081"
|
||||
Reference in New Issue
Block a user