(
method: Extract<InstallMethod, { kind: 'bundle' }>,
latest: string,
deps: UpgradeDeps
)
| 605 | } |
| 606 | |
| 607 | function upgradeWindowsBundle( |
| 608 | method: Extract<InstallMethod, { kind: 'bundle' }>, |
| 609 | latest: string, |
| 610 | deps: UpgradeDeps |
| 611 | ): number { |
| 612 | const arch = process.arch === 'arm64' ? 'arm64' : 'x64'; |
| 613 | const script = buildWindowsUpgradeScript(method.bundleRoot, latest, arch); |
| 614 | // -EncodedCommand (base64 UTF-16LE), NOT -Command: Node's Windows argv→command |
| 615 | // -line quoting mangles a long multi-statement script, so PowerShell never |
| 616 | // parses it. Encoding sidesteps all shell quoting — the canonical approach. |
| 617 | const encoded = Buffer.from(script, 'utf16le').toString('base64'); |
| 618 | deps.log(c.dim(`Downloading and installing ${latest}…`)); |
| 619 | const code = deps.run('powershell.exe', ['-NoProfile', '-ExecutionPolicy', 'Bypass', '-EncodedCommand', encoded]); |
| 620 | if (code !== 0) { |
| 621 | deps.error(`Installer exited with code ${code}.`); |
| 622 | return 1; |
| 623 | } |
| 624 | deps.log(''); |
| 625 | // The running node.exe was renamed aside, so the version probe in |
| 626 | // runUpgrade already exercises the NEW binary — no terminal hedge needed. |
| 627 | deps.log(c.green('✓ Upgrade complete.')); |
| 628 | deps.log(reindexAdvisory()); |
| 629 | return 0; |
| 630 | } |
| 631 | |
| 632 | /** |
| 633 | * How to invoke npm. On Windows npm is a .cmd batch file, which Node refuses |
no test coverage detected