#requires -Version 7.0 #requires -PSEdition Core <# .SYNOPSIS Publishes npm workspace packages to the npm registry. .DESCRIPTION Publishes packages in configured order using npmSecret (logical secret name). Pass the token via an environment variable named like the configured npm secret (e.g. Npm). Uses a temporary .npmrc in the workspace root. #> if (-not (Get-Command Import-PluginDependency -ErrorAction SilentlyContinue)) { $srcDir = Split-Path (Split-Path $PSScriptRoot -Parent) -Parent $pluginSupportModulePath = Join-Path $srcDir "modules/Engine/PluginSupport.psm1" if (Test-Path $pluginSupportModulePath -PathType Leaf) { Import-Module $pluginSupportModulePath -Force -Global -ErrorAction Stop } } function Invoke-Plugin { param( [Parameter(Mandatory = $true)] $Settings ) Import-PluginDependency -ModuleName "Logging" -RequiredCommand "Write-Log" Import-PluginDependency -ModuleName "ScriptConfig" -RequiredCommand "Assert-Command" Import-PluginDependency -ModuleName "EngineContext" -RequiredCommand "Resolve-RelativePaths" $pluginSettings = $Settings $shared = $Settings.context $dryRun = Test-PluginSkipsRemoteMutation -Plugin $pluginSettings -SharedSettings $shared Assert-Command npm $workspaceRoot = $null if ($pluginSettings.workspaceRoot) { $workspaceRoots = @(Resolve-RelativePaths -Value $pluginSettings.workspaceRoot -BasePath $shared.scriptDir) $workspaceRoot = $workspaceRoots[0] } elseif ($shared.PSObject.Properties['npmWorkspaceRoot'] -and -not [string]::IsNullOrWhiteSpace([string]$shared.npmWorkspaceRoot)) { $workspaceRoot = [string]$shared.npmWorkspaceRoot } else { throw "NpmPublish plugin requires 'workspaceRoot' or a prior NpmReleaseVersion plugin run." } $registry = if ([string]::IsNullOrWhiteSpace([string]$pluginSettings.registry)) { 'https://registry.npmjs.org' } else { [string]$pluginSettings.registry } $access = if ([string]::IsNullOrWhiteSpace([string]$pluginSettings.access)) { 'public' } else { [string]$pluginSettings.access } $publishOrder = @() if ($pluginSettings.publishOrder) { if ($pluginSettings.publishOrder -is [System.Collections.IEnumerable] -and -not ($pluginSettings.publishOrder -is [string])) { $publishOrder = @($pluginSettings.publishOrder | Where-Object { -not [string]::IsNullOrWhiteSpace([string]$_) }) } elseif (-not [string]::IsNullOrWhiteSpace([string]$pluginSettings.publishOrder)) { $publishOrder = @([string]$pluginSettings.publishOrder) } } if ($publishOrder.Count -eq 0) { throw "NpmPublish plugin requires non-empty 'publishOrder' (workspace package names)." } if ($dryRun) { foreach ($packageName in $publishOrder) { Write-Log -Level "INFO" -Message "Dry run: would publish npm package '$packageName' to $registry" } return } $npmSecret = Resolve-PluginSecretName -PluginSettings $pluginSettings -PropertyName 'npmSecret' if ([string]::IsNullOrWhiteSpace($npmSecret)) { throw "NpmPublish plugin requires 'npmSecret' in scriptSettings.json (logical secret name, e.g. Npm)." } $npmToken = Get-SecretEnvironmentValue -Name $npmSecret if ([string]::IsNullOrWhiteSpace($npmToken)) { throw "npm API key is not set. Set environment variable '$npmSecret'." } $registryHost = ([uri]$registry).Host $tempNpmRcPath = Join-Path $workspaceRoot ".npmrc.release-temp" $npmRcContent = @" registry=$registry //$registryHost/:_authToken=$npmToken "@ Push-Location $workspaceRoot try { Set-Content -Path $tempNpmRcPath -Value $npmRcContent -Encoding UTF8 -NoNewline foreach ($packageName in $publishOrder) { Write-Log -Level "STEP" -Message "Publishing npm package '$packageName'..." npm publish -w $packageName --access $access --userconfig $tempNpmRcPath if ($LASTEXITCODE -ne 0) { throw "Failed to publish npm package '$packageName'." } Write-Log -Level "OK" -Message " Published $packageName." } Write-Log -Level "OK" -Message " npm publish completed." $shared | Add-Member -NotePropertyName publishCompleted -NotePropertyValue $true -Force } finally { if (Test-Path $tempNpmRcPath -PathType Leaf) { Remove-Item -Path $tempNpmRcPath -Force -ErrorAction SilentlyContinue } Pop-Location } } function Get-PluginMetadata { [pscustomobject]@{ mutatesRemote = $true } } Export-ModuleMember -Function Invoke-Plugin, Get-PluginMetadata