#!/usr/bin/env pwsh <# .SYNOPSIS Streamlined metadata retrieval wrapper for Salesforce CLI .DESCRIPTION A user-friendly wrapper around 'sf project retrieve' commands that simplifies metadata retrieval from Salesforce orgs with intelligent defaults and validation. .PARAMETER mt Comma-separated list of metadata types to retrieve (e.g., "ApexClass,CustomObject") .PARAMETER mf Path to package.xml or manifest file for retrieval .PARAMETER pk Package name for package-based retrieval .PARAMETER od Output directory for retrieved metadata (default: current directory) .PARAMETER to Target org username or alias (uses default if not specified) .PARAMETER wt Wait time in minutes for the retrieve operation (default: 10) .PARAMETER ve Enable verbose output .PARAMETER hp Show this help message .EXAMPLE .\sf-retrieve.ps1 -mt "ApexClass,CustomObject" -to myorg -od retrieved .\sf-retrieve.ps1 -mf "manifest/package.xml" .\sf-retrieve.ps1 -pk "MyPackage" -to "myorg" .\sf-retrieve.ps1 -mt "Flow" -od "./retrieved" -ve .NOTES This script automatically checks for Salesforce CLI installation and runs diagnostics if the CLI is not found. #> param( [string]$mt, [string]$mf, [string]$pk, [string]$od, [string]$to, [int]$wt = 10, [switch]$ve, [switch]$hp ) # Show help if no parameters provided if (-not ($mt -or $mf -or $pk -or $hp)) { Get-Help $MyInvocation.MyCommand.Path -Detailed exit 0 } # Show help if requested if ($hp) { Get-Help $MyInvocation.MyCommand.Path -Detailed exit 0 } # Function to check if Salesforce CLI is installed function Test-SalesforceCLI { try { $null = Get-Command sf -ErrorAction Stop return $true } catch { return $false } } # Function to run sf-check diagnostics function Invoke-SalesforceCheck { $checkScript = if (Test-Path "sf-check.ps1") { ".\sf-check.ps1" } elseif (Test-Path "sf-check.sh") { "bash sf-check.sh" } else { $null } if ($checkScript) { Write-Host "Running Salesforce CLI diagnostics..." -ForegroundColor Yellow Invoke-Expression $checkScript } else { Write-Host "Salesforce CLI not found and no diagnostic script available." -ForegroundColor Red Write-Host "Please install the Salesforce CLI: https://developer.salesforce.com/tools/salesforcecli" -ForegroundColor Red } } # Silently check for Salesforce CLI if (-not (Test-SalesforceCLI)) { Invoke-SalesforceCheck exit 1 } # Validate that exactly one retrieval method is specified $methodCount = @($mt, $mf, $pk | Where-Object { $_ }).Count if ($methodCount -eq 0) { Write-Host "Error: Must specify one of: -mt, -mf, or -pk" -ForegroundColor Red Write-Host "" Write-Host "Usage examples:" -ForegroundColor Yellow Write-Host " .\sf-retrieve.ps1 -mt `"ApexClass,CustomObject`"" -ForegroundColor Gray Write-Host " .\sf-retrieve.ps1 -mf `"manifest/package.xml`"" -ForegroundColor Gray Write-Host " .\sf-retrieve.ps1 -pk `"MyPackage`"" -ForegroundColor Gray Write-Host "" Write-Host "Use -hp for detailed usage information." -ForegroundColor Yellow exit 1 } if ($methodCount -gt 1) { Write-Host "Error: Can only specify one of: -mt, -mf, or -pk" -ForegroundColor Red exit 1 } # Validate manifest file exists if specified if ($mf -and -not (Test-Path $mf)) { Write-Host "Error: Manifest file not found: $mf" -ForegroundColor Red exit 1 } # Build the sf command $sfArgs = @("project", "retrieve", "start") # Add retrieval method if ($mt) { $sfArgs += "--metadata" $sfArgs += $mt Write-Host "Retrieving metadata types: $mt" -ForegroundColor Green } elseif ($mf) { $sfArgs += "--manifest" $sfArgs += $mf Write-Host "Retrieving from manifest: $mf" -ForegroundColor Green } elseif ($pk) { $sfArgs += "--package-name" $sfArgs += $pk Write-Host "Retrieving package: $pk" -ForegroundColor Green } # Add optional parameters if ($od) { if (-not (Test-Path $od)) { Write-Host "Creating output directory: $od" -ForegroundColor Yellow New-Item -ItemType Directory -Path $od -Force | Out-Null } $sfArgs += "--output-dir" $sfArgs += $od } if ($to) { $sfArgs += "--target-org" $sfArgs += $to Write-Host "Target org: $to" -ForegroundColor Cyan } if ($wt -ne 10) { $sfArgs += "--wait" $sfArgs += $wt.ToString() } # Add verbose flag if requested if ($ve) { $sfArgs += "--verbose" } # Display the command being run Write-Host "" Write-Host "Executing: sf $($sfArgs -join ' ')" -ForegroundColor Gray Write-Host "" # Execute the command try { & sf @sfArgs $exitCode = $LASTEXITCODE if ($exitCode -eq 0) { Write-Host "" Write-Host "✅ Metadata retrieval completed successfully!" -ForegroundColor Green } else { Write-Host "" Write-Host "❌ Metadata retrieval failed with exit code: $exitCode" -ForegroundColor Red exit $exitCode } } catch { Write-Host "Error executing sf command: $($_.Exception.Message)" -ForegroundColor Red exit 1 }