Types/OpenPackage.Source/Node.ps1
|
<# .SYNOPSIS Gets a node package .DESCRIPTION Gets a node package as an open package #> param( # A node package. # This can be the name of the package in npm or a package link from `npmjs.com` or `npmx.dev` [Parameter(ValueFromPipelineByPropertyName)] [Alias('nodepackages', 'nodepack')] [string[]] $NodePackage, # A list of file wildcards to include. [Parameter(ValueFromPipelineByPropertyName)] [SupportsWildcards()] [string[]] $Include, # A list of file wildcards to exclude. [Parameter(ValueFromPipelineByPropertyName)] [SupportsWildcards()] [string[]] $Exclude, # The base path within the package. # Content should be added beneath this base path. [string] $BasePath = '/', # A content type map. # This maps extensions and URIs to a content type. [Collections.IDictionary] $TypeMap = $( ([PSCustomObject]@{PSTypeName='OpenPackage.ContentTypeMap'}).TypeMap ), # The compression option. [IO.Packaging.CompressionOption] [Alias('CompressionLevel')] $CompressionOption = 'Superfast', # If set, will force the redownload of various resources and remove existing files or directories [switch] $Force, # If set, will include hidden files and folders, except for files beneath `.git` [Alias('IncludeDotFiles')] [switch] $IncludeHidden, # If set, will include the `.git` directory contents if found. # By default, this content will be excluded. [Alias('IncludeGitFile','IncludeGitFiles','IncludeGitDirectory')] [switch] $IncludeGit, # If set, will include any content found in `/node_modules`. # By default, this content will be excluded. [Alias('IncludeNodeModules')] [switch] $IncludeNodeModule, # If set, will include any content found in `/_site`. # By default, this content will be excluded. [Alias('IncludeWebsite')] [switch] $IncludeSite, [string[]] $NodeRepositoryDomain = @( 'npmjs.com' 'npmx.dev' 'www.npmjs.com' 'www.npmx.dev' ) ) $npmApp = $ExecutionContext.SessionState.InvokeCommand.GetCommand('npm', 'Application') if (-not $npmApp) { throw "npm not installed or in path"} # Collect all named parameters to this, # so we can pass most of them to the next step. $namedParameters = [Ordered]@{} foreach ($key in $MyInvocation.MyCommand.Parameters.Keys) { $var = $ExecutionContext.SessionState.PSVariable.Get($key) if (-not [string]::IsNullOrEmpty($var.value)) { $namedParameters[$key] = $var.value } } # Remove any node package specific parameters. $namedParameters.Remove('NodePackage') $namedParameters.Remove('NodeRepositoryDomain') # We want to if (-not $env:OpenPackagePath) {throw "No Open Package Path"} # Get our first OpenPackage package path $myAppData = @($env:OpenPackagePath -split $( if ($IsLinux -or $IsMacOS) { ':' } else { ';' } ))[0] # and put all npm packages beneathh this location. $nodePackRoot = Join-Path $myAppData "node_packages" # If we do not have this directory already, create it if (-not (Test-Path $nodePackRoot)) { $null = New-Item -ItemType Directory -Path $nodePackRoot -Force } # Push into this location Push-Location $nodePackRoot # Go over each package we want to get. foreach ($nodePack in $nodePackage) { # Packages can be in direct named form, or in a url $nodePackUri = $nodePack -as [uri] # If the url was absolute if ($nodePackUri.IsAbsoluteUri) { # check it against possible domain names. if ($nodePackUri.DnsSafeHost -notin $NodeRepositoryDomain) { Write-Error "Can only use an absolute url from $NodeRepositoryDomain" continue } # If the url was versioned if ($nodePackUri.Segments -match 'v/') { # split it into two parts $beforeV, $afterV = $nodePackUri.Segments -join '' -split 'v/' # and put things in the format npm wants. $nodePack = "$($beforeV -replace '^/' -replace '^/package' -replace '/$')@$afterV" } else { # Otherwise, split off the package segment of the url $nodePack = $nodePackUri.Segments[0..3] -ne '/' -join '' -replace '^package/' -replace '/$' } } # `npm pack` will download a package as .tar.gz # (with a number of messages on standard error) $npmOutput = @(& $npmApp pack $nodePack *>&1) # some of these may actually be errors, so create a collection. $npmErrors = @() # and make sure we track if the package has been downloaded # (for it will actually provide the name twice) $packageDownloaded = $false # Go over each output. :gotPackage foreach ($npmOut in $npmOutput) { # If any of the output is an error record if ($npmOut -is [Management.Automation.ErrorRecord]) { # add it to our list $npmErrors += $npmOut } # If the output is not .tgz if ($npmOut -notmatch '\S+\.tgz$') { continue # continue } # Get the file path from our match $npmTarFile = $matches.0 # If the file does not exist if (-not (Test-Path $npmTarFile)) { # output our errors $npmErrors } else { # Otherwise, get the tar file as an open package. $nodePackage = Get-OpenPackage -FilePath "./$npmTarFile" @namedParameters # If the output was a package if ($nodePackage -is [IO.Packaging.Package]) { # mark that we've downloaded it, $packageDownloaded = $true $nodePackage # emit the package, break gotPackage # and take a break. } } } # If the packge was not downloaded, output errors. if (-not $packageDownloaded) { $npmErrors } } Pop-Location |