functions/_Get-GistMapData.ps1

# <copyright file="_Get-GistMapData.ps1" company="Endjin Limited">
# Copyright (c) Endjin Limited. All rights reserved.
# </copyright>

<#
.SYNOPSIS
    Internal helper function to read and parse the gist-map configuration file.

.DESCRIPTION
    This private function handles reading and parsing the gist-map.yml file.
    It is used by ArgumentCompleter blocks to provide tab completion for
    Group and Name parameters.

.PARAMETER ScriptRoot
    The script root directory to use for locating the gist-map.yml file.
    This should typically be $PSScriptRoot from the calling context.

.PARAMETER NoCache
    When specified, bypasses the cache and forces a fresh read from disk.

.OUTPUTS
    Returns a hashtable containing the parsed gist-map data, or $null if the file doesn't exist.

.EXAMPLE
    _Get-GistMapData $PSScriptRoot

.EXAMPLE
    _Get-GistMapData $PSScriptRoot -NoCache

.NOTES
    This is a private helper function (prefixed with '_') and is not exported from the module.
    Results are cached for 30 seconds to improve tab-completion performance.
#>

$script:cachedMap = $null
$script:cacheTimestamp = [datetime]::MinValue
$script:cacheTtlSeconds = 30

function _Get-GistMapData {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory)]
        [string] $ScriptRoot,

        [Parameter()]
        [switch] $NoCache
    )

    # Return cached data if within TTL
    if (-not $NoCache -and $script:cachedMap -and
        ([datetime]::UtcNow - $script:cacheTimestamp).TotalSeconds -lt $script:cacheTtlSeconds) {
        return $script:cachedMap
    }

    $mapPath = Join-Path $ScriptRoot 'gist-map.yml'
    if (Test-Path $mapPath) {
        $map = Get-Content -Path $mapPath -Raw | ConvertFrom-Yaml

        # Validate schema: every gist entry must have required fields
        $requiredFields = @('name', 'source', 'ref', 'includePaths')
        foreach ($groupName in $map.Keys) {
            foreach ($gist in $map[$groupName]) {
                foreach ($field in $requiredFields) {
                    if (-not $gist.ContainsKey($field)) {
                        throw "Gist '$($gist.name)' in group '$groupName' is missing required field: $field"
                    }
                }
            }
        }

        $script:cachedMap = $map
        $script:cacheTimestamp = [datetime]::UtcNow
        return $map
    }
    return $null
}