Private/Invoke-TCMGraphRequest.ps1

function Invoke-TCMGraphRequest {
    <#
    .SYNOPSIS
        Internal helper to call TCM Graph API endpoints.
    .DESCRIPTION
        Wraps Invoke-MgGraphRequest with TCM base URL, error handling, and pagination support.
    #>

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

        [ValidateSet('GET', 'POST', 'PATCH', 'DELETE')]
        [string]$Method = 'GET',

        [object]$Body,

        [switch]$All
    )

    $uri = "$script:TCM_BASE_URL/$Endpoint"

    $params = @{
        Method = $Method
        Uri    = $uri
    }

    if ($Body) {
        $params['Body']        = $Body | ConvertTo-Json -Depth 20
        $params['ContentType'] = 'application/json'
    }

    try {
        $response = Invoke-MgGraphRequest @params

        if ($Method -eq 'DELETE') {
            return
        }

        # Handle collections with pagination
        # Check for .value key existence (not truthiness — empty arrays are valid)
        $hasValue = $false
        if ($response -is [System.Collections.IDictionary]) {
            $hasValue = $response.ContainsKey('value')
        }
        elseif ($response.PSObject.Properties.Name -contains 'value') {
            $hasValue = $true
        }

        if ($hasValue) {
            $results = [System.Collections.Generic.List[object]]::new()
            if ($response.value) {
                $results.AddRange([object[]]$response.value)
            }

            if ($All) {
                while ($response.'@odata.nextLink') {
                    $response = Invoke-MgGraphRequest -Method GET -Uri $response.'@odata.nextLink'
                    if ($response.value) {
                        $results.AddRange([object[]]$response.value)
                    }
                }
            }

            return $results
        }

        return $response
    }
    catch {
        $statusCode = $_.Exception.Response.StatusCode
        $errorBody  = $_.ErrorDetails.Message

        if (-not $errorBody) {
            $errorBody = $_.Exception.Message
        }

        Write-Error "TCM API error [$Method $Endpoint] ($statusCode): $errorBody"
    }
}