functions/public/Get-KlippyGcodeItem.ps1

function Get-KlippyGcodeItem {
    <#
    .SYNOPSIS
        Gets files and folders from a Klipper printer's gcodes directory.

    .DESCRIPTION
        Lists both files and directories from the printer's gcodes storage.
        Similar to Get-ChildItem, returns both types of items.
        Supports wildcard filtering and recursive listing.

    .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 Path
        Path filter or subdirectory to list. Supports wildcards.

    .PARAMETER Recurse
        Include items from subdirectories.

    .PARAMETER Directory
        Return only directories/folders.

    .PARAMETER File
        Return only files.

    .EXAMPLE
        Get-KlippyGcodeItem
        Lists all items (files and folders) in the root gcodes directory.

    .EXAMPLE
        Get-KlippyGcodeItem -PrinterName "voronv2" -Directory
        Lists only folders.

    .EXAMPLE
        Get-KlippyGcodeItem -Path "*.gcode" -File
        Lists all .gcode files.

    .EXAMPLE
        Get-KlippyGcodeItem -Recurse
        Lists all items recursively.

    .OUTPUTS
        PSCustomObject[] with file and folder information.
    #>

    [CmdletBinding(DefaultParameterSetName = 'Default')]
    [OutputType([PSCustomObject[]])]
    param(
        [Parameter(Mandatory = $true, ParameterSetName = 'ById')]
        [ValidateNotNullOrEmpty()]
        [string]$Id,

        [Parameter(Mandatory = $true, ParameterSetName = 'ByName')]
        [ValidateNotNullOrEmpty()]
        [string]$PrinterName,

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

        [Parameter(Position = 0)]
        [string]$Path,

        [Parameter()]
        [switch]$Recurse,

        [Parameter()]
        [switch]$Directory,

        [Parameter()]
        [switch]$File
    )

    process {
        # Resolve printer
        $resolveParams = @{}
        switch ($PSCmdlet.ParameterSetName) {
            'ById' { $resolveParams['Id'] = $Id }
            'ByName' { $resolveParams['PrinterName'] = $PrinterName }
            'ByObject' { $resolveParams['InputObject'] = $InputObject }
        }

        $printer = Resolve-KlippyPrinterTarget @resolveParams

        try {
            Write-Verbose "[$($printer.PrinterName)] Fetching directory listing..."

            $results = [System.Collections.Generic.List[PSCustomObject]]::new()

            # Get folders unless -File is specified
            if (-not $File) {
                $folders = Get-KlippyGcodeFolder @resolveParams -Path $Path
                foreach ($folder in $folders) {
                    $folder | Add-Member -NotePropertyName 'ItemType' -NotePropertyValue 'Directory' -Force
                    $folder | Add-Member -NotePropertyName 'Size' -NotePropertyValue $null -Force
                    $folder | Add-Member -NotePropertyName 'SizeMB' -NotePropertyValue $null -Force
                    $results.Add($folder)
                }
            }

            # Get files unless -Directory is specified
            if (-not $Directory) {
                $fileParams = @{}
                if ($Path) { $fileParams['Path'] = $Path }
                if ($Recurse) { $fileParams['Recurse'] = $true }

                $files = Get-KlippyGcodeFile @resolveParams @fileParams
                foreach ($file in $files) {
                    $file | Add-Member -NotePropertyName 'ItemType' -NotePropertyValue 'File' -Force
                    $results.Add($file)
                }
            }

            # Sort results: directories first, then by name
            $sortedResults = $results | Sort-Object -Property @{Expression = {$_.ItemType -eq 'File'}}, Name

            return $sortedResults
        }
        catch {
            Write-Error "[$($printer.PrinterName)] Failed to list items: $_"
        }
    }
}