private/Private.ps1
#Private Variables $script:BaseURI = "https://api.meraki.com/api/v1" #Private function function Read-Config () { $ConfigPath = "$home/.meraki/config.json" $config = Get-Content -Raw -Path $ConfigPath | ConvertFrom-Json if ($config.APIKey -eq "Secure") { $Secret = Get-Secret -Name "MerakiAPI" -AsPlainText | ConvertFrom-Json $config.APIKey = $Secret.APIKey } return $config } function ConvertTo-UTime () { Param( [datetime]$DateTime ) $uTime = ([System.DateTimeOffset]$DateTime).ToUnixTimeMilliseconds() / 1000 return $Utime } function ConvertFrom-UTime() { Param( [decimal]$Utime ) [DateTime]$DateTime = [System.DateTimeOffset]::FromUnixTimeMilliseconds(1000 * $Utime).LocalDateTime return $DateTime } function Get-Headers() { $config = Read-Config $Headers = @{ "Authorization" = "Bearer $($config.APIKey)" "Accept" = 'application/json' "Content-Type" = 'application/json' } return $Headers } function Format-ApiError { param( [Parameter(Mandatory = $true)] [string]$ErrorResponse ) # First, try to determine if this is JSON $isJson = $false $errorObject = $null try { $errorObject = $ErrorResponse | ConvertFrom-Json $isJson = $true } catch { # Not valid JSON, treat as plain text $isJson = $false } if ($isJson) { # Handle various JSON error formats $formattedErrors = @() # Format 1: { "errors": ["message1", "message2"] } if ($errorObject.errors -and $errorObject.errors.Count -gt 0) { foreach ($errorMessage in $errorObject.errors) { $formattedErrors += Format-ErrorMessage -Message $errorMessage } } # Format 2: { "error": "single message" } elseif ($errorObject.error) { $formattedErrors += Format-ErrorMessage -Message $errorObject.error } # Format 3: { "message": "error message" } elseif ($errorObject.message) { $formattedErrors += Format-ErrorMessage -Message $errorObject.message } # Format 4: { "detail": "error detail" } elseif ($errorObject.detail) { $formattedErrors += Format-ErrorMessage -Message $errorObject.detail } # Format 5: Direct object with error properties elseif ($errorObject.PSObject.Properties.Name -contains 'status' -or $errorObject.PSObject.Properties.Name -contains 'code') { $errorParts = @() if ($errorObject.status) { $errorParts += "Status: $($errorObject.status)" } if ($errorObject.code) { $errorParts += "Code: $($errorObject.code)" } if ($errorObject.message) { $errorParts += $errorObject.message } $formattedErrors += ($errorParts -join " - ") } else { # Fallback: convert entire object to readable format $formattedErrors += Format-ErrorMessage -Message ($errorObject | ConvertTo-Json -Compress) } return $formattedErrors } else { # Plain text error message return @(Format-ErrorMessage -Message $ErrorResponse) } } function Format-ErrorMessage { param([string]$Message) # Clean up unicode escape sequences $cleanMessage = $Message -replace '\\u0022', '"' $cleanMessage = $cleanMessage -replace '\\u0027', "'" $cleanMessage = $cleanMessage -replace '\\n', "`n" $cleanMessage = $cleanMessage -replace '\\t', "`t" # Add some structure for field validation errors if ($cleanMessage -match 'network\[.*?\]' -or $cleanMessage -match '\w+\[\w+\]\[\d+\]\[\w+\]') { $cleanMessage = $cleanMessage -replace '([\w\[\]]+)(\s+[A-Z])', "`n Field: `$1`n Error: `$2" } return $cleanMessage.Trim() } function Write-ApiError () { [CmdletBinding()] Param ( [Parameter( Mandatory = $true, ParameterSetName = 'exception', ValueFromPipelineByPropertyName )] [System.Exception]$Exception, [Parameter( Mandatory = $false, ParameterSetName = 'exception', ValueFromPipelineByPropertyName )] [System.Management.Automation.ErrorDetails]$ErrorDetails, [Parameter( Mandatory = $true, ParameterSetName = 'message' )] [string]$Message ) If ($Exception) { $errorMessage = $Exception.Message } else { $errorMessage = $Message } if ($ErrorDetails) { $detailsMessage = $ErrorDetails.Message $formattedDetailsMessage = Format-ApiError -ErrorResponse $detailsMessage } $formattedMessage = Format-ApiError -ErrorResponse $errorMessage if ($env:MerakiAPI -eq 'dev') { Write-error -Message $formattedMessage throw $_ } else { Write-Host "API Error:" -ForegroundColor Red If ($formattedDetailsMessage) { Write-Host $formattedDetailsMessage -ForegroundColor Yellow } $formattedMessage | ForEach-Object { Write-Host $_ -ForegroundColor Yellow } exit } } |