Public/Web/Invoke-ApiListPaged.ps1
function Invoke-ApiListPaged { <# .SYNOPSIS Calls web API returning paged list of records. For example to list all PullRequests for a project. .DESCRIPTION Calls web API returning paged list of records. If both $Top and $Skip are not specified, iterates the request with increasing $Skip by $Top on each iteration, until records are no longer returned. .PARAMETER ApiCredential Credential to use for authentication. If not specified, $global:AzureDevOpsApi_ApiCredential (set by Set-AzureDevopsVariables) is used. .PARAMETER ApiVersion Requested version of Azure DevOps API. If not specified, $global:AzureDevOpsApi_ApiVersion (set by Set-AzureDevopsVariables) is used. .PARAMETER Uri Address of the service including query parameters. .PARAMETER Body Object to POST as a request. .PARAMETER Method The HTTP method to use. If not specified, it is decided according to whether the Body parameter is given. If not, GET is used, otherwise POST. .PARAMETER PageSize Count of records per page. Used when function should iterate through the records. If not specified, 100 is used, because for many API functions that is the maximum allowed by Azure DevOps. .PARAMETER Top Count of records to return page. Used when function should NOT iterate through the records - calling function is responsible for paging. If not specified, 100 is used, because for many API functions that is the maximum allowed by Azure DevOps. .PARAMETER Skip Count of records to skip before returning the $Top count of records. If not specified, iterates the request with increasing $Skip by $Top, while records are being returned. .PARAMETER AsHashTable If specified, deserializes the JSON response to a hashtable, instead of standard [PSObject]. .PARAMETER RetryCount The maximum number of retry attempts for transient failures. Default is 3. .PARAMETER RetryDelay The base delay in seconds between retry attempts. Default is 1 second. .PARAMETER DisableRetry Disables retry logic completely. #> [CmdletBinding()] param( [AllowNull()] [PSTypeName('PSTypeNames.AzureDevOpsApi.ApiCredential')] [PSCustomObject] $ApiCredential, $ApiVersion, [Parameter(Mandatory)] $Uri, $Body, $Method, [switch] $AsHashTable, $PageSize, $Top, $Skip, [Parameter(ParameterSetName = 'ShowProgress')] $Activity, [ValidateRange(0, 10)] [int] $RetryCount, [ValidateRange(0.1, 300)] [double] $RetryDelay, [switch] $DisableRetry ) begin { $showProgress = $PSCmdlet.ParameterSetName -eq 'ShowProgress' # Use global configuration as defaults if not specified if (-not $PSBoundParameters.ContainsKey('RetryCount')) { $RetryCount = $global:AzureDevOpsApi_RetryConfig.RetryCount } if (-not $PSBoundParameters.ContainsKey('RetryDelay')) { $RetryDelay = $global:AzureDevOpsApi_RetryConfig.RetryDelay } if (-not $PSBoundParameters.ContainsKey('DisableRetry')) { $DisableRetry = $global:AzureDevOpsApi_RetryConfig.DisableRetry } } process { # If Paging is not driven by caller, iterate through the records $paging = Use-PagingParameters -Top:$Top -Skip:$Skip -PageSize:$PageSize # Determine whether relative or absolute uri was given if (-not ([Uri]::new($Uri, [UriKind]::RelativeOrAbsolute)).IsAbsoluteUri) { throw "Uri must be absolute. Given: $Uri" } # If ApiVersion is not specified, use default value $ApiVersion = Use-ApiVersion -ApiVersion $ApiVersion # Add ApiVersion parameter to the Uri $genericUrl = Add-QueryParameter -Uri $Uri -Parameters @{ 'api-version' = $ApiVersion } do { if ($showProgress) { Write-Progress -Activity $Activity -Status $paging.Skip } $finalUri = Add-QueryParameter -Uri $genericUrl -Parameters @{ '$skip' = $paging.Skip '$top' = $paging.Top } # Get the data try { $httpResponse = Invoke-CustomWebRequest ` -ApiCredential $ApiCredential ` -Uri $finalUri ` -Body $Body ` -Method $Method ` -RetryCount $RetryCount ` -RetryDelay $RetryDelay ` -DisableRetry:$DisableRetry } catch { throw } $data = @($httpResponse.Content | ConvertFrom-JsonCustom -AsHashtable:$AsHashTable) # Sends data down the pipeline if ($data.value) { Write-Output $data.value } # Adjust paging $paging.Skip += $data.value.Count } # Iterate as needed while ((!$paging.ShouldPage) -and ($data.value.Count -eq $paging.Top)) } end { if ($showProgress) { Write-Progress -Activity $Activity -Completed } } } Set-Alias -Name Invoke-ApiList -Value Invoke-ApiListPaged |