Modules/businessdev.ALbuild.Apps/Private/Get-BcCallGraphContext.ps1

function Get-BcCallGraphContext {
    <#
    .SYNOPSIS
        Resolves a call graph folder into its graph, its apps (as engine AppInfo), the workspace root and the
        architecture file that applies to it.
 
    .DESCRIPTION
        The workspace root comes from -WorkspaceRoot, else from apps.json (recorded by New-BcCallGraph). The
        architecture file is -ArchitecturePath, else callgraph.architecture.json in the workspace root when it
        exists; without one the engine derives the parts from the folders.
 
    .OUTPUTS
        PSCustomObject: Graph (Resolve-BcCallGraphPath result), Apps (AppInfo[]), WorkspaceRoot, ArchitecturePath.
    #>

    [CmdletBinding()]
    [OutputType([PSCustomObject])]
    param(
        [Parameter(Mandatory)] [string] $GraphPath,
        [string] $WorkspaceRoot,
        [string] $ArchitecturePath
    )

    Import-BcCallGraphEngine
    $graph = Resolve-BcCallGraphPath -Path $GraphPath -Require
    $apps = @()
    if ($graph.AppsPath) {
        # Assigned first: Windows PowerShell's ConvertFrom-Json emits a JSON array as ONE pipeline object, so
        # @(... | ConvertFrom-Json) would be a one-element array holding the whole list.
        $records = Get-Content -LiteralPath $graph.AppsPath -Raw -Encoding UTF8 | ConvertFrom-Json
        $folders = New-Object System.Collections.Generic.List[string]
        $apps = @(foreach ($a in $records) {
                $info = New-Object ALbuild.CallGraph.AppInfo
                $info.Id = "$($a.id)"; $info.Name = $a.name; $info.Publisher = $a.publisher; $info.Version = $a.version
                $info.Role = $a.role; $info.HasSource = [bool]$a.hasSource
                $root = $a.PSObject.Properties['workspaceRoot']
                if (-not $WorkspaceRoot -and $a.role -eq 'own' -and $root -and $root.Value) { $WorkspaceRoot = $root.Value }
                $folder = $a.PSObject.Properties['folder']
                if ($a.role -eq 'own' -and $folder -and $folder.Value) { $folders.Add([string]$folder.Value) }
                $info
            })
        # A graph from before the workspace root was recorded: the common parent of the project folders.
        if (-not $WorkspaceRoot -and $folders.Count -gt 0) {
            $common = Split-Path -Parent $folders[0]
            foreach ($f in $folders) { while ($common -and -not ("$f\" -replace '/', '\').StartsWith("$common\" -replace '/', '\', [System.StringComparison]::OrdinalIgnoreCase)) { $common = Split-Path -Parent $common } }
            if ($common) { $WorkspaceRoot = $common }
        }
    }
    else {
        Write-ALbuildLog -Level Warning "No apps.json next to '$($graph.GraphPath)'; every app in the graph header counts as own."
    }
    if (-not $ArchitecturePath -and $WorkspaceRoot) {
        $candidate = Join-Path -Path $WorkspaceRoot -ChildPath 'callgraph.architecture.json'
        if (Test-Path -LiteralPath $candidate) { $ArchitecturePath = $candidate }
    }
    [PSCustomObject]@{
        Graph            = $graph
        Apps             = [ALbuild.CallGraph.AppInfo[]]$apps
        WorkspaceRoot    = $WorkspaceRoot
        ArchitecturePath = $ArchitecturePath
    }
}