Files
goauto/scripts/start-web.ps1
T
QiuSWandClaude Opus 5 1d9dbfda76 fix(#48): keep PowerShell scripts ASCII — Chinese comments broke parsing
PowerShell 5.1 reads a .ps1 with no BOM using the ANSI code page. Every
byte of a UTF-8 Chinese character is >= 0x80, so GBK pairs them up two at
a time; a comment line carrying an odd number of those bytes pairs its
last byte with the trailing newline and swallows it, folding the next
line into the comment. That commented out the `try {` I had added and
left `} catch { }` orphaned, which is the parse error reported at
startup — and it shifted the line numbers, which is why the earlier
PowerShell error positions never matched the file.

My previous Chinese comment survived only because its byte count happened
to be even. Both scripts are back to ASCII, matching the English already
used throughout them, with a note saying why it matters.

Also restores CRLF: .gitattributes marks *.ps1 eol=crlf, and rewriting
these files from Python had left them LF in the working tree.

Verified this time rather than handed over untested: Windows PowerShell
is reachable from WSL, so both scripts were parse-checked and run with
-ValidateConfigOnly, and the chcp block was executed on its own
(code page 65001, console encoding utf-8).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 09:57:57 +08:00

123 lines
4.1 KiB
PowerShell

[CmdletBinding()]
param(
[string]$ConfigPath,
[switch]$ValidateConfigOnly
)
$ErrorActionPreference = "Stop"
# The Go processes emit UTF-8. Without this the console decodes their output
# using the ANSI code page (936 on Simplified Chinese systems) and every
# non-ASCII log line arrives as mojibake.
#
# Setting [Console]::OutputEncoding alone is not enough: PowerShell 5.1 decodes
# child process output by the console code page, so chcp has to change too.
#
# NOTE: keep this file pure ASCII. PowerShell 5.1 reads a .ps1 without a BOM as
# ANSI, and a comment line holding an odd number of UTF-8 high bytes pairs its
# last byte with the newline, swallowing it and commenting out the line below.
try {
$null = & chcp.com 65001
[Console]::OutputEncoding = [Text.Encoding]::UTF8
$OutputEncoding = [Text.Encoding]::UTF8
} catch { }
$workspaceRoot = Split-Path -Parent $PSScriptRoot
$webDirectory = Join-Path $workspaceRoot "web"
function ConvertFrom-YamlScalar {
param([string]$Value)
$value = $Value.Trim()
if ($value.Length -ge 2) {
if ($value.StartsWith('"') -and $value.EndsWith('"')) {
return $value.Substring(1, $value.Length - 2).Replace('\"', '"').Replace('\\', '\')
}
if ($value.StartsWith("'") -and $value.EndsWith("'")) {
return $value.Substring(1, $value.Length - 2).Replace("''", "'")
}
}
return $value
}
function Read-PortConfig {
param([string]$Path)
if (-not (Test-Path -LiteralPath $Path -PathType Leaf)) {
throw "Local configuration file was not found: $Path. Copy config.example.yaml to config.yaml."
}
$values = @{}
$insidePorts = $false
foreach ($line in Get-Content -LiteralPath $Path) {
if ($line -match '^\s*(#.*)?$') {
continue
}
if ($line -match '^ports\s*:\s*$') {
$insidePorts = $true
continue
}
if ($insidePorts -and $line -match '^\S') {
break
}
if ($insidePorts -and $line -match '^\s+(server|web)\s*:\s*(.*?)\s*$') {
$values[$Matches[1]] = ConvertFrom-YamlScalar $Matches[2]
}
}
foreach ($key in 'server', 'web') {
$parsedPort = 0
if (-not $values.ContainsKey($key) -or
-not [int]::TryParse([string]$values[$key], [ref]$parsedPort) -or
$parsedPort -lt 1 -or $parsedPort -gt 65535) {
throw "ports.$key must be an integer between 1 and 65535 in: $Path"
}
$values[$key] = $parsedPort
}
if ($values.server -eq $values.web) {
throw "ports.server and ports.web must be different in: $Path"
}
return @{ Server = [int]$values.server; Web = [int]$values.web }
}
if ([string]::IsNullOrWhiteSpace($ConfigPath)) {
$ConfigPath = Join-Path $workspaceRoot "config.yaml"
}
elseif (-not [IO.Path]::IsPathRooted($ConfigPath)) {
$ConfigPath = Join-Path $workspaceRoot $ConfigPath
}
$ConfigPath = [IO.Path]::GetFullPath($ConfigPath)
$ports = Read-PortConfig $ConfigPath
Write-Host "GoAuto web UI" -ForegroundColor Cyan
Write-Host "Config: $ConfigPath"
Write-Host "Ports: server=$($ports.Server), web=$($ports.Web)"
if ($ValidateConfigOnly) {
Write-Host "Local port configuration is valid." -ForegroundColor Green
return
}
$pnpm = Get-Command pnpm.cmd -ErrorAction SilentlyContinue
if (-not $pnpm) {
throw "pnpm was not found. Install pnpm and try again."
}
Push-Location $webDirectory
try {
if (-not (Test-Path -LiteralPath "node_modules" -PathType Container)) {
Write-Host "Installing frontend dependencies..." -ForegroundColor Cyan
& $pnpm.Source install --frozen-lockfile
if ($LASTEXITCODE -ne 0) {
throw "Frontend dependency installation failed."
}
}
$env:VUE_APP_BASE_API = "http://127.0.0.1:$($ports.Server)"
Write-Host "Starting GoAuto web UI at http://127.0.0.1:$($ports.Web)" -ForegroundColor Green
& $pnpm.Source exec vite --host 127.0.0.1 --port $ports.Web --strictPort
if ($LASTEXITCODE -ne 0) {
throw "Frontend exited with code $LASTEXITCODE."
}
}
finally {
Remove-Item Env:VUE_APP_BASE_API -ErrorAction SilentlyContinue
Pop-Location
}