Public/Invoke-CpmfUipsCLI.ps1

function Invoke-CpmfUipsCLI {
    <#
    .SYNOPSIS
        Single entry point for the CpmfUipsCLI wrapper. Dispatches to CpmfUipsPack public functions.
 
    .DESCRIPTION
        Invoke-CpmfUipsCLI routes a subcommand string to the corresponding CpmfUipsPack function.
        All remaining parameters are forwarded via splatting. Repo-root defaults and environment
        variables are applied before forwarding, following the same path-first hierarchy as CpmfUipsPack.
 
        Subcommands:
          pack Invoke-CpmfUipsPack
          analyze Invoke-CpmfUipsAnalyze
          install-tool Install-CpmfUipsPackCommandLineTool
          uninstall-tool Uninstall-CpmfUipsPackCommandLineTool
          install-uipathcli Install-UipathcliTool
          uninstall-uipathcli Uninstall-UipathcliTool
          install-config Install-CpmfUipsPackConfig
          uninstall-config Uninstall-CpmfUipsPackConfig
          install-hook Install-CpmfUipsPackGitHook
          diagnose Get-CpmfUipsPackDiagnostics
 
    .PARAMETER Command
        The subcommand to execute. Tab-completable. Optional when using -Version.
 
    .PARAMETER ShowVersion
        Print the wrapper and dependency versions and exit without dispatching a subcommand.
 
    .PARAMETER ProjectJson
        Path to the UiPath project.json. Forwarded to pack and install-hook subcommands.
 
    .PARAMETER FeedPath
        NuGet feed path. Forwarded to pack. Defaults to the repo config / env var layer if set.
 
    .PARAMETER ProjectVersion
        Explicit version string written to project.json before packing. Forwarded to pack.
        Use in CI pipelines that derive the version from a git tag (e.g. GITHUB_REF_NAME).
 
    .PARAMETER OutputPath
        Base directory for native uipcli pack output. Forwarded to pack. The shared
        pack module will create a unique child directory under this root for each run.
 
    .PARAMETER UipcliPathNet6
        Absolute path to the net6 uipcli.exe. Forwarded to pack and install-tool.
 
    .PARAMETER UipcliPathNet8
        Absolute path to the net8 uipcli.exe. Forwarded to pack and install-tool.
 
    .PARAMETER Targets
        Target TFMs to build. E.g. @('net6') or @('net6','net8'). Forwarded to pack.
 
    .PARAMETER NoBump
        Skip the version bump. Forwarded to pack.
 
    .PARAMETER UseWorktree
        Pack from a clean git worktree. Forwarded to pack.
 
    .PARAMETER SkipInstall
        Skip uipcli auto-install. Forwarded to pack.
 
    .PARAMETER MultiTfm
        Merge net6/net8 TFM outputs into a single nupkg. Forwarded to pack.
 
    .PARAMETER Backend
        Pack backend: 'uipcli' (default), 'uipathcli', or 'workflowcompiler'.
        Forwarded to pack and analyze.
 
        'workflowcompiler' invokes UiPath.WorkflowCompiler directly. It is the only
        backend that can keep project sources out of the package (uipcli hardcodes
        --include-sources true) and the only one that can override the package id.
        net8 only; analyze is not supported for it.
 
    .PARAMETER PublisherProps
        Path to a publisher .props file supplying shared package identity and pack
        policy. Forwarded to pack. Explicit parameters win over the props file.
 
    .PARAMETER PackageId
        Package id written to the nuspec, overriding project.json's "name". Forwarded to pack.
 
    .PARAMETER PackageAuthor
        Package author. Forwarded to pack. Defaults to PublisherAuthors from the props file.
 
    .PARAMETER PackageDescription
        Package description. Forwarded to pack.
 
    .PARAMETER PackageTags
        Space-separated package tags. Forwarded to pack.
 
    .PARAMETER IconUrl
        Package icon URL. Forwarded to pack.
 
    .PARAMETER ProjectUrl
        Package project URL. Forwarded to pack.
 
    .PARAMETER ReleaseNotes
        Package release notes. Forwarded to pack.
 
    .PARAMETER RepositoryType
        Repository type stamped into the package. Forwarded to pack.
 
    .PARAMETER RepositoryUrl
        Repository URL. Derived from git when omitted. Forwarded to pack.
 
    .PARAMETER RepositoryBranch
        Repository branch. Derived from git when omitted. Forwarded to pack.
 
    .PARAMETER RepositoryCommit
        Repository commit. Derived from git when omitted. Forwarded to pack.
 
    .PARAMETER IncludeSources
        Ship project sources inside the package. Default false. Forwarded to pack.
 
    .PARAMETER WorkflowCompilerPath
        Path to UiPath.WorkflowCompiler.dll or .exe. Forwarded to pack.
 
    .PARAMETER DotnetPath
        Dotnet host for a .dll compiler. Forwarded to pack.
 
    .PARAMETER ConfigFile
        Per-project config file (.psd1). Forwarded to pack.
 
    .PARAMETER CliVersion
        uipcli version (deprecated alias). Forwarded to pack.
 
    .PARAMETER CliVersionNet6
        uipcli version for the net6 target. Forwarded to pack and install-tool.
 
    .PARAMETER CliVersionNet8
        uipcli version for the net8 target. Forwarded to pack and install-tool.
 
    .PARAMETER ToolBase
        Base directory for managed tool installs. Forwarded to pack, install-tool, uninstall-tool.
 
    .PARAMETER ToolBasePath
        Canonical tool root directory. Same as -ToolBase; kept for the shared path-var naming convention.
 
    .PARAMETER Force
        Overwrite existing config. Forwarded to install-config.
 
    .EXAMPLE
        Invoke-CpmfUipsCLI pack -ProjectJson C:\repos\MyBot\project.json
 
    .EXAMPLE
        Invoke-CpmfUipsCLI pack -ProjectJson C:\repos\MyBot\project.json -Targets net6,net8 -WhatIf
 
    .EXAMPLE
        Invoke-CpmfUipsCLI pack -ProjectJson C:\repos\MyLib\project.json -Targets net8 `
            -Backend workflowcompiler -PublisherProps D:\schemas\publisher.props `
            -PackageId MyBrand.MyLib
 
    .EXAMPLE
        Invoke-CpmfUipsCLI install-tool
 
    .EXAMPLE
        Invoke-CpmfUipsCLI diagnose
 
    .OUTPUTS
        [string[]] for the pack subcommand (paths to staged .nupkg files).
        [string] for the diagnose subcommand (pseudonymized environment report).
        No output for lifecycle subcommands.
    #>

    [CmdletBinding(SupportsShouldProcess)]
    [OutputType([string[]], ParameterSetName = '__AllParameterSets')]
    param(
        [Parameter(Position = 0)]
        [ValidateSet('pack', 'analyze', 'install-tool', 'uninstall-tool', 'install-uipathcli', 'uninstall-uipathcli', 'install-config', 'uninstall-config', 'install-hook', 'diagnose')]
        [string] $Command,
        [switch] $ShowVersion,

        # --- shared / pack / analyze ---
        [string]   $ProjectJson,
        [string]   $ProjectVersion,
        [string]   $FeedPath,
        [string]   $OutputPath,
        [string[]] $Targets,
        [ValidateSet('uipcli', 'uipathcli', 'workflowcompiler')]
        [string]   $Backend,
        [switch]   $NoBump,
        [switch]   $UseWorktree,
        [switch]   $SkipInstall,
        [switch]   $MultiTfm,
        [string]   $ConfigFile,

        # --- publisher identity / workflowcompiler backend (pack only) ---
        [string]   $PublisherProps,
        [string]   $PackageId,
        [string]   $PackageAuthor,
        [string]   $PackageDescription,
        [string]   $PackageTags,
        [string]   $IconUrl,
        [string]   $ProjectUrl,
        [string]   $ReleaseNotes,
        [string]   $RepositoryType,
        [string]   $RepositoryUrl,
        [string]   $RepositoryBranch,
        [string]   $RepositoryCommit,
        [switch]   $IncludeSources,
        [string]   $WorkflowCompilerPath,
        [string]   $DotnetPath,

        # --- tool version ---
        [string]   $CliVersion,        # deprecated passthrough
        [string]   $CliVersionNet6,
        [string]   $CliVersionNet8,
        [string]   $UipcliPathNet6,
        [string]   $UipcliPathNet8,
        [Alias('ToolBase')]
        [string]   $ToolBasePath = (Join-Path $env:LOCALAPPDATA 'cpmf\tools'),

        # --- install-config ---
        [switch]   $Force
    )

    if ($ShowVersion) {
        $cliVersion = (Get-Module CpmfUipsCLI).Version
        $packVersion = (Get-Module CpmfUipsPack).Version
        Write-Output "CpmfUipsCLI $cliVersion (CpmfUipsPack $packVersion)"
        return
    }

    if ([string]::IsNullOrWhiteSpace($Command)) {
        throw "Command is required unless -ShowVersion is specified."
    }

    $cfg = Get-CpmfUipsCLIEffectiveConfig
    foreach ($key in @('FeedPath', 'OutputPath', 'Targets', 'NoBump', 'SkipInstall', 'UseWorktree', 'WorktreeBase', 'WorktreeSibling', 'MultiTfm', 'Backend', 'CliVersionNet6', 'CliVersionNet8', 'UipcliPathNet6', 'UipcliPathNet8', 'ToolBasePath',
                       'PublisherProps', 'PackageId', 'PackageAuthor', 'PackageDescription', 'PackageTags',
                       'IconUrl', 'ProjectUrl', 'ReleaseNotes', 'RepositoryType', 'RepositoryUrl',
                       'RepositoryBranch', 'RepositoryCommit', 'IncludeSources', 'WorkflowCompilerPath', 'DotnetPath')) {
        if (-not $PSBoundParameters.ContainsKey($key) -and $cfg.ContainsKey($key)) {
            if ($key -in @('Targets')) {
                $value = [string[]]$cfg[$key]
            } elseif ($key -in @('NoBump', 'SkipInstall', 'UseWorktree', 'MultiTfm', 'IncludeSources')) {
                $value = [bool]$cfg[$key]
            } else {
                $value = $cfg[$key]
            }
            Set-Variable -Name $key -Value $value
            $PSBoundParameters[$key] = $value
        }
    }

    # Build a plain hashtable copy for splatting — PSBoundParametersDictionary has no .Clone().
    $forwardParams = @{}
    foreach ($kv in $PSBoundParameters.GetEnumerator()) { $forwardParams[$kv.Key] = $kv.Value }
    $forwardParams.Remove('Command') | Out-Null

    # Also remove CLI-only params not accepted by specific subcommands.
    $configOnly   = @('Force')

    switch ($Command) {
        'pack' {
            $remove = @('Force')
            foreach ($k in $remove) { $forwardParams.Remove($k) | Out-Null }
            Write-Verbose "[CpmfUipsCLI] → Invoke-CpmfUipsPack"
            $projectName = if ($ProjectJson) { Split-Path (Split-Path $ProjectJson -Parent) -Leaf } else { '(unknown)' }
            Write-Host "[pack] Packing $projectName …"
            $packResults = @(Invoke-CpmfUipsPack @forwardParams)
            foreach ($path in $packResults) {
                Write-Host "[pack] Staged: $(Split-Path $path -Leaf)"
            }
            Write-Output $packResults
        }

        'analyze' {
            $remove = @('FeedPath', 'OutputPath', 'UseWorktree', 'WorktreeSibling', 'MultiTfm', 'ProjectVersion', 'Force',
                        'PublisherProps', 'PackageId', 'PackageAuthor', 'PackageDescription', 'PackageTags',
                        'IconUrl', 'ProjectUrl', 'ReleaseNotes', 'RepositoryType', 'RepositoryUrl',
                        'RepositoryBranch', 'RepositoryCommit', 'IncludeSources', 'WorkflowCompilerPath', 'DotnetPath')
            foreach ($k in $remove) { $forwardParams.Remove($k) | Out-Null }
            Write-Verbose "[CpmfUipsCLI] → Invoke-CpmfUipsAnalyze"
            $projectName = if ($ProjectJson) { Split-Path (Split-Path $ProjectJson -Parent) -Leaf } else { '(unknown)' }
            Write-Host "[analyze] Analyzing $projectName …"
            Write-Output (Invoke-CpmfUipsAnalyze @forwardParams)
        }

        'install-uipathcli' {
            $keep = @('ToolBasePath', 'WhatIf', 'Confirm', 'Verbose')
            $toRemove = @($forwardParams.Keys) | Where-Object { $_ -notin $keep }
            foreach ($k in $toRemove) { $forwardParams.Remove($k) | Out-Null }
            Write-Verbose "[CpmfUipsCLI] → Install-UipathcliTool"
            Install-UipathcliTool @forwardParams
        }

        'uninstall-uipathcli' {
            $keep = @('ToolBasePath', 'WhatIf', 'Confirm', 'Verbose')
            $toRemove = @($forwardParams.Keys) | Where-Object { $_ -notin $keep }
            foreach ($k in $toRemove) { $forwardParams.Remove($k) | Out-Null }
            Write-Verbose "[CpmfUipsCLI] → Uninstall-UipathcliTool"
            Uninstall-UipathcliTool @forwardParams
        }

        'install-tool' {
            $keep = @('ToolBasePath', 'WhatIf', 'Confirm', 'Verbose')
            $toRemove = @($forwardParams.Keys) | Where-Object { $_ -notin $keep }
            foreach ($k in $toRemove) { $forwardParams.Remove($k) | Out-Null }
            if ($PSBoundParameters.ContainsKey('UipcliPathNet8')) {
                $forwardParams['UipcliPath'] = $UipcliPathNet8
            } elseif ($PSBoundParameters.ContainsKey('UipcliPathNet6')) {
                $forwardParams['UipcliPath'] = $UipcliPathNet6
            } elseif ($PSBoundParameters.ContainsKey('CliVersionNet8')) {
                $forwardParams['CliVersion'] = $CliVersionNet8
            } elseif ($PSBoundParameters.ContainsKey('CliVersionNet6')) {
                $forwardParams['CliVersion'] = $CliVersionNet6
            } elseif ($PSBoundParameters.ContainsKey('CliVersion')) {
                $forwardParams['CliVersion'] = $CliVersion
            }
            Write-Verbose "[CpmfUipsCLI] → Install-CpmfUipsPackCommandLineTool"
            Install-CpmfUipsPackCommandLineTool @forwardParams
        }

        'uninstall-tool' {
            $keep = @('ToolBasePath', 'WhatIf', 'Confirm', 'Verbose')
            $toRemove = @($forwardParams.Keys) | Where-Object { $_ -notin $keep }
            foreach ($k in $toRemove) { $forwardParams.Remove($k) | Out-Null }
            if ($PSBoundParameters.ContainsKey('UipcliPathNet8')) {
                $forwardParams['UipcliPath'] = $UipcliPathNet8
            } elseif ($PSBoundParameters.ContainsKey('UipcliPathNet6')) {
                $forwardParams['UipcliPath'] = $UipcliPathNet6
            } elseif ($PSBoundParameters.ContainsKey('CliVersionNet8')) {
                $forwardParams['CliVersion'] = $CliVersionNet8
            } elseif ($PSBoundParameters.ContainsKey('CliVersionNet6')) {
                $forwardParams['CliVersion'] = $CliVersionNet6
            } elseif ($PSBoundParameters.ContainsKey('CliVersion')) {
                $forwardParams['CliVersion'] = $CliVersion
            }
            Write-Verbose "[CpmfUipsCLI] → Uninstall-CpmfUipsPackCommandLineTool"
            Uninstall-CpmfUipsPackCommandLineTool @forwardParams
        }

        'install-config' {
            $keep = $configOnly + @('WhatIf', 'Confirm', 'Verbose')
            $toRemove = @($forwardParams.Keys) | Where-Object { $_ -notin $keep }
            foreach ($k in $toRemove) { $forwardParams.Remove($k) | Out-Null }
            Write-Verbose "[CpmfUipsCLI] → Install-CpmfUipsPackConfig"
            Install-CpmfUipsPackConfig @forwardParams
        }

        'uninstall-config' {
            $toRemove = @($forwardParams.Keys) | Where-Object { $_ -notin @('WhatIf', 'Confirm', 'Verbose') }
            foreach ($k in $toRemove) { $forwardParams.Remove($k) | Out-Null }
            Write-Verbose "[CpmfUipsCLI] → Uninstall-CpmfUipsPackConfig"
            Uninstall-CpmfUipsPackConfig @forwardParams
        }

        'install-hook' {
            $keep = @('ProjectJson', 'WhatIf', 'Confirm', 'Verbose')
            $toRemove = @($forwardParams.Keys) | Where-Object { $_ -notin $keep }
            foreach ($k in $toRemove) { $forwardParams.Remove($k) | Out-Null }
            Write-Verbose "[CpmfUipsCLI] → Install-CpmfUipsPackGitHook"
            Install-CpmfUipsPackGitHook @forwardParams
        }

        'diagnose' {
            $toRemove = @($forwardParams.Keys) | Where-Object { $_ -notin @('Verbose') }
            foreach ($k in $toRemove) { $forwardParams.Remove($k) | Out-Null }
            Write-Verbose "[CpmfUipsCLI] → Get-CpmfUipsPackDiagnostics"
            Write-Output (Get-CpmfUipsPackDiagnostics @forwardParams)
        }
    }
}