PSDependScripts/Npm.ps1
|
<#
.SYNOPSIS Install a node package from NPM. .DESCRIPTION Install a node package from NPM. Note: We require npm in your path. Lock behavior (Resolve): PSDepend's lock pins only the declared package to an exact version. Transitive node dependencies are not resolved by PSDepend; npm's own package-lock.json governs the package's subtree. Relevant Dependency metadata: DependencyName (Key): Node Package Name Version: Exact version or npm semver range (for example, '^1.2.0' or '>=1 <2'); defaults to latest. NuGet range syntax is not supported. Target: Path to place the node_modules folder, and all relevant packages, in. You can specify a full path, a UNC path, or a relative path from the current directory. You can also specify the special keyword, 'Global', which will cause the node package to be installed globally for the user who runs PSDepend against this dependency. .PARAMETER Dependency Dependency to process .PARAMETER Global If specified, the node package will be installed globally. .PARAMETER PSDependAction Test, Install or Resolve the dependency. Defaults to Install Test: Return true or false on whether the dependency is in place Install: Install the dependency Resolve: Query npm for the highest version satisfying Version and report it. NuGet range syntax is rejected. Performs no installation. .EXAMPLE @{ 'gitbook-cli' = @{ DependencyType = 'Npm' Version = '0.1.0' Target = 'Global' } } # Full syntax # DependencyName (key) uses (unique) name 'gitbook-cli' # Specify a version to install # Ensure the package is installed globally. .EXAMPLE @{ 'gitbook-cli' = @{ DependencyType = 'Npm' } } # Simple syntax # The example package, 'gitbook-cli' will be installed at the latest version from NPM to the current directory. #> [CmdletBinding()] param ( [PSTypeName('PSDepend.Dependency')] [PSObject[]]$Dependency, [ValidateSet('Test', 'Install', 'Resolve')] [string[]]$PSDependAction = @('Install'), [switch]$Force, [switch]$Global ) #region Extract Dependency Data $Name = $Dependency.DependencyName $Version = $Dependency.Version $Target = $Dependency.Target If (-not [string]::IsNullOrEmpty($Target) -and $Target -ne 'global') { # If the target matches a full path or UNC path, don't modify it; # Otherwise, assume that its a folder _in the current directory_. # If no target is specified, it will install to the current directory. If ($Target -notmatch '(^/|:|\\\\)') { $Target = Join-Path $PWD $Target } If (-not (Test-Path $Target) -and $PSDependAction -contains 'Install') { Write-Verbose "Creating folder [$Target] for node module dependency [$Name]" $null = New-Item -ItemType directory -Path $Target -Force } } #endregion Extract Dependency Data #region Resolve Action If ($PSDependAction -contains 'Resolve') { if ($Version -match '[\[\]\(\),]') { Write-Error "Npm dependency [$Name] uses NuGet range syntax [$Version]; use an npm semver range instead" return } $Candidates = @(Find-NodeModule -PackageName $Name -Version $Version) $Resolved = $null foreach ($Candidate in $Candidates) { if ($null -eq $Resolved -or (Compare-Version -ReferenceVersion $Candidate -DifferenceVersion $Resolved) -gt 0) { $Resolved = $Candidate } } if ($null -eq $Resolved) { Write-Error "No version of [$Name] at [npm] satisfies [$Version]" return } [PSCustomObject]@{ PSTypeName = 'PSDepend.ResolvedDependency' Name = $Name Version = $Resolved Dependencies = @{} } return } #endregion Resolve Action #region Test Action If ($PSDependAction -contains 'Test') { If ([string]::IsNullOrEmpty($Target)) { $InstalledNodeModules = Get-NodeModule } ElseIf ($Target -eq 'global') { $InstalledNodeModules = Get-NodeModule -Global } Else { Push-Location $Target $InstalledNodeModules = Get-NodeModule Pop-Location } $InstalledModule = $InstalledNodeModules.$Name If ($null -eq $InstalledModule) { return $false } ElseIf ($null -ne $Version -and $InstalledModule.Version -ne $Version) { return $false } Else { return $true } } #endregion Test Action #region Install Action If ($PSDependAction -contains 'Install') { If ([string]::IsNullOrEmpty($Target)) { $null = Install-NodeModule -PackageName $Name -Version $Version } ElseIf ($Target -eq 'global') { $null = Install-NodeModule -PackageName $Name -Version $Version -Global } Else { Push-Location $Target $null = Install-NodeModule -PackageName $Name -Version $Version Pop-Location } } #endregion Install Action |