- Fixed parameter conflicts in sf-data-export.ps1, sf-data-import.ps1, sf-retrieve.ps1, and sf-test-run.ps1 - Renamed conflicting \ parameter to \ to avoid conflicts with PowerShell's built-in -Verbose common parameter - Added proper parameter sets to ensure -Help parameter works correctly in all scripts - Added -hp aliases where needed for consistency across all scripts - All scripts now properly support help functionality without parameter conflicts This resolves issues where scripts would fail with 'A parameter with the name Verbose was defined multiple times' error.
330 lines
10 KiB
PowerShell
330 lines
10 KiB
PowerShell
#!/usr/bin/env pwsh
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
Data export wrapper for Salesforce CLI with SOQL query support
|
|
|
|
.DESCRIPTION
|
|
A user-friendly wrapper around 'sf data export' that simplifies data export
|
|
from Salesforce orgs with SOQL query support, multiple formats, and intelligent defaults.
|
|
|
|
.PARAMETER Query
|
|
SOQL query to export data (alias: -qy)
|
|
|
|
.PARAMETER File
|
|
File containing SOQL query (alias: -fl)
|
|
|
|
.PARAMETER SObject
|
|
Standard object query (exports common fields) (alias: -so)
|
|
|
|
.PARAMETER Output
|
|
Output file path (default: export.csv) (alias: -ot)
|
|
|
|
.PARAMETER TargetOrg
|
|
Target org username or alias (alias: -to)
|
|
|
|
.PARAMETER Format
|
|
Output format: csv, json (default: csv) (alias: -fm)
|
|
|
|
.PARAMETER Bulk
|
|
Use bulk API for large datasets (alias: -bk)
|
|
|
|
.PARAMETER Wait
|
|
Wait time in minutes (default: 10) (alias: -wt)
|
|
|
|
.PARAMETER VerboseOutput
|
|
Enable verbose output (alias: -ve)
|
|
|
|
.PARAMETER Help
|
|
Show this help message (alias: -hp)
|
|
|
|
.EXAMPLE
|
|
.\sf-data-export.ps1 -qy "SELECT Id, Name FROM Account LIMIT 100"
|
|
.\sf-data-export.ps1 -so Account -fm json -ot accounts.json
|
|
.\sf-data-export.ps1 -fl queries/contacts.soql -bk -wt 15
|
|
.\sf-data-export.ps1 -qy "SELECT Id FROM User" -to production
|
|
|
|
.NOTES
|
|
This script automatically checks for Salesforce CLI installation and runs
|
|
diagnostics if the CLI is not found.
|
|
#>
|
|
|
|
param(
|
|
[Parameter(ParameterSetName="Query")]
|
|
[Parameter(ParameterSetName="Help")]
|
|
[Alias("qy")]
|
|
[string]$Query,
|
|
|
|
[Parameter(ParameterSetName="File")]
|
|
[Parameter(ParameterSetName="Help")]
|
|
[Alias("fl")]
|
|
[string]$File,
|
|
|
|
[Parameter(ParameterSetName="SObject")]
|
|
[Parameter(ParameterSetName="Help")]
|
|
[Alias("so")]
|
|
[string]$SObject,
|
|
|
|
[Parameter(ParameterSetName="Query")]
|
|
[Parameter(ParameterSetName="File")]
|
|
[Parameter(ParameterSetName="SObject")]
|
|
[Parameter(ParameterSetName="Help")]
|
|
[Alias("ot")]
|
|
[string]$Output = "export.csv",
|
|
|
|
[Parameter(ParameterSetName="Query")]
|
|
[Parameter(ParameterSetName="File")]
|
|
[Parameter(ParameterSetName="SObject")]
|
|
[Parameter(ParameterSetName="Help")]
|
|
[Alias("to")]
|
|
[string]$TargetOrg,
|
|
|
|
[Parameter(ParameterSetName="Query")]
|
|
[Parameter(ParameterSetName="File")]
|
|
[Parameter(ParameterSetName="SObject")]
|
|
[Parameter(ParameterSetName="Help")]
|
|
[ValidateSet("csv", "json")]
|
|
[Alias("fm")]
|
|
[string]$Format = "csv",
|
|
|
|
[Parameter(ParameterSetName="Query")]
|
|
[Parameter(ParameterSetName="File")]
|
|
[Parameter(ParameterSetName="SObject")]
|
|
[Parameter(ParameterSetName="Help")]
|
|
[Alias("bk")]
|
|
[switch]$Bulk,
|
|
|
|
[Parameter(ParameterSetName="Query")]
|
|
[Parameter(ParameterSetName="File")]
|
|
[Parameter(ParameterSetName="SObject")]
|
|
[Parameter(ParameterSetName="Help")]
|
|
[Alias("wt")]
|
|
[int]$Wait = 10,
|
|
|
|
[Parameter(ParameterSetName="Query")]
|
|
[Parameter(ParameterSetName="File")]
|
|
[Parameter(ParameterSetName="SObject")]
|
|
[Parameter(ParameterSetName="Help")]
|
|
[Alias("ve")]
|
|
[switch]$VerboseOutput,
|
|
|
|
[Parameter(ParameterSetName="Help", Mandatory=$true)]
|
|
[Alias("hp")]
|
|
[switch]$Help
|
|
)
|
|
|
|
# Show help if requested
|
|
if ($Help) {
|
|
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
|
|
}
|
|
}
|
|
|
|
# Function to build standard object query
|
|
function New-SObjectQuery {
|
|
param([string]$SObjectType)
|
|
|
|
switch ($SObjectType) {
|
|
"Account" {
|
|
return "SELECT Id, Name, Type, Industry, Phone, Website, BillingCity, BillingState, BillingCountry FROM Account"
|
|
}
|
|
"Contact" {
|
|
return "SELECT Id, FirstName, LastName, Email, Phone, AccountId, Account.Name FROM Contact"
|
|
}
|
|
"Lead" {
|
|
return "SELECT Id, FirstName, LastName, Email, Phone, Company, Status, Source FROM Lead"
|
|
}
|
|
"Opportunity" {
|
|
return "SELECT Id, Name, AccountId, Account.Name, Amount, CloseDate, StageName, Probability FROM Opportunity"
|
|
}
|
|
"Case" {
|
|
return "SELECT Id, CaseNumber, Subject, Status, Priority, Origin, AccountId, Account.Name, ContactId, Contact.Name FROM Case"
|
|
}
|
|
"User" {
|
|
return "SELECT Id, Name, Email, Username, Profile.Name, IsActive, LastLoginDate FROM User"
|
|
}
|
|
default {
|
|
return "SELECT Id, Name FROM $SObjectType"
|
|
}
|
|
}
|
|
}
|
|
|
|
# Function to validate SOQL query
|
|
function Test-SOQLQuery {
|
|
param([string]$QueryText)
|
|
|
|
if ($QueryText -notmatch '^\s*SELECT\s+') {
|
|
Write-Host "Error: Query must start with SELECT" -ForegroundColor Red
|
|
return $false
|
|
}
|
|
|
|
return $true
|
|
}
|
|
|
|
# Silently check for Salesforce CLI
|
|
if (-not (Test-SalesforceCLI)) {
|
|
Invoke-SalesforceCheck
|
|
exit 1
|
|
}
|
|
|
|
# Validate that exactly one query method is specified
|
|
$queryMethods = @($Query, $File, $SObject | Where-Object { $_ }).Count
|
|
if ($queryMethods -eq 0) {
|
|
Write-Host "Error: Must specify one of: -Query, -File, or -SObject" -ForegroundColor Red
|
|
Write-Host ""
|
|
Write-Host "Usage examples:" -ForegroundColor Yellow
|
|
Write-Host " .\sf-data-export.ps1 -Query `"SELECT Id, Name FROM Account`"" -ForegroundColor Gray
|
|
Write-Host " .\sf-data-export.ps1 -File queries/accounts.soql" -ForegroundColor Gray
|
|
Write-Host " .\sf-data-export.ps1 -SObject Account" -ForegroundColor Gray
|
|
Write-Host ""
|
|
Write-Host "Use -Help for detailed usage information." -ForegroundColor Yellow
|
|
exit 1
|
|
}
|
|
|
|
if ($queryMethods -gt 1) {
|
|
Write-Host "Error: Can only specify one of: -Query, -File, or -SObject" -ForegroundColor Red
|
|
exit 1
|
|
}
|
|
|
|
# Determine the final query
|
|
$finalQuery = ""
|
|
if ($Query) {
|
|
$finalQuery = $Query
|
|
Write-Host "Using inline query" -ForegroundColor Green
|
|
} elseif ($File) {
|
|
if (-not (Test-Path $File)) {
|
|
Write-Host "Error: Query file not found: $File" -ForegroundColor Red
|
|
exit 1
|
|
}
|
|
$finalQuery = Get-Content $File -Raw
|
|
Write-Host "Using query from file: $File" -ForegroundColor Green
|
|
} elseif ($SObject) {
|
|
$finalQuery = New-SObjectQuery $SObject
|
|
Write-Host "Using standard query for $SObject" -ForegroundColor Green
|
|
}
|
|
|
|
# Validate the query
|
|
if (-not (Test-SOQLQuery $finalQuery)) {
|
|
exit 1
|
|
}
|
|
|
|
# Build the sf command based on bulk vs regular query
|
|
if ($Bulk) {
|
|
# Use Bulk API 2.0 for large datasets
|
|
$sfArgs = @("data", "export", "bulk", "--query", $finalQuery, "--output-file", $Output, "--result-format", $Format)
|
|
|
|
if ($Wait -ne 10) {
|
|
$sfArgs += "--wait"
|
|
$sfArgs += $Wait.ToString()
|
|
}
|
|
|
|
Write-Host "Using Bulk API 2.0" -ForegroundColor Yellow
|
|
} else {
|
|
# Use regular data query for smaller datasets
|
|
$sfArgs = @("data", "query", "--query", $finalQuery, "--output-file", $Output, "--result-format", $Format)
|
|
}
|
|
|
|
# Add optional parameters
|
|
if ($TargetOrg) {
|
|
$sfArgs += "--target-org"
|
|
$sfArgs += $TargetOrg
|
|
Write-Host "Target org: $TargetOrg" -ForegroundColor Cyan
|
|
}
|
|
|
|
Write-Host "Output format: $Format" -ForegroundColor Cyan
|
|
Write-Host "Output file: $Output" -ForegroundColor Cyan
|
|
|
|
# Add verbose flag if requested
|
|
if ($VerboseOutput) {
|
|
$sfArgs += "--verbose"
|
|
}
|
|
|
|
# Display export information
|
|
Write-Host ""
|
|
Write-Host "📊 Starting Data Export" -ForegroundColor Blue
|
|
Write-Host "=======================" -ForegroundColor Blue
|
|
|
|
# Show query preview if verbose
|
|
if ($VerboseOutput) {
|
|
Write-Host ""
|
|
Write-Host "📝 SOQL Query:" -ForegroundColor Yellow
|
|
Write-Host "----------------------------------------" -ForegroundColor Gray
|
|
Write-Host $finalQuery -ForegroundColor Gray
|
|
Write-Host "----------------------------------------" -ForegroundColor Gray
|
|
}
|
|
|
|
# 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
|
|
|
|
Write-Host ""
|
|
if ($exitCode -eq 0) {
|
|
Write-Host "✅ Data export completed successfully!" -ForegroundColor Green
|
|
|
|
# Show file information if it exists
|
|
if (Test-Path $Output) {
|
|
$fileInfo = Get-Item $Output
|
|
$fileSize = if ($fileInfo.Length -gt 1MB) {
|
|
"{0:N1} MB" -f ($fileInfo.Length / 1MB)
|
|
} elseif ($fileInfo.Length -gt 1KB) {
|
|
"{0:N1} KB" -f ($fileInfo.Length / 1KB)
|
|
} else {
|
|
"$($fileInfo.Length) bytes"
|
|
}
|
|
|
|
if ($Format -eq "csv") {
|
|
# Count records (excluding header)
|
|
$recordCount = (Get-Content $Output).Count - 1
|
|
Write-Host "📁 Exported $recordCount records to $Output ($fileSize)" -ForegroundColor Cyan
|
|
} else {
|
|
Write-Host "📁 Data exported to $Output ($fileSize)" -ForegroundColor Cyan
|
|
}
|
|
}
|
|
|
|
if ($VerboseOutput) {
|
|
Write-Host "💡 Use a spreadsheet application or text editor to view the exported data" -ForegroundColor Yellow
|
|
}
|
|
} else {
|
|
Write-Host "❌ Data export failed with exit code: $exitCode" -ForegroundColor Red
|
|
Write-Host "💡 Check query syntax and permissions" -ForegroundColor Yellow
|
|
exit $exitCode
|
|
}
|
|
} catch {
|
|
Write-Host "Error executing sf command: $($_.Exception.Message)" -ForegroundColor Red
|
|
exit 1
|
|
}
|