satellite.psm1
|
# Satellite module for Delta-Code # Manages satellite discovery, registration, validation, and command execution # Resolve module dependencies from the sibling directory when available (repository # and flat-install layouts) and fall back to module-name resolution (PSGallery). foreach ($dependencyName in @('delta-code')) { $dependencyManifest = Join-Path $PSScriptRoot "$dependencyName.psd1" if (Test-Path -LiteralPath $dependencyManifest) { Import-Module $dependencyManifest -ErrorAction Stop -DisableNameChecking } else { Import-Module $dependencyName -ErrorAction Stop -DisableNameChecking } } Remove-Variable dependencyName, dependencyManifest -ErrorAction SilentlyContinue # Satellite registry - stores discovered/registered satellites $script:SatelliteRegistry = @{} $script:SatellitePaths = @() function Get-DeltaCodeSatellite { [CmdletBinding()] param( [Parameter(Mandatory = $true, Position = 0)] [string]$Name ) if ($script:SatelliteRegistry.ContainsKey($Name)) { return $script:SatelliteRegistry[$Name] } Write-Error "Satellite '$Name' not found in registry" return $null } function Get-DeltaCodeSatellites { [CmdletBinding()] param( [string[]]$Filter ) $sats = $script:SatelliteRegistry.Values if ($Filter) { $sats = $sats | Where-Object { $Filter -contains $_.Category } } return $sats } function Register-DeltaCodeSatellite { [CmdletBinding()] param( [Parameter(Mandatory = $true, Position = 0)] [string]$Name, [Parameter(Mandatory = $true, Position = 1)] [string]$Path, [Parameter(Mandatory = $false)] [string]$Category = 'General', [Parameter(Mandatory = $false)] [string]$Description = '', [Parameter(Mandatory = $false)] [hashtable]$Metadata = @{} ) $normalizedPath = (Resolve-Path -LiteralPath $Path).ProviderPath if (-not (Test-Path $normalizedPath)) { Write-Error "Satellite path does not exist: $normalizedPath" return $false } $satellite = [PSCustomObject]@{ Name = $Name Path = $normalizedPath Category = $Category Description = $Description Metadata = $Metadata Registered = (Get-Date -Format 'yyyy-MM-dd HH:mm:ss') Module = $null } $script:SatelliteRegistry[$Name] = $satellite if ($script:SatellitePaths -notcontains $normalizedPath) { $script:SatellitePaths += $normalizedPath } Write-Verbose "Registered satellite '$Name' at $normalizedPath" return $true } function Test-DeltaCodeSatellite { [CmdletBinding()] param( [Parameter(Mandatory = $true, Position = 0)] [string]$Name ) $sat = Get-DeltaCodeSatellite -Name $Name if (-not $sat) { return $false } $modulePath = Join-Path $sat.Path "$Name.psm1" $manifestPath = Join-Path $sat.Path "$Name.psd1" $valid = $true $issues = @() if (-not (Test-Path $modulePath)) { $issues += "Missing module file: $modulePath" $valid = $false } if (-not (Test-Path $manifestPath)) { $issues += "Missing manifest file: $manifestPath" $valid = $false } if ($valid) { try { Import-Module $modulePath -PassThru | Out-Null $sat.Module = $modulePath $script:SatelliteRegistry[$Name] = $sat } catch { $issues += "Module import failed: $($_.Exception.Message)" $valid = $false } } if (-not $valid) { Write-Warning "Satellite '$Name' validation failed: $($issues -join '; ')" } else { Write-Verbose "Satellite '$Name' validated successfully" } return $valid } function Invoke-DeltaCodeSatellite { [CmdletBinding()] param( [Parameter(Mandatory = $true, Position = 0)] [string]$Name, [Parameter(Mandatory = $true, Position = 1)] [string]$Command, [Parameter(ValueFromRemainingArguments = $true)] [string[]]$Args ) $sat = Get-DeltaCodeSatellite -Name $Name if (-not $sat) { Write-Error "Satellite '$Name' not found" return $null } if (-not $sat.Module) { Test-DeltaCodeSatellite -Name $Name if (-not $sat.Module) { Write-Error "Satellite '$Name' is not loaded/valid" return $null } } $funcName = "Invoke-$Name$Command" if (-not (Get-Command $funcName -ErrorAction SilentlyContinue)) { Write-Error "Satellite '$Name' does not implement command '$Command' (expected function $funcName)" return $null } try { & $funcName @Args } catch { Write-Error "Satellite '$Name' command '$Command' failed: $($_.Exception.Message)" return $null } } function Initialize-DeltaCodeSatellites { [CmdletBinding()] param( [string[]]$SearchPaths ) if (-not $SearchPaths) { $SearchPaths = @( "$PSScriptRoot\satellites", "$PSScriptRoot\..\satellites", (Join-Path $env:USERPROFILE ".delta-code\satellites") ) } foreach ($basePath in $SearchPaths) { if (Test-Path $basePath) { $dirs = Get-ChildItem -Path $basePath -Directory foreach ($dir in $dirs) { $satName = $dir.Name $satPath = $dir.FullName $manifest = Join-Path $satPath "$satName.psd1" if (Test-Path $manifest) { Register-DeltaCodeSatellite -Name $satName -Path $satPath } } } } # Auto-validate all registered $names = @($script:SatelliteRegistry.Keys) foreach ($name in $names) { Test-DeltaCodeSatellite -Name $name } } function Unregister-DeltaCodeSatellite { [CmdletBinding()] param( [Parameter(Mandatory = $true, Position = 0)] [string]$Name ) if ($script:SatelliteRegistry.ContainsKey($Name)) { $script:SatelliteRegistry.Remove($Name) Write-Verbose "Unregistered satellite '$Name'" return $true } return $false } function Reset-DeltaCodeSatelliteRegistry { [CmdletBinding()] param() $script:SatelliteRegistry = @{} $script:SatellitePaths = @() Write-Verbose "Satellite registry reset" } Export-ModuleMember -Function @( 'Get-DeltaCodeSatellite' 'Get-DeltaCodeSatellites' 'Register-DeltaCodeSatellite' 'Test-DeltaCodeSatellite' 'Invoke-DeltaCodeSatellite' 'Initialize-DeltaCodeSatellites' 'Unregister-DeltaCodeSatellite' 'Reset-DeltaCodeSatelliteRegistry' ) |