tasks/20-NPM.ps1
|
@{ Id = 'NPM' DisplayName = 'Node.js + npm cache' Description = 'Installs the configured Node.js major version via nvm, then relocates the npm cache' WingetPackages = @('CoreyButler.NVMforWindows') Action = { [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'Medium')] param( [Parameter(Mandatory)] [System.Collections.IDictionary] $Paths ) Write-Header -Name 'NPM' # --- Step 1: install + activate the configured Node.js major via nvm --- $nodeMajor = Get-NodeJsVersionConfig if ($nodeMajor) { # The metadata-driven winget pass already installed nvm, but # PATH may not have propagated to this process - especially # if the installer wrote PATH after Reset-EnvPath ran. # Re-read it here as a last chance. if (-not (Get-Command nvm -ErrorAction SilentlyContinue)) { Reset-EnvPath } if (-not (Get-Command nvm -ErrorAction SilentlyContinue)) { Write-Status -Level Warn -Message ' [WARN] nvm is not on PATH after the winget install pass; dumping diagnostics.' # Env vars (process + registry). Write-Status -Level Debug -Message " [DEBUG] PATH (process): $env:PATH" Write-Status -Level Debug -Message " [DEBUG] PATH (Machine reg): $([System.Environment]::GetEnvironmentVariable('PATH','Machine'))" Write-Status -Level Debug -Message " [DEBUG] PATH (User reg): $([System.Environment]::GetEnvironmentVariable('PATH','User'))" foreach ($scope in 'Process','Machine','User') { foreach ($name in 'NVM_HOME','NVM_SYMLINK') { $val = [System.Environment]::GetEnvironmentVariable($name, $scope) Write-Status -Level Debug -Message " [DEBUG] $name ($scope) = $val" } } # If NVM_HOME is set, that's the install dir. Otherwise # search common locations. $nvmHome = [System.Environment]::GetEnvironmentVariable('NVM_HOME','User') if (-not $nvmHome) { $nvmHome = [System.Environment]::GetEnvironmentVariable('NVM_HOME','Machine') } $candidates = @() if ($nvmHome) { $candidates += (Join-Path $nvmHome 'nvm.exe') } $candidates += @( (Join-Path $env:APPDATA 'nvm\nvm.exe'), (Join-Path $env:LOCALAPPDATA 'nvm\nvm.exe'), "$env:ProgramFiles\nvm\nvm.exe", "${env:ProgramFiles(x86)}\nvm\nvm.exe", 'C:\nvm\nvm.exe' ) foreach ($p in $candidates) { Write-Status -Level Debug -Message " [DEBUG] Test-Path $p = $(Test-Path -LiteralPath $p)" } Write-Status -Level Skip -Message ' [SKIP] nvm is not on PATH; Node install would happen on a real run after winget bootstraps it.' } else { # Parse `nvm list` output for installed major versions. # Lines look like "* 22.5.1 (Currently using 64-bit executable)" # or " 20.10.0". $listOutput = nvm list 2>&1 $installedMajors = @($listOutput | ForEach-Object { if ($_ -match '^\s*\*?\s*(\d+)\.\d+\.\d+') { $Matches[1] } }) if ($nodeMajor -in $installedMajors) { Write-Status -Level Info -Message " [INFO] Node.js $nodeMajor.x is already installed via nvm." } elseif ($PSCmdlet.ShouldProcess("Node.js $nodeMajor (latest .x)", 'nvm install')) { Write-Status -Level Info -Message " [INFO] Installing Node.js $nodeMajor.x via nvm..." nvm install $nodeMajor 2>&1 | Format-ToolOutput if ($LASTEXITCODE -ne 0) { throw "nvm install $nodeMajor failed with exit code $LASTEXITCODE (nvm-windows usually requires elevation)." } Write-Status -Level Info -Message " [INFO] Node.js $nodeMajor installed." } # Only fire ShouldProcess if the active major isn't already # what we want; otherwise the "What if: nvm use ..." line # bleeds out of the spinner buffer on every dry run even # when nothing would change. $currentRaw = nvm current 2>&1 | Out-String $alreadyActive = $currentRaw -match "v?$([regex]::Escape($nodeMajor))\." if ($alreadyActive) { Write-Status -Level Info -Message " [INFO] Node.js $nodeMajor.x is already the active nvm version." } elseif ($PSCmdlet.ShouldProcess("Node.js $nodeMajor", 'nvm use')) { # nvm use exit codes are unreliable across versions; # silence its noisy output and let downstream steps fail # if Node still isn't available. nvm use $nodeMajor 2>&1 | Out-Null } } } # --- Step 2: relocate the npm cache --- $params = @{ Name = 'npm_config_cache' TargetRoot = $Paths.NpmCache DefaultSource = '%LocalAppData%\npm-cache' } Set-CacheLocation @params } } |