Private/Transport.ps1
|
$script:LaunchLibraryConnection = [ordered]@{ BaseUri = 'https://ll.thespacedevs.com' ApiKey = $null UseDevelopment = $false } function ConvertTo-LaunchLibraryQueryString { [CmdletBinding()] param([hashtable]$Query) if (-not $Query -or $Query.Count -eq 0) { return '' } $pairs = foreach ($key in $Query.Keys | Sort-Object) { $value = $Query[$key] if ($null -eq $value) { continue } if ($value -is [System.Collections.IEnumerable] -and $value -isnot [string]) { $value = @($value) -join ',' } '{0}={1}' -f [uri]::EscapeDataString([string]$key), [uri]::EscapeDataString([string]$value) } @($pairs) -join '&' } function Get-LaunchLibraryRequestUri { [CmdletBinding()] param( [Parameter(Mandatory)][string]$Path, [hashtable]$Query ) if ($Path -notmatch '^/2\.3\.0/') { throw "Path must begin with '/2.3.0/'." } $uri = '{0}{1}' -f $script:LaunchLibraryConnection.BaseUri.TrimEnd('/'), $Path $queryString = ConvertTo-LaunchLibraryQueryString -Query $Query if ($queryString) { $uri = '{0}?{1}' -f $uri, $queryString } $uri } function Get-LaunchLibraryResponseDetail { [CmdletBinding()] param( $Response, [string]$ErrorDetails ) $bodies = [System.Collections.Generic.List[string]]::new() if ($Response) { try { if ($Response.Content) { $bodies.Add($Response.Content.ReadAsStringAsync().GetAwaiter().GetResult()) } elseif ($Response.PSObject.Methods.Name -contains 'GetResponseStream') { $stream = $Response.GetResponseStream() if ($stream) { $reader = [IO.StreamReader]::new($stream) try { $bodies.Add($reader.ReadToEnd()) } finally { $reader.Dispose() $stream.Dispose() } } } } catch { Write-Verbose "Unable to read the HTTP error response body." } } if (-not [string]::IsNullOrWhiteSpace($ErrorDetails)) { $bodies.Add($ErrorDetails) } $fallback = $null foreach ($body in $bodies) { if ([string]::IsNullOrWhiteSpace($body)) { continue } try { $errorBody = $body | ConvertFrom-Json -ErrorAction Stop if ($errorBody.detail) { return [string]$errorBody.detail } } catch { if (-not $fallback) { $fallback = $body.Trim() } } } $fallback } function Invoke-LaunchLibraryApiRequest { [CmdletBinding()] param( [Parameter(Mandatory)][string]$Uri, [switch]$Raw ) $headers = @{ Accept = 'application/json' } if ($script:LaunchLibraryConnection.ApiKey) { $headers.Authorization = 'Token {0}' -f $script:LaunchLibraryConnection.ApiKey } try { $response = Invoke-RestMethod -Method Get -Uri $Uri -Headers $headers -ErrorAction Stop } catch { $statusCode = $null $errorResponse = $_.Exception.Response if ($errorResponse) { $statusCode = [int]$errorResponse.StatusCode } $suffix = if ($statusCode) { " (HTTP $statusCode)" } else { '' } $detail = Get-LaunchLibraryResponseDetail -Response $errorResponse -ErrorDetails $_.ErrorDetails.Message $message = if ($detail) { $detail } else { $_.Exception.Message } throw "Launch Library request failed${suffix}: $message" } if ($Raw) { return $response } if ($response.PSObject.Properties.Name -contains 'results') { return $response.results } $response } function Invoke-LaunchLibraryPagedRequest { [CmdletBinding()] param( [Parameter(Mandatory)][string]$Uri, [switch]$All, [switch]$Raw ) $nextUri = $Uri do { $response = Invoke-LaunchLibraryApiRequest -Uri $nextUri -Raw if ($Raw) { $response } elseif ($response.PSObject.Properties.Name -contains 'results') { $response.results } else { $response } $nextUri = if ($response.PSObject.Properties.Name -contains 'next') { $response.next } else { $null } } while ($All -and $nextUri) } function Invoke-LaunchLibraryResourceCommand { [CmdletBinding()] param( [Parameter(Mandatory)][pscustomobject]$Resource, [string]$Id, [ValidateSet('All', 'Previous', 'Upcoming')][string]$Scope = 'All', [hashtable]$Query, [switch]$All, [switch]$Raw ) if ($Id -and -not $Resource.SupportsId) { throw "$($Resource.Name) does not support an ID endpoint." } if ($Scope -ne 'All' -and -not $Resource.SupportsScope) { throw "$($Resource.Name) does not support previous or upcoming scopes." } $path = $Resource.Path if ($Scope -ne 'All') { $path = '{0}{1}/' -f $path, $Scope.ToLowerInvariant() } if ($Id) { $path = '{0}{1}/' -f $path, [uri]::EscapeDataString($Id) } $uri = Get-LaunchLibraryRequestUri -Path $path -Query $Query Invoke-LaunchLibraryPagedRequest -Uri $uri -All:$All -Raw:$Raw } function Initialize-LaunchLibraryResourceCommand { foreach ($resource in $script:LaunchLibraryResources) { $command = $resource.Command $resourceName = $resource.Name $definition = @" [CmdletBinding()] param( [Parameter(Position = 0)] [string]`$Id, [ValidateSet('All', 'Previous', 'Upcoming')] [string]`$Scope = 'All', [hashtable]`$Query, [switch]`$All, [switch]`$Raw ) Get-LaunchLibraryResource -Resource '$resourceName' -Id `$Id -Scope `$Scope -Query `$Query -All:`$All -Raw:`$Raw "@ Set-Item -Path "Function:script:$command" -Value ([scriptblock]::Create($definition)) } } |