AnyGet.psm1
|
# AnyGet - Universal Package Manager # Define supported sources $script:SupportedSources = @{ 'winget' = @{ 'Name' = 'Windows Package Manager' 'Command' = 'winget' 'InstallCommand' = 'winget install {0} --accept-package-agreements --accept-source-agreements' 'UninstallCommand' = 'winget uninstall {0}' 'Platforms' = @('Windows') 'TestCommand' = 'winget --version' } 'scoop' = @{ 'Name' = 'Scoop' 'Command' = 'scoop' 'InstallCommand' = 'scoop install {0}' 'UninstallCommand' = 'scoop uninstall {0}' 'Platforms' = @('Windows', 'Linux', 'macOS') 'TestCommand' = 'scoop --version' } 'choco' = @{ 'Name' = 'Chocolatey' 'Command' = 'choco' 'InstallCommand' = 'choco install {0} -y' 'UninstallCommand' = 'choco uninstall {0} -y' 'Platforms' = @('Windows') 'TestCommand' = 'choco --version' } 'npm' = @{ 'Name' = 'Node Package Manager' 'Command' = 'npm' 'InstallCommand' = 'npm install -g {0}' 'UninstallCommand' = 'npm uninstall -g {0}' 'Platforms' = @('Windows', 'Linux', 'macOS') 'TestCommand' = 'npm --version' } } # Helper function to get current platform function Get-CurrentPlatform { if ($IsWindows -or $PSVersionTable.PSVersion.Major -lt 6) { return 'Windows' } elseif ($IsLinux) { return 'Linux' } elseif ($IsMacOS) { return 'macOS' } else { return 'Unknown' } } # Helper function to test if a source is available function Test-SourceAvailability { param([string]$Source) if (-not $script:SupportedSources.ContainsKey($Source)) { return $false } $sourceInfo = $script:SupportedSources[$Source] $currentPlatform = Get-CurrentPlatform if ($currentPlatform -notin $sourceInfo.Platforms) { return $false } try { $testCommand = $sourceInfo.TestCommand $null = Invoke-Expression $testCommand 2>$null return $LASTEXITCODE -eq 0 } catch { return $false } } # AnyGet-Sources function function AnyGet-Sources { <# .SYNOPSIS Get information about available package manager sources. .DESCRIPTION This function returns information about all supported package managers and their availability on the current system. .PARAMETER AvailableOnly Show only sources that are currently available on the system. .EXAMPLE Get-AnyGetSources Shows all supported package managers and their availability. .EXAMPLE Get-AnyGetSources -AvailableOnly Shows only package managers that are currently available. #> [CmdletBinding()] param( [Parameter(Mandatory = $false)] [switch]$AvailableOnly ) $currentPlatform = Get-CurrentPlatform $results = @() foreach ($source in $script:SupportedSources.Keys) { $sourceInfo = $script:SupportedSources[$source] $isAvailable = Test-SourceAvailability -Source $source $supportsCurrentPlatform = $currentPlatform -in $sourceInfo.Platforms if ($AvailableOnly -and -not $isAvailable) { continue } $result = [PSCustomObject]@{ Source = $source Name = $sourceInfo.Name Command = $sourceInfo.Command Available = $isAvailable Platforms = $sourceInfo.Platforms -join ', ' Status = if ($isAvailable) { 'Available' } elseif ($supportsCurrentPlatform) { 'Not Installed' } else { 'Not Supported' } } $results += $result } if ($results.Count -gt 0) { Write-Host "`nPackage Manager Sources:" -ForegroundColor Cyan Write-Host "=" * 50 -ForegroundColor Cyan $results | Format-Table -AutoSize -Property @( @{Name = 'Source'; Expression = { $_.Source }; Width = 10 }, @{Name = 'Name'; Expression = { $_.Name }; Width = 20 }, @{Name = 'Status'; Expression = { $_.Status }; Width = 15 }, @{Name = 'Platforms'; Expression = { $_.Platforms }; Width = 20 } ) Write-Host "`nCurrent Platform: $currentPlatform" -ForegroundColor Yellow Write-Host "Available Sources: $($results | Where-Object { $_.Available } | Measure-Object).Count" -ForegroundColor Green } else { Write-Warning "No package manager sources found matching the specified criteria." } return $results } # AnyGet-Install function function AnyGet-Install { <# .SYNOPSIS Install a package using any available package manager. .DESCRIPTION This function searches for and installs a package using the first available package manager that finds the package. .PARAMETER Name The name of the package to install. .PARAMETER Source The specific package manager to use. If not specified, will try all available sources. .PARAMETER Force Force installation without prompts. .EXAMPLE Install-AnyGet -Name "git" Installs git using the first available package manager. .EXAMPLE Install-AnyGet -Name "nodejs" -Source "winget" Installs nodejs specifically using winget. #> [CmdletBinding(SupportsShouldProcess)] param( [Parameter(Mandatory = $true, Position = 0)] [string]$Name, [Parameter(Mandatory = $false)] [ValidateSet('any', 'winget', 'scoop', 'choco', 'npm')] [string]$Source = 'any', [Parameter(Mandatory = $false)] [switch]$Force ) Write-Verbose "Installing package '$Name' using source '$Source'" # Get available sources $availableSources = @() foreach ($source in $script:SupportedSources.Keys) { if (Test-SourceAvailability -Source $source) { $availableSources += $source } } if ($availableSources.Count -eq 0) { Write-Error "No supported package managers are available on this system." return } # Determine which sources to try $sourcesToTry = @() if ($Source -eq 'any') { $sourcesToTry = $availableSources } else { if ($availableSources -contains $Source) { $sourcesToTry = @($Source) } else { Write-Error "Package manager '$Source' is not available on this system." return } } # Try each source until we find and install the package foreach ($sourceName in $sourcesToTry) { Write-Verbose "Trying to install '$Name' using $sourceName" $sourceInfo = $script:SupportedSources[$sourceName] $installCommand = $sourceInfo.InstallCommand -f $Name if ($Force) { switch ($sourceName) { 'winget' { $installCommand += ' --force' } 'choco' { $installCommand = $installCommand -replace ' -y', ' -y --force' } } } if ($PSCmdlet.ShouldProcess($Name, "Install using $sourceName")) { try { Write-Host "Installing '$Name' using $sourceName..." -ForegroundColor Green $result = Invoke-Expression $installCommand if ($LASTEXITCODE -eq 0) { Write-Host "Successfully installed '$Name' using $sourceName" -ForegroundColor Green return } else { Write-Warning "Failed to install '$Name' using $sourceName (Exit code: $LASTEXITCODE)" } } catch { Write-Warning "Error installing '$Name' using $sourceName`: $($_.Message)" } } } Write-Error "Failed to install '$Name' using any available package manager." } # AnyGet-Uninstall function function AnyGet-Uninstall { <# .SYNOPSIS Uninstall a package using any available package manager. .DESCRIPTION This function searches for and uninstalls a package using the first available package manager that finds the package. .PARAMETER Name The name of the package to uninstall. .PARAMETER Source The specific package manager to use. If not specified, will try all available sources. .PARAMETER Force Force uninstallation without prompts. .EXAMPLE Uninstall-AnyGet -Name "git" Uninstalls git using the first available package manager. .EXAMPLE Uninstall-AnyGet -Name "nodejs" -Source "winget" Uninstalls nodejs specifically using winget. #> [CmdletBinding(SupportsShouldProcess)] param( [Parameter(Mandatory = $true, Position = 0)] [string]$Name, [Parameter(Mandatory = $false)] [ValidateSet('any', 'winget', 'scoop', 'choco', 'npm')] [string]$Source = 'any', [Parameter(Mandatory = $false)] [switch]$Force ) Write-Verbose "Uninstalling package '$Name' using source '$Source'" # Get available sources $availableSources = @() foreach ($source in $script:SupportedSources.Keys) { if (Test-SourceAvailability -Source $source) { $availableSources += $source } } if ($availableSources.Count -eq 0) { Write-Error "No supported package managers are available on this system." return } # Determine which sources to try $sourcesToTry = @() if ($Source -eq 'any') { $sourcesToTry = $availableSources } else { if ($availableSources -contains $Source) { $sourcesToTry = @($Source) } else { Write-Error "Package manager '$Source' is not available on this system." return } } # Try each source until we find and uninstall the package foreach ($sourceName in $sourcesToTry) { Write-Verbose "Trying to uninstall '$Name' using $sourceName" $sourceInfo = $script:SupportedSources[$sourceName] $uninstallCommand = $sourceInfo.UninstallCommand -f $Name if ($Force) { switch ($sourceName) { 'winget' { $uninstallCommand += ' --force' } 'choco' { $uninstallCommand = $uninstallCommand -replace ' -y', ' -y --force' } } } if ($PSCmdlet.ShouldProcess($Name, "Uninstall using $sourceName")) { try { Write-Host "Uninstalling '$Name' using $sourceName..." -ForegroundColor Yellow $result = Invoke-Expression $uninstallCommand if ($LASTEXITCODE -eq 0) { Write-Host "Successfully uninstalled '$Name' using $sourceName" -ForegroundColor Green return } else { Write-Warning "Failed to uninstall '$Name' using $sourceName (Exit code: $LASTEXITCODE)" } } catch { Write-Warning "Error uninstalling '$Name' using $sourceName`: $($_.Message)" } } } Write-Error "Failed to uninstall '$Name' using any available package manager." } # Main anyget function that handles subcommands function anyget { <# .SYNOPSIS Universal package manager command-line interface. .DESCRIPTION Main command for AnyGet that handles subcommands like install, uninstall, and sources. .PARAMETER Command The subcommand to execute (install, uninstall, sources). .PARAMETER Name The name of the package (for install/uninstall commands). .PARAMETER Source The specific package manager to use. .PARAMETER Force Force operation without prompts. .EXAMPLE anyget install git Installs git using any available package manager. .EXAMPLE anyget uninstall nodejs -Source winget Uninstalls nodejs specifically using winget. .EXAMPLE anyget sources Shows available package managers. #> [CmdletBinding()] param( [Parameter(Mandatory = $true, Position = 0)] [ValidateSet('install', 'uninstall', 'sources')] [string]$Command, [Parameter(Mandatory = $false, Position = 1)] [string]$Name, [Parameter(Mandatory = $false)] [ValidateSet('any', 'winget', 'scoop', 'choco', 'npm')] [string]$Source = 'any', [Parameter(Mandatory = $false)] [switch]$Force ) switch ($Command) { 'install' { if (-not $Name) { Write-Error "Package name is required for install command. Usage: anyget install <package-name>" return } AnyGet-Install -Name $Name -Source $Source -Force:$Force } 'uninstall' { if (-not $Name) { Write-Error "Package name is required for uninstall command. Usage: anyget uninstall <package-name>" return } AnyGet-Uninstall -Name $Name -Source $Source -Force:$Force } 'sources' { AnyGet-Sources -AvailableOnly } } } # No aliases needed - use the main anyget function # Export functions and aliases Export-ModuleMember -Function @( 'anyget', 'AnyGet-Sources', 'AnyGet-Install', 'AnyGet-Uninstall' ) # No aliases to export |