src/public/System/Find-AitherScriptFile.ps1
|
#Requires -Version 7.0 <# .SYNOPSIS Find automation script file by ID .DESCRIPTION Searches for automation script files by script ID (number or name pattern). This is a private helper function to eliminate duplication between Get-AitherScript and Invoke-AitherScript. .PARAMETER ScriptId Script identifier - can be a number (e.g., '0501') or script name pattern .PARAMETER ScriptsPath Path to the automation-scripts directory .PARAMETER ThrowOnNotFound Throw an error if script is not found (default: return $null) .NOTES This is a private helper function. #> function Find-AitherScriptFile { [CmdletBinding()] param( [Parameter(Mandatory = $false)] [AllowEmptyString()] [string]$ScriptId, [Parameter(Mandatory)] [string]$ScriptsPath, [switch]$ThrowOnNotFound ) if ([string]::IsNullOrWhiteSpace($ScriptId)) { if ($ThrowOnNotFound) { throw "Script ID cannot be empty" } return $null } # Normalize path separators $ScriptId = $ScriptId -replace '\\', '/' # 1. Handle subdirectory/script format (e.g., "00-bootstrap/0001_Validate-Prerequisites") if ($ScriptId -match '/') { $parts = $ScriptId -split '/' $subDir = $parts[0..($parts.Length - 2)] -join '/' $scriptName = $parts[-1] $subDirPath = Join-Path $ScriptsPath $subDir Write-Verbose "Looking for script '$scriptName' in subdirectory '$subDirPath'" if (Test-Path $subDirPath) { # Try exact match with .ps1 extension $exactPath = Join-Path $subDirPath "$scriptName.ps1" if (Test-Path $exactPath) { Write-Verbose "Found exact match: $exactPath" return Get-Item $exactPath } # Try pattern match in subdirectory $pattern = "*${scriptName}*.ps1" $found = Get-ChildItem -Path $subDirPath -Filter $pattern -ErrorAction SilentlyContinue | Where-Object { $_.DirectoryName -notmatch '_archive' } | Select-Object -First 1 if ($found) { Write-Verbose "Found pattern match: $($found.FullName)" return $found } } } # 2. Try exact filename match in ScriptsPath $exactPath = Join-Path $ScriptsPath $ScriptId Write-Verbose "Checking exact path: $exactPath" if (Test-Path $exactPath) { Write-Verbose "Found exact match: $exactPath" return Get-Item $exactPath } # 3. Try exact number match first (Strict Convention: 0000_Name.ps1) if ($ScriptId -match '^\d{4}$') { $strictPattern = "${ScriptId}_*.ps1" Write-Verbose "Trying strict pattern: $strictPattern" # Search recursively but exclude _archive $found = Get-ChildItem -Path $ScriptsPath -Filter $strictPattern -Recurse -ErrorAction SilentlyContinue | Where-Object { $_.DirectoryName -notmatch '_archive' } | Select-Object -First 1 if ($found) { Write-Verbose "Found strict match: $($found.FullName)" return $found } } # 4. Try relaxed pattern match - search recursively $pattern = if ($ScriptId -match '\.ps1$') { # If it ends in .ps1, assume it's a filename or partial filename "*$ScriptId" } else { "*${ScriptId}*.ps1" } # Search recursively, excluding _archive $found = Get-ChildItem -Path $ScriptsPath -Filter $pattern -Recurse -ErrorAction SilentlyContinue | Where-Object { $_.DirectoryName -notmatch '_archive' } | Select-Object -First 1 # Fallback: Try listing all and filtering in memory (slower but more robust) if (-not $found) { Write-Verbose "Pattern match failed, trying memory filter recursively..." $found = Get-ChildItem -Path $ScriptsPath -File -Recurse -ErrorAction SilentlyContinue | Where-Object { $_.DirectoryName -notmatch '_archive' -and $_.Name -like $pattern } | Select-Object -First 1 } # 5. Check Current Working Directory (PWD) explicitly if (-not $found) { Write-Verbose "Not found in ScriptsPath. Checking PWD: $PWD" # Try exact path in PWD $pwdExact = Join-Path $PWD $ScriptId if (Test-Path $pwdExact) { return Get-Item $pwdExact } # Try pattern in PWD $found = Get-ChildItem -Path $PWD -Filter $pattern -ErrorAction SilentlyContinue | Select-Object -First 1 if ($found) { Write-Verbose "Found in PWD: $($found.FullName)" return $found } } Write-Verbose "Find-AitherScriptFile: Searching for '$ScriptId' in '$ScriptsPath'" Write-Verbose "Pattern: $pattern" if ($found) { Write-Verbose "Found: $($found.FullName)" return $found } else { Write-Verbose "Not found." } if ($ThrowOnNotFound) { # Get a list of all scripts recursively, excluding _archive $allScripts = Get-ChildItem -Path $ScriptsPath -Filter "*.ps1" -Recurse -ErrorAction SilentlyContinue | Where-Object { $_.DirectoryName -notmatch '_archive' } | Select-Object -ExpandProperty Name $similar = $allScripts | Where-Object { $_ -like "*$ScriptId*" } $msg = "Script not found: '$ScriptId'. Searched in '$ScriptsPath' with pattern '$pattern'." if ($similar) { $msg += " Did you mean: $($similar -join ', ')?" } else { # List the first few scripts to prove we are looking in the right place $firstFew = $allScripts | Select-Object -First 10 $msg += " Directory contains $($allScripts.Count) scripts. First few: $($firstFew -join ', ')" } throw $msg } return $null } |