Public/Common.ps1

function Invoke-TMRestMethod {
    <#
    .SYNOPSIS
        Invokes a TransitionManager REST API request.
 
    .DESCRIPTION
        Builds and submits a REST request against the TM API using either an
        API resource name or a full URI. The current project id is included in
        the request body automatically.
 
    .PARAMETER Api
        The TM API resource name to append to the standard TM REST base path.
 
    .PARAMETER Uri
        A full URI to invoke when using the `byUri` parameter set.
 
    .PARAMETER Method
        The HTTP method to use for the request, such as `Get`, `Post`, `Put`,
        or `Delete`.
 
    .PARAMETER BodyParams
        A hashtable of additional body parameters to include in the JSON
        payload.
 
    .PARAMETER ApiParams
        Query-string parameters to append to the API resource name.
 
    .PARAMETER TMSession
        A TMSession object or session name to use for the request. Defaults to
        `'Default'`.
 
    .EXAMPLE
        Invoke-TMRestMethod -Api task -Method Get -ApiParams 'rows=25&page=1'
 
        Invokes the `task` API using the standard TM REST base path.
 
    .EXAMPLE
        Invoke-TMRestMethod -Uri 'https://tm.example.com/tdstm/api/task' -Method Get
 
        Invokes a fully qualified TM REST endpoint directly.
 
    .NOTES
        The active project id from the resolved session is added to the body by
        default.
    #>

    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true, ParameterSetName = 'byApi')][string] $Api,
        [Parameter(Mandatory = $true, ParameterSetName = 'byUri') ][string] $Uri,
        [Parameter(Mandatory = $true)][string] $Method,
        [Parameter(Mandatory = $false)][hashtable] $BodyParams,
        [Parameter(Mandatory = $false)][string] $ApiParams,
        [Parameter(Mandatory = $false)][psobject] $TMSession = 'Default'
    )

    begin {
        if ($PSCmdlet.ParameterSetName -eq 'byUri') {
            $pattern = '/api/([^/?]+)'
            if ($uri -match $pattern) {
                $api = $matches[1]
                Write-Verbose "API Name: $api"
            } else {
                Write-Verbose 'No API name found.'
            }
        }

        $TMSession = Get-TMSession $TMSession

        $Body = @{
            project = $TMSession.UserContext.Project.Id
        }
        if ( $PSBoundParameters.ContainsKey('BodyParams')) {
            $BodyParams.Keys.foreach({$Body[$_] = $BodyParams[$_]})
        }
        if ( $PSBoundParameters.ContainsKey('ApiPArams') ) {
            $Api = [string]::Concat($Api, '?', $ApiParams)
        }

        $RestSplat = @{
            Uri                  = 'https://{0}/tdstm/api/{1}' -f $TMSession.TMServer, $Api
            Method               = $Method
            WebSession           = $TMSession.TMRestSession
            StatusCodeVariable   = 'StatusCode'
            SkipHttpErrorCheck   = $true
            SkipCertificateCheck = $TMSession.AllowInsecureSSL
            Body                 = $Body | ConvertTo-Json -EnumsAsStrings -Compress
        }
    }

    process {
        $response = Invoke-RestMethod @RestSplat
        if ($StatusCode -ne 200) {
            throw "Status Code $StatusCode does not indicate success. Response: $response"
        }
        return $response
    }
}