@@ -44,12 +44,6 @@ function Require-Npm {
4444 }
4545}
4646
47- function Get-NpmPath {
48- $cmd = Get-Command npm - ErrorAction Stop
49- # On Windows this is typically ...\npm.cmd
50- return $cmd.Source
51- }
52-
5347function Read-Secure ([string ]$msg ) {
5448 $secure = Read-Host $msg - AsSecureString
5549 $bstr = [Runtime.InteropServices.Marshal ]::SecureStringToBSTR($secure )
@@ -72,21 +66,30 @@ function Ensure-Registry([string]$reg) {
7266 return $reg
7367}
7468
75- function SetCfg ([string ]$k , [string ]$v ) {
76- if ($DryRun ) { Info " DRYRUN: npm config set --global $k <value>" ; return }
77- npm config set -- global $k $v | Out-Null
78- if ($LASTEXITCODE -ne 0 ) { throw " npm config set failed ($k ). exit=$LASTEXITCODE " }
69+ function New-TempNpmrc {
70+ $path = Join-Path $env: TEMP (" deepstudio-npmrc-" + [Guid ]::NewGuid().ToString(" N" ) + " .npmrc" )
71+ return $path
7972}
8073
81- function DelCfg ([string ]$k ) {
82- if ($DryRun ) { Info " DRYRUN: npm config delete --global $k " ; return }
83- try { npm config delete -- global $k | Out-Null } catch {}
84- }
74+ function Write-IsolatedNpmrc ([string ]$path , [string ]$registry , [string ]$authPrefix , [string ]$pat ) {
75+ # Use _authToken to avoid conflicts with user's existing .npmrc and avoid base64 encoding pitfalls.
76+ # NOTE: This writes PAT into a temporary file; we delete it in finally.
77+ $content = @"
78+ registry=$registry /
79+ ${authPrefix} :_authToken=$pat
80+ "@
8581
86- # IMPORTANT: Do NOT name parameters as $args (PowerShell automatic variable).
87- function Run-NpmInstall ([string []]$npmArgs ) {
88- $cmdLine = " npm " + ($npmArgs -join " " )
82+ if ($DryRun ) {
83+ Info " DRYRUN: write isolated npmrc to $path "
84+ Info (" DRYRUN: npmrc content (token masked):`n registry=$registry /`n ${authPrefix} :_authToken=$ ( Mask- Token $pat ) " )
85+ return
86+ }
8987
88+ # ASCII is safest for .npmrc formatting
89+ Set-Content - Path $path - Value $content - Encoding ASCII
90+ }
91+
92+ function Run-NpmViaCmd ([string ]$cmdLine ) {
9093 if ($DryRun ) {
9194 Info (" DRYRUN: " + $cmdLine )
9295 return
@@ -146,7 +149,6 @@ function Run-NpmInstall([string[]]$npmArgs) {
146149 }
147150}
148151
149-
150152# ---------------------------
151153# Start
152154# ---------------------------
@@ -171,7 +173,7 @@ $registry = Ensure-Registry $registryInput
171173$uri = [Uri ]$registry
172174$authPrefix = " //" + $uri.Host + $uri.AbsolutePath + " /"
173175
174- # Read PAT securely then TRIM it (fix common 401 due to whitespace/newlines)
176+ # Read PAT securely then TRIM it (fix common whitespace/newlines)
175177$patRaw = Read-Secure " Enter Azure DevOps PAT (Packaging:Read)"
176178if ([string ]::IsNullOrWhiteSpace($patRaw )) { throw " PAT is empty." }
177179
@@ -183,16 +185,11 @@ Info ("PAT (masked): " + (Mask-Token $pat))
183185Info " Tip: if masked prefix/suffix looks wrong, you likely pasted extra chars/spaces."
184186Info " "
185187
186- $patB64 = [Convert ]::ToBase64String([Text.Encoding ]::UTF8.GetBytes($pat ))
187- $pat = $null
188-
189- # npm install args
188+ # npm install args / loglevel
190189$logLevel = if ($VerboseInstall ) { " verbose" } else { " notice" }
191- $npmInstallArgs = @ (
192- " install" , " -g" , " $PackageName @latest" ,
193- " --registry" , " $registry /" ,
194- " --loglevel" , $logLevel
195- )
190+
191+ # Create isolated npmrc to avoid user's existing ~/.npmrc conflicts
192+ $tmpNpmrc = New-TempNpmrc
196193
197194# Optional: extra debug signal for npm
198195if ($VerboseInstall ) {
@@ -201,25 +198,23 @@ if ($VerboseInstall) {
201198}
202199
203200try {
204- Info " Configuring npm auth for this registry ..."
205- SetCfg " registry" " $registry / "
206- SetCfg " ${authPrefix} :username " " ms "
207- SetCfg " ${authPrefix} :_password " $patB64
208- SetCfg " ${authPrefix} :email " " npm@example.com "
209- # NOTE: always-auth intentionally not set (deprecated/invalid in modern npm)
201+ Info " Preparing isolated npm config (ignores your existing .npmrc) ..."
202+ Write-IsolatedNpmrc - path $tmpNpmrc - registry $registry - authPrefix $authPrefix - pat $pat
203+
204+ # Build command line (use cmd.exe to avoid PowerShell alias/function issues with npm)
205+ # IMPORTANT: Use --userconfig so npm only reads our isolated temp npmrc for this run.
206+ $installCmd = ' npm install -g "{0}@latest" --registry "{1}/" --loglevel {2} --userconfig "{3}" ' -f $PackageName , $registry , $logLevel , $tmpNpmrc
210207
211208 Info " "
212- Info (" Command: npm " + ( $npmInstallArgs -join " " ) )
209+ Info (" Command: " + $installCmd )
213210 Info " "
214211
215- Run- NpmInstall $npmInstallArgs
212+ Run- NpmViaCmd $installCmd
216213
217- # Extra safety: verify it's actually installed
214+ # Extra safety: verify it's actually installed (still using isolated userconfig is ok)
218215 if (-not $DryRun ) {
219- npm list - g -- depth= 0 " $PackageName " | Out-Null
220- if ($LASTEXITCODE -ne 0 ) {
221- throw " Install command finished but package not found in global npm list. Something is wrong."
222- }
216+ $verifyCmd = ' npm list -g --depth=0 "{0}" --userconfig "{1}"' -f $PackageName , $tmpNpmrc
217+ Run- NpmViaCmd $verifyCmd
223218 }
224219
225220 Info " "
@@ -247,7 +242,7 @@ catch {
247242 } else {
248243 Warn " "
249244 Warn " Tip: re-run with verbose:"
250- Warn " `$ env:DEEPSTUDIO_VERBOSE='1'; irm <url> | iex"
245+ Warn " `$ env:DEEPSTUDIO_VERBOSE='1'; `$ env:DEEPSTUDIO_LOG='1'; irm <url> | iex"
251246 }
252247
253248 if ($EnableLog -and -not $DryRun ) {
@@ -258,18 +253,15 @@ catch {
258253 throw
259254}
260255finally {
261- Info " "
262- Info " Cleaning up npm global config..."
263- DelCfg " registry"
264- DelCfg " ${authPrefix} :username"
265- DelCfg " ${authPrefix} :_password"
266- DelCfg " ${authPrefix} :email"
267-
256+ # Clean up temp npmrc and env vars
257+ if (-not $DryRun ) {
258+ Remove-Item $tmpNpmrc - Force - ErrorAction SilentlyContinue
259+ }
268260 if ($VerboseInstall ) {
269261 Remove-Item Env:\NPM_CONFIG_LOGLEVEL - ErrorAction SilentlyContinue
270262 Remove-Item Env:\NPM_CONFIG_PROGRESS - ErrorAction SilentlyContinue
271263 }
272-
264+ Info " "
273265 Info " ✅ Cleanup complete."
274266 Info " "
275267}
0 commit comments