functions/public/Update-KlippyComponent.ps1

function Update-KlippyComponent {
    <#
    .SYNOPSIS
        Updates Klipper components.

    .DESCRIPTION
        Updates specified components (Klipper, Moonraker, etc.) or performs
        a full system update of all components.

    .PARAMETER Id
        The unique identifier of the printer.

    .PARAMETER PrinterName
        The friendly name of the printer.

    .PARAMETER InputObject
        A printer object from pipeline input.

    .PARAMETER Component
        The component to update (e.g., "klipper", "moonraker", "mainsail").

    .PARAMETER All
        Update all components.

    .PARAMETER Force
        Skip confirmation prompt.

    .EXAMPLE
        Update-KlippyComponent -Component "klipper"
        Updates Klipper on the default printer.

    .EXAMPLE
        Update-KlippyComponent -All -PrinterName "voronv2"
        Updates all components on the specified printer.

    .EXAMPLE
        Get-KlippyUpdate | Where-Object UpdateAvailable | Update-KlippyComponent
        Updates all components that have updates available.

    .NOTES
        Updates may require service restarts and the printer may be
        temporarily unavailable during the update process.

    .OUTPUTS
        None.
    #>

    [CmdletBinding(SupportsShouldProcess, DefaultParameterSetName = 'ByComponent')]
    param(
        [Parameter(ParameterSetName = 'ById')]
        [Parameter(ParameterSetName = 'ByIdAll')]
        [ValidateNotNullOrEmpty()]
        [string]$Id,

        [Parameter(ParameterSetName = 'ByName', Position = 0)]
        [Parameter(ParameterSetName = 'ByNameAll')]
        [ValidateNotNullOrEmpty()]
        [string]$PrinterName,

        [Parameter(ParameterSetName = 'ByObject', ValueFromPipeline = $true)]
        [Parameter(ParameterSetName = 'ByObjectAll', ValueFromPipeline = $true)]
        [PSCustomObject]$InputObject,

        [Parameter(Mandatory = $true, ParameterSetName = 'ById')]
        [Parameter(Mandatory = $true, ParameterSetName = 'ByName')]
        [Parameter(ParameterSetName = 'ByObject', ValueFromPipelineByPropertyName = $true)]
        [ValidateNotNullOrEmpty()]
        [string]$Component,

        [Parameter(Mandatory = $true, ParameterSetName = 'ByIdAll')]
        [Parameter(Mandatory = $true, ParameterSetName = 'ByNameAll')]
        [Parameter(Mandatory = $true, ParameterSetName = 'ByObjectAll')]
        [switch]$All,

        [Parameter()]
        [switch]$Force
    )

    process {
        # Resolve printer
        $resolveParams = @{}
        if ($Id) { $resolveParams['Id'] = $Id }
        elseif ($PrinterName) { $resolveParams['PrinterName'] = $PrinterName }
        elseif ($InputObject) {
            # Handle pipeline from Get-KlippyUpdate
            if ($InputObject.PSTypeName -eq 'KlippyCLI.UpdateStatus') {
                $resolveParams['Id'] = $InputObject.PrinterId
                if (-not $Component) {
                    $Component = $InputObject.Component
                }
            }
            else {
                $resolveParams['InputObject'] = $InputObject
            }
        }

        $printer = Resolve-KlippyPrinterTarget @resolveParams

        try {
            if ($All) {
                $updateAction = "Update All Components"
                $endpoint = "machine/update/full"

                if ($Force -or $PSCmdlet.ShouldProcess($printer.PrinterName, $updateAction)) {
                    Write-Host "Starting full system update on '$($printer.PrinterName)'..." -ForegroundColor Yellow
                    Write-Host "This may take several minutes. The printer may restart." -ForegroundColor Yellow

                    $null = Invoke-KlippyJsonRpc -Printer $printer -Method $endpoint -Timeout 600
                    Write-Host "Full update initiated. Monitor progress with Get-KlippyUpdate." -ForegroundColor Green
                }
            }
            else {
                if (-not $Component) {
                    Write-Error "Component name is required. Use -Component or -All."
                    return
                }

                $updateAction = "Update $Component"
                $endpoint = "machine/update/client?name=$Component"

                # Check if it's a git repo type (klipper, moonraker) vs client (mainsail, fluidd)
                $updateInfo = Get-KlippyUpdate -Id $printer.Id -Component $Component
                if ($updateInfo -and $updateInfo.Branch) {
                    # Git repo update
                    $endpoint = "machine/update/$Component"
                }

                if ($Force -or $PSCmdlet.ShouldProcess($printer.PrinterName, $updateAction)) {
                    Write-Host "Updating '$Component' on '$($printer.PrinterName)'..." -ForegroundColor Yellow

                    $null = Invoke-KlippyJsonRpc -Printer $printer -Method $endpoint -Timeout 300
                    Write-Host "Update for '$Component' initiated." -ForegroundColor Green
                }
            }
        }
        catch {
            Write-Error "Failed to update on '$($printer.PrinterName)': $_"
        }
    }
}