Support/Package/Eigenverft.Manifested.Sandbox.Package.Npm.ps1
|
<#
Eigenverft.Manifested.Sandbox.Package.Npm #> function Get-PackageModelNpmGlobalConfigPath { [CmdletBinding()] param( [Parameter(Mandatory = $true)] [psobject]$PackageModelResult ) $packageModelRoot = Split-Path -Parent ([string]$PackageModelResult.PackageModelConfig.OwnershipIndexFilePath) return ([System.IO.Path]::GetFullPath((Join-Path $packageModelRoot 'npm\npmrc'))) } function New-PackageModelNpmCacheDirectory { [CmdletBinding()] param( [Parameter(Mandatory = $true)] [psobject]$PackageModelResult ) $segments = @( 'npm-cache' [string]$PackageModelResult.DefinitionId [string]$PackageModelResult.Package.releaseTrack [string]$PackageModelResult.Package.version [string]$PackageModelResult.Package.flavor ) | ForEach-Object { ([string]$_).Trim() -replace '[\\/:\*\?"<>\|]', '-' } $cacheDirectory = [System.IO.Path]::GetFullPath((Join-Path $PackageModelResult.PackageModelConfig.InstallWorkspaceRootDirectory ($segments -join '\'))) $null = New-Item -ItemType Directory -Path $cacheDirectory -Force return $cacheDirectory } function Initialize-PackageModelNpmGlobalConfig { [CmdletBinding()] param( [Parameter(Mandatory = $true)] [string]$GlobalConfigPath ) $resolvedPath = [System.IO.Path]::GetFullPath($GlobalConfigPath) $directoryPath = Split-Path -Parent $resolvedPath if (-not [string]::IsNullOrWhiteSpace($directoryPath)) { $null = New-Item -ItemType Directory -Path $directoryPath -Force } if (-not (Test-Path -LiteralPath $resolvedPath -PathType Leaf)) { Set-Content -LiteralPath $resolvedPath -Value '' -Encoding UTF8 } return $resolvedPath } function Resolve-PackageModelPackageManagerDependencyCommand { [CmdletBinding()] param( [Parameter(Mandatory = $true)] [psobject]$PackageModelResult ) $install = $PackageModelResult.Package.install if (-not $install.PSObject.Properties['managerDependency'] -or $null -eq $install.managerDependency) { throw "PackageModel npm install for '$($PackageModelResult.PackageId)' requires install.managerDependency." } $dependency = $install.managerDependency $definitionId = if ($dependency.PSObject.Properties['definitionId']) { [string]$dependency.definitionId } else { $null } $commandName = if ($dependency.PSObject.Properties['command']) { [string]$dependency.command } else { $null } if ([string]::IsNullOrWhiteSpace($definitionId) -or [string]::IsNullOrWhiteSpace($commandName)) { throw "PackageModel npm install for '$($PackageModelResult.PackageId)' requires install.managerDependency.definitionId and install.managerDependency.command." } if ([string]::Equals($definitionId, [string]$PackageModelResult.DefinitionId, [System.StringComparison]::OrdinalIgnoreCase)) { throw "PackageModel npm install for '$($PackageModelResult.PackageId)' cannot depend on its own definition '$definitionId'." } Write-PackageModelExecutionMessage -Message ("[STEP] Ensuring package-manager dependency '{0}' for command '{1}'." -f $definitionId, $commandName) $dependencyResult = Invoke-PackageModelDefinitionCommand -DefinitionId $definitionId -CommandName ("Invoke-{0}" -f $definitionId) if (-not $dependencyResult -or -not [string]::Equals([string]$dependencyResult.Status, 'Ready', [System.StringComparison]::OrdinalIgnoreCase)) { $dependencyStatus = if ($dependencyResult) { [string]$dependencyResult.Status } else { '<none>' } throw "PackageModel npm install dependency '$definitionId' did not become ready. Status='$dependencyStatus'." } $entryPoint = @( $dependencyResult.EntryPoints.Commands | Where-Object { [string]::Equals([string]$_.Name, $commandName, [System.StringComparison]::OrdinalIgnoreCase) } | Select-Object -First 1 ) $commandPath = if ($entryPoint) { [string]$entryPoint[0].Path } else { $null } if ([string]::IsNullOrWhiteSpace($commandPath) -or -not (Test-Path -LiteralPath $commandPath -PathType Leaf)) { throw "PackageModel npm install dependency '$definitionId' did not expose command '$commandName'." } $dependencyInfo = [pscustomobject]@{ DefinitionId = $definitionId Command = $commandName Status = [string]$dependencyResult.Status CommandPath = [System.IO.Path]::GetFullPath($commandPath) } if ($PackageModelResult.PSObject.Properties['PackageManagerDependency']) { $PackageModelResult.PackageManagerDependency = $dependencyInfo } else { $PackageModelResult | Add-Member -MemberType NoteProperty -Name PackageManagerDependency -Value $dependencyInfo } Write-PackageModelExecutionMessage -Message ("[STATE] Package-manager dependency ready: definition='{0}', command='{1}', path='{2}'." -f $definitionId, $commandName, $dependencyInfo.CommandPath) return $dependencyInfo } function Install-PackageModelNpmPackage { <# .SYNOPSIS Installs an exact npm package spec into a staged PackageModel-owned prefix. #> [CmdletBinding()] param( [Parameter(Mandatory = $true)] [psobject]$PackageModelResult ) $install = $PackageModelResult.Package.install if (-not $install.PSObject.Properties['packageSpec'] -or [string]::IsNullOrWhiteSpace([string]$install.packageSpec)) { throw "PackageModel npm install for '$($PackageModelResult.PackageId)' requires install.packageSpec." } $packageSpec = Resolve-PackageModelTemplateText -Text ([string]$install.packageSpec) -PackageModelConfig $PackageModelResult.PackageModelConfig -Package $PackageModelResult.Package $dependencyInfo = Resolve-PackageModelPackageManagerDependencyCommand -PackageModelResult $PackageModelResult $cacheDirectory = New-PackageModelNpmCacheDirectory -PackageModelResult $PackageModelResult $globalConfigPath = Initialize-PackageModelNpmGlobalConfig -GlobalConfigPath (Get-PackageModelNpmGlobalConfigPath -PackageModelResult $PackageModelResult) $stagePath = New-TemporaryStageDirectory -Prefix ('npm-' + ([string]$PackageModelResult.DefinitionId).ToLowerInvariant()) $stagePromoted = $false $commandArguments = @('install', '-g', '--prefix', $stagePath, '--cache', $cacheDirectory) $commandArguments += @(Get-NpmGlobalConfigArguments -GlobalConfigPath $globalConfigPath) $commandArguments += $packageSpec Write-PackageModelExecutionMessage -Message ("[STATE] npm package-manager install:") Write-PackageModelExecutionMessage -Message ("[PATH] npm command: {0}" -f $dependencyInfo.CommandPath) Write-PackageModelExecutionMessage -Message ("[PATH] npm stage: {0}" -f $stagePath) Write-PackageModelExecutionMessage -Message ("[PATH] npm cache: {0}" -f $cacheDirectory) Write-PackageModelExecutionMessage -Message ("[PATH] npm global config: {0}" -f $globalConfigPath) Write-PackageModelExecutionMessage -Message ("[STATE] npm package spec: {0}" -f $packageSpec) try { Push-Location $stagePath try { & $dependencyInfo.CommandPath @commandArguments $exitCode = $LASTEXITCODE if ($null -eq $exitCode) { $exitCode = 0 } } finally { Pop-Location } if ($exitCode -ne 0) { throw "PackageModel npm install for '$($PackageModelResult.PackageId)' failed with exit code $exitCode." } $installParent = Split-Path -Parent $PackageModelResult.InstallDirectory if (-not [string]::IsNullOrWhiteSpace($installParent)) { $null = New-Item -ItemType Directory -Path $installParent -Force } Remove-PathIfExists -Path $PackageModelResult.InstallDirectory | Out-Null Move-Item -LiteralPath $stagePath -Destination $PackageModelResult.InstallDirectory -Force $stagePromoted = $true } finally { if (-not $stagePromoted) { Remove-PathIfExists -Path $stagePath | Out-Null } } return [pscustomobject]@{ Status = Get-PackageModelOwnedInstallStatus -PackageModelResult $PackageModelResult InstallKind = 'packageManagerInstall' ManagerKind = 'npm' InstallDirectory = $PackageModelResult.InstallDirectory ReusedExisting = $false PackageSpec = $packageSpec Dependency = $dependencyInfo CommandPath = $dependencyInfo.CommandPath CommandArguments = @($commandArguments) CacheDirectory = $cacheDirectory GlobalConfigPath = $globalConfigPath StagePath = $stagePath ExitCode = $exitCode } } |