Public/Invoke-Connector.ps1

<#
.SYNOPSIS
Imports configured SuccessFactors OData resources into IAM Core Connector Space.

.DESCRIPTION
Validates the configured resource definitions, authenticates to SuccessFactors, retrieves every
configured resource, generates stable external IDs, and emits connector objects without applying
tenant-specific business rules or cross-resource filtering.

.PARAMETER ConnectorConfiguration
Connector configuration containing authentication settings and a resourcetypes JSON array.

.OUTPUTS
System.Collections.Hashtable. One connector object for every row returned by SuccessFactors.

.NOTES
The connector deliberately imports source rows losslessly. Data-quality and projection policy
belong in source-system validation and IAM Core sync rules rather than in this import function.
#>

function Invoke-Connector {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory)]
        $ConnectorConfiguration
    )

    $resourceTypes = @(ConvertFrom-SFResourceTypesConfiguration -ConnectorConfiguration $ConnectorConfiguration)
    Connect-SF -ConnectorConfiguration $ConnectorConfiguration
    Write-ConnectorVerbose "Connected successfully"

    $asOfDate = [DateTimeOffset]::UtcNow

    foreach ($resourceTypeConfiguration in $resourceTypes) {
        $resourceType = [string]$resourceTypeConfiguration.Type
        $queryString = Resolve-SFQueryString `
            -QueryString ([string]$resourceTypeConfiguration.QueryString) `
            -AsOfDate $asOfDate

        Write-ConnectorVerbose "Retrieving SuccessFactors resource type '$resourceType'"
        $resources = @(Invoke-SFRestMethod `
            -Resource $resourceType `
            -BaseUrl $ConnectorConfiguration.configuration.baseurl `
            -QueryString $queryString)

        # Validate every external ID before emitting this resource type. This prevents a
        # malformed or duplicate source key from being silently omitted from the snapshot.
        $externalIds = [System.Collections.Generic.HashSet[string]]::new([System.StringComparer]::Ordinal)
        $preparedResources = @(
            foreach ($resource in $resources) {
                $externalId = Get-SFExternalId `
                    -Resource $resource `
                    -ResourceTypeConfiguration $resourceTypeConfiguration

                if (-not $externalIds.Add($externalId)) {
                    throw "SuccessFactors resource type '$resourceType' produced duplicate external ID '$externalId'."
                }

                $data = $resource |
                    ConvertTo-Json -Depth 20 |
                    ConvertFrom-Json -AsHashtable -Depth 20

                [PSCustomObject]@{
                    ExternalId = $externalId
                    Data       = $data
                }
            }
        )

        foreach ($preparedResource in $preparedResources) {
            Build-ConnectorObject `
                -ExternalId $preparedResource.ExternalId `
                -Data $preparedResource.Data `
                -ObjectType $resourceType
        }

        Write-ConnectorVerbose "Processed $($preparedResources.Count) resources of type '$resourceType'"
    }
}