Private/Get-DFToolIdentityGuide.ps1
|
#Requires -Version 7.0 # Lazy-loaded, indexed tool-identity guide: canonical tool -> verified # per-catalog package ids, consulted by Resolve-DFCatalogQueryMerge as an # additional (never sole, never authoritative-over-Tools/*.json) identity # source. Ships as data/tool-identities.json; Update-DFToolIdentityGuide can # place a newer copy under $XDG_DATA_HOME/dotforge/. function Get-DFToolIdentityGuide { <# .SYNOPSIS Loads (and indexes) the trifle tool-identity guide. Lazy singleton; never throws — an unreadable file degrades to an empty, valid, harmless guide object. .PARAMETER Path Override the shipped-side location (a test seam — lets a fixture stand in for the real shipped file). The refreshed-vs-shipped precedence check against $Env:XDG_DATA_HOME still runs normally against this override. Always forces a fresh, uncached read. .PARAMETER Force Reload from the resolved location, bypassing the singleton cache. #> [CmdletBinding()] [OutputType([PSCustomObject])] param( [string]$Path, [switch]$Force ) if (-not $Path -and -not $Force -and $script:DFToolIdentityGuide) { return $script:DFToolIdentityGuide } $shippedPath = $Path ? $Path : (Join-Path $PSScriptRoot '../data/tool-identities.json') $resolvedPath = $shippedPath if ($Env:XDG_DATA_HOME) { $refreshedPath = Join-Path $Env:XDG_DATA_HOME 'dotforge/tool-identities.json' if (Test-Path $refreshedPath) { try { $shippedUpdated = (Test-Path $shippedPath) ? (Get-Content $shippedPath -Raw | ConvertFrom-Json).updated : $null $refreshedUpdated = (Get-Content $refreshedPath -Raw | ConvertFrom-Json).updated if (-not $shippedUpdated -or [datetime]$refreshedUpdated -gt [datetime]$shippedUpdated) { $resolvedPath = $refreshedPath } } catch { Write-Verbose "DotForge: unreadable refreshed tool-identity guide '$refreshedPath', using shipped: $_" } } } $tryLoadGuide = { param($p) if (-not (Test-Path $p)) { return $null } try { $doc = Get-Content $p -Raw | ConvertFrom-Json $errs = $null if (Test-DFToolIdentityGuideSchema -Database $doc -Errors ([ref]$errs)) { return $doc } Write-Verbose "DotForge: tool-identity guide at '$p' failed schema validation: $($errs -join '; ')" return $null } catch { Write-Verbose "DotForge: unreadable tool-identity guide '$p': $_" return $null } } $usedRefreshed = ($resolvedPath -ne $shippedPath) $raw = & $tryLoadGuide $resolvedPath if (-not $raw -and $usedRefreshed) { $raw = & $tryLoadGuide $shippedPath } if (-not $raw -and -not $script:DFToolIdentityGuideWarned) { Write-Warning 'DotForge: tool-identity guide is unavailable — cross-catalog identity resolution falls back to Tools/*.json only.' $script:DFToolIdentityGuideWarned = $true } $idIndex = @{} if ($raw) { foreach ($prop in $raw.tools.PSObject.Properties) { $key = $prop.Name $entry = $prop.Value if (-not $entry.packages) { continue } foreach ($pkgProp in $entry.packages.PSObject.Properties) { $idIndex["$($pkgProp.Name):$($pkgProp.Value)".ToLowerInvariant()] = $key } } } $guide = [pscustomobject]@{ Raw = $raw IdIndex = $idIndex } if (-not $Path) { $script:DFToolIdentityGuide = $guide } $guide } |