Private/Get-GraphLegacyIndex.ps1

function Get-GraphLegacyIndex {
    <#
    .SYNOPSIS
        Loads and caches the AzureAD/MSOnline -> Mg legacy command index.
    .DESCRIPTION
        Reads data/graph-legacy-command-index.json, produced by
        scripts/sync-graph-legacy-mapping.ps1 from the official MgLegacyCommandMapping.json.
        Returns $null (with a verbose message, not a thrown error) when the file is not present,
        so a GraphShell install without this optional data can still use every other cmdlet;
        Get-GraphLegacyMapping is the only caller affected.
    #>

    [CmdletBinding()]
    [OutputType([pscustomobject])]
    param(
        [switch]$Force
    )

    if (-not $Force -and $script:GraphLegacyIndexCache) {
        return $script:GraphLegacyIndexCache
    }

    $paths = Get-GraphCatalogPath
    if (-not $paths.LegacyCommandIndexPath) {
        Write-Verbose "GraphShell legacy command index (graph-legacy-command-index.json) is not available in this installation."
        return $null
    }
    Write-Verbose "Loading GraphShell legacy command index from $($paths.LegacyCommandIndexPath)"

    $raw = Get-Content -LiteralPath $paths.LegacyCommandIndexPath -Raw
    $parsed = $raw | ConvertFrom-Json

    $byLegacyCommand = [System.Collections.Generic.Dictionary[string, object]]::new([System.StringComparer]::OrdinalIgnoreCase)
    foreach ($property in $parsed.mappings.PSObject.Properties) {
        $byLegacyCommand[$property.Name] = [string[]]$property.Value
    }

    $script:GraphLegacyIndexCache = [pscustomobject]@{
        Source           = $parsed.source
        ByLegacyCommand  = $byLegacyCommand
        LegacyCommands   = [string[]]$byLegacyCommand.Keys
    }

    return $script:GraphLegacyIndexCache
}