Private/Get-UKGNextPage.ps1

function Get-UKGNextPage {
    <#
    .SYNOPSIS
        Parses pagination headers from API responses.

    .DESCRIPTION
        Extracts cursor information from the Link header (RFC 5988) or
        Next-Cursor/Previous-Cursor headers for pagination.

    .PARAMETER Headers
        The response headers from the API call.

    .OUTPUTS
        PSCustomObject with NextCursor, PreviousCursor, TotalCount, and PerPage properties.
    #>

    [CmdletBinding()]
    [OutputType([PSCustomObject])]
    param(
        [Parameter(Mandatory)]
        [hashtable]$Headers
    )

    $result = [PSCustomObject]@{
        NextCursor     = $null
        PreviousCursor = $null
        TotalCount     = $null
        PerPage        = $null
        HasNextPage    = $false
    }

    # Check for Next-Cursor header
    if ($Headers.ContainsKey('Next-Cursor') -and $Headers['Next-Cursor']) {
        $result.NextCursor = $Headers['Next-Cursor']
        $result.HasNextPage = $true
    }

    # Check for Previous-Cursor header
    if ($Headers.ContainsKey('Previous-Cursor') -and $Headers['Previous-Cursor']) {
        $result.PreviousCursor = $Headers['Previous-Cursor']
    }

    # Check for X-Total-Count header
    if ($Headers.ContainsKey('X-Total-Count') -and $Headers['X-Total-Count']) {
        $result.TotalCount = [int]$Headers['X-Total-Count']
    }

    # Check for X-Per-Page header
    if ($Headers.ContainsKey('X-Per-Page') -and $Headers['X-Per-Page']) {
        $result.PerPage = [int]$Headers['X-Per-Page']
    }

    # Parse Link header (RFC 5988) if present
    if ($Headers.ContainsKey('Link') -and $Headers['Link']) {
        $linkHeader = $Headers['Link']

        # Parse links like: <url>; rel="next", <url>; rel="prev"
        $links = $linkHeader -split ','
        foreach ($link in $links) {
            if ($link -match '<([^>]+)>.*rel="?([^";\s]+)"?') {
                $url = $Matches[1]
                $rel = $Matches[2]

                # Extract cursor from URL if present
                if ($url -match '[?&]cursor=([^&]+)') {
                    $cursor = $Matches[1]

                    switch ($rel) {
                        'next' {
                            $result.NextCursor = [System.Web.HttpUtility]::UrlDecode($cursor)
                            $result.HasNextPage = $true
                        }
                        'prev' {
                            $result.PreviousCursor = [System.Web.HttpUtility]::UrlDecode($cursor)
                        }
                        'previous' {
                            $result.PreviousCursor = [System.Web.HttpUtility]::UrlDecode($cursor)
                        }
                    }
                }
            }
        }
    }

    return $result
}

function Get-UKGAllPages {
    <#
    .SYNOPSIS
        Retrieves all pages of results from a paginated API endpoint.

    .DESCRIPTION
        Automatically follows pagination cursors to retrieve all results
        from an API endpoint.

    .PARAMETER Endpoint
        The API endpoint to call.

    .PARAMETER Method
        The HTTP method to use (default: GET).

    .PARAMETER Body
        The request body for POST requests.

    .PARAMETER QueryParameters
        Additional query parameters.

    .PARAMETER PerPage
        Number of items per page (default: 100).
    #>

    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [string]$Endpoint,

        [Parameter()]
        [string]$Method = 'GET',

        [Parameter()]
        [hashtable]$Body,

        [Parameter()]
        [hashtable]$QueryParameters,

        [Parameter()]
        [int]$PerPage = 100
    )

    $allResults = @()
    $cursor = $null
    $hasMore = $true

    # Initialize query parameters if not provided
    if ($null -eq $QueryParameters) {
        $QueryParameters = @{}
    }

    # Set per_page if not already set
    if (-not $QueryParameters.ContainsKey('per_page')) {
        $QueryParameters['per_page'] = $PerPage
    }

    while ($hasMore) {
        # Add cursor to query parameters if we have one
        if ($null -ne $cursor) {
            $QueryParameters['cursor'] = $cursor
        }

        # Make the request
        $response = Invoke-UKGRequest -Endpoint $Endpoint -Method $Method -Body $Body -QueryParameters $QueryParameters -ReturnHeaders

        if ($null -eq $response) {
            break
        }

        # Add results to collection
        if ($response.Data -is [array]) {
            $allResults += $response.Data
        }
        elseif ($null -ne $response.Data) {
            $allResults += $response.Data
        }

        # Check for more pages
        $pagination = Get-UKGNextPage -Headers $response.Headers
        if ($pagination.HasNextPage -and $pagination.NextCursor) {
            $cursor = $pagination.NextCursor
        }
        else {
            $hasMore = $false
        }
    }

    return $allResults
}